fireFox 和 Chrome 在图像上的 transform 属性上 css 过渡渲染的差异

Posted

技术标签:

【中文标题】fireFox 和 Chrome 在图像上的 transform 属性上 css 过渡渲染的差异【英文标题】:Difference in the rendering of css transition on transform property on an image between fireFox and Chrome 【发布时间】:2014-11-19 04:46:51 【问题描述】:

我在 css 中为 img 设置了动画,并使用了一些切换类的 javascript。此类将转换属性添加到 img 已经有一个转换。这样我可以让这张图片在 3 秒内从 0px 移动到 10px。

http://codepen.io/poolboy/pen/swcup

img 
  transition: transform 3s ease-in-out;


img.trans 
  transform: translateX(10px) translateZ(0);

 

var myImg = document.getElementsByTagName('img');

setInterval(function()
  myImg[0].classList.toggle('trans');  
, 3000)

使用 Chrome,此动画很流畅,但图像变得模糊。使用 Firefox,过渡是逐像素的(所以不是平滑的,我们可以看到过渡中的步骤),但图像不会变得模糊。

在这种情况下,图像有 3 秒的时间移动到 +10px,这意味着在动画的 1 秒时,图像应该距离其起点 3,33px 的距离。 Firefox 的行为似乎是这样的:“3,33 像素是不可能的,所以我将图像保留在 3 像素”(如果图像应该在 3,51 像素,他可能会将其移动到 4 像素)。 Chrome 的行为似乎更像这样:“3,33px 是不可能的,所以我尝试重新渲染图像来制作它,但图像已降级”

不确定我的推理,但事实是,这两个动画都很丑陋,有没有什么解决方案可以长时间移动图像通过一点像素?是否可以在这两者之间进行相同的渲染?

【问题讨论】:

我无法访问图像 - 只是超时。 【参考方案1】:

在本例中,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;。不幸的是,optimizeQualityoptimizeSpeed 的值都是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" />
    <div>A Rotated image with translation</div>
    <img id="myTestImage2"
            src="http://img15.hostingpics.net/pics/549536saphRaw00.png" />
    <div>Moving at 24 pixels/s</div>
    <img id="myTestImage3"
            src="http://img15.hostingpics.net/pics/549536saphRaw00.png" />

当移动实现为动画时,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" />
<div>A rotated image with animation</div>
<img id="myTestImage2" src="http://img15.hostingpics.net/pics/549536saphRaw00.png" />
<div>Animation moving at 24 pixels/s</div>
<img id="myTestImage3" src="http://img15.hostingpics.net/pics/549536saphRaw00.png" />

【讨论】:

以上是关于fireFox 和 Chrome 在图像上的 transform 属性上 css 过渡渲染的差异的主要内容,如果未能解决你的问题,请参考以下文章

Chrome vs Firefox之战-表格单元格中的图像叠加[重复]

Firefox中带有边框图像的旋转div上的抗锯齿

画布上的 CORS 在 Chrome 和 Safari 上不起作用

在 Chrome 和 Firefox 上重新加载 js 和 CSS

测量图像的宽度和高度在 Chrome 和 Firefox 中返回 0,但在 Safari 中有效

使用 nameProp 的 JQuery 图像翻转在 Firefox 和 Chrome 中不起作用