Подтвердить что ты не робот

Canvas - IndexSizeError: индекс или размер отрицательный или больше допустимой суммы

Итак, в Firefox я получаю эту ошибку в консоли при использовании drawImage в элементе canvas.

"IndexSizeError: Index or size is negative or greater than the allowed amount"

Все работает отлично в Chrome. Общими причинами этого я возвращал отрицательные значения или пытался нарисовать изображение на холсте до того, как изображение загрузится. Ни один из них, похоже, не так. Что мне здесь не хватает?

Любые идеи будут высоко оценены. http://jsfiddle.net/Ra9KQ/3/

var NameSpace = NameSpace || {};

NameSpace.Pixelator = (function() {

    var _cache = {
        'wrapper' : null,
        'canvas'  : null,
        'ctx'     : null,
        'img'     : new Image()
    },

    _config = {
        'canvasWidth'      : 250,
        'canvasHeight'     : 250,
        'isPlaying'        : false,
        'distortMin'       : 3,
        'distortMax'       : 100,
        'distortValue'     : 100, // matches distortMax by default
        'initDistortValue' : 3,
        'speed'            : 2.5,
        'delta'            : 2.5,   // delta (+/- step), matches speed by default
        'animation'        : null,
        'origImgWidth'     : null,
        'origImgHeight'    : null,
        'imgHeightRatio'   : null,
        'imgWidthRatio'    : null,
        'newImgWidth'      : null,
        'newImgHeight'     : null
    },

    _init = function _init() {

        _setupCache();
        _setupCanvas();
        _setupImage();

    },

    _setupCache = function _setupCache() {

        _cache.wrapper = $('#dummy-wrapper');
        _cache.canvas = document.getElementById('dummy-canvas');
        _cache.ctx = _cache.canvas.getContext('2d');

    },

    _setupCanvas = function _setupCanvas() {

        _cache.ctx.mozImageSmoothingEnabled = false;
        _cache.ctx.webkitImageSmoothingEnabled = false;
        _cache.ctx.imageSmoothingEnabled = false;

    },

    _setupImage = function _setupImage() {

        _cache.img.onload = function() {

            _adjustImageScale();
            _pixelate();
            _assignEvents();

        };

        _cache.img.src = _cache.canvas.getAttribute('data-src');

    },

    _adjustImageScale = function _adjustImageScale() {

        var scaledHeight,
            scaledWidth;

        _config.origImgWidth = _cache.img.width;
        _config.origImgHeight = _cache.img.height;
        _config.imgHeightRatio = _config.origImgHeight / _config.origImgWidth;
        _config.imgWidthRatio = _config.origImgWidth / _config.origImgHeight;

        scaledHeight = Math.round(250 * _config.imgHeightRatio);
        scaledWidth = Math.round(250 * _config.imgWidthRatio);

        if (scaledHeight < 250) {

            _config.newImgHeight = 250;
            _config.newImgWidth = Math.round(_config.newImgHeight * _config.imgWidthRatio);

        } else if (scaledWidth < 250) {

            _config.newImgWidth = 250;
            _config.newImgHeight = Math.round(_config.newImgWidth * _config.imgHeightRatio);

        }

    },

    _assignEvents = function _assignEvents() {

        _cache.wrapper.on('mouseenter', _mouseEnterHandler);
        _cache.wrapper.on('mouseleave', _mouseLeaveHandler);

    },

    _mouseEnterHandler = function _mouseEnterHandler(e) {

        _config.delta = -_config.speed;

        if (_config.isPlaying === false) {
            _config.isPlaying = true;
            _animate();
        }

    },

    _mouseLeaveHandler = function _mouseLeaveHandler(e) {

        _config.delta = _config.speed;

        if (_config.isPlaying === false) {
            _config.isPlaying = true;
            _animate();
        }

    },

    _pixelate = function _pixelate(val) {

        var size = val ? val * 0.01 : 1,
            w = Math.ceil(_config.newImgWidth * size),
            h = Math.ceil(_config.newImgHeight * size);

        console.log('w: ' + w,'h: ' + h,'_config.newImgWidth: ' + _config.newImgWidth,'_config.newImgHeight: ' + _config.newImgHeight);

        _cache.ctx.drawImage(_cache.img, 0, 0, w, h);

        _cache.ctx.drawImage(_cache.canvas, 0, 0, w, h, 0, 0, _config.canvasWidth, _config.canvasHeight);

    },

    _animate = function _animate() {

        // increase/decrese with delta set by mouse over/out
        _config.distortValue += _config.delta;

        if (_config.distortValue >= _config.distortMax || _config.distortValue <= _config.distortMin) {

            _config.isPlaying = false;
            cancelAnimationFrame(_config.animation);
            return;

        } else {

            // pixelate
            _pixelate(_config.distortValue);
            _config.animation = requestAnimationFrame(_animate);

        }

    };

    return {
        init: _init
    };

})();

NameSpace.Pixelator.init();
4b9b3361

Ответ 1

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

Итак, если вы добавите контроль ограничения, он должен работать. Вот один из способов сделать это (перед использованием функции отсечения drawImage):

if (w > _config.canvasWidth) w = _config.canvasWidth;
if (h > _config.canvasHeight) h = _config.canvasHeight;

_cache.ctx.drawImage(_cache.canvas, 0, 0, w, h,
                      0, 0, _config.canvasWidth, _config.canvasHeight);

Измененная скрипка здесь.

Совет 1:
Обычно это также относится к x и y, но поскольку они равны 0, здесь нет необходимости проверять.

Совет 2:
Если вам нужно, чтобы изображение было нарисовано уже, чем вам нужно, вместо изменения области источника, измените область цели.

Ответ 2

Ширина и Высота изображения, которое вы рисуете, когда вы указываете значения размера , должно быть больше или равно 1. Также для преимуществ производительности floor все значения, которые вы передаете ему.
Если ширина и/или высота равно 0, это приведет к:

IndexSizeError: Index or size is negative or greater than the allowed amount

В Firefox:

width = Math.max(1, Math.floor(width));
height = Math.max(1, Math.floor(height));
ctx.drawImage(image, x, y, width, height);

Ответ 3

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

var image = new Image();
image.crossOrigin = "use-credentials";
image.onload = function(){
    // here canvas behavior
};
image.src = imgSrc;

Ответ 4

У меня была такая же проблема, но в IE и Safari. В частности, было три вещи, которые я должен был исправить:

1) Я должен был установить width и height изображения вручную.

var image = new Image();
...
image.width = 34;
image.height = 34;

2) При создании ol.style.Icon мне пришлось избегать отрицательного смещения. В этом случае мне пришлось менять значок SVG, но это в значительной степени зависит от вашего значка. Таким образом, это приведет к исключению из-за отрицательного смещения:

var icon = new ol.style.Style({
    "image": new ol.style.Icon({
        ...
        "offset": [0, -50]
    })
});

3) Мне пришлось округлить значения ширины и высоты. Поскольку некоторые из них были рассчитаны динамически, у меня были такие значения, как 34.378, которые вызывали проблемы. Поэтому мне пришлось округлить их и передать значение Integer.