Firefox 上的 Canvas Draw Image 问题,在 chrome 中运行良好

IT技术 javascript firefox canvas drawimage
2021-03-17 09:35:58

我会假设这是某种兼容性问题。在 chrome 中一切正常,但在 Firefox 中<canvas>根本不绘制任何东西。

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);
    }
}

编辑: 是我制作的“测试”代码示例的 dropbox 链接,简单得多,1 张图像、1 个画布、1 个 div、类似(几乎相同)的脚本,它仍然无法在 Firefox 中工作,但可以在 chrome 中工作。如果你能在那里解决问题,那么这也将得到解决。

更新:数组如下,根据请求,它们是不同元素/坐标的简单输入。不过我向你保证,阵列本身没有问题,在 chrome 中一切正常。函数中的 DrawImage() 方法导致了我要说的问题。(阵列下方的进一步解释)

images 是<img>元素id 的(全局)数组

    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 是井、尺寸、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]]
};

说明: 该函数的目的是在屏幕上绘制不同的元素,属于这些元素的字符。它们是在画布中绘制的(稍后也会在画布中进行动画处理)。stageNum这是唯一参数的函数需要确定哪些会被吸引。

有谁知道问题是什么?(我已经阅读了一些类似的帖子,但所有帖子的问题都是鼠标位置的 layerX、layerY,但是我根本没有在这里使用 mouseover/mousein/mouseout,仍然没有绘制元素。

1个回答

您的问题是您尝试绘制的图像是 svg 图像,并且这些 svg 文档具有相关性widthheight属性。

浏览器无法为其必须绘制的图像设置高度或宽度,因此无法将其渲染到画布上。(它能够在文档中进行估计,因为它可以与某物相关,但不能在画布中进行)。

所以解决方案是在你的 svg 文件中设置绝对值widthheight属性,

或者,更复杂的是,首先将其绘制为 an<iframe>或 an <object>,然后绘制一个序列化版本,您将在其中设置这些属性。

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);
}
一旦我再次访问服务器,家庭自动取款机,我会尝试。感谢所有的帮助!
2021-04-29 09:35:58
要添加(上面缺少字符空间),我尝试<img>使用<div>具有宽度/高度标签围绕标签,因为 svg 设置为 100% 100%,但这也不起作用,它必须在SVG。对我来说,这是一个可以接受的解决方案,因为我将在绘图时使用静态尺寸,但看看如何使用建议的函数来计算它们可能是值得的,因为如果要多次使用不同尺寸的 SVG,它有遗憾的是,要成为多个 svg 图像。
2021-05-03 09:35:58
是的,要访问 iframe,您可能必须在服务器上使用它(无论是localhost)。我认为在 file:// 系统上它会失败。例如,只需用这个块替换 script.js 中的代码,它应该可以工作(在服务器上)
2021-05-04 09:35:58
感谢您的广泛回答。我用你的代码运行,似乎有一个在线错误var doc = iframe.contentDocument;,如下所示: > 未捕获的安全错误:无法从“HTMLIFrameElement”读取“contentDocument”属性:阻止了原点为“null”的框架访问原点框架“空值”。协议、域和端口必须匹配。然而,将绝对值放入 .svg 文件中就可以了。奇怪的是,chrome 知道如何根据<img>标签内的值计算它们,而 Firefox 不知道。
2021-05-19 09:35:58
我的<svg>元素有width="100%" height="100%". 你是个天才,因为你知道 Firefox(仅)需要那些存在并更改为绝对数字!
2021-05-19 09:35:58