Firefox CSS Animation Smoothing(亚像素平滑)

Posted

技术标签:

【中文标题】Firefox CSS Animation Smoothing(亚像素平滑)【英文标题】:Firefox CSS Animation Smoothing (sub-pixel smoothing) 【发布时间】:2015-03-09 00:42:16 【问题描述】:

我正在创建一个 CSS 关键帧动画,让一个元素看起来好像是随意/缓慢地浮动一点。它嵌套在双亲中,一个使用 translateX() 缓慢地左右移动,一个使用 translateY() 缓慢独立地上下移动。

Chrome 和 Safari 完美地呈现了这一点,使其具有逐渐摇摆的运动。它使动画平滑(也许使用亚像素平滑?),使一切看起来都非常平滑。然而,Firefox 会逐个像素地对其进行动画处理,因此您可以看到它在每个像素处跳跃,而不是平滑地摇摆。

在 Chrome 和 FireFox 中查看 JSFiddle 以查看差异:http://jsfiddle.net/gonygdfz/6/

有没有什么方法可以让 FireFox 平滑渲染,而不是让它逐个像素地跳跃?这在实际应用中非常明显。

标记:

<div id="parent">
    <div id="move-x">
        <div id="move-y">
            <div id="child"></div>
        </div>
    </div>
</div>

CSS:

