Javascript HTML5画布:在缩放和/或移动时,使用/缓存drawImage绘制的元素会平滑
我确实知道Javascript HTML5画布:在缩放和/或移动时,使用/缓存drawImage绘制的元素会平滑,javascript,html,canvas,Javascript,Html,Canvas,我确实知道drawImage的x和y的浮点/整数值的情况。但我需要的是一个平滑的动画,能够缓存我的形状 例如,我想在画布上画一次复杂的形状(如SVG tiger),然后用ctx.translate和ctx.drawImage平滑地移动它。我需要浮点值,因为我得到的是一步一步的移动: 以下是JSFIDLE的示例: :速度快,将Math.floor应用于translate参数(x和y等于以秒为单位的时间乘以10):动画奇怪(顺序,不平滑) :慢速,将Math.floor应用于transla
drawImage
的x
和y
的浮点/整数值的情况。但我需要的是一个平滑的动画,能够缓存我的形状
ctx.translate
和ctx.drawImage
平滑地移动它。我需要浮点值,因为我得到的是一步一步的移动:
以下是JSFIDLE的示例:
- :速度快,将
应用于Math.floor
参数(translate
和x
等于以秒为单位的时间乘以y
):动画奇怪(顺序,不平滑)10
- :慢速,将
应用于Math.floor
参数(translate
和x
等于以秒为单位的时间):动画怪异(连续,不平滑)y
- :快速、无舍入、浮点值(
和x
等于时间(秒)乘以y
)。速度很快,所以动画看起来不错10
- :低速、无舍入、浮点值(
和x
等于时间,单位为秒)。速度很慢,所以动画看起来是脉动的为什么?y
mozimagesoothingEnabled
()的属性,但在其他浏览器中没有该属性的帮助。而且它还消除了路径平滑
代码摘录:
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) {
. . .
}
var shapeCanvas=null;
var w=320,h=240;
var startTime=0;
函数start(){
startTime=Date.now();
var docCanvas=document.getElementById('canvas');
. . .
shapeCanvas=document.createElement('canvas');
. . .
drawShape(shapeCanvas.getContext('2d');
drawNext(docCanvas.getContext('2d');
}
函数drawNext(ctx){
var msec=(Date.now()-startTime);
var time=msec/1000;//从开始到结束的时间为秒
ctx.clearRect(0,0,w,h);
ctx.save();
//要更改的行:time |(time*10)| Math.floor(time*10)
ctx.翻译(时间<500)?数学地板(时间*10):500,
(时间<500)?数学地板(时间*10):500;
ctx.drawImage(shapeCanvas,0,0);
ctx.restore();
__下一帧(函数(){
下一步(ctx);
});
}
函数drawShape(ctx){
. . .
}
我在您的第一个链接中编写了教程
只是想澄清一下:
shapeCanvas.style.width = w + 'px';
shapeCanvas.style.height = h + 'px';
这真的不值得做。如果只是一个内存中的画布,那么设置样式就没有意义了,而且你不应该真的想设置画布的宽度和高度样式,它只是让事情变得混乱
埃利斯本在评论中所说的几乎就是正在发生的事情
我敢打赌,有可能用一些粗俗的方式绕过它。一种方法可能是确保它永远不会绘制在整数像素上。另一种可能是在绘制任何东西之前使用ctx.scale(.99.99)
,以便始终消除锯齿。在这里很难得到一致的解决方案,因为不同浏览器的抗锯齿实现是不同的
以下是我自己的一些实验:
前两个是从画布绘制的形状,也从PNG绘制
第二对是同一对,但按.99、.99
最后一个是真的。它仍然有点模糊,但看起来比使用图像清晰得多
我的任何实验都不会结束你的脉动,至少在微观层面上不会。我认为,如果你想在半像素空间上制作像素级完美图像的动画,这就是你必须接受的东西
如果你真的觉得你不能只画完美的像素,那么你的(第二)最佳一致性选择可能是找到一种方法,在任何时候强制消除混叠。确保您总是转换为非整数,或者稍微调整它,这是不错的选择,但可能还有其他选择
老实说,在绝对需要这些动画路径的性能之前,最好不要缓存这些动画路径。缓存你制作的样式化按钮和其他静态东西,但是如果你有需要缓慢精确移动的动画路径,并且看起来非常好,除非你真的需要我的缓存优化,否则你最好还是坚持使用真实的东西。有点无耻的插件,但是:我已经用有点黑客的方式在HTML5老虎机游戏中实现了平滑的动画。生成的缓存图像在小画布上绘制一次,然后我使用translate3d()和-moz transform/-webkit transform样式在画布上移动、镜像和缩放图像 代前
路径通过抗锯齿在
shapeCanvas
上呈现。在画布上非整数位置绘制具有抗锯齿的图像时,在抗锯齿的基础上获得抗锯齿。在整数像素位置中间绘制图像时,笔划的脉动模糊边缘变得最厚,而在整数像素位置上精确绘制图像时,笔划的脉动模糊边缘消失。向上投票:1)令人沮丧的样式宽度和高度2)令人沮丧的缓存。非常感谢,您的答案是最详细的。至少现在我知道问题不在我的代码中,而且,这是一个有趣的实验)。也许我会放弃这种缓存方式,我需要考虑更多的时间。我认为我的缓存方式很好,如果你有像fancy button这样的静态东西