Автор оригинала: FreeCodeCamp Community Member.
НАРЕНДРА Н Шетти
В этом посте я говорю о том, как добиться перехода общего элемента с реактивным встроенным для IOS, так и для Android.
Я опубликовал код на Github И вы можете посмотреть, если вы хотите прыгнуть прямо в него.
Намерение
Позволяет взглянуть на то, что мы собираемся построить. Ниже приведен пример сетки, где мы добавим общий переход элемента. Таким образом, мы можем плавно переходить между сеткой и страницей деталей для фотографии, которую мы выбираем.
Это намного более гладкая и непрерывный опыт.
Подход
Прежде чем мы построим это, позвольте мне рассказать вам, как работает система под капотом. Поскольку React Naious не поддерживает истинные общие элементы, когда мы говорим, что мы выполняем переход для общего элемента между двумя экранами, мы не используем какие-либо элементы. Вместо этого каждый экран имеет свой собственный элемент.
То, что я делаю, это передает информацию о общей элементе – например, его положение и размер – между этими двумя элементами.
Когда экран деталей запускается, его фона устанавливается на прозрачный, и он скрывает все его элементы. Затем он изменяет атрибуты общего элемента к прохождению, затем делает его видимым. Затем он оживляет себя в свое естественное положение. Поскольку переход прогрессирует, окно предпосылки и остальные не общие элементы медленно исчезают до тех пор, пока они не будут непрозрачными.
Поэтому, в то время как элемент не используется технически совместно, эта умная хитрость дыма и зеркала делает его казаться тем, что они есть.
Так что теперь, когда мы понимаем, как работает этот процесс, давайте пойти пошаговым шагом, чтобы понять, как этот элемент MOCK был разделен, и как мы можем контролировать анимацию.
Шаг 1: Анимация входа и выхода
У меня здесь есть два экрана: сетка и детали. С экрана сетки мы можем запустить экран детализации, нажав на одно из изображений в сетке. Затем мы можем вернуться к экрану сетки, ударив на заднюю кнопку.
Когда мы идем с экрана сетки на экран с подробным экраном, у нас есть возможность запускать два набора анимаций переходных данных – выходной переход для экрана сетки и переход ввода и входа для детализации экрана.
Давайте посмотрим, как мы реализуем это.
Без какого-либо перехода, вот как выглядит приложение. Нажатие на отдельное изображение отвечает вам на экран детализации.
Давайте добавим выходной переход на первый экран сетки. Здесь мы используем простое переход исчезновения, используя Анимированные
API, который интерполизирует атрибут непрозрачности контейнера экрана сетки от 1 до 0.
Теперь, когда мы сделали это, вот как это выглядит:
Не плохо. Мы видим, что сетка исчезает, когда мы двигаемся на экран деталей.
Давайте теперь добавим еще один переход к содержимому экрану детализации, как приходит. Давайте скользим текст в место снизу.
Это сделано путем назначения интерполированного Анимированные
ценность для Перевести
Свойство текстового контейнера.
И вот как это выглядит:
Ну, заголовок и описание скользит очень хорошо, но изображение появляется резко. Это связано с тем, что наш переход не целена для изображения конкретно. Мы исправим это в ближайшее время.
Шаг 2: Переходный слой для общего элемента
Теперь добавляем переходный слой, который появляется во время перехода, и содержит только общий элемент.
Этот слой срабатывает при нажатии изображения в сетке. Он получает информацию о совместном элементе, например, его позиции и размер с экрана сетки, так и экрана деталей.
Шаг 3: анимация в переходном слое
У нас есть информация в переходном уровне об источнике и положении назначения общего элемента. Нам просто нужно их оживить.
Давайте сначала установите элемент на основе исходного положения и размера, затем анимируйте его в место назначения. Это можно сделать двумя способами. Давайте посмотрим на них обоих.
Интерполировать на ширине, высоту, верх и слева
Это простой подход. Если мы хотим, чтобы элемент изменился с одного размера к другому, и из одной позиции в другое, мы изменяем свойства ширины, высоты, топ и левого стиля элемента.
И вот как это выглядит:
Анализ производительности
При использовании анимированных мы объявляем график узлов, которые представляют анимацию, которые мы хотим выполнить, а затем использовать драйвер для обновления анимированного значения с использованием предопределенной кривой.
Вот разбивка шагов для анимации и где это происходит:
- JavaScript: драйвер анимации использует
ProwelsimationFrame
Чтобы выполнить на каждом кадре и обновить значение, которое он приводит к приводу, используя новое значение, которое он рассчитывает на основе кривой анимации. - JavaScript: промежуточные значения рассчитываются и передаются в узел реквизита, который прикреплен к
Вид
Отказ - JavaScript:
Вид
обновляется с помощьюСетнационныеProps
Отказ - JavaScript на родной мост.
- На родной:
UIView
илиAndroid.View
обновляется.
Как видите, большая часть работы происходит на ните JavaScript. Если он заблокирован, анимация пройдет кадры. Это также необходимо пройти через JavaScript на родной мост на каждом раме, чтобы обновить родные представления.
Эта проблема может быть решена с помощью Usenativedriver
Отказ Это перемещает все эти шаги к родным.
Поскольку анимированные производит график анимированных узлов, он может быть сериализован и отправлен на родной только один раз, когда анимация запускается. Это устраняет необходимость обратного вызова в нить JavaScript. Нативный код может позаботиться об обновлении представлений непосредственно на нити UI на каждом кадре.
Основным ограничением является то, что мы можем только анимировать свойства не макета. Такие вещи, как трансформировать
и непрозрачность
Будет работать, но Flexbox и Posither Properties, как, используемая выше, не будет.
Интерполяция при преобразовании и с использованием USENATIVEDIVEDRIVER
Давайте теперь будем анимировать, используя преобразование. Это потребует некоторой математики для расчета масштаба, положения X и Y.
С этой реализацией, если мы масштабируемся от меньшего изображения до более крупного, изображение будет пикселат. Таким образом, мы сделаем увеличенное изображение, затем масштабируйте его до его начального размера, а затем анимируйте его до естественного размера.
Мы можем получить значение начала масштабирования с линейкой JavaScript, как это:
openingScale = sourceDimension.width / destinationDimension.width;
Вы видите, что масштабированное изображение и исходное изображение не выглядят одинаково, что это связано с тем, что соотношение сторон исходного изображения и изображения по назначению различны, поэтому решить его, мы сделаем изображение с соотношением исходного аспекта на основе измерения назначения.
const sourceAspectRatio = source.width / source.height;const destAspectRatio = destination.width / destination.height;
if (aspectRatio - destAspectRatio > 0) { // Landscape image const newWidth = aspectRatio * destination.height; openingScale = source.width / newWidth;} else { // Portrait image const newHeight = destination.width / aspectRatio; openingScale = source.height / newHeight;}
Теперь, когда масштаб верна, нам нужно получить новую позицию на основе изображения назначения. Это может быть рассчитано по позиции назначения минус половины разницы между старым измерением и новым измерением. Который бы приравнивал к:
if (aspectRatio - destAspectRatio > 0) { // Landscape image destination.pageX -= (newWidth - destinationWidth) / 2;} else { // Portrait image destination.pageY -= (newHeight - destinationHeight) / 2;}
Это идеально! Теперь у нас есть правильное измерение, а также позиция для переходного изображения.
Теперь нам нужно рассчитать положение перевода, из которой нужно оживить изображение. Мы масштабируем изображение из центра, поэтому нам нужно применить наш перевод, учитывая, что мы просто перемещаем центр фото. Таким образом, мы просто сделаем сравнительно легкую математику, принимая исходную позицию плюс половину измерения источника. Это приравнивало бы к этому:
const translateInitX = source.pageX + source.width / 2;const translateInitY = source.pageY + source.height / 2;
const translateDestX = destination.pageX + destination.width / 2;const translateDestY = destination.pageY + destination.height / 2;
Теперь мы можем рассчитать положение перевода в разницу между центром исходного изображения и изображения назначения
const openingInitTranslateX = translateInitX - translateDestX;const openingInitTranslateY = translateInitY - translateDestY;
С этим найденным начальным масштабом и переводными значениями мы можем анимировать, используя Анимированные
API.
Вот и все. Теперь у нас есть переходная работа. Теперь мы можем использовать Usenativedriver
Так как мы сейчас анимируем только неразрушивающие свойства.
Шаг 4: Скрытие источника и изображения назначения во время перехода
В предыдущем Гифу мы увидели, что во время перехода нажатое изображение было все еще в том же положении, и изображение назначения появилось до того, как переход был завершен.
Давайте сюжем имидж исходного и назначения во время перехода, так что это
Давайте теперь увидим вывод.
Шаг 5: обрабатывать кнопку назад
Во время перехода на детальный экран с помощью Animated.timing ()
Мы меняем AnimatedValue
от 0 до 1., поэтому, когда нажата кнопка назад,
Вот и все. Вы можете проверить код на Github и попробовать демонстрацию на Экспо Отказ
Narendrashetty/Photo-Gallery-Rn Способствуйте разработку фотогалерея-RN, создавая учетную запись на GitHub. github.com Фотогалерея на Экспо Пустой новый проект экспонция
Также оформить заказ Эрик Висенди ‘s трансляция на общий элемент переход Отказ
Спасибо за то время и прочитав этот пост. Если вы нашли это полезное, пожалуйста, хлопайте и поделитесь им. Вы можете подключиться со мной в Twitter @narendra_shetty Отказ