Udostępnij przez


Tworzenie punktów przyciągania za pomocą modyfikatorów inercji

W tym artykule dokładnie przyjrzymy się, jak używać funkcji InertiaModifier w InteractionTracker, aby tworzyć doświadczenia ruchu przyciągające do określonego punktu.

Wymagania wstępne

W tym miejscu przyjęto założenie, że znasz pojęcia omówione w następujących artykułach:

Co to są punkty zatrzasku i dlaczego są przydatne?

Podczas tworzenia niestandardowych środowisk manipulowania czasami warto utworzyć wyspecjalizowane punkty położenia w kanwie z możliwością przewijania/powiększania, w której zawsze będzie spoczywać element InteractionTracker. Często nazywa się je punktami przyciągania .

Zwróć uwagę na to, że w poniższym przykładzie przewijanie może pozostawić interfejs użytkownika w niezręcznej pozycji między różnymi obrazami:

przewijanie bez punktów przyciągania

Gdy dodasz punkty przyciągania, po zatrzymaniu przewijania między obrazami, zostaną one automatycznie przesunięte do określonej pozycji. Dzięki punktom przyciągania przewijanie obrazów jest znacznie czystsze i bardziej reaktywne.

przewijanie z pojedynczym punktem przyciągania

InteractionTracker i InertiaModifiers

Podczas tworzenia dostosowanych doświadczeń manipulacji za pomocą rozwiązania InteractionTracker, można tworzyć doświadczenia ruchu z punktami przyciągania, korzystając z modułów InertiaModifiers. InertiaModifiers są zasadniczo sposobem na zdefiniowanie miejsca lub w jaki sposób obiekt InteractionTracker dociera do miejsca docelowego podczas wprowadzania stanu inercji. Można zastosować modyfikatory bezwładności, aby wpłynąć na położenie X lub Y albo właściwości skali elementu InteractionTracker.

Istnieją 3 typy InertiaModifierów:

  • InteractionTrackerInertiaRestingValue — sposób modyfikowania końcowej pozycji spoczynku po interakcji lub szybkości programowej. Wstępnie zdefiniowany ruch spowoduje przejście InteractionTracker na tę pozycję.
  • InteractionTrackerInertiaMotion — sposób definiowania określonego ruchu, który InteractionTracker wykona po interakcji lub przy prędkości programowo ustalonej. Ostateczne stanowisko będzie pochodzić z tego wniosku.
  • InteractionTrackerInertiaNaturalMotion — sposób definiowania końcowej pozycji spoczynku po interakcji lub prędkości programowej, ale z animacją opartą na fizyce (NaturalMotionAnimation).

Podczas wprowadzania inercji funkcja InteractionTracker ocenia każdy z przypisanych do niego modułów InertiaModifiers i określa, czy którykolwiek z nich ma zastosowanie. Oznacza to, że można utworzyć i przypisać wiele modułów InertiaModifiers do elementu InteractionTracker, ale podczas definiowania każdego z nich należy wykonać następujące czynności:

  1. Określ warunek – wyrażenie, które definiuje instrukcję warunkową, kiedy powinien być użyty ten konkretny InertiaModifier. Często wymaga to przyjrzenia się NaturalRestingPosition w InteractionTracker (docelowej pozycji przy domyślnej inercji).
  2. Zdefiniuj RestingValue/Motion/NaturalMotion — określ, jakie dokładnie wyrażenie Resting Value, wyrażenie Motion czy NaturalMotionAnimation ma miejsce po spełnieniu warunku.

Uwaga / Notatka

Aspekt warunku modułu InertiaModifiers jest obliczany tylko raz, gdy moduł InteractionTracker przechodzi w inercję. Jednak tylko w przypadku InertiaMotion wyrażenie ruchu jest przeliczane dla modyfikatora w każdej klatce, jeśli jego warunek jest spełniony.

Przykład

Teraz przyjrzyjmy się, jak za pomocą InertiaModifiers utworzyć kilka efektów punktów przyciągania, aby odtworzyć płótno przewijania obrazów. W tym przykładzie każda manipulacja ma na celu potencjalnie przejście przez pojedynczy obraz — jest to często nazywane pojedynczymi obowiązkowymi punktami przyciągania.

