Canvas drawImage выбрасывает INDEX_SIZE_ERR при локальном запуске, но не из Интернета - PullRequest
2 голосов
/ 18 сентября 2011

Я бегу по учебникам 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>

Когда полная версия запускается с веб-сайта MDN, она работает как положено. При копировании на мой локальный компьютер и загрузке с URL-адреса «file: ///» (с правильным относительным путем для изображений) это приводит к выдаче INDEX_SIZE_ERR в строке drawImage ... 'source'.

Изображения загружаются как положено через теги img.

Присваивание document.getElementById('source') переменной и передача этой переменной в drawImage показывает, что переменная не равна нулю и имеет classWidth 300 (через простое alert), и по-прежнему выдает ошибку.

Линия ctx.drawImage(document.getElementById('frame'),0,0); правильно рисует на холсте.

Почему мой локальный компьютер ведет себя не так, как веб-версия? Ограничения безопасности? (Новичок здесь, извинения, если ответ прост.)

1 Ответ

6 голосов
/ 18 сентября 2011

Вы получаете INDEX_SIZE_ERR, потому что вы звоните drawImage() с параметрами, которые либо отрицательны, либо находятся за пределами ваших данных. В этом случае мы можем исключить отрицательные значения.

Вместо этого вы, вероятно, видите ошибку, потому что вы запрашиваете информацию за пределами измерений данных исходного изображения. Когда вы указываете исходные и конечные координаты и измерения (как вы делаете здесь), вы получаете право передавать значения за пределы целевых измерений (как положительных, так и отрицательных). Где вы можете столкнуться с неприятностями, так это с исходными значениями.

В вашем случае, я думаю, что ваше исходное изображение на самом деле не 300px by 227px, несмотря на то, что вы обозначаете в CSS. Несмотря на то, что изображение может отображаться таким большим в вашем браузере, фактическое количество пикселей, хранящихся в объекте изображения, загруженном в DOM, меньше. Таким образом, даже несмотря на то, что ваш вызов drawImage() имеет действительные параметры с учетом размера, заданного вами для каждого элемента DOM, вы запрашиваете пиксели 33 -> 137 в измерении x и пиксели 71 -> 195 в измерении y. Один (или оба) из этих диапазонов превышают размеры исходного изображения. Дважды проверьте фактический размер исходного изображения.

Что касается того, почему вы испытываете различное поведение между локальным и сетевым выполнением, у вас, вероятно, возникают проблемы при запросе изображений. Помимо того факта, что вы, как правило, не сможете управлять элементами canvas локально (если только вы не настроите специальную среду разработки или не настроите свой браузер вручную), изображения все равно придется «загружать» в браузер независимо от их местоположения. Получение изображений в браузере выполняется асинхронно, поэтому, учитывая имеющийся у вас код, при вызове функции 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>

Обратите внимание, что проблема с вашими параметрами при вызове drawImage() для носорога все еще остается в приведенном выше примере; Я не знаю, каковы размеры вашего изображения rhino.jpg, поэтому я не могу рекомендовать исправление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...