Технология FLIP, упрощающая анимацию

React.js

Однажды меня спросили, как добиться следующих эффектов анимации:

Несколько карт элементов располагаются сверху вниз. При добавлении или удалении карты остальные карты будутtransitionАнимированные формы перемещаются на место, а не мерцают неподвижно.

я случайно увиделVueвстроенные компоненты вtransitionреализации, понимая, что можно использоватьtransitionЧасть принципа компонента для достижения этого эффекта, но поскольку я не исследовал, почему это так, он остается только на поверхности, я знаю это, но не знаю почему, поэтому, хотя я знаю, как достичь этот эффект, трудно объяснить, почему это так, язык сложнее организовать

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

FLIP

FLIPдаFirst,Last,Invertа такжеPlayаббревиатура инициалов из четырех слов

First, относится к записи положения и размера текущего элемента до того, как что-либо произойдет (до перехода), то есть информацию о положении и размере элемента в момент до начала анимации, вы можете использоватьgetBoundingClientRect()этоAPIиметь дело (в большинстве случаев на самом делеoffsetLeftа такжеoffsetTopэто тоже нормально)

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

Invert: вычисляет первую позицию элемента (First) и последняя позиция (Last) (и, при необходимости, изменение размера между двумя состояниями), а затем использовать эти числа для выполнения определенных вычислений для перемещения элемента (черезtransformизменить положение и размер элемента), тем самым создавая иллюзию того, что он находится в первой позиции (исходной позиции)

То есть, как только вы подойдете, пусть элемент будет в конечном состоянии анимации, а затем используйтеtransformинвертирует элемент обратно в начальное состояние анимации (информация об этом состоянии находится вFirstполучить шаги)

Play: инвертировать элемент (представить, что он находится вfirstположение), можно положитьtransformУстановить какnone, потому что потерялtransformОграничение , поэтому элемент обязательно переместится в положение, где он должен быть (то есть состояние в конце анимации), то естьlastпозиция, если вы добавите к элементуtransitionсвойства, то этот процесс естественно происходит в виде анимации

Насколько я понимаю, это количественная оценка начального и конечного состояний элементов анимации, выраженная в формуле. Большинство непрерывных анимаций можно выполнить, применив эту формулу для повышения эффективности разработки анимации. Для получения более подробной информации, пожалуйста обратитесь к своим.Изменения, внесенные технологией FLIP в веб-верстку

Реализовать анимацию добавления и удаления карт

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

First

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

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

// First
activeList.forEach((itemEle, index) => {
  rectInfo = itemEle.getBoundingClientRect()
  transArr[index + stepIndex][0] = rectInfo.left
  transArr[index + stepIndex][1] = rectInfo.top
})

Last

Конечным состоянием анимации на самом деле является состояние оставшихся карточек после добавления или удаления карточек:

if (updateStatus === 0) {
  // 增加卡片
  newListData = this.state.listData.slice(0, activeIndex).concat({
    index: cardIndex++
  }, this.state.listData.slice(activeIndex))
} else {
  // 删除卡片
  newListData = this.state.listData.filter((value, index) => index !== activeIndex)
}

Потому что я не добавил карту в это времяtransitionатрибут, поэтому процесс обновления количества карточек на самом деле является мгновенной вещью.Человеческий глаз не может обнаружить никаких изменений, но элементы на странице действительно изменились, и тогда информация о положении карточек измеряется в это время, что являетсяLastНеобходимые данные

Invert

Получив информацию о расположении затронутых карт в начале анимации, вы можете пройтиtransformАтрибут меняет положение элемента

