javascript - HTML5 Canvas - 动画未按预期工作

标签 javascript html canvas

我制作了简单的背景生成器,它使背景充满了相同大小的不同灰色的立方体( block )。然后我准备了将一些随机 block 动画化为蓝色然后返回起始颜色的函数。我设置了每 5 秒运行一次随机 block 的时间间隔。内部函数有两个循环(2x 100 步),超时设置为 25 毫秒(总共 5 秒)。问题是,控制台颜色会发生变化,但 Canvas 上不会发生变化。请问你能找出哪里出了问题吗?

jsFiddle 上的代码,放在这里只是为了让我提出问题:

var blockSize = 20; // Size of one block
var canW = 200; // Size of canvas
var canH = 100;
var cvsName = 'cvsBg'; // Name of canvas
var color = [0, 0, 0]; // container for changing color
var defaultColor = [0, 0, 0] // container for block color given by prepareBG()
var blueColor = [0, 204, 255]; // color to which is default color changing
var rndPositonW = getRandomInt(0, canW); // random point on Canvas, to select actually changing block
var rndPositonH = getRandomInt(0, canH);
var cSteps = 100; // animation steps between default color and blue color
var cChangeInterval = 5000; // run one block animation  each 5s

var can = document.getElementById(cvsName);
can.width = canW;
can.height = canH;
var ctx = can.getContext('2d');

prepareBG(ctx); //prepare bg with gray colored blocks

setInterval(colorAnimation, cChangeInterval, ctx, rndPositonW, rndPositonH);
// in this interval to do animation: 
//    100 steps from default color to blue
//    100 steps from blue back to default color

