Мигает картинка при использовании blur

220
28 мая 2018, 17:40

При наведении курсора на картинку, добавляется с помощью JS class .active

В стиле active указано, что картинка должно стать blur(10px) и transform: translateY(20px);

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

Как можно исправить?

Answer 1

Сниппет для воспроизведения проблемы:

for (let img of document.querySelectorAll('.test')) { 
  img.addEventListener('mouseenter', function () { this.classList.add('active'); });  
  img.addEventListener('mouseleave', function () { this.classList.remove('active'); });  
}
.test   { transition: all 0.3s ease-out; } 
.active { filter: blur(10px); transform: translateY(20px); }
<img class="test" src="https://picsum.photos/200/150/?image=11"> 
<img class="test" src="https://picsum.photos/200/150/?image=15"> 
<img class="test" src="https://picsum.photos/200/150/?image=16">

Причина - ресурсоемкость размытия.
Соответственно, на 100% решить проблему невозможно. Но, можно применить CSS-вуду некоторые оптимизации, которые помогут в большинстве случаев.
upd.: После прочтения комментариев и проверки в Firefox (Win, Andr) и Opera (Win), делаю вывод что я ошибался относительно причин. Видимо, они все-таки в Chrome под винду и андроид.

Вариант решения:

for (let img of document.querySelectorAll('.test')) { 
  img.addEventListener('mouseenter', function () { this.classList.add('active'); });  
  img.addEventListener('mouseleave', function () { this.classList.remove('active'); });  
}
.test { 
  transition: filter 0.3s steps(18), 
              transform 0.3s ease-out;  
  backface-visibility: hidden !important;  
  transform: translate3d(0, 0, 0) scale(1, 1);  
} 
.active { 
  filter: blur(10px);  
  transform: translate3d(0, 20px, 0) scale(1, 1);  
}
<img class="test" src="https://picsum.photos/200/150/?image=11"> 
<img class="test" src="https://picsum.photos/200/150/?image=15"> 
<img class="test" src="https://picsum.photos/200/150/?image=16">

Данное решение включает в себя (в порядке значимости):

  • ограничение числа кадров перехода, steps(18)
    60кадров/с (лимит браузера) * 0,3с = 18
    Это также делает временную функцию перехода линейной, что сильно ускоряет подсчеты (но это не просто аналог linear, а лучше).

  • отключение отрисовки оборотной стороны элемента через backface-visibility: hidden
    Смысл очевиден: флип не выполняется => нет смысла рендерить оборотку.

  • исключение из пересчета transform трансформации по X и Z, а также масштабирования
    Плюс, translate3d создает новый слой при рендеринге элемента - что, в свою очередь, должно вынудить браузер задействовать GPU не только при размытии.

READ ALSO
Как сделать видео чат с отправлением запросов другу с WebRtc?

Как сделать видео чат с отправлением запросов другу с WebRtc?

Как сделать видео чат в котором, например я пишу в инпуте имя друга и ему отправляется запрос на чат, если он его принимает - начинать с помощью...

193
Как поставить или исключить пробел?

Как поставить или исключить пробел?

Вопрос по сути продолжение этого вопроса

224
Перебор содержимого внутри всех div

Перебор содержимого внутри всех div

Подскажите,как правильно реализовать перебор содержимого всех div с одинаковым классомНапример есть следующая структура:

248
Проблема с поиском потомков

Проблема с поиском потомков

есть следующая структура:

173