// Last + Invert
const stepIndex = updateStatus === 0 ? 1 : 0
activeList.forEach((itemEle, index) => {
  rectInfo = itemEle.getBoundingClientRect()
  transArr[index + stepIndex][0] = transArr[index + stepIndex][0] - rectInfo.left
  transArr[index + stepIndex][1] = transArr[index + stepIndex][1] - rectInfo.top
}

Play

Этап подготовки готов, можно переходить к завершающему шагуPlayВставай, ключ к этому шагу — добавить элементы вtransitionатрибут и удалитьtransformИзменение позиции привело к элементу:

// Play
// 重置
transArr = getArrByLen(this.state.listData.length)
setTimeout(() => {
  this.setState({
    animateStatus: 3
  })
}, 0)

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

На данный момент анимационный эффект в начале статьи выполнен.Live Demo, если вам интересно, вы можете попробовать сами, а код также можно загрузить наGithub

Реализовать увеличение/восстановление анимации изображения

Когда вы нажимаете на изображение предварительного просмотра в интерфейсе чата приложения WeChat, процесс изображения из диалогового окна в полноэкранный предварительный просмотр использует анимацию перехода, чтобы показать весь процесс изображения от маленького изображения к большому изображению и от большого изображения к маленькому Процесс масштабирования Аналогично следующему:

Это тоже непрерывная анимация, конечно тоже можно пройтиFLIPсделать это легко

First

Это включает в себя изменение положения и размера изображения, изображение изFirstИсходное положение эскиза и размер эскиза становятсяLastПоложение большого изображения и размер большого изображения в состоянии, поэтому необходимо получить эти два данных одновременно, по сути его можно вызвать одним вызовомgetBoundingClientRectЗаканчивать

Last

Получите информацию о размере и положении изображения уже в состоянии предварительного просмотра, также используйтеgetBoundingClientRectЗаканчивать

Кроме того, для более эффективного использованияtransformАнимация, здесь я трансформирую изменение размера картинки в двух состояниях вscaleизменение стоимости,Firstа такжеLastСоотношение ширины или высоты в состоянии этоscaleдолжно принимать значение (без изменения соотношения сторон изображения)

scaleValue = rectInfo.width / lastRectInfo.width

Invert

использоватьtransformположение и размер (т.е. изменениеscaleзначение) инверсия

Здесь следует отметить, что, посколькуtransformанимация по умолчаниюtransform-originявляется центром элемента, т.е.50% 50%, но рассчитанныйleftа такжеtopНо это относительно немасштабированного изображения, поэтому, когдаscaleЕсли значение не уникально, анимация изображенияFirstсостояние будет отклоняться, и необходимоtransformустановить как0 0устранить это предубеждение

Play

добавить к изображениюtransitionатрибут и удалить связанныйtransformсвойство для запуска анимации

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

Что касается стадии восстановления увеличенной картинки до маленькой, то ее можно рассматривать как еще однуFLIPАнимация, продолжайте применять, но эта анимация обратна предыдущей анимации увеличения, получена необходимая информация о размере и положении, вы можете сохранить вызовgetBoundingClientRectпроцесс

сделал то же самоеLive Demo, если вам интересно, вы можете попробовать сами, а код также можно загрузить наGithub

Зачем использовать ФЛИП

Некоторые люди могут быть более сбиты с толку, если вы хотите получить анимацию напрямую.transformЭто нормально, зачем это делать?FLIPконцепция вышла?

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

Для некоторых анимаций вы явно знаете их начальное состояние (First) и конечное состояние (Last), например, вы хотите сделать элемент изleft:10px;перейти кleft:100px;, то вы сразуtransformВсе в порядке, это совсем не обязательноFLIP, но использовать его лишнее;

Но кроме того, есть некоторые начальные состояния, которые нельзя указать (First) или конечное состояние (Last) анимация, такая как анимация карты в начале, если вы не ограничите размер каждой карты и размер всей страницы, вы не сможете понять, где должны быть другие карты после того, как вы произвольно вставите или удалите карту.

Например, под вашим браузером ширина и высота каждой карточки 100, а ширина страницы браузера 1380, поэтому в каждом столбце можно расположить 13 карточек, но это только в вашем браузере, на странице браузера пользователя Ширина может быть 1280 или 1980, количество карточек в каждой колонке может быть 12 или 19 и так далее, причем можно даже произвольноresizeРазмер страницы, то в это время, как вы определяете все карты в каждый моментlastинформация о состоянии?

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

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

Как говорится в названии,让动画变得更简单, можно и не использовать, но если умеешь пользоваться, то анимация - это формула для тебя, и не толькоeasy.

резюме

Многие фронтендеры как будто не особо заботятся об анимации, думая, что это всего лишь вспомогательная способность, главное бизнес-логика, а все остальное остается позади.Даже если есть время, все зависит от настроения перед решить, делать это или нет.

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