INDEX_SIZE_ERR при рисовании изображения на холсте

Мне нужно нарисовать объект Image на холсте, но у меня есть исключение INDEX_SIZE_ERR в Firefox и IE10, но не в Chrome и Safari...

Согласно W3C: If one of the sw or sh arguments is zero, the implementation must raise an INDEX_SIZE_ERR exception..

Вот код, который вызывает проблему:

function writePhotoOnCanvas(data, width, height) {
    // Get the canvas
    var canvasGallery = document.getElementById("canvasGallery");
    // Clear the canvas
    canvasGallery.width = canvasGallery.width;
    // Get its context
    var ctxCapture = canvasGallery.getContext("2d");

    // Create an image in order to draw in the canvas
    var img = new Image();
    // Set image width
    img.width = width;
    // Set image height
    img.height = height;

    // To do when the image is loaded
    img.onload = function() {
        console.log("img.width="+img.width+", img.height="+img.height);
        console.log("width="+width+", height="+height+", canvasGallery.width="+canvasGallery.width+", canvasGallery.height="+canvasGallery.height);
        //  Draw the picture
        try {
            ctxCapture.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvasGallery.width, canvasGallery.height);
        } catch(e) {
            console.error(e.message);
        }
    };

    // Set image content from specified photo
    img.src = data;
}

Консоль показывает:

img.width=640, img.height=480
width=640, height=480, canvasGallery.width=589, canvasGallery.height=440
Index or size is negative or greater than the allowed amount

Каков источник проблемы?

Спасибо


person Maxbester    schedule 05.02.2014    source источник
comment
У меня была точно такая же ошибка, не могли бы вы попробовать следующее. Попробуйте сделать рекурсивный цикл в том месте, где вы поймали ошибку. Например, console.error(e.message); setTimeout (функция () { writePhotoOnCanvas (данные, ширина, высота)}, 10); возвращаться;   -  person Alexander Kludt    schedule 05.02.2014


Ответы (2)


Вы вручную устанавливаете ширину и высоту изображения (img.width = width; img.height = height;). Я не совсем понимаю, зачем вы это делаете, но, вероятно, это не нужно.

Они должны рассчитываться автоматически на основе загружаемых данных изображения. Попробуйте удалить их, чтобы увидеть, каков фактический размер данных.

person Philipp    schedule 05.02.2014
comment
Спасибо, ваше предложение решило мою проблему в Firefox, но не в IE. Однако консоль ничего не печатает. Похоже, функция не вызывается. Проблема может быть в другом. - person Maxbester; 05.02.2014

Изображения width и height являются свойствами только для чтения, поэтому они могут вызвать сбой кода в некоторых браузерах.

Если вы абсолютно хотите установить ширину и высоту перед загрузкой изображения, вы можете сделать:

var img = new Image(width, height);

Затем вы можете прочитать img.width и img.height, когда изображение загрузится (или прочитать img.naturalWidth и img.naturalHeight, чтобы получить исходный размер).

Хотя в этом нет необходимости. Просто вызовите свой drawImage() следующим образом:

ctxCapture.drawImage(img, 0, 0, canvasGallery.width, canvasGallery.height);

Это будет использовать полный размер изображения и масштабировать его до размера canvasGallery.

Подсказка: если вы используете эту функцию для загрузки нескольких изображений, вам нужно обменять img на this внутри обработчика onload.

Модифицированный код:

function writePhotoOnCanvas(data, width, height) {

    var canvasGallery = document.getElementById("canvasGallery");
    var ctxCapture = canvasGallery.getContext("2d");

    /// setting width to clear does not work in all browser, to be sure:
    ctxCapture.clearRect(0, 0, canvasGallery.width, canvasGallery.height);

    var img = new Image();
    img.onload = function() {
        //  Draw the picture
        try {
            ctxCapture.drawImage(this, 0, 0,
                                     canvasGallery.width, canvasGallery.height);
        } catch(e) {
            console.error(e.message);
        }
    };

    // Set image content from specified photo
    img.src = data;
}
person Community    schedule 05.02.2014
comment
Спасибо за Ваш ответ. Что конкретно делает clearRect? Мне нужно, чтобы фон холста был черным по умолчанию. Из того, что я видел в Интернете, он просто рисует белый прямоугольник. - person Maxbester; 06.02.2014
comment
@Maxbester clearRect очищает холст до исходного состояния для определенного прямоугольника, то есть прозрачных черных пикселей. Чтобы очистить черным, просто используйте вместо этого ctx.fillStyle = '#000'; ctx.fillRect(x, y, w, h);. - person ; 06.02.2014