简体   繁体   中英

HTML5 Canvas - animation not working as expected

I made easy background generator, which makes bg filled with same-sized diferently grayed cubes (blocks). Then I've prepared function to animate some random block to blue and then back to starting color. I set interval to run random block each 5 seconds. Inside function are two loops (2x 100 steps), with timeout setted to 25ms (5 sec in total). Problem is, that by console color changes but not on Canvas. Can you find, what is wrong, please?

Code on jsFiddle, this is here only to allow me to ask the question:

 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 eg 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 eg 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"> 

Great, thanks Kaiido! It was my wrong understanding to how setTimeout works... I've wrongly expected behavior similar to pause because that was what i searched for.

 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 eg 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"> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM