使用 drawImage() 时,Canvas 的跨浏览器像素网格不一致
我认识到
您可能希望通过他们的 bug-tracker 让他们知道.
解决方法是确保您永远不会停留在浮动坐标上,即使在您的转换矩阵中也是如此.
I recognize that Canvas drawImage is inexplicably offset by 1 Pixel is a very similar issue, but I was already applying the advice given in that question's answer before I even came across this problem.
I'm implementing a sprite sheet system for an HTML5-based game. Individual frames are defined simply:
frame = new AnimationFrame(img, x, y, w, h);
Inside the AnimationFrame constructor, all of the numeric parameters are truncated to integers.
Then when I go to draw it on the canvas, I use what should also be simple code:
context.drawImage(frame.img,
frame.x,
frame.y,
frame.w,
frame.h,
this.position.x | 0,
this.position.y | 0,
frame.w,
frame.h,
);
Unfortunately, I get different results in different browsers.
In Chrome on Mac and Firefox on Mac, slicing the sprite sheet this way causes the individual frames to be offset by half a pixel, causing the top edge of the character's head to be drawn too thin and the top of the next sprite down to peek into the bottom of this one.
I can accommodate this problem with frame.x - 0.5
and frame.y - 0.5
but if I do that then I get the opposite problem in Safari on Mac and iOS and in Firefox on Windows.
I don't particularly WANT to do a browser detect to decide how to nudge the coordinate system, so I'm looking for suggestions for a way to either (1) force the various browsers to behave the same way, or (2) detect the issue at page load time with a test so I can just store the pixel grid offset in a variable.
NB: I'm going for a chunky pixel aesthetic, so my canvas is scaled by a factor of 2. This works fine without blurring, but it makes the half-pixel issue more clearly visible. Without scaling, the edges of the sprite still get distorted, so that's not the problem.
解决方案I can't tell for IE, but at least for Safari, this sounds like a bug in their nearest-neighbor algorithm when the transformation matrix translate is set to exactly n.5
.
onload = function() {
var ctx = document.querySelector('canvas').getContext('2d');
ctx.imageSmoothingEnabled = false;
var img = document.querySelector('#hero');
ctx.setTransform(2, 0, 0, 2, 99.49, 99.49);
ctx.drawImage(img, 32, 32, 16, 16, 0, 0, 16, 16);
ctx.setTransform(2, 0, 0, 2, 99.5, 99.5);
ctx.drawImage(img, 32, 32, 16, 16, 16, 0, 16, 16);
ctx.setTransform(2, 0, 0, 2, 99.51, 99.51);
ctx.drawImage(img, 32, 32, 16, 16, 32, 0, 16, 16);
};
<img src='http://xmpps.greenmaw.com/~coda/html52d/hero.png' id='hero' style='display:none' />
<canvas width='200' height='200'></canvas>
Result in Safari 11.0.3
You may want to let them know about it from their bug-tracker.
The workaround would be to make sure that you never lay on floating coordinates, even in your transformation matrix.
相关文章