fireFox和Chrome之间图像上转换属性上css转换渲染的差异

sim*_*erc 2 css firefox google-chrome css-transitions css-transforms

img使用一些javascript切换一个类来为css 设置动画.此类将转换属性添加到img已经具有转换的转换.这样我就可以在3秒内将此图像从0px移动到10px.

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

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

img.trans {
  transform: translateX(10px) translateZ(0);
}
Run Code Online (Sandbox Code Playgroud)

 

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

setInterval(function(){
  myImg[0].classList.toggle('trans');  
}, 3000)
Run Code Online (Sandbox Code Playgroud)

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

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

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

Mak*_*yen 5

在这种情况下,Firefox和Chrome之间的区别在于,他们选择了两种不同的方法来处理动画帧,这些方法最终不会出现在像素边界上.

Firefox中的问题是它们只显示像素边界上的图像,而不是将图像转换为像素之间的图像.这种变换称为插值.假设它们没有插入图像不在像素边界上的帧,则显示的图像实际上仅在将其放置在下一个完整像素中时发生变化.

您选择的移动:3秒内10个像素,每个像素留下0.3秒.这远高于闪烁融合阈值.因此,我们人类经历它,因为从一个像素到另一个像素的个别不同的跳跃.为了使3秒内的10个像素经历平滑,必须显示额外的帧,其中插入的图像与图像在像素之间时所显示的一样.拥有额外的中间图像可让您的大脑将运动视为连续的.

假设我们试图获得看起来平滑且仅限于在像素边界上显示图像的移动,那么我们需要在转变时间期间显示足够的中间图像,使得显示的变化率高于闪烁融合阈值.虽然闪烁融合阈值会因相当多的因素而变化,但您可以通过了解视频和电影以每秒至少约24幅图像显示的方式,了解人类的动作速度是否开始变得平滑.

因此,在这种情况下,如果您将过渡的距离更改为导致变化率高于闪烁融合阈值的量,您将看到它平滑.在3秒内,如果我们要移动1个像素,每次更改为每秒24次更改,即72像素.可在此处找到此示例的一个版本,该图像在3秒内将图像移动72像素.显然,您不必使所有转换仅以此速率移动.但是你必须考虑到这个问题才能使转变顺利进行.

实际情况是,计算机动画不能一致地,或者甚至通常是平滑的,而没有内插帧,这些帧不会在像素边界上结束图像.Firefox应该进行插值以显示图像.

Chrome的问题几乎可以肯定,他们正在使用一种算法来插值帧,从而导致图像质量较低.存在多种算法可用于将源图像插值到表示中,这使得它看起来好像已经移动了一小部分像素.通常,看起来更好的算法需要更多的CPU时间.在Chrome中,Google可以选择使用哪种算法(或者可能是一组算法,根据可用的CPU时间选择一种算法,然后才能满足实际显示帧的截止时间).使用的算法使此图像在转换期间在您的计算机上看起来模糊.

不幸的是,目前还没有官方的方法来影响浏览器在转换期间如何执行插值.CSS属性image-rendering应该能够影响插值的执行方式,但是没有办法强制浏览器使用更高质量的模式.这可以设置为image-rendering: optimizeQuality;.不幸的是,这两个值optimizeQualityoptimizeSpeed弃用,处于被定义为同义词处理auto.另一方面,auto旨在表明高品质的外观:

auto 应使用最大化图像外观的算法缩放图像.特别是,"平滑"颜色的缩放算法是可接受的,例如双线性插值.这适用于照片等图像.

使用auto默认情况下,显式不会阻止浏览器(用户代理,UA)在转换期间选择较低质量的算法(高CPU负载):

此属性不指示要使用的任何特定缩放算法.例如,使用图像渲染:auto,用户代理可以默认使用双线性插值缩放图像,在高负载情况下切换到最近邻插值,并切换到高质量缩放算法,如Lanczos插值,用于静态图像没有移动或改变.

Firefox的解决方法:

[ simonLeClerc找到了解决方法]:

如果图像稍微旋转(例如1度),Firefox将使用插值来渲染图像,即使在过渡期间也是如此.最终,这会导致运动持续出现.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);
Run Code Online (Sandbox Code Playgroud)
    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;
    }
Run Code Online (Sandbox Code Playgroud)
    <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=""/>
Run Code Online (Sandbox Code Playgroud)

当移动实现为动画时,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; }  }
Run Code Online (Sandbox Code Playgroud)
<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=""/>
Run Code Online (Sandbox Code Playgroud)