Membuat titik rekam jepret dengan pengubah inertia

Dalam artikel ini, kami mendalami cara menggunakan fitur InertiaModifier InteractionTracker untuk membuat pengalaman gerakan yang memposisikan ke titik tertentu.

Prasyarat

Di sini, kami berasumsi bahwa Anda terbiasa dengan konsep yang dibahas dalam artikel ini:

Apa itu titik rekam jepret dan mengapa berguna?

Saat membangun pengalaman manipulasi kustom, terkadang akan sangat membantu untuk membuat titik posisi khusus dalam kanvas yang dapat digulir/diperbesar yang akan selalu diam oleh InteractionTracker. Ini sering disebut titik rekam jepret.

Perhatikan dalam contoh berikut bagaimana pengguliran dapat meninggalkan UI dalam posisi canggung di antara gambar yang berbeda:

Menggulir tanpa titik rekam jepret

Jika Anda menambahkan titik jepret, saat Anda berhenti menggulir di antara gambar, titik tersebut "memposisikan" ke posisi tertentu. Dengan titik lekatan, itu membuat pengalaman menggulir gambar jauh lebih bersih dan lebih responsif.

Menggulir dengan satu titik jepret

InteractionTracker dan InertiaModifiers

Saat membangun pengalaman manipulasi yang disesuaikan dengan InteractionTracker, Anda dapat membuat pengalaman gerakan titik jepret dengan menggunakan InertiaModifiers. InertiaModifiers pada dasarnya adalah cara bagi Anda untuk menentukan di mana atau bagaimana InteractionTracker mencapai tujuannya saat memasuki status Inertia. Anda dapat menerapkan InertiaModifiers untuk memengaruhi posisi X atau Y atau Properti skala InteractionTracker.

Ada 3 jenis InertiaModifiers:

  • InteractionTrackerInertiaRestingValue – cara untuk memodifikasi posisi istirahat akhir setelah interaksi atau kecepatan terprogram. Gerakan yang telah ditentukan sebelumnya akan membawa InteractionTracker ke posisi tersebut.
  • InteractionTrackerInertiaMotion – cara untuk menentukan gerakan tertentu yang akan dilakukan InteractionTracker setelah interaksi atau kecepatan terprogram. Posisi akhir akan berasal dari gerakan ini.
  • InteractionTrackerInertiaNaturalMotion – cara untuk menentukan posisi istirahat akhir setelah interaksi atau kecepatan terprogram tetapi dengan animasi berbasis fisika (NaturalMotionAnimation).

Saat memasukkan Inertia, InteractionTracker mengevaluasi setiap InertiaModifiers yang ditetapkan untuknya dan menentukan apakah salah satu dari mereka berlaku. Ini berarti Anda dapat membuat dan menetapkan beberapa InertiaModifiers ke InteractionTracker, Tetapi, saat menentukan masing-masing, Anda perlu melakukan hal berikut:

  1. Tentukan Kondisi – Ekspresi yang menentukan pernyataan kondisional ketika InertiaModifier khusus ini harus berlangsung. Ini sering mengharuskan melihat NaturalRestingPosition InteractionTracker (tujuan yang diberikan inertia default).
  2. Tentukan RestingValue/Motion/NaturalMotion – tentukan Ekspresi Nilai Resting, Ekspresi Gerakan, atau NaturalMotionAnimation yang sebenarnya yang terjadi saat kondisi terpenuhi.

Catatan

Aspek kondisi InertiaModifiers hanya dievaluasi sekali ketika InteractionTracker memasuki Inertia. Namun, hanya untuk InertiaMotion, Ekspresi gerakan dievaluasi setiap bingkai untuk pengubah yang kondisinya benar.

Contoh

Sekarang mari kita lihat bagaimana Anda dapat menggunakan InertiaModifiers untuk membuat beberapa pengalaman titik jepret untuk membuat ulang kanvas gulir gambar. Dalam contoh ini, setiap manipulasi dimaksudkan untuk berpotensi bergerak melalui satu gambar - ini sering disebut sebagai Single Mandatory Snap Points.

Mari kita mulai dengan menyiapkan InteractionTracker, VisualInteractionSource, dan Ekspresi yang akan memanfaatkan posisi 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);
}

Selanjutnya, karena perilaku Single Mandatory Snap Point akan memindahkan konten ke atas atau ke bawah, Anda akan memerlukan dua pengubah inertia yang berbeda: yang memindahkan konten Yang Dapat Digulir ke atas, dan yang memindahkannya ke bawah.

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

Apakah akan memposisikan ke atas atau ke bawah ditentukan berdasarkan di mana InteractionTracker secara alami akan mendarat dalam relatif terhadap jarak jepret - jarak antara lokasi snap. Jika melewati titik setengah, maka snap down, jika tidak snap up. (Dalam contoh ini, Anda menyimpan jarak jepret dalam PropertySet)

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

Diagram ini memberikan deskripsi visual untuk logika yang sedang terjadi:

Diagram pengubah inertia

Sekarang Anda hanya perlu menentukan Nilai Istirahat untuk setiap InertiaModifier: pindahkan posisi InteractionTracker ke posisi snap sebelumnya atau yang berikutnya.

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

Terakhir, tambahkan InertiaModifiers ke InteractionTracker. Sekarang ketika InteractionTracker memasukinya adalah InertiaState, itu akan memeriksa kondisi InertiaModifiers Anda untuk melihat apakah posisinya harus dimodifikasi.

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