Zacznijmy od skonfigurowania elementu InteractionTracker, elementu VisualInteractionSource oraz wyrażenia, które będzie wykorzystywać pozycję InteractionTracker.

private void SetupInput()
{
    _tracker = InteractionTracker.Create(_compositor);
    _tracker.MinPosition = new Vector3(0f);
    _tracker.MaxPosition = new Vector3(3000f);

    _source = VisualInteractionSource.Create(_root);
    _source.ManipulationRedirectionMode =
        VisualInteractionSourceRedirectionMode.CapableTouchpadOnly;
    _source.PositionYSourceMode = InteractionSourceMode.EnabledWithInertia;
    _tracker.InteractionSources.Add(_source);

    var scrollExp = _compositor.CreateExpressionAnimation("-tracker.Position.Y");
    scrollExp.SetReferenceParameter("tracker", _tracker);
    ElementCompositionPreview.GetElementVisual(scrollPanel).StartAnimation("Offset.Y", scrollExp);
}

Następnie, ponieważ zachowanie pojedynczego obowiązkowego punktu przyciągania powoduje przenoszenie zawartości w górę lub w dół, potrzebujesz dwóch różnych modyfikatorów inercji: jednego, który przesuwa zawartość przewijalną w górę, i drugiego, który przesuwa ją w dół.

// Snap-Point to move the content up
var snapUpModifier = InteractionTrackerInertiaRestingValue.Create(_compositor);
// Snap-Point to move the content down
var snapDownModifier = InteractionTrackerInertiaRestingValue.Create(_compositor);

Określa, czy przyciągać w górę, czy w dół, w zależności od tego, gdzie InteractionTracker naturalnie wylądowałby w stosunku do odległości przyciągania — odległości między lokalizacjami przyciągania. Jeśli minęło się połowę drogi, zatrzaśnij w dół, w przeciwnym razie zatrzaśnij w górę. (W tym przykładzie przechowujesz odległość przyciągania w zestawie właściwości)

// Is NaturalRestingPosition less than the halfway point between Snap Points?
snapUpModifier.Condition = _compositor.CreateExpressionAnimation(
"this.Target.NaturalRestingPosition.y < (this.StartingValue - " + 
"mod(this.StartingValue, prop.snapDistance) + prop.snapDistance / 2)");
snapUpModifier.Condition.SetReferenceParameter("prop", _propSet);
// Is NaturalRestingPosition greater than the halfway point between Snap Points?
snapDownModifier.Condition = _compositor.CreateExpressionAnimation(
"this.Target.NaturalRestingPosition.y >= (this.StartingValue - " + 
"mod(this.StartingValue, prop.snapDistance) + prop.snapDistance / 2)");
snapDownModifier.Condition.SetReferenceParameter("prop", _propSet);

Ten diagram przedstawia wizualny opis logiki, która się dzieje:

Diagram modyfikatora inercji

Teraz wystarczy zdefiniować wartości spoczynkowe dla każdego InertiaModifier: przenieś pozycję InteractionTracker do poprzedniej pozycji przyciągania lub do następnej.

snapUpModifier.RestingValue = _compositor.CreateExpressionAnimation(
"this.StartingValue - mod(this.StartingValue, prop.snapDistance)");
snapUpModifier.RestingValue.SetReferenceParameter("prop", _propSet);
snapDownModifier.RestingValue = _compositor.CreateExpressionAnimation(
"this.StartingValue + prop.snapDistance - mod(this.StartingValue, " + 
"prop.snapDistance)");
snapDownModifier.RestingValue.SetReferenceParameter("prop", _propSet);

Na koniec dodaj moduły InertiaModifiers do elementu InteractionTracker. Gdy InteractionTracker wchodzi w stan InertiaState, sprawdza warunki modułów InertiaModifiers, aby ocenić, czy jego pozycja powinna być zmieniona.

var modifiers = new InteractionTrackerInertiaRestingValue[] { 
snapUpModifier, snapDownModifier };
_tracker.ConfigurePositionYInertiaModifiers(modifiers);