画布上的drawImage在Firefox中具有奇怪的纵横比和其他问题

Posted

技术标签:

【中文标题】画布上的drawImage在Firefox中具有奇怪的纵横比和其他问题【英文标题】:drawImage on canvas has weird aspect ratio in firefox and other problems 【发布时间】:2010-12-28 05:15:54 【问题描述】:

我正在运行 Firefox 3.5.6。

我想在画布上显示图像并在其上画几条线。它需要在 Firefox 和 Internet Explorer 中正确显示(使用 excanvas)。

这是我得到的:

上图是我在IE8中看到的,下图是我在firefox中看到的。

就画布大小错误而言,IE 似乎有点混乱,但 Firefox 快疯了!这个纵横比有什么用?为什么我的弧的后半部分没有出现? 此外,有时 Firefox 完全没有显示任何内容。

Here is my code by the way.

【问题讨论】:

【参考方案1】:

长宽比问题

如果您没有在 canvas 元素上设置宽度,则默认为 300x150。在您的 CSS 中,您将 style 设置为 94x120,因此它将图像缩放到该大小。要修复它,您需要在 htmljavascript 中设置宽度和高度。

在 HTML 中:

<canvas id="c"  >Ugh, this just ain't gonna work</canvas>

在 JavaScript 中(使用 jQuery):

$('canvas').attr('width', '94').attr('height', '120');

Internet Explorer 的大小不正确

将尺寸添加到画布元素也应该可以解决这个问题。由于 IE 使用 VML 而不是画布来呈现图像,因此画布的 CSS 规则将不适用。 excanvas 应该会看到指定的大小并将其应用到 IE 中。

缺少弧线的后半部分

当幅度为负时,simpleArc 函数在 Firefox 中不起作用。问题是负幅度会导致弧的负半径,根据canvas spec,这是非法的。它实际上应该抛出一个 INDEX_SIZE_ERR 异常,但 Firefox 似乎只是忽略了这个调用。

有两种可能的解决方案(基本上;有几种方法可以实现):当您传递负幅度时,或者计算弧的参数,同时考虑负半径(具有不同的中心点和角度,等),或更改符号并使用变换来旋转圆弧。我实现了这样的第二个解决方案:

ctx.simpleArc = function(x,y, length, amplitude) 
    var rotate = false;

    // Check whether we need to rotate the image
    if (amplitude < 0) 
        rotate = true;
        amplitude = -amplitude;
    
    var radius = amplitude/2+ length*length/(8*amplitude);
    var outerAngle = Math.asin((radius-amplitude)/radius);
    var innerAngle = Math.PI - 2*outerAngle;

    // The translate/rotate/translate steps could be combined into one matrix
    // transformation, but I think this is clearer and less error-prone.
    if (rotate) 
        this.save(); // So we can easily undo the transformation
        this.translate(x + length, y);
        this.rotate(Math.PI);
        this.translate(-length, -y);
    
    this.arc(x+length/2, y+(radius-amplitude), radius, -(outerAngle+innerAngle), -outerAngle, false);

    // Reset the transformation matrix to its original value
    if (rotate) 
        this.restore();
    
    return this;

Firefox 没有显示任何内容

在您的代码中,您创建图像并设置源代码,但在执行其余代码之前可能不会加载它。图像是异步加载的,当您将图像绘制到画布上时,它不会等待它完成。您将需要从 onload 事件中调用使用图像的代码。

var img = $('<img>');
img[0].onload = function() 
    ctx.drawImage(img[0], 0, 0);
    ctx.strokeStyle = "blue";
    ctx.simpleStroke(function(ctx)  ctx.simpleArc(0, 70, img_w/2, 3));
    ctx.simpleStroke(function(ctx)  ctx.simpleArc(img_w / 2, 70, img_w/2, -3));
;

// I moved this so it happens after you set the `onload` event, because I
// think IE won't call `onload` if it happens to already be loaded.
img.attr('src', 'shortcylinder.png');

您还可以预先加载您需要的所有图像,而不是在需要时创建它们。在加载所有图像之前,您仍然需要阻止代码运行。

【讨论】:

嗯,是的,这适用于纵横比,但不适用于其他问题。具体来说,有时根本没有绘制任何东西,当它只有一半的弧时出现在 Firefox 中 我忘记了其他问题。我会用解决方案更新答案。【参考方案2】:

我最近注意到使用样式来定义画布元素的宽度和高度会导致这样的问题。取自之前的例子

这适用于 FF 9.0.1 Mac

<canvas id="c"  >Ugh, this just ain't gonna work</canvas>

对比

在 FF 9.0.1 Mac 中,这与您的示例有类似的显示问题

<canvas id="c" style="width:94;height:120;">Ugh, this just ain't gonna work</canvas>

也许是这样?

【讨论】:

以上是关于画布上的drawImage在Firefox中具有奇怪的纵横比和其他问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Chrome 上使用 drawImage 和 Canvas 非常慢

Firefox 错误 - globalCompositeOperation 不适用于 SVG 元素的 drawImage

如何使 Firefox 的画布与基于 Chromium 的浏览器中的行为相同?

裁剪画布/导出具有特定宽度和高度的 html5 画布

JavaScript将视频并入画布框

canvas中的drawImage