画布上的drawImage在firefox和其他问题中具有奇怪的宽高比

时间:2009-12-18 22:59:18

标签: javascript firefox html5 canvas

我正在运行firefox 3.5.6。

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

这是我得到的:

alt text

顶部图像是我在IE8中看到的,底部是我在firefox中看到的。

IE似乎有点乱,因为画布尺寸不对,但是firefox很疯狂!这个宽高比给出了什么?为什么我的弧的下半部分没有出现? 此外,有些时候firefox只是没有显示任何东西。

Here is my code by the way.

2 个答案:

答案 0 :(得分:19)

宽高比问题

如果未在canvas元素上设置宽度,则默认为300x150。在CSS中,将样式设置为94x120,因此它会将图像缩放到该大小。要修复它,您需要在HTML中设置宽度和高度,或者使用JavaScript。

在HTML中:

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

在JavaScript中(使用jQuery):

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

Internet Explorer的大小不正确

将大小添加到canvas元素也应解决此问题。由于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');

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

答案 1 :(得分:2)

我最近注意到使用样式来定义宽度和宽度。 canvas元素的高度引起了这样的问题。以前面的例子为例

适用于FF 9.0.1 Mac

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

VS

这与您的示例在FF 9.0.1 Mac

中有类似的显示问题
<canvas id="c" style="width:94;height:120;">Ugh, this just ain't gonna work</canvas>

也许就是这样?