Сглаживание анимации Firefox CSS (сглаживание подпикселей)

Я создаю анимацию ключевого кадра CSS, чтобы элемент выглядел так, как будто он случайно/медленно плавает вокруг. Он вложен в родителях, который использует translateX(), чтобы медленно перемещать его влево и вправо, и тот, который использует translateY(), чтобы медленно и независимо перемещать его вверх и вниз.

Chrome и Safari отлично справляются с этим, давая ему постепенное колебательное движение. Он сглаживает анимацию (возможно, сглаживание подпикселей?), Так что все выглядит очень гладко. Однако Firefox оживляет пиксель за пикселем, поэтому вместо того, чтобы плавно качаться, вы можете увидеть, как он прыгает на каждом пикселе.

Посмотрите JSFiddle в Chrome и FireFox, чтобы увидеть разницу: 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); 
  }
}

Ответ 1

Механизмы рендеринга для каждого браузера, очевидно, разные. Firefox не реализует эффект сглаживания для CSS-анимации. Это по сути не делает это лучше или хуже, это просто зависит от того, что вы оживляете. Например, линейные переходы могут выглядеть нежелательно размытыми в Chrome.

Тем не менее, кажется, что вы хотели бы добиться сглаженных переходов с сглаживанием на субпикселях. Мы не можем изменить способ рендеринга движка, но мы можем манипулировать анимацией, чтобы она была мягче для конечного пользователя.


ВСЕ НЕ ПОТЕРЯЛИ

Я изменил ваш ответ и предоставил более гладкую версию рядом с вашим оригиналом. Это должно выглядеть мягче при просмотре в Firefox.

ЩЕЛКНИТЕ ДЛЯ СРАВНЕНИЯ

Методы, используемые для этого эффекта:

  • Линейные переходы вместо легкости.
  • Коробка-тень на анимированном объекте. (Смягченный край помогает создать искусственный эффект АА).
  • Повернуть объект Добавление наименьшего поворота помогает лучше использовать движок рендеринга. †

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);}
}

ЗАКЛЮЧИТЕЛЬНОЕ СЛОВО

Вы все равно можете немного подправить эффекты в соответствии с вашими требованиями. Это не идеально, но я надеюсь, что это поможет смягчить конечный эффект для вашей реальной анимации.

Ответ 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>