Canvas drawImage在本地运行时抛出INDEX_SIZE_ERR,但不从Web运行

时间:2011-09-18 03:09:10

标签: javascript html5 canvas

我正在使用drawImage method for slicing an image运行MDN教程。精简页面代码如下所示:

  <html>
  <head>
    <script type="application/x-javascript">
    function draw() {
           var ctx = document.getElementById('canvas').getContext('2d');
           ctx.drawImage(document.getElementById('frame'),0,0);
           ctx.drawImage(document.getElementById('source'),33,71,104,124,21,20,87,104);
    }
    </script>
  </head>
  <body onload="draw();">
      <canvas id="canvas" width="150" height="150"></canvas>
      <img id="source" src="images/rhino.jpg" width="300" height="227" alt="">
      <img id="frame" src="images/picture_frame.png" width="132" height="150" alt="">
  </body>
</html>

从MDN网站运行完整版时,它按预期工作。当复制到我的本地机器并从“file:///”url(具有正确的图像相对路径)加载时,这将在drawImage ...'source'行上抛出INDEX_SIZE_ERR。

图片通过img标签按预期加载。

document.getElementById('source')分配给变量并将该变量传递给drawImage表示该变量为非null且classWidth为300(通过简单的alert),并仍然抛出错误。

ctx.drawImage(document.getElementById('frame'),0,0);行确实正确地绘制到画布。

为什么我的本地计算机的行为与Web版本不同?安全限制? (新手在这里,如果答案很简单,请道歉。)

1 个答案:

答案 0 :(得分:6)

您收到INDEX_SIZE_ERR,因为您正在调用drawImage(),其参数为负数或超出数据范围。在这种情况下,我们可以排除负值。

相反,您可能会看到错误,因为您要求提供源图像数据维度之外的信息。当您指定源和目标坐标和尺寸时(正如您在此处所做的那样), 允许传递超出目标尺寸范围的值(正面和负面)。你可能遇到麻烦的地方是源值。

在您的情况下,我认为正在发生的事情是您的源图像实际上不是300px by 227px,尽管您在CSS中表示了什么。即使图像可能在浏览器中显示得很大,但是加载到DOM中的图像对象中存储的实际像素数也较小。因此,即使您对drawImage()的调用具有为每个DOM元素指定的大小调整的有效参数,您也要求33 -> 137维度中的像素x和像素71 -> 195y维度。这些范围中的一个(或两个)超出了源图像的尺寸。仔细检查源图像的实际大小。

至于为什么你在本地和网络执行之间遇到不同的行为,你可能会在请求图像时遇到问题。除了您通常无法在本地操作画布元素(除非您设置特殊开发环境或手动配置浏览器)之外,无论位置如何,图像仍然必须“下载”到您的浏览器。浏览器中的图像采集是异步完成的,所以考虑到现在的代码,当调用draw()函数时,两个(或任一个)图像在内存中都可用时,无法保证。

相反,你应该做的是使用内置于图像元素中的onload回调函数。在您的情况下,由于您有两个图像,您需要维护一个标志以确定何时加载两个图像。您可以尝试这样的事情:

<html>
<head>
<script type="application/x-javascript">
    var images_loaded = 0;

    function imageLoaded() {
        ++images_loaded;

        if (images_loaded == 2) {
            draw(); 
        }
    }

    function draw() {
        var ctx = document.getElementById('canvas').getContext('2d');
        ctx.drawImage(document.getElementById('frame'),0,0);
        ctx.drawImage(document.getElementById('source'),33,71,104,124,21,20,87,104);
    }
</script>
</head>
<body>
    <canvas id="canvas" width="150" height="150"></canvas>
    <img id="source" onload="imageLoaded();" src="images/rhino.jpg" width="300" height="227" alt="">
    <img id="frame" onload="imageLoaded();" src="images/picture_frame.png" width="132" height="150" alt="">
</body>
</html>

请注意,对于rhino的drawImage()调用中的参数问题仍然在上面的示例中;我不知道你的rhino.jpg图像的尺寸是多少,所以我不能推荐修正。