키 프레임 애니메이션 및 감속/가속 함수 애니메이션

선형 키 프레임 애니메이션, KeySpline 값이 있는 키 프레임 애니메이션 또는 감속/가속 함수는 거의 동일한 시나리오에 대한 세 가지 기술로, 좀 더 복잡하며 시작 상태에서 종료 상태까지 비선형 애니메이션 동작을 사용하는 스토리보드 애니메이션을 생성합니다.

필수 조건

스토리보드 애니메이션 주제를 읽어 보십시오. 이 주제는 스토리보드 애니메이션에 설명된 애니메이션 개념을 기반으로 하며, 다시는 다루지 않습니다. 예를 들어 스토리보드 애니메이션에서는 대상 애니메이션 설정 방법, 리소스로서의 스토리보드, Timeline 속성 값인 Duration, FillBehavior 등에 대해 설명합니다.

키 프레임 애니메이션을 사용하는 애니메이션 효과

키 프레임 애니메이션을 사용하면 애니메이션 타임라인의 한 지점에서 도달하는 목푯값이 두 개 이상일 수 있습니다. 즉, 각 키 프레임에서 다른 중간 값을 지정할 수 있으며 마지막에 도달한 키 프레임이 최종 애니메이션 값입니다. 애니메이션 효과를 주도록 여러 값을 지정하면 더 복잡한 애니메이션을 만들 수 있습니다. 또한 키 프레임 애니메이션은 애니메이션 유형마다 다른 KeyFrame 하위 클래스로 구현되는 다양한 보간 논리를 사용하도록 설정합니다. 특히 각 키 프레임 애니메이션 유형에는 키 프레임 지정을 위해 Discrete, Linear, SplineEasingKeyFrame 클래스에 대한 변형이 있습니다. 예를 들어 Double을 대상으로 하고 키 프레임을 사용하는 애니메이션을 지정하려면 DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame, EasingDoubleKeyFrame으로 키 프레임을 선언할 수 있습니다. 단일 KeyFrames 컬렉션 내에서 이러한 유형을 모두 사용하여 새 키 프레임에 도달할 때마다 보간을 변경할 수 있습니다.

보간 동작의 경우 각 키 프레임은 KeyTime 시간에 도달할 때까지 보간을 제어합니다. 해당 Value 또한 해당 시간에 도달합니다. 그 이후 키 프레임이 더 있을 때에는 그 값이 시퀀스의 다음 키 프레임 시작 값이 됩니다.

애니메이션 시작 시점에 KeyTime이 "0:0:0"인 키 프레임이 없으면 속성의 애니메이션 효과가 적용되지 않은 값이 시작 값이 됩니다. 이 방식은 From/To/By 애니메이션이 From이 없을 때 작동하는 방식과 유사합니다.

키 프레임 애니메이션의 지속 기간은 암시적으로 해당 키 프레임에서 설정된 가장 큰 KeyTime 값과 같습니다. 원하는 경우 명시적인 Duration을 설정할 수 있지만 키 프레임의 KeyTime보다 짧은 경우 애니메이션의 일부가 잘릴 수 있으므로 주의하십시오.

Duration 외에 키 프레임 애니메이션의 Timeline 기반 속성도 설정할 수 있습니다. From/To/By 애니메이션과 마찬가지로 키 프레임 애니메이션 클래스 또한 Timeline에서 파생되었기 때문입니다. 이는 다음과 같습니다.

  • AutoReverse: 마지막 키 프레임에 도달하면 프레임이 끝에서부터 반대로 반복됩니다. 이렇게 하면 애니메이션의 명확한 기간이 두 배로 늘어납니다.
  • BeginTime: 애니메이션 시작을 지연합니다. 프레임의 KeyTime 값에 대한 타임라인은 BeginTime에 도달할 때까지 카운트가 시작되지 않으므로 프레임이 잘려나갈 위험이 없습니다.
  • FillBehavior: 마지막 키 프레임에 도달할 때 발생하는 상황을 제어합니다. FillBehavior 는 중간 키 프레임에 영향을 주지 않습니다.
  • RepeatBehavior:
    • Forever로 설정되어 있는 경우 키 프레임 및 타임라인이 무한히 반복됩니다.
    • 반복 카운트를 설정하면 타임라인이 해당 횟수만큼 반복됩니다.
    • Duration으로 설정하면 해당 시간에 도달할 때까지 타임라인이 반복됩니다. 이렇게 하면 타임라인의 암시적 지속 시간이 정수가 아닌 경우 키 프레임 시퀀스 중간에 애니메이션이 변경될 수 있습니다.
  • SpeedRatio(일반적으로 사용되지 않음)

