web-dev-qa-db-fra.com

Canvas - IndexSizeError: l'index ou la taille est négatif ou supérieur au montant autorisé

Donc, dans Firefox, je reçois cette erreur dans la console lorsque j'utilise drawImage sur un élément de type canvas. 

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

Tout fonctionne bien dans Chrome. Les causes courantes de ce problème que je rencontrais étaient le renvoi de valeurs négatives ou l’essai de dessiner l’image sur la toile avant que l’image ne soit réellement chargée. Ni l'un ni l'autre ne semble être le cas. Qu'est-ce que j'oublie ici?

Toutes les idées seraient grandement appréciées. 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();
22
brandongray

Lorsque vous utilisez le découpage, vous devez vous assurer que la région source se trouve dans l'image (non nécessaire pour la cible, car celle-ci sera découpée par un canevas).

Donc, si vous ajoutez un contrôle de restriction, cela devrait fonctionner. Voici une façon de procéder (avant d’utiliser la fonctionnalité de découpage de 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);

Fiddle modifié ici.

Astuce 1:
Normalement, cela s’applique également à x et y, mais comme il s’agit de 0 ici, il n’est pas nécessaire de vérifier.

Astuce 2:
Si vous souhaitez que l’image soit plus étroite que nécessaire, au lieu de changer de région source, modifiez la région cible.

14
user1693593

Largeur et Hauteur de l'image que vous dessinez lorsque vous spécifiez des valeurs de taille doit être supérieure ou égale à 1 . De même pour les avantages en termes de performances floor toutes les valeurs que vous lui transmettez.
Si width et/ou height est 0, il en résultera:

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

Dans Firefox:

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

Pour aider les autres, j'ai eu le même problème dans canvas et je résous en tenant compte du chargement d'image, par exemple:

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

J'ai eu le même problème mais dansC'EST-&AGRAVE;-DIREet Safari . Il y avait trois choses en particulier que je devais corriger:

1) Je devais définir manuellement les width et height de l'image.

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

2) Je devais éviter d'utiliser un décalage négatif lors de la création de ol.style.Icon. Dans ce cas, j'ai dû changer d'icône SVG, mais cela dépend beaucoup de votre icône. Donc, cela provoquerait une exception à cause du décalage négatif:

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

3) Je devais arrondir les valeurs de largeur et de hauteur. Certains d’entre eux étant calculés dynamiquement, j’avais des valeurs telles que 34.378 qui posaient problème. J'ai donc dû les contourner et passer la valeur Integer.

0
Mahdi