предисловие
Обычно большинство веб-приложений, которые мы используем, просто переключаются с одного представления на другое, что приводит к неинтуитивному взаимодействию с пользователем, но мы можем сделать это интерактивное поведение более приличным с помощью технических средств:
При создании пользовательского интерфейса добавьте разумные эффекты перехода пользовательского интерфейса, чтобы избежать прыжков и телепортации. Если вы примените какие-то естественные движения в жизни к анимации пользовательского интерфейса, это вызовет яркие эмоции у ваших пользователей. В конце концов, все, с чем вы взаимодействуете, проистекает из естественного движения жизни.
Далее мы рассмотрим класс значимых анимаций пользовательского интерфейса, улучшающих взаимодействие с пользователем, с которыми вы, возможно, знакомы. У этой техники есть технический термин, а именно FLIP (первый, последний, инвертированный, воспроизведенный). Технология FLIP может динамически изменять положение и размер элементов DOM с высокой производительностью, независимо от того, как рассчитывается или визуализируется их макет (например, высота, ширина, плавающая точка, абсолютное позиционирование, Flexbox, сетка и т. д.). В процессе изменения будет дан определенный динамический эффект, чтобы достичь нужной нам цели, сделать динамический эффект пользовательского интерфейса более разумным и соответственно улучшить работу пользователя.
переход между представлениями
При переходе из одного представления в другое в мобильном приложении элемент, находящийся в фокусе, часто перемещается из одной позиции в другую между представлениями. Например, следующие сценарии:
Эффекты расширения и сжатия изображения
Если вы хотите сделать анимацию более плавной, постарайтесь сделать количество вычислений стиля как можно меньше и как можно быстрее. Ключ в том, чтобы использовать в анимации только трансформацию и непрозрачность. Просто использовать преобразование и непрозрачность просто разочаровывает. Но, к счастью, FLIP позволяет нам имитировать изменения макета, используя только преобразование.
Что такое ФЛИП
FLIP — это запоминающее устройство и технология, впервые предложенная Полом Льюисом. FLIP — это аббревиатура от четырех слов First, Last, Invert и Play. Вот краткое заявление:
Во-первых, прежде чем что-либо произойдет (до перехода), запишите положение и размер текущего элемента. Вы можете использовать API getBoundingClientRect() для обработки, например:
const first = el.getBoundingClientRect()
Этот код используется для получения границ элемента getBoundingClientRect() вернет объект DOMRect, как показано ниже:
Последнее: выполнение фрагмента кода, соответствующее изменение элемента и запись положения и размера элемента в последнем состоянии, например:
// 通过给元素添加一个类名,设置元素最后状态的位置和大小
//(在.totes-at-the-end中添加相应的样式规则),布局发生了变化
el.classList.add('totes-at-the-end')
// 记录元素最后状态的位置和尺寸大小
const last = el.getBoundingClientRect()
Инвертировать: рассчитать изменение положения между первой позицией (первой) и последней позицией (последней) элемента (и изменение размера между двумя состояниями, если необходимо), а затем использовать эти числа для выполнения определенных вычислений, позволяя элементу двигаться (путем преобразования положения и размера элемента), создавая иллюзию того, что он находится в первой позиции (начальной позиции):
const deltaX = first.left - last.left const deltaY = first.top - last.top
const deltaW = first.width / last.width const deltaH = first.height / last.height
Воспроизведение: чтобы инвертировать элемент (представить, что он находится в первой позиции), мы можем установить для преобразования значение none, переместить его в последнюю позицию и анимировать элемент:
elm.animate([ { transformOrigin: 'top left', transform: ` translate(${deltaX}px, ${deltaY}px) scale(${deltaW}, ${deltaH}) ` }, { transformOrigin: 'top left', transform: 'none' }], { duration: 300, easing: 'ease-in-out', fill: 'both' } );
Примечание. В Play используется API веб-анимации. Если вы никогда не касались соответствующего API,нажмите сюда, чтобы узнать больше
Соедините весь код следующим образом:
// 获取当前元素的边界
const first = el.getBoundingClientRect()
// 通过给元素添加一个类名,设置元素最后状态的位置和大小 (在.totes-at-the-end中添加相应的样式规则) // 布局发生了变化
el.classList.add('totes-at-the-end') // 记录元素最后状态的位置和尺寸大小
const last = el.getBoundingClientRect()
const deltaX = first.left - last.left const deltaY = first.top - last.top
const deltaW = first.width / last.width const deltaH = first.height / last.height elm.animate([ { transformOrigin: 'top left', transform: ` translate(${deltaX}px, ${deltaY}px) scale(${deltaW}, ${deltaH}) ` }, { transformOrigin: 'top left', transform: 'none' }], { duration: 300, easing: 'ease-in-out', fill: 'both' } );
Чтобы всем было проще понять принцип динамического эффекта, создаваемого технологией FLIP, для демонстрации используется следующая картинка, которая может быть проще для понимания:
Эффект анимации, достигнутый с помощью последнего процесса Play, показан на следующем рисунке:
Специальное заявление об отказе от ответственности: два изображения выше предоставлены @davidkpiano на CSS Dev Conf 2017.«FLIP сообщает об анимированных макетах»в теме
Переходы для общих элементов
В приложениях переход представлений и переход элементов в разные состояния является очень распространенным эффектом.Самый основной принцип заключается в том, что начальное состояние элемента отличается от конечного состояния. В Android это похоже на переходы между общими элементами, за исключением того, что элементы не «перерабатываются» из одного представления в другое в DOM, как в Android.
Далее, давайте посмотрим на эффект перехода FLIP:
Кратко объясните процесс расчета:
// 首先获取点被点击图片的位置和尺寸
let firstRect = itemImage.getBoundingClientRect();
// 然后获取详情的位置和尺寸
let lastRect = detailItem.getBoundingClientRect(); // 详情到图片的动效
detailItem.animate( [ { transform: ` translateX(${firstRect.left - lastRect.left}px) translateY(${firstRect.top - lastRect.top}px) scale(${firstRect.width / lastRect.width}) ` }, { transform: ` translateX(0) translateY(0) scale(1) ` } ], { duration: 600, easing: 'cubic-bezier(0.2, 0, 0.2, 1)' } );
// 详情的位置和尺寸
let itemImageRect = itemImage.getBoundingClientRect();
// 原图片的位置和尺寸
let detailItemRect = detailItem.getBoundingClientRect();
// 详情回到图片的动效
itemImage.animate( [ { zIndex: 2, transform: ` translateX(${detailItemRect.left - itemImageRect.left}px) translateY(${detailItemRect.top - itemImageRect.top}px) scale(${detailItemRect.width / itemImageRect.width}) ` }, { zIndex: 2, transform: ` translateX(0) translateY(0) scale(1) ` } ], { duration: 600, easing: 'cubic-bezier(0.2, 0, 0.2, 1)' } );
Суммировать
Я надеюсь, что эта статья будет полезна для вашего производства анимации!