【问题标题】:HTML5 : getImageData with onmousemove make slow my application in FirefoxHTML5:带有 onmousemove 的 getImageData 使我在 Firefox 中的应用程序变慢
【发布时间】:2016-06-04 01:25:57
【问题描述】:

我用画布创建了一个 html5 小游戏。

在画布中,有许多显示的精灵,其中一个自动从左到右移动。其他都是静态的。

当我将鼠标移动到画布上时,我会在一个临时画布中绘制所有精灵,并使用 getImageData 来查找鼠标所在的精灵。

但是 getImageData 会使 Firefox 中的移动精灵异常缓慢。

那么有什么办法可以避免这种减速呢?

这是我的代码:

function getSelectedObject(array_objects)
{
    //Clear the temporary canvas :
    tmpcx.clearRect(0, 0, tmpc.width, tmpc.height);

    /*Search the right sprite object :*/
    for(var i = array_objects.length-1; i >= 0; i--)
    {
        array_objects[i].draw(tmpcx);

        imageData = tmpcx.getImageData(mouse_x, mouse_y, 1, 1);

        component = imageData.data;

        if(component[3] > 0)
        {   
            //Return the sprite object found : 
            return array_objects[i];
        }

        else
        {
            tmpcx.clearRect(0, 0, tmpc.width, tmpc.height);
        }
    }

    return false;
}


canvas.onmousemove = function(event)
{

selectedObject = getSelectedObject(array_objects);

}

【问题讨论】:

  • 那么有什么办法可以避免这种减速呢?
  • 不清楚您要在此处完成什么。您想要在画布上移动精灵来跟踪鼠标位置吗?
  • 移动精灵只是为了检查应用程序的性能:如果移动精灵减速,则表示应用程序性能不佳。通常,移动的精灵不能减速。
  • 在临时画布上不断绘图和擦除似乎不必要地昂贵。对此我有两个建议: 1. 为您的游戏使用两个画布,一个用于渲染背景和任何装饰性的东西,另一个用于您想要跟踪的交互元素。 2. 存储每个精灵边界框的坐标。这样,你可以先检查鼠标是否在交互的东西上,然后你可以使用坐标来确定它在哪个元素内
  • 我不明白的是为什么你循环通过精灵和绘制/读取画布数据。这是一个超级昂贵的“性能测试”。

标签: javascript html getimagedata


【解决方案1】:

不确定您会获得多少性能提升 - 无需清除精灵之间的临时画布....像素在绘制精灵之前是清晰的!

我引用了一个名为 checkBoundingBoxisOver 的函数 - 不确定你是否可以编写这个函数,但我现在不能 - 此外,我什至不知道你的 array_objects 是什么!!!

我认为这很简单,只需要精灵的 x、y、宽度、高度来初步检查精灵是否可能在鼠标下方,然后再进行昂贵的绘制

function getSelectedObject(array_objects) {
    //Clear the temporary canvas :
    tmpcx.clearRect(0, 0, tmpc.width, tmpc.height);
    var sprite;
    /*Search the right sprite object :*/
    for (var i = array_objects.length - 1; i >= 0; i--) {

        sprite = array_objects[i];

        if (checkBoundingBoxisOver(sprite, mouse_x, mouse_y)) {

            sprite.draw(tmpcx);
            imageData = tmpcx.getImageData(mouse_x, mouse_y, 1, 1);
            component = imageData.data;
            if (component[3] > 0) {
                return sprite;
            }
        }
    }
    return false;
}

【讨论】:

  • 非常感谢,我去试试!在检查像素 alpha 之前先检查边界框是否结束是个好主意!
【解决方案2】:

我遇到了类似的问题,从动画的每一帧读取大位图的像素。在我的例子中,它是一张黑白图像,显示世界是水还是陆地。

即使只读取一个像素,getImageData 在 Firefox 上也非常慢。

我的解决方案是只调用一次 getImageData 并将结果存储在 imageData 变量中

    var imageData = self.context.getImageData(0,0,image.width, image.height);

然后你就可以反复调用图片数据,拉出你想要的图片部分。就我而言,我只需要一个像素或一种颜色,看起来像这样

    var pixelRed = this.imageData.data[(y* imageWidth * 4) + (x * 4)] == 0;

x 和 y 是不言自明的,因为像素是 4 字节值(红色、绿色、蓝色、Alpha),我需要将数组索引乘以 4。事实证明这对我来说非常快。

只要不是太大,使用此代码直接从数组中抓取任何部分都非常容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-05
    • 2011-11-30
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多