function colorAnimation(ctx, cBlockX, cBlockY) {
  var pixelData = ctx.getImageData(cBlockX, cBlockY, 1, 1).data; // get default color at randomly selected point
  defaultColor = [pixelData[0], pixelData[1], pixelData[2]];

  var blockX = Math.floor(cBlockX / blockSize) * blockSize; // get zero coordinated of block under randomly selected point 
  var blockY = Math.floor(cBlockY / blockSize) * blockSize;

  var i, j;
  for (i = 0; i <= cSteps; i++) { // coloring from default color to blue: 100 steps, one step each 25ms (color change interval is 5000 divided by total steps 200 )
    for (j = 0; j < 3; j++) { // compute changing RGB e.g. if i is near 100, color will be almost blue
      color[j] = defaultColor[j] + ((blueColor[j] - defaultColor[j]) / cSteps) * i;
    }
    console.log("Drawing: X=%i, Y=%i, Color=%i,%i,%i", blockX, blockY, color[0], color[1], color[2]);
    setTimeout(drawBlock, cChangeInterval / cSteps / 2, ctx, blockX, blockY, color, blockSize);
  }
  for (i = 0; i <= cSteps; i++) { // coloring from blue color to defalut: 100 steps, one step each 25ms (color change interval is 5000 divided by total steps 200 )
    for (j = 0; j < 3; j++) { // compute changing RGB e.g. if i is near 100, color will be almost default
      color[j] = blueColor[j] - ((blueColor[j] - defaultColor[j]) / cSteps) * i;
    }
    setTimeout(drawBlock, cChangeInterval / cSteps / 2, ctx, blockX, blockY, color, blockSize);
  }
  rndPositonW = getRandomInt(0, canW); // find new random point for next block animation
  rndPositonH = getRandomInt(0, canH);
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function prepareBG(ctx) {
  var x = 0;
  var y = 0;
  var c = 0
  for (x = 0; x <= can.width; x += blockSize) {
    for (y = 0; y <= can.height; y += blockSize) {
      c = getRandomInt(50, 56);
      drawBlock(ctx, x, y, [c, c, c], blockSize);
    }
  }
  //CANVAS will be used as body's background:
  //document.body.style.background = 'url(' + can.toDataURL() + ')';
}

function drawBlock(ctx, x, y, c, blocksize) {
  ctx.fillStyle = 'rgb(' + c[0] + ', ' + c[1] + ', ' + c[2] + ')';
  ctx.fillRect(x, y, blockSize, blockSize);
}
<canvas id="cvsBg">

最佳答案

太好了,谢谢凯多!这是我对 setTimeout 如何工作的错误理解...我错误地期望类似于暂停的行为,因为这就是我搜索的内容。

var blockSize = 20; // Size of one block
var canW = 500; // Size of canvas
var canH = 200;
var cvsName = 'cvsBg'; // Name of canvas
var color = [0,0,0]; // container for changing color
var defaultColor = [0,0,0] // container for block color given by prepareBG()
var blueColor = [0,204,255]; // color to which is default color changing
var animationSteps = 30; // total animation steps up & down
var animationPause = 1000; // pause between animations
var animationTime = 1000; // duration of one animation
var animationRunning = false;

var can = document.getElementById(cvsName); 
can.width = canW;
can.height = canH;
var ctx = can.getContext('2d');

prepareBG(ctx); //prepare bg with gray colored blocks

var count = 0;
function update(rndPositonW,rndPositonH) {
  if(!animationRunning) {
    var pixelData = ctx.getImageData(rndPositonW, rndPositonH, 1, 1).data; // get default color at randomly selected point
    defaultColor = [pixelData[0],pixelData[1],pixelData[2]];
    animationRunning = true;
  }
  var blockX = Math.floor(rndPositonW / blockSize) * blockSize; // get zero coordinated of block under randomly selected point 
  var blockY = Math.floor(rndPositonH / blockSize) * blockSize;
  var j;
  for(j=0; j<3; j++){ // compute changing RGB e.g. if i is near 100, color will be almost blue
    if(count < (animationSteps / 2)) color[j] = defaultColor[j] + ((blueColor[j] - defaultColor[j]) / (animationSteps / 2)) * count; //way up
    else color[j] = blueColor[j] - ((blueColor[j] - defaultColor[j]) / (animationSteps / 2)) * (count - (animationSteps / 2)); //way down
  }
  drawBlock(ctx, blockX, blockY, color, blockSize);
  
  if (++count <= animationSteps) {
    setTimeout(update, animationTime / animationSteps, rndPositonW, rndPositonH);
  } else {
    count = 0;
    animationRunning = false;
    setTimeout(update, animationPause, getRandomInt(0, canW), getRandomInt(0, canH));
  }       
}
update(getRandomInt(0, canW), getRandomInt(0, canH));

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
} 

function prepareBG(ctx){     
  var x = 0;
  var y = 0;
  var c = 0
  for (x = 0; x <= can.width; x+=blockSize) {
    for (y = 0; y <= can.height; y+=blockSize) {
      c = getRandomInt(50, 60);
      drawBlock(ctx, x, y, [c,c,c], blockSize);
    }
  }
  //CANVAS will be used as body's background:
  //document.body.style.background = 'url(' + can.toDataURL() + ')';
}

function drawBlock(ctx,x,y,c,blocksize){
  ctx.fillStyle = 'rgb(' + c[0] + ', ' + c[1] + ', ' + c[2] + ')';
  ctx.fillRect(x, y, blockSize, blockSize);
}
<canvas id="cvsBg">

关于javascript - HTML5 Canvas - 动画未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52873550/

相关文章:

html - float :right in the correct order it appears in HTML code

html - 关联 CSS 样式表

python - 动态改变 Canvas 大小

css - HTML5 Canvas 作为背景

javascript - HTML5 Canvas画线点间距离

javascript - HTML5/Canvas 是否支持双缓冲?

javascript - jQuery UI 拖动 div 不起作用

javascript - 请帮助优化简单的 JQuery 函数

JavaScript 与无 JavaScript 链接和表单

javascript - 使用 JQuery 选择具有特定类的所有 <tr> 元素