admin管理员组文章数量:1405636
I do know about the case of float/integer values for drawImage
's x
and y
. But what I need is a smooth animation with an ability to cache my shapes.
- Article on caching plex paths with backup canvas
- Article on
drawImage
with float parameters
For example, I want to draw some plex shape (i.e. SVG-tiger, converted to canvas-mands) to canvas just once and then move it smoothly with ctx.translate
and ctx.drawImage
. I need the float values then, because instead I get a step-by-step moving:
Here's the examples at JSFiddle:
- One: Fast speed, with
Math.floor
applied totranslate
parameters (x
andy
are equal to time in seconds multiplied by10
): Animation is weird (sequential, not smooth). - Two: Slow speed, with
Math.floor
applied totranslate
parameters (x
andy
are equal to time in seconds): Animation is weird (sequential, not smooth). - Three: Fast speed, no rounding, float values (
x
andy
are equal to time in seconds multiplied by10
). Speed is fast, so animation looks good. - Four: Slow speed, no rounding, float values (
x
andy
are equal to time in seconds). Speed is slow, so animation looks pulsating. Why?
The last case is the one that confuses me. Am I wrong in my tryings and there is a possibility to make this caching trick work nice?
In Firefox, there is a property of canvas named mozImageSmoothingEnabled
(see), but there is no help from that in other browsers. And it also removes paths smoothing.
Code extract:
var shapeCanvas = null;
var w = 320, h = 240;
var startTime = 0;
function start() {
startTime = Date.now();
var docCanvas = document.getElementById('canvas');
. . .
shapeCanvas = document.createElement('canvas');
. . .
drawShape(shapeCanvas.getContext('2d'));
drawNext(docCanvas.getContext('2d'));
}
function drawNext(ctx) {
var msec = (Date.now() - startTime);
var time = msec / 1000; // seconds passed from start
ctx.clearRect(0, 0, w, h);
ctx.save();
// the lines to change: time | (time * 10) | Math.floor(time * 10)
ctx.translate((time < 500) ? Math.floor(time * 10) : 500,
(time < 500) ? Math.floor(time * 10) : 500);
ctx.drawImage(shapeCanvas, 0, 0);
ctx.restore();
__nextFrame(function() {
drawNext(ctx);
});
}
function drawShape(ctx) {
. . .
}
I do know about the case of float/integer values for drawImage
's x
and y
. But what I need is a smooth animation with an ability to cache my shapes.
- Article on caching plex paths with backup canvas
- Article on
drawImage
with float parameters
For example, I want to draw some plex shape (i.e. SVG-tiger, converted to canvas-mands) to canvas just once and then move it smoothly with ctx.translate
and ctx.drawImage
. I need the float values then, because instead I get a step-by-step moving:
Here's the examples at JSFiddle:
- One: Fast speed, with
Math.floor
applied totranslate
parameters (x
andy
are equal to time in seconds multiplied by10
): Animation is weird (sequential, not smooth). - Two: Slow speed, with
Math.floor
applied totranslate
parameters (x
andy
are equal to time in seconds): Animation is weird (sequential, not smooth). - Three: Fast speed, no rounding, float values (
x
andy
are equal to time in seconds multiplied by10
). Speed is fast, so animation looks good. - Four: Slow speed, no rounding, float values (
x
andy
are equal to time in seconds). Speed is slow, so animation looks pulsating. Why?
The last case is the one that confuses me. Am I wrong in my tryings and there is a possibility to make this caching trick work nice?
In Firefox, there is a property of canvas named mozImageSmoothingEnabled
(see), but there is no help from that in other browsers. And it also removes paths smoothing.
Code extract:
var shapeCanvas = null;
var w = 320, h = 240;
var startTime = 0;
function start() {
startTime = Date.now();
var docCanvas = document.getElementById('canvas');
. . .
shapeCanvas = document.createElement('canvas');
. . .
drawShape(shapeCanvas.getContext('2d'));
drawNext(docCanvas.getContext('2d'));
}
function drawNext(ctx) {
var msec = (Date.now() - startTime);
var time = msec / 1000; // seconds passed from start
ctx.clearRect(0, 0, w, h);
ctx.save();
// the lines to change: time | (time * 10) | Math.floor(time * 10)
ctx.translate((time < 500) ? Math.floor(time * 10) : 500,
(time < 500) ? Math.floor(time * 10) : 500);
ctx.drawImage(shapeCanvas, 0, 0);
ctx.restore();
__nextFrame(function() {
drawNext(ctx);
});
}
function drawShape(ctx) {
. . .
}
Share
Improve this question
edited Nov 27, 2020 at 17:36
C. Tewalt
2,5072 gold badges32 silver badges52 bronze badges
asked Dec 7, 2011 at 9:15
shaman.sirshaman.sir
3,3083 gold badges30 silver badges36 bronze badges
1
-
1
The path is rendered on
shapeCanvas
with anti-aliasing. When you draw an image with antialiasing onto a canvas at a non-integer location, you get anti-aliasing on top of anti-aliasing. The pulsating blurry edge of the stroke bees thickest when drawing the image halfway between integer pixel locations and vanishes when drawing the image exactly on integer pixel locations. – ellisbben Commented Feb 1, 2012 at 21:52
2 Answers
Reset to default 4 +50I wrote the tutorial in your first link.
Just to clear the air:
shapeCanvas.style.width = w + 'px';
shapeCanvas.style.height = h + 'px';
is not really worth doing. No point setting the style if its just a in-memory canvas, and you shouldn't really ever want to set the width and height style of a canvas anyway, it just confounds things.
What ellisbben said in the ment is pretty much what's happening.
It's possible to get around it in a few hackish ways I bet. One way might be to make sure its never drawn on an integer pixel. Another might be to use ctx.scale(.99,.99)
before drawing anything so it is always anti-aliased. It's tough to get a consistent solution here because different browswer's implementations of anti-aliasing are different.
Here are a few experiments from myself:
http://jsfiddle/KYZYT/29/
The first two are the shape drawn from a canvas and also drawn from a PNG
The second two are the same pair but scaled by .99,.99
The last one is the real thing. It still blurs a bit but looks a lot sharper than using the images.
None of my experiments lead to an end of your pulsating, at least not on a microscopic level. I think this is just something you're going to have to live with if you want to animate pixel-perfect images onto half-pixel spaces.
If you really feel you can't just draw on perfect pixels then your (second) best bet for consistency is probably to find a way to force anti-aliasing at all times. Making sure you are always translated to a non-integer or scaling it ever so slightly are decent candidates, but there may be others.
To be honest, you best bet is to not cache these animated paths until you absolutely need the performance from them. Cache the stylized buttons and other static things you make, but if you've got animated paths that need to move slowly and precisely and look very good, you might as well stick with the true thing over my caching optimization unless you really need it for those too.
Bit shameless plug but: I've implement smooth animation in HTML5 slot game with bit hacky way. The generated cached Image is drawn on small canvas once and then I used translate3d() with -moz-transform / -webkit-transform styles for the canvas to move, mirror and scale the image around.
Pregeneration
- Create Image
- Draw image content
- Create canvas object in DOM
Animation phase
- Clear canvas
- Draw the cached image to the canvas
- Use CSS3 transforms (scale3d and translate3d) to move canvas around.
本文标签:
版权声明:本文标题:javascript - HTML5 Canvas: Elements drawn withcached for drawImage are smoothed when scaled andor moved - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744294271a2599266.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论