Udostępnij za pośrednictwem


Animacje oparte na relacjach

Ten artykuł zawiera krótkie omówienie, jak tworzyć animacje oparte na relacjach za pomocą kompozycji ExpressionAnimations.

Dynamiczne środowiska oparte na relacjach

Podczas kompilowania środowisk ruchu w aplikacji występują czasy, gdy ruch nie jest oparty na czasie, ale raczej zależny od właściwości na innym obiekcie. KeyFrameAnimations nie są w stanie łatwo wyrazić tego typu doświadczeń ruchu. W tych konkretnych przypadkach ruch nie musi już być dyskretny i wstępnie zdefiniowany. Zamiast tego ruch może dynamicznie dostosowywać się na podstawie relacji z innymi właściwościami obiektu. Można na przykład animować nieprzezroczystość obiektu na podstawie jego położenia poziomego. Inne przykłady to doświadczenia ruchu, takie jak Sticky Headers i Parallax.

Te typy doświadczeń ruchowych umożliwiają tworzenie interfejsu użytkownika, który wydaje się bardziej zintegrowany, zamiast być postrzeganym jako pojedynczy i niezależny. Dla użytkownika jest to wrażenie dynamicznego środowiska interfejsu użytkownika.

Koło orbitujące

Widok listy z efektem paralaksy

Używanie animacji wyrażeń

Aby tworzyć doświadczenia ruchowe oparte na relacjach, użyj typu ExpressionAnimation. ExpressionAnimations (lub Expressions dla skrótu) to nowy rodzaj animacji, który pozwala wyrazić zależność matematyczną — zależność używaną przez system do obliczania wartości właściwości animowanej w każdej klatce. Mówiąc inaczej, wyrażenia są po prostu równaniem matematycznym, które definiuje żądaną wartość właściwości animowania na ramkę. Wyrażenia są bardzo wszechstronnym składnikiem, który może być używany w wielu różnych scenariuszach, w tym:

Podczas pracy z aplikacją ExpressionAnimations warto wspomnieć o kilku rzeczach z góry:

  • Never Ending — w przeciwieństwie do swojego odpowiednika, KeyFrameAnimation, Expression nie mają skończonego czasu trwania. Ponieważ wyrażenia są relacjami matematycznymi, są to animacje, które są stale "uruchomione". Jeśli wybierzesz, możesz zatrzymać te animacje.
  • Uruchamianie, ale nie zawsze ocenianie — wydajność jest zawsze problemem z animacjami, które stale działają. Nie trzeba się jednak martwić, że system jest wystarczająco inteligentny, że wyrażenie będzie ponownie oceniać tylko wtedy, gdy którykolwiek z jego danych wejściowych lub parametrów uległ zmianie.
  • Rozpoznawanie odpowiedniego typu obiektu — ponieważ wyrażenia są relacjami matematycznymi, ważne jest, aby upewnić się, że równanie definiujące wyrażenie jest rozpoznawane jako ten sam typ właściwości objętej animacją. Na przykład, jeśli animujesz przesunięcie, jego wyrażenie powinno przyjmować wartość typu Vector3.

Składniki wyrażenia

Podczas tworzenia relacji matematycznej wyrażenia istnieje kilka podstawowych składników:

  • Parameters — wartości reprezentujące wartości stałe lub odwołania do innych obiektów Kompozycji.
  • Operatory matematyczne — typowe operatory matematyczne plus(+), minus(-), pomnożące(*), divide(/), które łączą parametry w celu utworzenia równania. Uwzględniane są również operatory warunkowe, takie jak większe niż (>), równe (==), operator trójargumentowy (warunek ? jeśliPrawda : jeśliFałsz) itp.
  • Funkcje matematyczne — funkcje matematyczne/skróty oparte na system.numerics. Aby uzyskać pełną listę obsługiwanych funkcji, zobacz ExpressionAnimation.

Wyrażenia obsługują również zestaw słów kluczowych — frazy specjalne, które mają odrębne znaczenie tylko w systemie ExpressionAnimation. Są one wymienione (wraz z pełną listą funkcji matematycznych) w dokumentacji ExpressionAnimation .

Tworzenie wyrażeń za pomocą programu ExpressionBuilder

Istnieją dwie opcje tworzenia wyrażeń w aplikacji WinUI:

  1. Skompiluj równanie jako ciąg za pomocą oficjalnego publicznego interfejsu API.
  2. Zbuduj równanie w modelu obiektowym z bezpiecznym typem za pomocą narzędzia ExpressionBuilder dołączonego do Windows Community Toolkit.