선형 키 프레임

선형 키 프레임은 프레임의 KeyTime에 도달할 때까지 값에 대해 단순 선형 보간을 생성합니다. 이 보간 동작은 앞서 스토리보드 애니메이션 주제에서 설명한 간단한 From/To/By 애니메이션과 가장 유사합니다.

다음은 선형 키 프레임을 통해 키 프레임 애니메이션을 사용하여 직사각형의 렌더링 높이를 조절하는 방법입니다. 이 예제에서는 처음 4초 동안 직사각형의 높이가 약간 선형으로 증가하는 애니메이션을 실행한 다음 마지막 1초 동안 직사각형이 시작 높이의 두 배가 될 때가지 빠르게 크기를 조절하는 애니메이션을 실행합니다.

<StackPanel>
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimationUsingKeyFrames
              Storyboard.TargetName="myRectangle"
              Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                <LinearDoubleKeyFrame Value="1.2" KeyTime="0:0:4"/>
                <LinearDoubleKeyFrame Value="2" KeyTime="0:0:5"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </StackPanel.Resources>
</StackPanel>

불연속 키 프레임

불연속 키 프레임은 보간을 전혀 사용하지 않습니다. KeyTime에 도달하면 새로운 Value가 적용됩니다. 애니메이션 효과를 주는 UI 속성에 따라 '건너뛰기'로 표시되는 애니메이션이 생성되는 경우가 많습니다. 정확히 필요한 심미적 동작인지 확인하십시오. 선언하는 키 프레임 수를 늘려 명백한 건너뛰기를 최소화할 수 있지만, 부드러운 애니메이션이 목표인 경우 선형 또는 스플라인 키 프레임을 대신 사용하는 것이 더 나을 수 있습니다.

참고 항목

불연속 키 프레임은 Double, PointColor 형식이 아닌 값에 DiscreteObjectKeyFrame으로 애니메이션 효과를 주는 유일한 방법입니다. 이번 주제의 뒷부분에서 DSC에 대해 자세히 설명합니다.

스플라인 키 프레임

스플라인 키 프레임은 KeySpline 속성의 값에 따라 값 사이의 가변 전환을 만듭니다. 이 속성은 애니메이션의 가속을 설명하는 Bezier 곡선의 첫 번째 및 두 번째 제어점을 지정합니다. 기본적으로 KeySpline은 함수-시간 그래프가 해당 베지어 곡선의 모양이 되는 시간에 따른 함수 관계를 정의합니다. 일반적으로 KeySpline 값은 네 개의 Double 값이 공백 또는 쉼표로 구분되는 XAML 속기 특성 문자열에 지정합니다. 이러한 값은 Bezier 곡선의 두 제어점에 대한 'X, Y' 쌍입니다. 'X'는 시간이며 'Y'는 해당 값에 대한 함수 한정자입니다. 각 값은 항상 0에서 1 이하여야 합니다. KeySpline에 대한 제어점을 수정하지 않았을 때 0, 0에서 1, 1까지의 직선은 선형 보간을 위한 시간에 따른 함수 표현입니다. 제어점은 해당 곡선의 모양을 변경하므로 스플라인 애니메이션에 대한 시간이 지남에 따라 함수의 동작이 변경됩니다. 시각적으로는 그래프로 확인하는 것이 가장 좋습니다. 브라우저에서 Silverlight 키 스플라인 비주얼라이저 예제를 실행하여 제어점이 곡선을 수정하는 방식과 KeySpline 값으로 사용할 때 예제 애니메이션이 실행되는 방식을 확인할 수 있습니다.

