gpt4 book ai didi

javascript - Canvas:逐像素绘制图像和requestAnimationFrame时序

转载 作者:行者123 更新时间:2023-11-30 11:58:30 29 4
gpt4 key购买 nike

出于学习目的,我正在编写一些代码以在 Canvas 中逐像素随机绘制图像。这是 link对于以下代码。

我希望动画在 1 秒内完成。但是,正如您从控制台中看到的那样,它大约需要 7 秒。我尝试使用较小的图像,数字接近 1 秒。

所以在这种情况下,requestAnimationFrame的时机是不靠谱的。我想知道原因。是不是因为 putImageData 在其数据数组中寻找一个像素需要太多时间?或者是因为别的什么。我认为了解 requestAnimationFrame 的计时何时不可靠对于制作好的动画至关重要。

此外,有没有更好的方法来做我想做的事情?

// At first, I get the image's data, then I build an array whose 
// length is equal to the number of pixels of the image, each element
// of the array represents one of the image's pixel. Then I shuffle
// this array and pop a certain number of elements for
// `ctx.putImageData` to draw the corresponding pixel per frame.

var ctx = c.getContext("2d"),
img = new Image();
img.onload = init;
img.src = "download.png"; //placehold.it's 300x200 image

function formArr(w,h){ //Build image pixel outputting sequence array based on image's width and height
var arr = [];
for (i=0;i<w*h;i++){
arr.push(i);
}
return arr;
}

function Point(i,w){ //locate pixel's X and Y base on image width
this.x = i%w;
this.y = Math.floor(i/w);
}

function shuffleRect(arr){ //shuffle the output sequence array
....
}

function init(){
var w = ctx.canvas.width = img.width*2;
var h = ctx.canvas.height = img.height*2;
//form Image Data
ctx.drawImage(img,0,0,w,h);
var imageData = ctx.getImageData(0,0,w,h);
ctx.clearRect(0,0,w,h);

//build output sequence
var sequence = formArr(w,h);
shuffleRect(sequence);

var sec = 1; //animation duration
var t1 = Date.now();
function animate(){
var pointsPerFrame = Math.floor(w*h/sec/60)+1;
for (i=0;i<Math.min(pointsPerFrame,sequence.length);i++){
var j = sequence.pop();
ctx.putImageData(imageData,0,0,new Point(j,w).x,new Point(j,w).y,1,1); //draw points for next frame

}
if(sequence.length){requestAnimationFrame(animate)}else{
var t2 = Date.now();
console.log(t2-t1);

}
}
animate();
}

最佳答案

使用裁剪版本的drawImage会比putImageData更快

// directly copy from image to canvas 1 pixel at a time
context.drawImage(image,x,y,1,1,x,y,1,1);

但使用合成可能比 putImageData 和 drawImage...更快

首先在内存中创建图像大小的第二个 Canvas 。

然后在每个动画循环中:

  • 在第二个 Canvas 上填充所需数量的新随机像素:memoryContext.beginPath + memoryContext.rect(x,y,1,1) 每个新像素 + memoryContext.fill()
  • 清除主 Canvas 。
  • 将辅助 Canvas 绘制到主 Canvas 上:drawImage(memoryCanvas,0,0)
  • 在主 Canvas 上将合成设置为 source-atop
  • drawImage 将图像拖到主 Canvas 上。合成将使图像仅出现在填充像素所在的位置。
  • 在主 Canvas 上将合成设置回 source-over

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvas2=document.createElement("canvas");
var ctx2=canvas2.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var newPixelCount;
var accumPixelCount=0;
var totPixels;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg";
function start(){
cw=canvas.width=canvas2.width=img.width;
ch=canvas.height=canvas2.height=img.height;
newPixelCount=cw*ch/60;
totPixels=cw*ch;
t1=performance.now();
requestAnimationFrame(animate);
}

function animate(){
ctx2.beginPath();
for(var i=0;i<newPixelCount;i++){
accumPixelCount++;
if(accumPixelCount<totPixels){
var y=parseInt(accumPixelCount/cw);
var x=accumPixelCount-y*cw;
ctx2.rect(x,y,1,1);
}
}
ctx2.fill();
ctx.clearRect(0,0,cw,ch);
ctx.drawImage(canvas2,0,0);
ctx.globalCompositeOperation='source-atop';
ctx.drawImage(img,0,0);
ctx.globalCompositeOperation='source-over';
//
if(accumPixelCount<totPixels){
requestAnimationFrame(animate);
}else{
alert('Complete: '+parseInt(performance.now()-t1)+'ms');
}
}

function animateDrawImage(){
ctx2.beginPath();
for(var i=0;i<newPixelCount;i++){
accumPixelCount++;
if(accumPixelCount<totPixels){
var y=parseInt(accumPixelCount/cw);
var x=accumPixelCount-y*cw;
ctx.drawImage(img,x,y,1,1,x,y,1,1);
}
}
//
if(accumPixelCount<totPixels){
requestAnimationFrame(animate);
}else{
alert('Complete: '+parseInt(performance.now()-t1)+'ms');

}
}
<canvas id="canvas" width=300 height=300></canvas>

关于javascript - Canvas:逐像素绘制图像和requestAnimationFrame时序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37245251/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com