开发者

drawImage on canvas has weird aspect ratio in firefox and other problems

开发者 https://www.devze.com 2022-12-14 15:03 出处:网络
I am running firefox 3.5.6. I want to display an image on a canvas and draw a couple lines on it.It needs to display properly in firefox and internet explorer (using excanvas).

I am running firefox 3.5.6.

I want to display an image on a canvas and draw a couple lines on it. It needs to display properly in firefox and internet explorer (using excanvas).

Here is what I am getting:

drawImage on canvas has weird aspect ratio in firefox and other problems

The top image is what I see in IE8, the bottom is what I see in firefox.

IE 开发者_如何学Pythonseems to be a bit messed up as far as the canvas is the wrong size but firefox is going crazy! What gives with this aspect ratio? Why does the second half of my arc not appear? Also, some times firefox just flat out doesn't show anything.

Here is my code by the way.


Aspect ratio problem

If you don't set a width on the canvas element, it defaults to 300x150. In your CSS, you set the style to 94x120, so it scales the image to that size. To fix it, you need to either set the width and height in the HTML, or with JavaScript.

In HTML:

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

In JavaScript (with jQuery):

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

Internet Explorer's incorrect size

Adding the size to the canvas element should fix this problem too. Since IE is using VML instead of a canvas to render the image, the CSS rule for canvas won't apply. excanvas should see the specified size and apply it in IE.

Missing the second half of the arc

The simpleArc function doesn't work in Firefox when the amplitude is negative. The problem is that a negative amplitude results in a negative radius for the arc, which is illegal according to the canvas spec. It should actually throw an INDEX_SIZE_ERR exception, but Firefox just seems to ignore the call.

There are two possible solutions (basically; there are several ways you could accomplish either): when you pass a negative amplitude, either calculate the parameters for the arc taking into account the negative radius (with a different center point and angles, etc.), or change the sign and use transformations to rotate the arc. I implemented the second solution like this:

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 not showing anything

In your code, you create the image and set the source, but it may not be loaded before the rest of the code get's executed. The image loads asynchronously, and when you draw the image onto the canvas, it doesn't wait for it to finish. You will need to call the code that uses the image from an onload event.

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

You could also pre-load all the images you will need instead of creating them when you need them. You would still need to prevent the code from running until all the images are loaded.


I've recently noticed that using style to define width & height for canvas elements caused an issue like this. Taking from an earlier example

This works in FF 9.0.1 Mac

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

vs.

This had similar display issues as your example, in FF 9.0.1 Mac

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

Maybe that's it?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号