Эта статья — перевод оригинальной статьи "Text Replace Transitions"

Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.

Вступление

Начнём с хорошего, финальная демка, как будто вы прочитали всё до конца.

https://codepen.io/argyleink/pen/KKBWwMr

Если вы видите ошибку поддержки, вот запись его работы в Chrome Canary (с включенным этим флагом ????.

tldr;

view-transition позволяет мне с помощью CSS описать, как убрать старое текстовое состояние и показать новое текстовое состояние.

Вдохновение

Идея этой демонстрации пришла из игры Session Skate. В начальных титрах «SESSION» каждая буква быстро исчезает. Это выглядело довольно круто, и я сразу понял, что могу сделать это с помощью view-transition, setInterval() и .textContent. Итак, я завёл себе задачу в todo, чтобы сделать это, потому что пришло время заняться фигнёй, а не работой.

Это превратилось в небольшой прототип. Взгляните на эти баребоны!

setInterval(() => {
  document.startViewTransition(() => {
    h1.textContent = word[index++]
    if (index >= word.length) index = 0
  })
}, 500)
  1. Каждые полсекунды.

  2. Сделай снепшот предыдущего состояния.

  3. Задай новый текст.

Когда работа завершается в коллбэке функции startViewTransition, браузер бесплатно интерполирует изменения для вас. В нашем случае была "V", теперь "i". Одна буква исчезла, одна буква появилась. Получаем кроссфейд!

https://codepen.io/argyleink/pen/BaPWpmQ

Оно. Мы сделали как в игре.

Настройка перехода

Кроссфейды — это круто (и вы все тоже), но что, если я захочу настроить, как будет меняться текст? Возможно, с чем-то типо Open Props?

Не проблема ????????

Во-первых, сделаем импорт easings и animation:

@import "https://unpkg.com/open-props/easings.min.css";
@import "https://unpkg.com/open-props/animations.min.css";

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

html {
  view-transition-name: none;
}

Теперь, когда мы сказали, что мы не хотим переходить, давайте уточним, что следует делать, h1!

h1 {
  /* be stable. fix that width. */
  inline-size: 1em;
  
  /* required for view-transitions  
     now it's not the whole page */
  contain: layout;
  
  /* yo browser; transition this! */
  view-transition-name: replace-effect;
}

Запомните что view-transition-name может ссылаться на своё состояния до и после в следующем этапе.

Теперь самое приятное

Используйте некоторые из этих пропсов, чтобы организовать появление и исчезновение буквы/снепшотов DOM. Начнем с того, как должна выйти предыдущая букву; давайте посмотрим, я хочу, чтобы она масштабировалась, например, от меня, и исчезала в то же время.

@media (prefers-reduced-motion: no-preference) {
  html::view-transition-old(replace-effect) {
    animation: 
      var(--animation-fade-out),
      var(--animation-scale-down);
  }
}

Восхитительная магия

Теперь для появления элемента; затемните его, сдвинув вверх!

@media (prefers-reduced-motion: no-preference) {
  html::view-transition-new(replace-effect) {
    z-index: 1;
    animation: 
      var(--animation-fade-out) reverse,
      var(--animation-slide-in-up);
  }
}

анимация затухания инвертируется, поэтому непрозрачность не нужно устанавливать на 0.

Меняйте и подбирайте пропсы для анимации в этом Codepen и получайте удовольствие ????

https://codepen.io/argyleink/pen/KKBWwMr

Заключение

Внесите изменения в DOM, скажите как анимировать изменения. Влюбитесь.

Комментарии (2)


  1. madmandarin
    12.01.2023 15:22

    Выглядит круто, но почему setInterval а неrequestAnimationFrame?


    1. devlev
      12.01.2023 16:58
      +2

      Я так понимаю setInterval здесь используется только чтобы менять непосредственно сами отображаемые буквы. А то как они будут перерисованы определяют правила на css. requestAnimationFrame вызывается на каждый кадр отрисовки - соответственно буквы будут так быстро меняться что мы просто не увидем анимацию их смены.