Анимация Chrome делает текст размытым

На Firefox все работает хорошо, но хром показывает размытый анимированный текст. Я сделал все, как -webkit-font-smoothing: subpixel-antialiased; , -webkit-transform: translate3d(0,0,0); и все упомянутое здесь ранее:

Пост-анимация размытого/искаженного текста на основе Webkit через translate3d

но проблема все еще существует.

Я сделал очень простой пример, чтобы показать вам, как это выглядит. Как я могу решить эту проблему?

var text = 1;

function next() {

  var next = (text == 2) ? 1 : 2;
  document.getElementById('text' + text).className = 'out';
  document.getElementById('text' + next).className = 'in';
  text = next;
}
body {
  padding: 0;
  margin: 0;
  font-family: tahoma;
  font-size: 8pt;
  color: black;
}
div {
  height: 30px;
  width: 100%;
  position: relative;
  overflow: hidden;
  margin-bottom: 10px;
}
div div {
  opacity: 0;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
}
.in {
  -webkit-animation: comein 1s 1;
  -moz-animation: comein 1s 1;
  animation: comein 1s 1;
  animation-fill-mode: both;
}
@keyframes comein {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
.out {
  -webkit-animation: goout 1s 1;
  -moz-animation: goout 1s 1;
  animation: goout 1s 1;
  animation-fill-mode: both;
}
@keyframes goout {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
<div>
  <div class="in" id="text1">Hello! I'm Test Text. I'm Test Text jr Father!</div>
  <div id="text2">Hi, I'm test text jr. I'm sharp and beautiful by nature but when I came in, Chrome made me blurry and I'm bad, I'm bad! ... Who bad :)</div>
</div>

<button onclick="next();">Next</button>

Ответ 1

Обновление 2018-10: в моих тестах это исправлено в Chrome/Chromium 72!

Это известная ошибка уже как минимум год: https://bugs.chromium.org/p/chromium/issues/detail?id=521364#c36.

Статус многообещающий от одного из разработчиков, работающего над этим, хотя:

Проблема была из-за того, что мы растрили вещи в элементе локального пространства. Если элемент имеет дробный перевод, тогда растеризованная текстура будет вставлена на экран с дробным переводом с использованием линейной передискретизации, что приведет к размытию.

Решение состоит в том, чтобы растрировать вещи в пространстве, которое выровнено по пикселям с нашим физическим экраном. т.е. применение дробного перевода к командам векторной графики вместо растровой текстуры.

Исправление будет состоять из двух частей:

  1. Первая часть, которая позволяет нашей растровой системе работать с любой общей матрицей. Эта часть почти закончена. У меня есть WIP, но он все еще имеет ошибку, которая приводит к снижению производительности. Я ожидаю, чтобы закончить это в течение нескольких дней. https://codereview.chromium.org/2075873002/

  2. Вторая часть, которая позволяет нашему менеджменту листов иметь возможность управлять набором текстур, которые идут с различными растровыми переводами. Первоначально я использовал общую матрицу, но оказалось, что вычисление покрытия тайла становится очень трудным. Вместо этого я сделаю более простую версию, которая поддерживает только перевод и масштабирование. Я считаю, что для этого потребуется еще неделя работы.

Ответ 2

Почему это происходит?

Как сказал @staypuftman здесь, это ошибка. но я заметил, что когда анимация достигла% 100, хром не выпустил анимацию. Причина, по которой Firefox действует правильно, заключается в том, что Firefox выпускает анимацию в конце, даже в animation-fill-mode: both.

Решение проблемы

Chrome освобождает анимацию в конце, когда animation-fill-mode - forward. Это не может помочь ситуации. потому что, наконец, нам нужно остановиться на конечный результат, а не вернуться к исходной точке начала анимации.

Трюк здесь состоит в том, чтобы сделать animation-fill-mode вперед. и сделать класс точно так же, как% 100. Например, в примере вопроса% 100 для comein составляет 100% {opacity:1;}. и мы используем это с анимацией.

Это может быть беспорядочно на css, но оно может решить проблему.

против

В конце может появиться небольшое отставание или мерцание.

Пример

Здесь вы можете увидеть, как этот простой трюк может решить проблему:

var text = 1;

function next() {

  var next = (text == 2) ? 1 : 2;
  document.getElementById('text' + text).className = 'out';
  document.getElementById('text' + next).className = 'in show';
  text = next;
}
body {
  padding: 0;
  margin: 0;
  font-family: tahoma;
  font-size: 8pt;
  color: black;
}
div {
  height: 30px;
  width: 100%;
  position: relative;
  overflow: hidden;
  margin-bottom: 10px;
}
div div {
  opacity: 0;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
}
.in {
  -webkit-animation: comein 1s 1;
  -moz-animation: comein 1s 1;
  animation: comein 1s 1;
  animation-fill-mode: forward;
}
@keyframes comein {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
.out {
  -webkit-animation: goout 1s 1;
  -moz-animation: goout 1s 1;
  animation: goout 1s 1;
  animation-fill-mode: both;
}
@keyframes goout {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
.show{
  opacity: 1; /*exactly like 100% of comein*/
}
<div>
  <div class="in show" id="text1">Hello! I'm Test Text. I'm Test Text jr Father!</div>
  <div id="text2">Hi, I'm test text jr. I'm sharp and beautiful by nature but when I came in, Chrome made me blurry and I'm bad, I'm bad! ... Who bad :)</div>
</div>

<button onclick="next();">Next</button>

Ответ 3

Это искажение часто появляется. Вы можете попробовать transform: translate3d(0, 0, 0) или transform: translateZ(0) и элемент с анимацией, но он не работает всегда.
-webkit-font-smoothing: antialised - это еще один вариант, но он никогда не работал у меня.

Ответ 4

Когда анимация перемещается в процентах, текст становится размытым из-за того, что браузер угадывает его точное местоположение на этапах перерисовки. Использование другого блока для перемещения, например, "px", позволит браузеру быть конкретным на этапе перерисовки и позволит тексту быть чистым и гладким.

Прочитав ниже, я понял, что эта же концепция также может иметь фактор, влияющий на размытый эффект на тексте.

Проценты являются относительными значениями, что означает, что они должны зависеть от некоторого другого значения для получения результата. Поэтому каждый раз, когда вы назначаете процентное значение, оно должно получать его относительное значение для выполнения расчета. При выполнении перевода с пикселями вам нужно только изменить значения перевода, но с процентами вы должны сначала получить размеры элемента, а затем применить перевод. И это должно быть сделано для каждого кадра анимации.

Вы можете прочитать больше об этом здесь: fooobar.com/questions/15709032/...

В моих тестах это, кажется, решает проблему полностью для всех моих анимаций в моем приложении. (10+)

Ответ 5

Лучшее решение для размытия текста при добавлении анимации - добавить "z-index: 1;" на стиль, где размещена анимация.

.in {
  -webkit-animation: comein 0.5s 1;
  -moz-animation: comein 0.5s 1;
  animation: comein 0.5s 1;
  animation-fill-mode: both;
  z-index: 1;
}

Ответ 6

вы можете проверить эту ссылку на свою версию времени анимации PLS по ссылке

var text = 1;

function next() {

  var next = (text == 2) ? 1 : 2;
  document.getElementById('text' + text).className = 'out';
  document.getElementById('text' + next).className = 'in';
  text = next;
}
body {
  padding: 0;
  margin: 0;
  font-family: tahoma;
  font-size: 8pt;
  color: black;
}
div {
  height: 30px;
  width: 100%;
  position: relative;
  overflow: hidden;
  margin-bottom: 10px;
}
div div {
  opacity: 0;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
}
.in {
  -webkit-animation: comein 0.5s 1;
  -moz-animation: comein 0.5s 1;
  animation: comein 0.5s 1;
  animation-fill-mode: both;
}
@keyframes comein {
  0% {
    opacity: 0;
  }
 
  100% {
    opacity: 1;
  }
}
.out {
  -webkit-animation: goout 0.5s 1;
  -moz-animation: goout 0.5s 1;
  animation: goout 0.5s 1;
  animation-fill-mode: both;
}
@keyframes goout {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
<div>
  <div class="in" id="text1">Hello! I'm Test Text. I'm Test Text jr Father!</div>
  <div id="text2">Hi, I'm test text jr. I'm sharp and beautiful by nature but when I came in, Chrome made me blurry and I'm bad, I'm bad! ... Who bad :)</div>
</div>

<button onclick="next();">Next</button>