Поделиться через


Анимации на основе отношений

В этой статье представлен краткий обзор того, как создавать анимацию на основе зависимостей с помощью Composition ExpressionAnimations.

Динамические интерфейсы на основе реляционных отношений

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

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

Орбитальный круг

Представление списка с параллаксом

Использование ExpressionAnimations

Чтобы создать анимации движения, основанные на выражениях, используйте тип ExpressionAnimation. ExpressionAnimations (или Expressions for short) — это новый тип анимации, который позволяет выразить математические отношения — связь, которая используется системой для вычисления значения свойства анимации каждого кадра. Другими словами, выражения — это просто математическое уравнение, определяющее требуемое значение свойства анимации для каждого кадра. Выражения — это очень универсальный компонент, который можно использовать в различных сценариях, в том числе:

При работе с ExpressionAnimations есть несколько вещей, которые стоит упомянуть заранее:

  • Никогда не заканчивается — в отличие от его брата KeyFrameAnimation, выражения не имеют конечной длительности. Поскольку выражения являются математическими связями, они являются анимациями, которые постоянно "выполняются". Вы можете остановить эти анимации при выборе.
  • Выполнение, но не всегда оценка — производительность всегда связана с анимациями, которые постоянно выполняются. Нет необходимости беспокоиться, система достаточно умна, чтобы выражение будет переоцениваться только в случае, если изменятся какие-либо из его входных данных или параметров.
  • Разрешение правильного типа объекта. Так как выражения являются математическими связями, важно убедиться, что уравнение, определяющее выражение, разрешается в том же типе свойства, который предназначен для анимации. Например, если вы анимируете смещение, то выражение должно вычисляться в тип Vector3.

Компоненты выражения

При построении математической связи выражения существует несколько основных компонентов:

  • Параметры — значения, представляющие постоянные значения или ссылки на другие объекты Композиции.
  • Математические операторы — типичные математические операторы plus(+), минус(-), умножение(*), деление(/), которые объединяют параметры для формирования уравнения. Также включены условные операторы, такие как больше (>), равно (==), тернарный оператор (condition ? ifTrue : ifFalse) и т. д.
  • Математические функции — математические функции и сочетания клавиш на основе System.Numerics. Полный список поддерживаемых функций см. в разделе ExpressionAnimation.

Выражения также поддерживают набор ключевых слов — специальные фразы, имеющие определенное значение только в системе ExpressionAnimation. Они перечислены (а также полный список математических функций) в документации ExpressionAnimation.

Создание выражений с помощью ExpressionBuilder

Существует два варианта создания выражений в приложении WinUI:

  1. Создайте уравнение в виде строки через официальный общедоступный API.
  2. Создайте уравнение в типобезопасной объектной модели с помощью средства ExpressionBuilder, включенного в набор средств сообщества Windows.

Для этого документа мы определим выражения с помощью ExpressionBuilder.

Параметры

Параметры составляют ядро выражения. Существует два типа параметров:

  • Константы: это параметры, представляющие типизированные переменные System.Numeric. Эти параметры получают значения, назначенные один раз при запуске анимации.
  • Ссылки: это параметры, представляющие ссылки на CompositionObjects. Эти параметры постоянно обновляют свои значения после запуска анимации.

Как правило, ссылки являются основным аспектом динамического изменения выходных данных выражения. По мере изменения этих ссылок результат выражения изменяется. Если вы создаете выражение со строками или используете их в сценарии шаблонизации (с целью нацеливания на несколько CompositionObjects), необходимо указать и задать значения ваших параметров. Дополнительные сведения см. в разделе "Пример".

Работа с KeyFrameAnimations

Выражения также можно использовать с keyFrameAnimations. В этих случаях нужно применять выражение для определения значения ключевого кадра в определенный момент времени – такие ключевые кадры называются ExpressionKeyFrames.

KeyFrameAnimation.InsertExpressionKeyFrame(Single, String)
KeyFrameAnimation.InsertExpressionKeyFrame(Single, ExpressionNode)

Однако, в отличие от ExpressionAnimations, ExpressionKeyFrames оцениваются только один раз при запуске анимации с ключевыми кадрами. Помните, что вы не передаете ExpressionAnimation в качестве значения ключевого кадра, а строку (или ExpressionNode, если вы используете ExpressionBuilder).

Пример

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

Орбитальный круг

Существует три компонента в игре для общего опыта:

  1. Ключевая анимация, анимирующая ось Y красного шара.
  2. Свойство PropertySet с параметром Rotation, которое помогает управлять орбитой, анимируемой другим KeyFrameAnimation.
  3. Анимация выражений, которая управляет смещением синего шара, ссылающаяся на смещение Красного шара и свойство поворота для поддержания идеальной орбиты.

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

В этом уравнении есть два свойства, на которые необходимо ссылаться из PropertySet; одно — это смещение по центру, а другое — поворот.

var propSetCenterPoint =
_propertySet.GetReference().GetVector3Property("CenterPointOffset");

// This rotation value will animate via KFA from 0 -> 360 degrees
var propSetRotation = _propertySet.GetReference().GetScalarProperty("Rotation");

Затем необходимо определить компонент Vector3, который учитывает фактическое поворот орбиты.

var orbitRotation = EF.Vector3(
    EF.Cos(EF.ToRadians(propSetRotation)) * 150,
    EF.Sin(EF.ToRadians(propSetRotation)) * 75, 0);

Замечание

EF — это сокращённая форма 'using' для определения функций ExpressionFunctions из библиотеки построителя выражений WinUI.

Наконец, объедините эти компоненты вместе и ссылайтесь на позицию Красного шара, чтобы определить математическую зависимость.

var orbitExpression = redSprite.GetReference().Offset + propSetCenterPoint + orbitRotation;
blueSprite.StartAnimation("Offset", orbitExpression);

В гипотетической ситуации, что если бы вы хотели использовать это же выражение, но с двумя другими визуальными элементами, то есть 2 набора орбитальных кругов. С помощью CompositionAnimations можно повторно применить анимацию и нацеливаться на несколько объектов CompositionObjects. Единственное, что необходимо изменить при использовании этого выражения для дополнительного варианта орбиты — ссылка на Visual. Мы называем это шаблонизацией.

В этом случае вы изменяете созданное ранее выражение. Вместо того, чтобы получить ссылку на CompositionObject, создайте ссылку с именем, а затем назначьте разные значения:

var orbitExpression = ExpressionValues.Reference.CreateVisualReference("orbitRoundVisual");
orbitExpression.SetReferenceParameter("orbitRoundVisual", redSprite);
blueSprite.StartAnimation("Offset", orbitExpression);
// Later on … use same Expression to assign to another orbiting Visual
orbitExpression.SetReferenceParameter("orbitRoundVisual", yellowSprite);
greenSprite.StartAnimation("Offset", orbitExpression);

Ниже приведен код, если вы определили выражение со строками через общедоступный API.

ExpressionAnimation expressionAnimation = compositor.CreateExpressionAnimation("visual.Offset + " +
    "propertySet.CenterPointOffset + " +
    "Vector3(cos(ToRadians(propertySet.Rotation)) * 150," + "sin(ToRadians(propertySet.Rotation)) * 75, 0)");
    
var propSetCenterPoint = _propertySet.GetReference().GetVector3Property("CenterPointOffset");
var propSetRotation = _propertySet.GetReference().GetScalarProperty("Rotation");
expressionAnimation.SetReferenceParameter("propertySet", _propertySet);
expressionAnimation.SetReferenceParameter("visual", redSprite);