다음을 통해 공유


관성 조절자를 사용하여 스냅 포인트 만들기

이 문서에서는 InteractionTracker의 InertiaModifier 기능을 사용하여 지정된 지점에 맞춰 동작 환경을 만드는 방법에 대해 자세히 알아보세요.

필수 조건

여기서는 다음 문서에서 설명하는 개념을 잘 알고 있다고 가정합니다.

스냅 포인트란 무엇이며 왜 유용한가요?

사용자 지정 조작 환경을 빌드할 때 InteractionTracker가 항상 휴식을 취할 수 있는 스크롤 가능/확대/축소 가능한 캔버스 내에서 특수한 위치 지점을 만드는 것이 도움이 될 수 있습니다. 이러한 것들을 끌기 지점이라고도 합니다.

다음 예제에서는 스크롤로 인해 UI가 다양한 이미지 사이에서 어색한 위치에 놓일 수 있음을 확인할 수 있습니다.

스냅 포인트 없이 스크롤

"스냅 지점을 추가하면 이미지 간 스크롤을 멈출 때 지정된 위치로 '스냅'됩니다." 스냅 포인트를 사용하면 이미지를 스크롤하는 환경이 훨씬 더 명확하고 반응성이 뛰어납니다.

단일 스냅 지점을 사용하여 스크롤

InteractionTracker 및 InertiaModifiers

InteractionTracker를 사용하여 사용자 지정된 조작 환경을 빌드할 때 InertiaModifiers를 활용하여 스냅포인트 동작 환경을 만들 수 있습니다. InertiaModifiers는 본질적으로 관성 상태를 입력할 때 InteractionTracker가 대상에 도달하는 위치 또는 방법을 정의하는 방법입니다. InertiaModifiers를 적용하여 InteractionTracker의 X 또는 Y 위치 또는 배율 속성에 영향을 미칠 수 있습니다.

InertiaModifiers에는 다음과 같은 세 가지 유형이 있습니다.

  • InteractionTrackerInertiaRestingValue – 상호 작용 또는 프로그래밍 속도 후 최종 휴식 위치를 수정하는 방법입니다. 미리 정의된 동작은 InteractionTracker를 해당 위치로 이동합니다.
  • InteractionTrackerInertiaMotion – 상호 작용 또는 프로그래밍 속도 후에 InteractionTracker가 수행하는 특정 동작을 정의하는 방법입니다. 최종 위치는 이 동작에서 파생됩니다.
  • InteractionTrackerInertiaNaturalMotion – 상호 작용 또는 프로그래밍 속도 후에 물리학 기반 애니메이션(NaturalMotionAnimation)을 사용하여 최종 휴식 위치를 정의하는 방법입니다.

관성 상태에 들어갈 때, InteractionTracker는 할당된 각 관성 수정자를 평가하여 어느 것이 적용될 수 있는지를 결정합니다. 즉, InteractionTracker에 여러 InertiaModifiers를 만들고 할당할 수 있지만 각각을 정의할 때 다음을 수행해야 합니다.

  1. 조건 정의 - 이 특정 InertiaModifier가 발생할 때 조건문을 정의하는 식입니다. 이를 위해서는 InteractionTracker의 NaturalRestingPosition(기본 관성이 지정된 대상)을 살펴보는 것이 필요한 경우가 많습니다.
  2. 휴식 값/동작/자연 동작 정의 – 조건이 충족될 때 발생하는 실제 휴식 값 수식, 동작 수식 또는 자연 동작 애니메이션을 정의합니다.

비고

InertiaModifiers의 조건 측면은 InteractionTracker가 관성 상태에 들어갈 때 한 번만 평가됩니다. 그러나 InertiaMotion의 경우에만, 조건이 true인 모디파이어에 대해 매 프레임마다 동작 표현식이 평가됩니다.

예시

이제 InertiaModifiers를 사용하여 이미지 스크롤용 캔버스를 재현하는 몇 가지 스냅 포인트 경험들을 만드는 방법을 살펴보겠습니다. 이 예제에서 각 조작은 단일 이미지를 통해 이동할 수 있습니다. 이를 단일 필수 스냅 포인트라고도 합니다.

먼저 InteractionTracker와 VisualInteractionSource를 설정하고, 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);
}

다음으로, 단일 필수 스냅 포인트 동작은 콘텐츠를 위로 또는 아래로 이동시킬 수 있기 때문에, 스크롤 가능한 콘텐츠를 위로 이동시키기 위한 관성 수정자와 아래로 이동시키기 위한 관성 수정자의 두 가지가 필요합니다.

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

위쪽 또는 아래쪽 맞춤 여부는 InteractionTracker가 스냅 거리를 기준으로 자연스럽게 착륙하는 위치(스냅 위치 간 거리)에 따라 결정됩니다. 중간 지점을 지나면 아래로 스냅하고, 그렇지 않으면 스냅업합니다. (이 예제에서는 스냅 거리를 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);

이 다이어그램은 발생하는 논리에 대한 시각적 설명을 제공합니다.

관성 한정자 다이어그램

이제 각 InertiaModifier에 대해 Resting Values를 정의하면 됩니다. InteractionTracker의 위치를 이전 스냅 위치로 이동하거나 다음 위치로 이동합니다.

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

마지막으로 InteractionTracker에 InertiaModifiers를 추가합니다. 이제 InteractionTracker가 InertiaState로 들어가면 InertiaModifiers의 조건을 확인하여 위치를 수정해야 하는지 확인합니다.

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