Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas Draw Image issue on firefox, works well in chrome

I will assume this is some sort of compatibility issue. Everything works perfectly in chrome, but in firefox the <canvas> simply doesn't draw anything.

function drawStage(stageNum) {
    var cap = canvasArray.length; //keeps the canvasElements
    var i;
    var stageImages = images["stage" + stageNum];
    var stageDimensions = imageDimensions["stage" + stageNum];
    //console.log("Cap is: " + cap);


    for (i = 0; i < cap; i++) {
        var canvas = document.getElementById(canvasArray[i]);
        var canvasContext = canvas.getContext("2d");
        var image = document.getElementById(stageImages[i]);

        canvasContext.clearRect(0, 0, 1280, 1280);
        canvasContext.drawImage(image, stageDimensions[i][0], stageDimensions[i][1], stageDimensions[i][2], stageDimensions[i][3]);
        //document.getElementById(zIndexes[i][0]).style["z-index"] = zIndexes[i][stageNum];
        //console.log(document.getElementById(zIndexes[i][0]).id);
    }
}

EDIT: here is dropbox link for "test" code-sample that I made, much simpler, 1 image, 1 canvas, 1 div, similar (practically same) script, that is still not working in firefox, yet works in chrome. If you can solve the issue there, then this will be solved as well.

UPDATE: Arrays are below, per request, they are simple imput of different elements/coordinates. I assure you though, there is no issue within the arrays themselves, everything works nice in chrome. Something about the DrawImage() method from the function is causing the problem I'd say. (further explanation below the arrays)

images is a (global) array of ids for the <img> elements.

    var images = {
    stage1: ["character1Base", "character2Base", "character3Base", "character4Base", "character5Base", "character6Base", "character3BotImg"],
    stage2: ["character1Sit", "character2Base", "character3Base", "character4Base", "character5Base", "character6Base", "character3BotImg"],
    stage3: ["character1Sit", "character2Drink", "character3Base", "character4Base", "character5Base", "character6Base", "character3BotImg"],
    stage4: ["character1Sit", "character2Drink", "character3Base", "character4Base", "character5Base", "character6Doll", "character3BotImg"],
    stage5: ["character1Sit", "character2Drink", "character3Eat", "character4Base", "character5Base", "character6Doll", "character3EatBot"],
    stage6: ["character1Sit", "character2Stand", "character3Eat", "character4Base", "character5Base", "character6Doll", "character3EatBot"],
    stage7: ["character1Sit", "character2Stand", "character3Eat", "character4Sit", "character5Base", "character6Doll", "character3EatBot"],
    stage8: ["character1Sit", "character2Stand", "character3Eat", "character4Sit", "character5Sit", "character6Doll", "character3EatBot"],
    stage9: ["character1Sit", "character2Eat", "character3Eat", "character4Sit", "character5Sit", "character6Doll", "character3EatBot"],
    stage10: ["character1Drink", "character2Eat", "character3Eat", "character4Sit", "character5Sit", "character6Doll", "character3EatBot"]
};

