我有以下小代码,用于确定画布上的颜色百分比,在这种情况下,颜色是透明的,imageData.data返回为[0,0,0]
由于我在mouseove上返回了这个百分比,因此运行和优化它是非常昂贵的。还要记住画布的颜色不断变化,所以我每次都需要获取imageData并对其进行迭代。
当然,瓶颈都在scratchPercentage函数中,我需要一种方法来优化它——例如,只获得新的更改,而不是每次都运行所有的图像数据。
scratchFunc: function(e, $this, event)
{
e.pageX = Math.floor(e.pageX - $this.canvas_offset.left);
e.pageY = Math.floor(e.pageY - $this.canvas_offset.top);
$this['scratch' + event](e, $this);
if($this.settings['scratch' + event])
$this.settings['scratch' + event](e, $this.scratchPercentage($this));
},
scratchPercentage: function($this)
{
var hits = 0;
var imageData = $this.ctx.getImageData(0,0,$this.canvas.width,$this.canvas.height)
for(var i=0, ii=imageData.data.length; i<ii; i=i+4)
{
if(
imageData.data[i] == 0 &&
imageData.data[i+1] == 0 &&
imageData.data[i+2] == 0 &&
imageData.data[i+3] == 0
) hits++;
}
return hits / ($this.pixels) * 100;
},
从这个修改开始:
scratchPercentage: function($this)
{
var hits = 0;
var imageData = $this.ctx.getImageData(0,0,$this.canvas.width,$this.canvas.height).data
var pixels = imageData.length;
for(var i=0, ii=pixels; i<ii; i=i+4)
{
if(
imageData[i] == 0 &&
imageData[i+1] == 0 &&
imageData[i+2] == 0 &&
imageData[i+3] == 0
) hits++;
}
return hits / ($this.pixels) * 100;
}
我没有现成的引用链接,但维护画布数据数组的句柄可以节省每次迭代时必须解析像素数据位置的循环。这实际上会显著提高性能。类似地,虽然不那么重要,但您也可以为数组的大小分配一个变量,这样您就不必在每次循环迭代后解析值。
除了这两个变化,我认为你不能让scratchPercentage()
变得更瘦。在不了解画布如何从一帧到另一帧变化的细节的情况下,我真的不能建议任何只计算变化的优化。根据您的精度需要,您可以考虑每隔一个像素进行检查。
我也可以想出一个粗略的WebGL解决方案,但它不是直接的。最终,如果你没有任何关于当前帧和前一帧之间变化的一致信息,你就无法预先计算这个百分比或显著加快它的速度。
编辑:根据您的画布大小,您可以尝试将内存中的副本大小调整为50%,然后进行计算。它不会是完美的,但应该是相对准确的。
1)降低采样率。
不要在每次mousemove事件发生时都调用计算,而是保存mouseX、mouseY,然后在setInterval
中调用示例函数(使用间隔值进行实验,其中100%准确和安全的值是渲染循环的间隔)
或者使用某种油门功能,如http://documentcloud.github.com/underscore/#throttle
2) 如果这个功能不一定要超精确,跳过一些像素
假设每2个for (...; i = i + 8)