HTML5 Canvas-动画无法正常工作

时间:2018-10-18 12:02:32

标签: javascript html html5 canvas

我简化了背景生成器,它使bg充满了相同大小的不同灰色的立方体(块)。然后,我准备了将一些随机块动画化为蓝色,然后再恢复为初始颜色的函数。我将间隔设置为每5秒运行一次随机块。内部函数有两个循环(2x 100步),超时设置为25ms(总计5秒)。问题是,通过控制台颜色更改而不是在Canvas上更改。您能找到问题在哪里吗?

关于jsFiddle的代码,这里仅是允许我提出以下问题:

emplid      year        month       Reason
------      ----        -----       ------
1234        2018         APR        Retire
5678        2018         FEB        Terminated
9876        2018         MAY        Transfer
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);
}

1 个答案:

答案 0 :(得分:1)

太好了,谢谢海道!这是我对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">