다음 예제는 애니메이션에 적용된 세 가지 키 프레임을 보여 주며 마지막 예제는 Double 값(SplineDoubleKeyFrame)에 대한 키 스플라인 애니메이션입니다. KeySpline에 적용된 문자열 '0.6, 0.0 0.9, 0.00'을 확인합니다. 이렇게 하면 애니메이션이 처음에는 느리게 실행되는 것처럼 보이지만 KeyTime에 도달하기 직전에는 빠르게 해당 값에 도달하는 곡선이 생성됩니다.

<Storyboard x:Name="myStoryboard">
    <!-- Animate the TranslateTransform's X property
        from 0 to 350, then 50,
        then 200 over 10 seconds. -->
    <DoubleAnimationUsingKeyFrames
        Storyboard.TargetName="MyAnimatedTranslateTransform"
        Storyboard.TargetProperty="X"
        Duration="0:0:10" EnableDependentAnimation="True">

        <!-- Using a LinearDoubleKeyFrame, the rectangle moves 
            steadily from its starting position to 500 over 
            the first 3 seconds.  -->
        <LinearDoubleKeyFrame Value="500" KeyTime="0:0:3"/>

        <!-- Using a DiscreteDoubleKeyFrame, the rectangle suddenly 
            appears at 400 after the fourth second of the animation. -->
        <DiscreteDoubleKeyFrame Value="400" KeyTime="0:0:4"/>

        <!-- Using a SplineDoubleKeyFrame, the rectangle moves 
            back to its starting point. The
            animation starts out slowly at first and then speeds up. 
            This KeyFrame ends after the 6th second. -->
        <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0" KeyTime="0:0:6"/>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

키 프레임 감속/가속

감속/가속 키 프레임은 보간이 적용되는 키 프레임이며 보간의 시간에 따른 함수가 여러 가지 미리 정의된 수학 수식에 의해 제어됩니다. 실제로 일부 감속/가속 함수 형식과 동일한 결과를 스플라인 키 프레임에서도 많이 생성할 수 있지만 스플라인에서 재현할 수 없는 BackEase와 같은 몇 가지 감속/가속 함수도 있습니다.

감속/가속 키 프레임에 감속/가속 함수를 적용하려면 EasingFunction 속성을 해당 키 프레임에 대한 XAML 속성 요소로 설정합니다. 값에 대해 감속/가속 함수 유형 중 하나에 대한 개체 요소를 지정합니다.

이 예제에서는 CubicEase를 적용한 다음 BounceEase를 연속 키 프레임으로 DoubleAnimation에 적용하여 바운싱 효과를 형성합니다.

<Storyboard x:Name="myStoryboard">
    <DoubleAnimationUsingKeyFrames Duration="0:0:10"
        Storyboard.TargetProperty="Height"
        Storyboard.TargetName="myEllipse">

        <!-- This keyframe animates the ellipse up to the crest 
            where it slows down and stops. -->
        <EasingDoubleKeyFrame Value="-300" KeyTime="00:00:02">
            <EasingDoubleKeyFrame.EasingFunction>
                <CubicEase/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>

        <!-- This keyframe animates the ellipse back down and makes
            it bounce. -->
        <EasingDoubleKeyFrame Value="0" KeyTime="00:00:06">
            <EasingDoubleKeyFrame.EasingFunction>
                <BounceEase Bounces="5"/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

이는 감속/가속 함수 예제 중 하나일 뿐입니다. 다음 섹션에서 자세히 살펴보겠습니다.

감속/가속 함수