#parent 
    width: 400px;
    height: 326px;
    background-color: yellow;
    background: url(http://paint.net.amihotornot.com.au/Features/Effects/Plugins/Render/Grid_CheckerBoard_Maker/Grid_CheckerBoard_Maker.Paint.NET.001.png) top center repeat;


#child 
    position: absolute;
    top: 75px;
    left: 150px;
    width: 100px;
    height: 100px;
    background-color: black;
    animation: range-y 10s infinite ease;


#move-x  
    animation: range-x 10s infinite ease; 
    -webkit-animation: range-x 10s infinite ease;

#move-y  
    animation: range-y 15s infinite ease; 
    -webkit-animation: range-y 15s infinite ease;


@keyframes range-x 
  0%    
    transform: translateX(0); 
  
  30% 
    transform: translateX(-8px); 
  
  50% 
    transform: translateX(1px); 
  
  65% 
    transform: translateX(6px); 
  
  80% 
    transform: translateX(0px); 

  
  89% 
    transform: translateX(-3px); 
  
  100% 
    transform: translateX(0); 
  



@keyframes range-y 
  0%    
    transform: translateY(0); 
  
  20% 
    transform: translateY(13px); 
  
  35% 
    transform: translateY(-1px); 
  
  70% 
    transform: translateY(-14px); 
  
  90% 
    transform: translateY(2px); 
  
  100% 
    transform: translateY(0); 
  



@-webkit-keyframes range-x 
  0%    
    transform: translateX(0); 
  
  30% 
    transform: translateX(-8px); 
  
  50% 
    transform: translateX(1px); 
  
  65% 
    transform: translateX(6px); 
  
  80% 
    transform: translateX(0px); 

  
  89% 
    transform: translateX(-3px); 
  
  100% 
    transform: translateX(0); 
  



@-webkit-keyframes range-y 
  0%    
    transform: translateY(0); 
  
  20% 
    transform: translateY(13px); 
  
  35% 
    transform: translateY(-1px); 
  
  70% 
    transform: translateY(-14px); 
  
  90% 
    transform: translateY(2px); 
  
  100% 
    transform: translateY(0); 
  

【问题讨论】:

虽然这不能解决您的亚像素平滑问题,但您可以使用transition 属性来帮助平滑定位。 transition: all 2s ease 0s; 【参考方案1】:

每个浏览器的渲染引擎明显不同。 Firefox 没有对 CSS 动画实现抗锯齿效果。这本身并不会使它变得更好或更糟,它仅取决于您制作动画的内容。例如,在 Chrome 中,线性过渡可能会出现令人不快的模糊。

看来您想要实现的是抗锯齿/亚像素平滑过渡。我们无法更改引擎的渲染方式,但我们可以操纵动画让最终用户看起来更柔和。


一切都不会丢失

我已经修改了您的答案,并在您的原始答案旁边呈现了一个更流畅的版本。在 Firefox 中查看时,它应该看起来更柔和。

CLICK FOR COMPARISON

用于此效果的技术:

线性过渡而不是缓动。 动画对象上的盒子阴影。 (软化边缘有助于创建假 AA 效果)。 旋转对象。添加最小旋转有助于更好地利用渲染引擎。

CSS

#parent 
    width: 50%;
    float:left;
    height: 326px;
    background-color: yellow;
    background: url(http://paint.net.amihotornot.com.au/Features/Effects/Plugins/Render/Grid_CheckerBoard_Maker/Grid_CheckerBoard_Maker.Paint.NET.001.png) top center repeat;

#child 
    position: absolute;
    top: 75px;
    left: 150px;
    width: 100px;
    height: 100px;
    background-color: black;
    box-shadow:0 0 1px rgba(0,0,0,0.7);
    animation: range-y 10s infinite linear;
    -webkit-animation: range-y 10s infinite linear;

#move-x  
    animation: range-x 10s infinite linear; 
    -webkit-animation: range-x 10s infinite linear;

#move-y  
    animation: range-y 15s infinite linear; 
    -webkit-animation: range-y 15s infinite linear;

@keyframes range-x 
    0%   transform: translateX(0);
    30%  transform: translateX(-8px) rotate(0.02deg);
    50%  transform: translateX(1px) rotate(0deg);
    65%  transform: translateX(6px) rotate(0.02deg);
    80%  transform: translateX(0px) rotate(0deg);
    89%  transform: translateX(-3px) rotate(0.02deg);
    100% transform: translateX(0) rotate(0deg);

@keyframes range-y 
    0%   transform: translateY(0);
    20%  transform: translateY(13px) rotate(0.02deg);
    35%  transform: translateY(-1px) rotate(0deg);
    70%  transform: translateY(-14px) rotate(0.02deg);
    90%  transform: translateY(2px) rotate(0deg);
    100% transform: translateY(0) rotate(0.02deg);

@-webkit-keyframes range-x 
    0%   transform: translateX(0);
    30%  transform: translateX(-8px) rotate(0.02deg);
    50%  transform: translateX(1px) rotate(0deg);
    65%  transform: translateX(6px) rotate(0.02deg);
    80%  transform: translateX(0px) rotate(0deg);
    89%  transform: translateX(-3px) rotate(0.02deg);
    100% transform: translateX(0) rotate(0deg);

@-webkit-keyframes range-y 
    0%   transform: translateY(0);
    20%  transform: translateY(13px) rotate(0.02deg);
    35%  transform: translateY(-1px) rotate(0deg);
    70%  transform: translateY(-14px) rotate(0.02deg);
    90%  transform: translateY(2px) rotate(0deg);
    100% transform: translateY(0) rotate(0.02deg);

最后一句话

您仍然可以稍微调整效果以满足您的要求。 它并不完美,但我希望它有助于软化您实际动画的最终效果。

【讨论】:

它确实变软了,但对我来说,盒子的形状似乎发生了变化。随着盒子向下移动,它的高度变小。当它向侧面移动时,它的宽度似乎发生了变化。 你只是从here复制了rotate(0.002deg),并没有注明出处。 @ThePragmatick 至少可以说是一个疯狂的假设。我已经使用这种技术几年了。这是否是我最初从那里学到的,我不能说,那是很久以前的事了。然而,是我花了两个小时试图为操作提出一个工作演示,没有其他人愿意提供帮助。 太棒了!那成功了。令人惊讶的是,在我的实际实现中,我实际上有第三个外部容器进行旋转。我把它拿出来用于演示目的。分别旋转 x 和 y 容器并不能解决问题,但是向单个 x 和 y 容器添加旋转肯定可以解决问题。谢谢! 添加 rotate(0.05deg) 挽救了我的生命,以防止动态缩放的精灵动画跳跃。【参考方案2】:

对变换使用少量旋转。这迫使 Firefox 避免优化并在每一帧上重新采样图像。

@keyframes optimized 
  0%
    transform: translateX(0%);
  
  100%
    transform: translateX(200px);
  


@keyframes subpixel 
  0%
    transform: translateX(0%) rotate(0.1deg);
  
  100%
    transform: translateX(200px) rotate(0.1deg);
  


div
  width:5px;
  height:50px;
  background-color: red;
  animation-duration:30s;
  animation-iteration-count: infinite;
  animation-direction:alternate;
  animation-timing-function:linear;


.optimized
  animation-name: optimized;
  margin-bottom:1px;


.subpixel
  animation-name: subpixel;
<div class="optimized">
</div>
<div class="subpixel">
</div>

【讨论】:

效果很好。

以上是关于Firefox CSS Animation Smoothing(亚像素平滑)的主要内容,如果未能解决你的问题,请参考以下文章

CSS3 TransformsTransitions和Animation属性总结

CSS 打字动画不适用于 Firefox

css3各个属性的兼容

css3常用属性animation-play-state的使用技巧

我的动画 CSS 不适用于 Firefox 和 IE

跨浏览器 CSS3 关键帧动画 Firefox