imageDimensions is a (global) array of well, dimensions, posX, posY, sizeX & sizeY.

    var imageDimensions = {
    stage1: [[0, 0, 233, 485], [0, 0, 153, 407], [20, 0, 220, 200], [0, 150, 505, 210], [0, 0, 315, 391], [0, 0, 480, 435], [1, 0, 220, 180]],
    stage2: [[105, 35, 180, 440], [0, 0, 153, 407], [20, 0, 220, 200], [0, 150, 505, 210], [0, 0, 315, 391], [0, 0, 480, 435], [1, 0, 220, 180]],
    stage3: [[105, 35, 180, 440], [0, 0, 153, 407], [20, 0, 220, 200], [0, 150, 505, 210], [0, 0, 315, 391], [0, 0, 480, 435], [1, 0, 220, 180]],
    stage4: [[105, 35, 180, 440], [0, 0, 153, 407], [20, 0, 220, 200], [0, 150, 505, 210], [0, 0, 315, 391], [0, 0, 480, 435], [1, 0, 220, 180]],
    stage5: [[105, 35, 180, 440], [0, 0, 153, 407], [3, 7, 226, 180], [0, 150, 505, 210], [0, 0, 315, 391], [0, 0, 480, 435], [1, 9, 220, 180]],
    stage6: [[105, 35, 180, 440], [0, 0, 172, 490], [3, 7, 226, 180], [0, 150, 505, 210], [0, 0, 315, 391], [0, 0, 480, 435], [1, 9, 220, 180]],
    stage7: [[105, 35, 180, 440], [0, 0, 172, 490], [3, 7, 226, 180], [70, 0, 341, 380], [0, 0, 315, 391], [0, 0, 480, 435], [1, 9, 220, 180]],
    stage8: [[105, 35, 180, 440], [0, 0, 172, 490], [3, 7, 226, 180], [70, 0, 341, 380], [18, 72, 305, 422], [0, 0, 480, 435], [1, 9, 220, 180]],
    stage9: [[105, 35, 180, 440], [0, 0, 173, 473], [3, 7, 226, 180], [70, 0, 341, 380], [18, 72, 305, 422], [0, 0, 480, 435], [1, 9, 220, 180]],
    stage10: [[105, 32, 162, 440], [0, 0, 173, 473], [3, 7, 226, 180], [70, 0, 341, 380], [18, 72, 305, 422], [0, 0, 480, 435], [1, 9, 220, 180]]
};

Explanation: The function is meant to draw on screen in different elements, characters that belong to these elements. They are drawn in canvas (will later be animated in canvas as well). The stageNum which is the only parameter the function takes determines what will be drawn.

Anyone know what the problem is? (I've read a few similar posts but issue in all of them was layerX, layerY of the mouse position, however I am not using mouseover / mousein / mouseout here at all, still elements are not drawn.

like image 458
Dellirium Avatar asked Dec 24 '22 10:12

Dellirium


1 Answers

Your problem is that the image your are trying to draw are svg images, and that these svg documents have relative width and height attributes.

The browser can't set a height nor a width to the image it has to draw, and hence it can't render it to the canvas. (It is able to do an estimation in the document, since it can be relative to something, but not in the canvas).

So the solution is to set absolute width and height attributes in your svg files,

Or, more complicated, to first draw it into an <iframe> or an <object>, then draw a serialized version where you'll have set these attributes.

function initialize() {
    var canvas = document.getElementById("char1Canvas");
    var canvasContext = canvas.getContext("2d");
    var image = document.getElementById("char1Img");
    resizeSVG(image, function(e){
        canvasContext.clearRect(0, 0, 1280, 1280);
        canvasContext.drawImage(this, 0, 0);
    });
};

var resizeSVG = function(svgImg, callback){
    // create an iframe
    var iframe = document.createElement('iframe');
    // so we don't see it
    iframe.height = 0;
    iframe.width = 0;
    iframe.onload = function(){
        var doc = iframe.contentDocument;
        var svg = doc.querySelector('svg');
        // get the computed width and height of your img element
        // should probably be tweaked
        var bbox = svgImg.getBoundingClientRect();
        // if it's a relative width
        if (svg.width.baseVal.unitType !== 1) {
            svg.setAttribute('width', bbox.width);
        }
        // or a relative height
        if (svg.height.baseVal.unitType !== 1) {
            svg.setAttribute('height', bbox.height);
        }
        // serialize our updated svg
        var svgData = (new XMLSerializer()).serializeToString(svg);
        var svgURL = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);
        // create a new Image Object that ill be draw on the canvas
        var img = new Image();
        img.onload = callback;
        img.src = svgURL;
        // remove the iframe
        document.body.removeChild(iframe);
    };
    iframe.src = svgImg.src;
    document.body.appendChild(iframe);
}
like image 199
Kaiido Avatar answered Feb 11 '23 11:02

Kaiido