WPF & C# - Animation을 구현 3가지 방법 요약 ( DoubleAnimation / 더블애니메이션 / DispatcherTimer / 디스패쳐타이머 / 디스패처타이머 / CompositionTarget / Redering EventHandler / 랜더링 이벤트 핸들러 / 렌더링 )

2018. 7. 31. 11:07Programing (프로그래밍)/WPF & C# (C Sharp)

728x90
반응형
 WPF & C# -  Animation을 구현 3가지 방법 요약 ( DoubleAnimation / 더블애니메이션 / DispatcherTimer / 디스패쳐타이머 / 디스패처타이머 / CompositionTarget / Redering EventHandler / 랜더링 이벤트 핸들러 / 렌더링 )

 

 

DoubleAnimation ( 더블애니메이션 )

 

 

 

 

 

 

MainWindow.xaml.cs

 

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public MainWindow()
{
    InitializeComponent();
    InitUI();
    DoubleAnimation_Start();
}
 
Canvas MainCanvas = new Canvas();
Canvas MyEllipseCanvas = new Canvas();
Ellipse MyEllipse = new Ellipse();
 
public void InitUI()
{
    // 윈도우 크기
    this.Width = 600;
    this.Height = 100;
 
    // 원 크기 및 색상
    MyEllipse.Width = 50;
    MyEllipse.Height = 50;
    MyEllipse.Fill = new SolidColorBrush(Colors.Blue);   // 색상
 
    //원을 품고 있는 캔버스를 다시 자식으로.
    MainCanvas.Children.Add(MyEllipse);
    Content = MainCanvas;
}
 
public void DoubleAnimation_Start()
{
    //더블 애니메이션 하나 설정 했다.
    DoubleAnimation MyDoubleAnimation = new DoubleAnimation();
    MyDoubleAnimation.From = 0.0;
    MyDoubleAnimation.To = this.Width - MyEllipse.Width;
 
    //가속도값 설정하기
    MyDoubleAnimation.AccelerationRatio = 1;
    MyDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
 
    //애니메이션 효과를 적용한 후에는 속성 값을 변경하기
    MyDoubleAnimation.FillBehavior = FillBehavior.HoldEnd;   // Stop 는 원위치에서 종료, HoldEnd는 현위치에서 종료
    MyDoubleAnimation.AutoReverse = true;   // 자동복원 설정
    MyDoubleAnimation.Completed += new EventHandler(MyDoubleAnimation_Completed);   // 종료 이벤트 설정
    MyEllipse.BeginAnimation(Canvas.LeftProperty, MyDoubleAnimation);
}
 
// 종료 이벤트 설정
void MyDoubleAnimation_Completed(object sender, EventArgs e)
{
    DoubleAnimation_Start();   // 다시 시작 설정
}
cs
 

 

 

DispatcherTimer ( 디스패쳐타이머 / 디스패처타이머 )

 

DispatcherTimer.zip
0.70MB

 

 

 

MainWindow.xaml.cs

 

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public MainWindow()
{
    InitializeComponent();
    InitUI();
    TimerSetting();
}
 
Canvas MainCanvas = new Canvas();
Ellipse MyEllipse = new Ellipse();
DispatcherTimer MyTimer = new DispatcherTimer();
 
public void InitUI()
{
    // 윈도우 크기
    this.Width = 600;
    this.Height = 100;
 
    // 원 크기 및 색상
    MyEllipse.Width = 50;
    MyEllipse.Height = 50;
    MyEllipse.Fill = new SolidColorBrush(Colors.Blue);   // 색상
 
    //원을 캔버스 다시 자식으로.
    MainCanvas.Children.Add(MyEllipse);
    this.Content = MainCanvas;
}
 
//타이머를 셋팅한다.
private void TimerSetting()
{
    //얼마의 주기로 호출할 것인가?
    MyTimer.Interval = new TimeSpan(10000);
    MyTimer.Tick += new EventHandler(MyTimer_Tick);
    MyTimer.Start(); //타이머 시작
}
 
double XPos = 0;
bool GoBack = true;
double speed = 0;
void MyTimer_Tick(object sender, EventArgs e)
{
 
    // Go or Back 에 따른 속도
    if (GoBack)
    {
        speed += 0.1;
        XPos += speed;
    }
    else
    {
        speed -= 0.1;
        XPos -= speed;
    }
 
    // 위치에 따른 Go or Back
    if (XPos <= 0)
    {
        GoBack = !GoBack;
        XPos = 0;
    }
    if (this.Width - MyEllipse.Width <= XPos)
    {
        GoBack = !GoBack;
        XPos = this.Width - MyEllipse.Width;
    }
 
    Canvas.SetLeft(MyEllipse, XPos);
}
cs
 

 

DispatcherTimer 의 경우 CPU를 많이 잡아 먹는다고 한다. 

Thread.Sleep(1); 을 사용해보면 CPU 점유율이 확 떨어진다. 참고하자.

 

 

 

CompositionTarget의 Redering 이벤트 핸들러 이용

 

CompositonTarget.zip
0.70MB

 

 

 

 

MainWindow.xaml.cs

 

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public MainWindow()
{
    InitializeComponent();
    InitUI();
    SetCompositionTarget();
}
 
Canvas MainCanvas = new Canvas();
Ellipse MyEllipse = new Ellipse();
DispatcherTimer MyTimer = new DispatcherTimer();
 
public void InitUI()
{
    // 윈도우 크기
    this.Width = 600;
    this.Height = 100;
 
    // 원 크기 및 색상
    MyEllipse.Width = 50;
    MyEllipse.Height = 50;
    MyEllipse.Fill = new SolidColorBrush(Colors.Blue);   // 색상
 
    //원을 캔버스 다시 자식으로.
    MainCanvas.Children.Add(MyEllipse);
    this.Content = MainCanvas;
}
 
private void SetCompositionTarget()
{
    CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
}
 
double XPos = 0;
bool GoBack = true;
double speed = 0;
void CompositionTarget_Rendering(object sender, EventArgs e)
{
    // Go or Back 에 따른 속도
    if (GoBack)
    {
        speed += 0.1;
        XPos += speed;
    }
    else
    {
        speed -= 0.1;
        XPos -= speed;
    }
 
    // 위치에 따른 Go or Back
    if (XPos <= 0)
    {
        GoBack = !GoBack;
        XPos = 0;
    }
    if (this.Width - MyEllipse.Width <= XPos)
    {
        GoBack = !GoBack;
        XPos = this.Width - MyEllipse.Width;
    }
 
    Canvas.SetLeft(MyEllipse, XPos);
}
cs
 

 

CompositonTarget은 System.Windows.Media 네임 스페이스를 쓰면 이용가능하다.

WPF를 내부적으로 보면 화면에 GPU 가속을 이용하여 Thread 형식으로 오브젝트를 계속 뿌린다.

GDI 방식과 차이가 있다. 그렇기 때문에 화면에 뿌려지는 속도가 매우 빠르다

 

요약내용 원문출처 : http://hewoo.tistory.com/m/5   ( WPF에서 Animation을 구현하는 3가지 방법. )

( 요약하다보니 코드를 거의 다 바꾸었습니다. 참고 바랍니다. )

 

728x90
반응형