감속/가속 함수를 사용하여 사용자 지정 수식을 애니메이션에 적용할 수 있습니다. 수학적 연산은 2차원 좌표계에서 실제 물리학을 시뮬레이션하는 애니메이션을 생성할 때 유용한 경우가 많습니다. 예를 들어 마치 스프링 위에 있는 것처럼 개체가 사실적으로 바운스되거나 동작하도록 하고 싶을 수 있습니다. 키 프레임 또는 심지어 From/To/By 애니메이션을 사용하여 이러한 효과를 대략적으로 나타낼 수 있지만 상당히 복잡한 작업이 필요하며 수식을 사용할 때보다 애니메이션이 덜 정확해집니다.

감속/가속 함수는 다음 세 가지 방법으로 애니메이션에 적용할 수 있습니다.

영향을 미치는 감속/가속 함수의 목록은 다음과 같습니다.

  • BackEase: 지시된 경로로 애니메이션을 시작하기 바로 전에 애니메이션이 움츠리는 동작을 하게 합니다.
  • BounceEase: 튀는 효과를 냅니다.
  • CircleEase: 순환수를 사용하여 가속하거나 감속하는 애니메이션을 만듭니다.
  • CubicEase: 수식 f(t) = t3를 사용하여 가속하거나 감속하는 애니메이션을 만듭니다.
  • ElasticEase: 멈출 때까지 앞뒤로 진동하는 스프링과 비슷한 애니메이션을 만듭니다.
  • ExponentialEase: 지수식을 사용하여 가속하거나 감속하는 애니메이션을 만듭니다.
  • PowerEase: 수식 f(t) = tp(p는 Power 속성과 같음)를 사용하여 가속하거나 감속하는 애니메이션을 만듭니다.
  • QuadraticEase: 수식 f(t) = t2를 사용하여 가속하거나 감속하는 애니메이션을 만듭니다.
  • QuarticEase: 수식 f(t) = t4를 사용하여 가속하거나 감속하는 애니메이션을 만듭니다.
  • QuinticEase: 수식 f(t) = t5를 사용하여 가속하거나 감속하는 애니메이션을 만듭니다.
  • SineEase: 사인 수식을 사용하여 가속하거나 감속하는 애니메이션을 만듭니다.

감속/가속 함수 중 일부에는 자체 속성이 있습니다. 예를 들어 BounceEase에는 BouncesBounciness의 두 속성이 있으며 이 두 속성은 해당 특정 BounceEase의 시간 경과에 따른 함수 동작을 수정합니다. 기타 감속/가속 함수 CubicEase 등은 EasingMode 속성 이외의 속성이 없으며, 해당 속성은 모든 감속/가속 함수가 공유하고 항상 동일한 시간 경과에 따른 동작을 생성합니다.

이러한 감속/가속 함수 중 일부는 속성이 있는 감속/가속 함수에서 속성을 설정하는 방법에 따라 약간 겹칩니다. 예를 들어 QuadraticEasePower가 2인 PowerEase와 정확히 동일합니다. 또한 CircleEase는 사실상 ExponentialEase의 기본값입니다.

BackEase 감속/가속 함수는 From/To 또는 키 프레임의 값으로 설정한 정상 범위를 벗어난 값을 변경할 수 있다는 점이 특징입니다. 일반적인 From/To 동작에서 예상되는 것과 반대 방향으로 값을 변경하여 애니메이션을 시작하고 From 또는 시작 값으로 돌아간 다음 애니메이션을 정상적으로 실행합니다.

이전 예제에서는 키 프레임 애니메이션에 대한 감속/가속 함수를 선언하는 방법을 살펴봤습니다. 다음 예제에서는 감속/가속 함수를 From/To/By 애니메이션에 적용합니다.

<StackPanel x:Name="LayoutRoot" Background="White">
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimation From="30" To="200" Duration="00:00:3" 
                Storyboard.TargetName="myRectangle" 
                Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
                <DoubleAnimation.EasingFunction>
                    <BounceEase Bounces="2" EasingMode="EaseOut" 
                                Bounciness="2"/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </StackPanel.Resources>
    <Rectangle x:Name="myRectangle" Fill="Blue" Width="200" Height="30"/>
