【问题标题】:Animating / Move canvas image that has been placed by putImageData动画/移动 putImageData 放置的画布图像
【发布时间】:2016-03-30 21:44:46
【问题描述】:

我有一个已解码的 jpeg 图像,我正在使用 putImageData 将其写入画布。然后可以移动这个图像吗?我找不到任何文档。

我的想法是我将用dirtyX和dirtyY裁剪解码图像的某个部分,现在我想裁剪图像的另一部分。我正在使用解码后的图像,如 spritesheet。

【问题讨论】:

  • 是的,你可以为它制作动画,但没有像 context.animate() 这样的方法。您必须使用 requestAnimationFrame (developer.mozilla.org/en-US/docs/Web/API/window/…),然后每帧移动图像。
  • 所以我必须在每次调用 requestAnimationFrame 时调用 putImageData?
  • 我认为最好的办法是 getImageData() 获取所有像素的信息,然后修改你需要移动的那些,然后 putImageData() w3schools.com/tags/canvas_getimagedata.asp
  • 谢谢,我试过这个版本,但性能非常低。每次调用 putImageData 处理图像数据似乎需要大约 40 毫秒(因此会跳过帧)。
  • putimagedata 通常用于实时视频效果,因此它应该足够快。试一试treeno的答案

标签: javascript canvas html5-canvas putimagedata


【解决方案1】:

使用 drawImage 的剪辑版本将您的各个精灵绘制到画布上

(不要使用 getImageData 和 putImageData 进行剪辑,因为 drawImage 更容易更快。)

如果您想将解码后的图像用作 spritesheet,则可以使用画布的剪辑版本 context.drawImage 剪辑 spritesheet 的特定子部分并将其绘制到画布上。

这是以前的 SO 帖子,关于 drawImage 的剪辑版本。

HTML / Java Script Canvas - how to draw an image between source and destination points?

这是示例代码和演示:

请注意,在画布上“移动”精灵的方法是清除画布并在新位置重新绘制所需的精灵。 (您不能“移动”画布上的现有绘图)。

$(window).load(function(){

  // canvas related variables       
  var canvas=document.getElementById("canvas");
  var ctx=canvas.getContext("2d");

  // animation related variables
  var lastFlap,lastMove;

  // define a bird object
  // x,y are the position of the bird on the canvas
  // spriteX,spriteY is the position of the first desired
  //      sprite image on the spritesheet
  // width,height is the size of 1 sprite image
  // currentFrame is the index of which of the sprite images to display
  // currentDirection.  The sprite plays forward and then backward to
  //      accomplish 1 flap.  This determines if the next frame index will
  //      be increased (play forward) or decreased (play backward)
  var bird={
    x:30,
    y:30,
    spriteX:0,
    spriteY:52,
    width:51,
    height:51,
    frames:4,
    currentFrame:0,
    currentDirection:1
  }

  // load the spritesheet and start the animation
  var spritesheet=new Image();
  spritesheet.onload=start;
  spritesheet.src="https://dl.dropboxusercontent.com/u/139992952/multple/birdSpritesheet.png";
  function start(){
    requestAnimationFrame(animate);
  }

  function animate(time){

    // request another animation frame

    if(bird.x<canvas.width){
      requestAnimationFrame(animate);
    }

    // if the lastFlap or lastMove times don't aren't set, then set them

    if(!lastFlap){lastFlap=time;}
    if(!lastMove){lastMove=time;}

    // calculate the elapsed times since the last flap and the last move

    var elapsedFlap=time-lastFlap;
    var elapsedMove=time-lastMove;

    // if 50ms have elapsed, advance to the next image in this sprite

    if(elapsedFlap>50){

      // advance to next sprite on the spritesheet (flap)

      bird.currentFrame+=bird.currentDirection;

      // clamp bird.currentFrame between 0-3  (0,1,2,3)
      // (because there are 4 images that make up the whole bird sprite)

      if(bird.currentFrame<0 || bird.currentFrame>bird.frames-1){
        bird.currentDirection*=-1;
        bird.currentFrame+=bird.currentDirection;
      }

      // reset the flap timer

      lastFlap=time;
    }

    // locate the current sprite from the spritesheet

    var sx=bird.spriteX+bird.currentFrame*bird.width;
    var sy=bird.spriteY;

    // if 100ms have elapsed, move the bird across the canvas

    if(elapsedMove>100){
      bird.x+=3;
      lastMove=time;
    }

    // clear the whole canvas

    ctx.clearRect(0,0,canvas.width,canvas.height);

    // draw the current part of the bird sprite at the current bird.x

    ctx.drawImage(spritesheet,
                  sx,sy,bird.width,bird.height,
                  bird.x,bird.y,bird.width,bird.height
                 );

  }

}); // end $(function(){});
body{ background-color: white; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>The canvas animating a clipped sprite</h4>
<canvas id="canvas" width=300 height=100></canvas>
<br>
<h4>The spritesheet</h4>
<img id=spritesheet src='https://dl.dropboxusercontent.com/u/139992952/multple/birdSpritesheet.png'>

【讨论】:

  • 非常感谢您,我会在周末后将其付诸实践,让您知道我的进展情况。最好的,
【解决方案2】:

是和否 :-) 由于画布以即时模式绘制,因此它不知道您已在画布上绘制了图像。因此,您不能一次在画布上绘制它并移动绘制的图像。您必须在每个动画帧中的新位置手动重绘完整图像。 正如 Jonas Grumann 解释的那样,您可以使用 requestAnimationFrame() 来做到这一点。

【讨论】:

    猜你喜欢
    • 2017-05-06
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 2013-10-27
    • 2013-11-18
    • 1970-01-01
    相关资源
    最近更新 更多