[WPF] Animation 만들기

[WPF] Animation 만들기

이번 글에서는 WPF에서 애니메이션에 대해서 알아보겠습니다. WPF에서는 모든 컨트롤을 애니메이션 지원을 해줍니다. 움직이거나, 회전하거나, 크기가 변경되는 등등 애니메이션처럼 표현해줍니다. 애니메이션을 만들 땐 몇 가지 핵심적인 설정 값이 있습니다.

  • From : 어디서
  • To : 어디까지
  • Duration : 애니메이션 시간(속도)
  • AutoReverse : 처음으로 다시 돌아 갈 건지
  • RepeatBehavior : 반복 여부

Behavior를 사용해서 컨트롤에 마우스 Enter 이벤트가 발생하면 UI 요소들의 크기를 커졌다 작아졌다 하는, 심장 박동 같은 애니메이션을 만들어 보도록 하겠습니다.

코드

우선 MainWindow.xaml에 컨트롤들을 몇 개 만들어 줍니다.

<Window x:Class="WpfAnimation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfAnimation"
        xmlns:b="clr-namespace:WpfAnimation.Behavior"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">
    <StackPanel Orientation="Vertical">
        <Button Content="hi"
                Margin="5"
                HorizontalAlignment="Center"
                Width="100">
            <i:Interaction.Behaviors>
                <b:AnimationBehavior/>
            </i:Interaction.Behaviors>
        </Button>

        <CheckBox Content="shake"
                  HorizontalAlignment="Center">
            <i:Interaction.Behaviors>
                <b:AnimationBehavior/>
            </i:Interaction.Behaviors>
        </CheckBox>
    </StackPanel>
</Window>

그 다음 Behavior 폴더를 만든 뒤 그 안에 AnimationBehavior.cs를 만들어줍니다.

public class AnimationBehavior : Behavior<FrameworkElement>
{
    public AnimationBehavior() { }

    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.MouseEnter += OnMouseEnter;
        AssociatedObject.MouseLeave += OnMouseLeave;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseEnter -= OnMouseEnter;
        AssociatedObject.MouseLeave -= OnMouseLeave;

        base.OnDetaching();
    }
    #region mouse enter, leave

    private void OnMouseEnter(object sender, MouseEventArgs e)
    {
        StartScale();
    }

    private void OnMouseLeave(object sender, MouseEventArgs e)
    {
        StopScale();
    }
    #endregion

    #region animation
    private void StartScale()
    {
        if (AssociatedObject == null)
            return;

        if (!(AssociatedObject.RenderTransform is ScaleTransform))
        {
            AssociatedObject.RenderTransform = new ScaleTransform();
            AssociatedObject.RenderTransformOrigin = new Point(0.5, 0.5); // 컨트롤 변형이 일어날 때 기준점.
        }
        
        DoubleAnimation anim = new DoubleAnimation
        {
            From = 0.9, // 시작
            To = 1.1, // 끝
            Duration = TimeSpan.FromMilliseconds(300), // 기간
            AutoReverse = true, // 처음으로 돌아감
            RepeatBehavior = RepeatBehavior.Forever, // 계속 반복
            EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseInOut }, // 효과
        };

        AssociatedObject.RenderTransform.BeginAnimation(ScaleTransform.ScaleXProperty, anim); // x축 으로 수행
        AssociatedObject.RenderTransform.BeginAnimation(ScaleTransform.ScaleYProperty, anim); // y축 으로 수행
    }

    private void StopScale()
        {
            if (AssociatedObject?.RenderTransform is ScaleTransform)
            {
                AssociatedObject.RenderTransform.BeginAnimation(ScaleTransform.ScaleXProperty, null);
                AssociatedObject.RenderTransform.BeginAnimation(ScaleTransform.ScaleYProperty, null);
            }
        }
    #endregion
}

MouseEnter와 MouseLeave를 사용하여 Mouse가 컨트롤에 Enter, Leave되는 이벤트를 받았습니다.

AssociatedObject의 RenderTransform 속성에 크기 조절을 하는 ScaleTransform을 생성해준 다음, 애니메이션의 설정 값이 담긴 DoubleAnimation 객체를 만들어 준 다음 ScaleTransform.BeginAnimation에 인자로 입력해줍니다.

실행

실행 시켜서 확인해봅니다.

애니메이션 효과를 여러 개 동시에 적용하고 싶으면 TransformGroup을 사용하면 된다고 합니다. 생각보다 간단하니 이 글에서는 다루진 않겠습니다.


github : https://github.com/3001ssw/c_sharp/tree/main/WPF/WPF_Basic/WpfAnimation