Анимация элементов HTML с помощью FLIP

В современных веб-приложениях вы сталкиваетесь с необходимостью анимировать элементы HTML. Будь то визуализация перехода между несколькими списками, переключение позиций в одном списке, рост элементов при выделении и т.д. Существует множество случаев, когда необходимо сделать приложение более «броским» с помощью анимации.

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

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

FLIP расшифровывается как First, Last, Invert and Play и был придуман Полом Льюисом.

  • Первый: Начальная точка элемента. Получите эту информацию из DOM.
  • Last: конечная позиция элемента. Также получите эту информацию из DOM.
  • Инвертировать: Рассчитывает трансформацию (масштаб, поворот, перевод и т.д.) от первой до последней позиции и меняет ее на противоположную. Таким образом, если вам нужно анимировать 100px вправо, используйте -100px на оси x. В результате ваш элемент будет отображаться в том же положении, в котором он находился до этого.
  • Play: Запустите анимацию. Теперь элемент перейдет из измененного начального положения в текущее. Больше ничего делать не нужно.

Давайте рассмотрим пример:

const flip = () => {
  // retrieve the block to animate
  const block1 = document.querySelector<HTMLDivElement>('#block1')

  // an array with 3 target elements
  const positions: Element[] = [
    document.querySelector('.middle'),
    document.querySelector('.end'),
    document.querySelector('.start'),
  ]
  let index = 0

  if (block1) {
    // animate the block on click
    block1.addEventListener('click', () => {
      // FLIP - First
      // retrieve the position of the block at its starting point
      const start = block1.getBoundingClientRect()

      // Move the element to its destination
      positions[index].appendChild(block1)

      // FLIP - Last
      // retrieve the position of the block at its final position
      const end = block1.getBoundingClientRect()

      // FLIP - Invert
      // Calculate the change from the start to the end position
      const dx = start.left - end.left
      const dy = start.top - end.top
      const dh = start.height - end.height
      const dw = start.width - end.width

      // FLIP - Play
      // Initiate the animation
      block1.animate(
        [
          {
            transformOrigin: 'top left',
            transform: `translate(${dx}px, ${dy}px)`,
            height: `${dh}px`,
            width: `${dw}px`,
          },
          {
            transformOrigin: 'top left',
            transform: 'none',
          },
        ],
        { duration: 400, fill: 'both', easing: 'ease-in-out' }
      )

      index = (index + 1) % positions.length
    })
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

При работе с FLIP вы можете столкнуться с некоторыми проблемами:

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

В любом случае, есть хороший плагин GSAP, который поможет решить эти и другие проблемы.


Фото Liam Shaw on Unsplash

Оцените статью
devanswers.ru
Добавить комментарий