为什么html canvas动画为每个新矩形渲染一个临时间隙?

时间:2018-12-29 08:15:31

标签: javascript html5 animation canvas html5-canvas

我有一个在html5画布上呈现的矩形数组或“管道”。新管道在渲染(和动画化)之前会动态添加到数组中。问题在于,每个新管道在其自身与上一个管道之间都具有微小的间隙,一旦引入下一个管道,该间隙就会消失。在任何时候都应该没有差距。

这太奇怪了,这让我发疯了。

下面的Codepen链接应该使这个问题更清楚。

Codepen working example.

const body = document.getElementsByTagName("body")[0];
const canvasWidth = 500;
const canvasHeight = 820;
const canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
var frame_count = 0;
var speed = 1;
var pipes = [];

function Pipe(height) {
  this.x = canvasWidth;
  this.height = height;
  this.update = function() {
    ctx.fill();
    ctx.fillStyle = 'black';
    ctx.beginPath();
    ctx.rect(this.x, 0, 100, this.height);
    this.x = this.x - (1 * speed);
  };
}

function setup() {
  // Render blank canvas to dom
  canvas.width = canvasWidth;
  canvas.height = canvasHeight;
  body.appendChild(canvas);
}

function draw() {
  // Clear canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Pipe generator
  if (frame_count % 100 === 0) {
    if (frame_count % 200 === 0) {
      pipes.push(new Pipe(100));
    } else {
      pipes.push(new Pipe(120));
    }
  }

  // Draw pipes
  for (i = 0; i < pipes.length; i++) {
    pipes[i].update();
  }

}

function loop() {
  setTimeout(function() {
    draw();
    frame_count++;
    requestAnimationFrame(loop);
  }, 0);
}

setup();
loop();

1 个答案:

答案 0 :(得分:3)

之所以会发生这种情况,是因为在绘图功能中您会反向进行所有操作;

当前,您首先要填充当前路径,然后声明它,最后更新位置。您需要从头到尾进行所有操作,以便填充最新版本的工程图,而不必等待一帧。

当绘制多个形状时,它似乎固定了,因为在同一帧中,下一个形状绘制了前一个形状的当前状态。

const body = document.getElementsByTagName("body")[0];
const canvasWidth = 500;
const canvasHeight = 820;
const canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
var frame_count = 0;
var speed = 1;
var pipes = [];

function Pipe(height) {
  this.x = canvasWidth;
  this.height = height;
  this.update = function() {
    // first update position
    this.x = this.x - (1 * speed);
    ctx.fillStyle = 'black';
    // then declare the path
    ctx.beginPath();
    ctx.rect(this.x, 0, 100, this.height);
    // finally draw it
    ctx.fill();
  };
}

function setup() {
  // Render blank canvas to dom
  canvas.width = canvasWidth;
  canvas.height = canvasHeight;
  body.appendChild(canvas);
}

function draw() {
  // Clear canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Pipe generator
  if (frame_count % 100 === 0) {
    if (frame_count % 200 === 0) {
      pipes.push(new Pipe(100));
    } else {
      pipes.push(new Pipe(120));
    }
  }

  // Draw pipes
  for (i = 0; i < pipes.length; i++) {
    pipes[i].update();
  }

}

function loop() {
// do not mix setTimeout and rAF, it's like having a Ferrari parked in a truck...
//  setTimeout(function() {
    draw();
    frame_count++;
    requestAnimationFrame(loop);
//  }, 0);
}

setup();
loop();