Na potrzeby tego dokumentu zdefiniujemy nasze wyrażenia przy użyciu programu ExpressionBuilder.

Parametry

Parametry składają się na rdzeń wyrażenia. Istnieją dwa typy parametrów:

  • Stałe: są to parametry, które reprezentują zmienne typowane w System.Numeric. Te parametry pobierają wartości przypisane raz po rozpoczęciu animacji.
  • Odwołania: są to parametry reprezentujące odwołania do obiektów CompositionObjects — te parametry są stale aktualizowane po rozpoczęciu animacji.

Ogólnie rzecz biorąc, odwołania są głównym aspektem sposobu dynamicznego zmieniania danych wyjściowych wyrażenia. W miarę zmiany tych odwołań dane wyjściowe wyrażenia zmieniają się w wyniku. Jeśli utworzysz wyrażenie z ciągami lub użyjesz ich w scenariuszu tworzenia szablonów (przy użyciu wyrażenia do celowania w wiele obiektów CompositionObjects), będziesz musiał nazwać i ustawić wartości parametrów. Aby uzyskać więcej informacji, zobacz sekcję Przykład.

Praca z elementami KeyFrameAnimation

Wyrażenia mogą być również używane z elementami KeyFrameAnimation. W takich przypadkach chcesz użyć wyrażenia, aby zdefiniować wartość klatki kluczowej w danym momencie czasu — tego typu klatki kluczowe nazywane są ExpressionKeyFrames.

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

Jednak w przeciwieństwie do ExpressionAnimations, ExpressionKeyFrames są obliczane tylko raz po uruchomieniu animacji KeyFrameAnimation. Pamiętaj, że jako wartość elementu KeyFrame przekazujesz nie element ExpressionAnimation, lecz ciąg (lub ExpressionNode, jeśli korzystasz z ExpressionBuilder).

Przykład

Przyjrzyjmy się teraz przykładowi użycia wyrażeń, w szczególności przykładu PropertySet z galerii przykładów interfejsu użytkownika systemu Windows. Przyjrzymy się wyrażeniu zarządzającemu ruchem orbitalnym niebieskiej piłki.

Koło orbitujące

Istnieją trzy składniki, które wpływają na ogólne doświadczenie.

  1. KeyFrameAnimation, animujący przesunięcie Y czerwonej piłki.
  2. PropertySet z właściwością Rotation, która napędza orbitę animowaną przez inną animację KeyFrameAnimation.
  3. ExpressionAnimation, który steruje przesunięciem niebieskiej piłki, korzysta z przesunięcia Czerwonej Piłki i właściwości obrotu, aby utrzymać idealną orbitę.

Skupimy się na funkcji ExpressionAnimation zdefiniowanej w pliku #3. Będziemy również używać klas ExpressionBuilder do konstruowania tego wyrażenia. Kopia kodu używanego do tworzenia tego doświadczenia za pomocą Strings jest wymieniona na końcu.

W tym równaniu istnieją dwie właściwości, do których należy odwołać się z zestawu właściwości; jeden jest przesunięciem punktu środkowego, a drugi to obrót.

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

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

Następnie należy zdefiniować składnik Vector3, który odpowiada rzeczywistej rotacji orbitowania.

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

Uwaga / Notatka

EF jest skróconą notacją "using" służącą do definiowania ExpressionFunctions z biblioteki konstruktora wyrażeń WinUI.

Na koniec połącz te składniki i odwołaj się do pozycji Czerwonej Kuli, aby zdefiniować relację matematyczną.

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

W hipotetycznej sytuacji, co jeśli chcesz użyć tego samego wyrażenia, ale z dwoma innymi wizualizacjami, co oznacza 2 zestawy okręgów orbitujących. Za pomocą CompositionAnimations można ponownie użyć animacji i zastosować ją do wielu obiektów CompositionObjects. Jedyną rzeczą, którą musisz zmienić, gdy używasz tego wyrażenia dla dodatkowego przypadku orbity, jest odniesienie do elementu wizualnego. Nazywamy to tworzeniem szablonów.

W tym przypadku zmodyfikujesz utworzone wcześniej wyrażenie. Zamiast "uzyskać" odwołanie do obiektu CompositionObject, należy utworzyć odwołanie o nazwie, a następnie przypisać różne wartości:

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);

Oto kod, jeśli wyrażenie zostało zdefiniowane za pomocą ciągów za pośrednictwem publicznego interfejsu 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);