</StackPanel>

From/To/By 애니메이션에 감속/가속 함수를 적용하면 애니메이션의 Duration에 따라 FromTo 값 사이에서 값이 보간되는 시간 경과에 따른 함수 특성이 변경됩니다. 감속/가속 함수가 없으면 선형 보간이 됩니다.

불연속 개체 값 애니메이션

애니메이션 유형은 Double, Point 또는 Color 유형이 아닌 속성에 애니메이션 값을 적용할 수 있는 유일한 방법이기 때문에 따로 언급하지 않습니다. 키 프레임 애니메이션 ObjectAnimationUsingKeyFrames입니다. Object 값을 사용하여 애니메이션에 효과를 주면 프레임 간 값을 보간할 가능성이 없기 때문에 상이합니다. 프레임의 KeyTime에 도달하면 애니메이션 효과가 적용된 값이 즉시 키 프레임에 Value로 지정된 값으로 설정됩니다. 보간이 없기 때문에 ObjectAnimationUsingKeyFrames 키 프레임 컬렉션에 사용하는 키 프레임은 다음 하나뿐입니다. DiscreteObjectKeyFrame

DiscreteObjectKeyFrameValue는 속성 요소 구문을 사용하여 설정되는 경우가 많습니다. 이는 설정하려는 개체 값이 특정 구문의 Value를 채우기 때문입니다. StaticResource와 같은 참조를 사용하는 경우에도 특성 구문을 사용할 수 있습니다.

기본 템플릿에서 ObjectAnimationUsingKeyFrames가 사용되는 것을 확인할 수 있는 위치 중 하나는 템플릿 속성이 Brush 리소스를 참조할 수 있는 경우입니다. 이러한 리소스는 SolidColorBrush 개체이며 단순히 Color 값이 아니라 시스템 테마인(ThemeDictionaries)로 정의된 리소스를 사용합니다. TextBlock.Foreground와 같은 Brush 유형 값에 직접 할당할 수 있으며 간접 타겟팅을 사용할 필요가 없습니다. SolidColorBrushDouble, Point 또는 Color가 아니기 때문에 ObjectAnimationUsingKeyFrames를 통해 리소스를 사용해야 합니다.

<Style x:Key="TextButtonStyle" TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="Transparent">
                    <TextBlock x:Name="Text"
                        Text="{TemplateBinding Content}"/>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="PointerOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
...
                       </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

또한 ObjectAnimationUsingKeyFrames를 통해 열거형 값을 사용하는 속성에 애니메이션을 적용할 수 있습니다. 다음은 Windows 런타임 기본 템플릿에서 가져온 명명된 스타일의 또 다른 예입니다. Visibility 열거형 상수를 취하는 Visibility 속성을 어떻게 설정하는지 확인하세요. 이 경우 특성 구문을 사용하여 값을 설정할 수 있습니다. 열거형 값이 있는 속성을 설정하려면 열거형의 정규화되지 않은 상수 이름(예: "Collapsed")만 필요합니다.

<Style x:Key="BackButtonStyle" TargetType="Button">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <Grid x:Name="RootGrid">
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal"/>
...           <VisualState x:Name="Disabled">
                <Storyboard>
                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame Value="Collapsed" KeyTime="0"/>
                  </ObjectAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
...
          </VisualStateManager.VisualStateGroups>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

ObjectAnimationUsingKeyFrames 프레임 집합에 하나 이상의 DiscreteObjectKeyFrame을 사용할 수 있습니다. 여러 개체 값이 유용할 수 있는 예시 시나리오로, Image.Source 값에 애니메이션 효과를 적용하여 '슬라이드 쇼' 애니메이션을 생성하는 것 또한 유용한 방법일 수 있습니다.