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

Joe*_*e Z 2 javascript html5 canvas

我正在浏览MDN教程,使用drawImage方法切片图像.精简页面代码如下所示:

  <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>
Run Code Online (Sandbox Code Playgroud)

从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版本不同? 安全限制?(新手在这里,如果答案很简单,请道歉.)

Xen*_*hyl 6

您收到的是INDEX_SIZE_ERR因为您drawImage()使用的参数设置为负数或超出数据范围.在这种情况下,我们可以排除负值.

相反,您可能会看到错误,因为您要求提供源图像数据维度之外的信息.当您指定的源和目标坐标和尺寸两者(如你在这里做),你允许通过的目标尺寸(正面和负面的)的边界之外的值.您可能遇到麻烦的地方是源值.

在你的情况下,我认为正在发生的事情是你的源图像实际上并非如此300px by 227px,尽管你在CSS中表示了什么.即使图像可能在浏览器中显示得很大,但是加载到DOM中的图像对象中存储的实际像素数也较小.所以,即使您的电话drawImage()给了有效的参数大小为每个DOM元素指定的,你所要求的像素33 -> 137x尺寸和像素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>
Run Code Online (Sandbox Code Playgroud)

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