在本例中,Firefox 和 Chrome 之间的区别在于,它们选择了两种不同的方法来处理不以像素边界结束的动画帧。
Firefox 的问题在于它们只显示像素边界上的图像,而不是将图像转换为像素之间的样子。这种变换称为插值。鉴于它们不是对图像不在像素边界上的帧进行插值,因此显示的图像只有在它被放置在下一个完整像素中时才会真正发生变化。
您选择的移动:在 3 秒内移动 10 个像素,每个像素留下 0.3 秒。这远高于Flicker fusion threshold。因此,我们人类将其体验为从一个像素到另一个像素的个体不同的跳跃。为了在 3 秒内体验 10 个像素的平滑度,必须显示额外的帧,其中插入的图像与图像在像素之间出现的一样。拥有额外的中间图像可以让您的大脑将运动感知为连续的。
假设我们试图获得看起来平滑的运动并且仅限于在像素边界上显示图像,那么我们需要在过渡时间内显示足够多的中间图像,以便显示的变化率高于闪烁融合临界点。虽然闪烁融合阈值因相当多的因素而变化,但您可以通过知道视频和电影以每秒至少约 24 张图像的速度显示来大致了解人类开始感觉平滑的运动速率。
因此,在这种情况下,如果您将过渡距离更改为导致变化率高于闪烁融合阈值的量,您将看到它是平滑的。在 3 秒内,如果我们要以每秒 24 次变化的速度移动 1 个像素,即 72 个像素。在 3 秒内将图像移动 72 像素的此示例的版本可以是 found here。显然,您不必让所有的转换都以这个速度移动。但是你必须在脑海中试验这个问题,才能使过渡顺利。
现实情况是,如果没有插值帧,计算机动画就不能始终如一,甚至通常是平滑的,而这些帧最终不会在像素边界上产生图像。 Firefox 应该进行插值以显示图像。
Chrome 的问题几乎可以肯定是他们使用了一种算法来插入帧,这会导致图像质量较低。有多种算法可用于将源图像插值到表示中,使其看起来好像移动了一小部分像素。一般来说,看起来更好的算法会占用更多的 CPU 时间。在 Chrome 中,Google 选择了使用哪种算法(或者可能是一组算法,根据在必须满足实际显示帧的最后期限之前可用的 CPU 时间从中选择一个算法)。在过渡期间,使用的算法使此图像在您的机器上看起来很模糊。
不幸的是,目前没有官方方法来影响任一浏览器在转换期间如何执行插值。 CSS 属性image-rendering 应该能够影响插值的执行方式,但是没有办法强制浏览器使用更高质量的模式。这可以设置为image-rendering: optimizeQuality;。不幸的是,optimizeQuality 和optimizeSpeed 的值都是deprecated and are in the process of being defined as synonyms to auto。另一方面,auto 旨在表示高品质的外观:
auto
应该使用最大化图像外观的算法来缩放图像。特别是,缩放算法
“平滑”的颜色是可以接受的,例如双线性插值。这
适用于照片等图像。
使用auto,默认explicitly does not prevent the browser(用户代理,UA)在转换期间选择较低质量的算法(高CPU负载):
此属性并不规定任何特定的缩放算法是
用过的。例如,使用 image-rendering: auto,用户代理可能
默认情况下使用双线性插值缩放图像,切换到
在高负载情况下的最近邻插值,并切换到
高质量的缩放算法,例如静态的 Lanczos 插值
没有移动或变化的图像。
Firefox 的解决方法:
[simonLeClerc找到解决方法]:
如果图像稍微旋转(例如 1 度),即使在过渡期间,Firefox 也会使用插值来渲染图像。最终,这导致运动看起来是连续的。
有一个example on CodePen。
JavaScript:
var myImg = document.getElementsByTagName('img');
setInterval(function(){
myImg[0].classList.toggle('trans');
myImg[1].classList.toggle('trans');
myImg[2].classList.toggle('trans');
}, 3000);
img {
transition: transform 3s ease-in-out;
}
img.trans {
transform: translateX(10px);
}
/*Adding a rotation causes FireFox to use interpolation to display the image on
* non-pixel boundaries. (resulting in the same blurry effect observe in
* chrome)*/
#myTestImage2 {
transform: rotateX(1deg);
}
#myTestImage2.trans {
transform: translateX(10px) rotateX(1deg);
}
/* Moving at 24 pixels/s. This means that there is a move to the next pixel with
* each frame at a rate of 24 moves per second. This is enough for us to
* perceive it as smooth motion.*/
#myTestImage3.trans {
transform: translateX(72px); ease-in-out;
}
<div>Transition (image not rotated)</div>
<img id="myTestImage1"
src="http://img15.hostingpics.net/pics/549536saphRaw00.png" alt=""/>
<div>A Rotated image with translation</div>
<img id="myTestImage2"
src="http://img15.hostingpics.net/pics/549536saphRaw00.png" alt=""/>
<div>Moving at 24 pixels/s</div>
<img id="myTestImage3"
src="http://img15.hostingpics.net/pics/549536saphRaw00.png" alt=""/>
当移动实现为动画时,Firefox 的解决方法不起作用:
不幸的是,当移动被实现为 CSS 动画 (CodePen) 时,解决方法没有成功:
img {
}
#myTestImage1,#myTestImage2 {
-webkit-animation: move10px 3s ease-in-out 0s infinite alternate;
-moz-animation: move10px 3s ease-in-out 0s infinite alternate;
-o-animation: move10px 3s ease-in-out 0s infinite alternate;
animation: move10px 3s ease-in-out 0s infinite alternate;
}
/* Moving at 24 pixels/s such that there is a move to the each frame more is 1/24*/
#myTestImage3 {
-webkit-animation: move72px 3s ease-in-out 0s infinite alternate;
-moz-animation: move72px 3s ease-in-out 0s infinite alternate;
-o-animation: move72px 3s ease-in-out 0s infinite alternate;
animation: move72px 3s ease-in-out 0s infinite alternate;
}
/*Adding a rotatation causes FireFox to use interpolation to display the image on non-pixel boundaries. (resulting in the same blurry effect observe in chrome)*/
#myTestImage2 {
transform: rotateX(1deg);
}
@-webkit-keyframes move10px { from { margin-left:0px; } to { margin-left:10px; } }
@-moz-keyframes move10px { from { margin-left:0px; } to { margin-left:10px; } }
@-o-keyframes move10px { from { margin-left:0px; } to { margin-left:10px; } }
@keyframes move10px { from { margin-left:0px; } to { margin-left:10px; } }
@-webkit-keyframes move72px { from { margin-left:0px; } to { margin-left:72px; } }
@-moz-keyframes move72px { from { margin-left:0px; } to { margin-left:72px; } }
@-o-keyframes move72px { from { margin-left:0px; } to { margin-left:72px; } }
@keyframes move72px { from { margin-left:0px; } to { margin-left:72px; } }
<div>Animation (image not rotated)</div>
<img id="myTestImage1" src="http://img15.hostingpics.net/pics/549536saphRaw00.png" alt=""/>
<div>A rotated image with animation</div>
<img id="myTestImage2" src="http://img15.hostingpics.net/pics/549536saphRaw00.png" alt=""/>
<div>Animation moving at 24 pixels/s</div>
<img id="myTestImage3" src="http://img15.hostingpics.net/pics/549536saphRaw00.png" alt=""/>