Tech/Silverlight2010. 1. 6. 17:11

1. Custom Animation?

Silverlight에서 Storyboard를 사용한 Animation을 적용하고자 할 때 특정한 Property에 대한 Animation 적용이 힘든 경우가 있다. (ex. Grid의 Margin)

그것을 위해서 사용자가 직접 Animation을 구현하는 Class를 작성하면 된다.

Custom Animation Class는 DependencyProperty로 Time, Target, From, To, TargetProperty를 구현한다.


2. Thickness Animation

Grid의 Margin은 Type이 Thickness이다. 이것의 Animation을 위한 ThicknessAnimation Class는 다음과 같이 구현할 수 있다.



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
69
70
71
72
73
74
75
76
77
78
79
80

using System.Windows;
using System.Windows.Media.Animation;

namespace CCPContentsList
{
    public class ThicknessAnimation  
    { 
        // The time along the animation from 0-1
        public static DependencyProperty TimeProperty = DependencyProperty.RegisterAttached(
            "Time", typeof(double), typeof(DoubleAnimation), new PropertyMetadata(OnTimeChanged));
        // The object being animated
        public static DependencyProperty TargetProperty = DependencyProperty.RegisterAttached(
            "Target", typeof(DependencyObject), typeof(ThicknessAnimation), null);
        // The thickness we're animating to
        public static DependencyProperty FromProperty = DependencyProperty.RegisterAttached(
            "From", typeof(Thickness), typeof(DependencyObject), null);
        // The tickness we're animating from
        public static DependencyProperty ToProperty = DependencyProperty.RegisterAttached(
            "To", typeof(Thickness), typeof(DependencyObject), null);
        // The target property to animate to.  Should have a property type of Thickness
        public static DependencyProperty TargetPropertyProperty = DependencyProperty.RegisterAttached(
            "TargetProperty", typeof(DependencyProperty), typeof(DependencyObject), null);

        /// <summary>
        /// Creates a Timeline used to animate the thickness of an object
        /// </summary>
        /// <param name="target">The object to animate</param>
        /// <param name="targetProperty">The property on the object to animate</param>
        /// <param name="duration">The length of the animation</param>
        /// <param name="from">The begining thickness</param>
        /// <param name="to">The final thickness</param>
        /// <returns>A timeline object that can be added to a storyboard</returns>
         public static Timeline Create(
             DependencyObject target, 
             DependencyProperty targetProperty, 
             Duration duration, 
             Thickness from, 
             Thickness to, 
             EasingFunctionBase ease)
         {
             DoubleAnimation timeAnimation = new DoubleAnimation() 
                    { From = 0, To = 1, Duration = duration, EasingFunction = ease };
             timeAnimation.SetValue(TargetProperty, target);
             timeAnimation.SetValue(TargetPropertyProperty, targetProperty);
             timeAnimation.SetValue(FromProperty, from);
             timeAnimation.SetValue(ToProperty, to);
             Storyboard.SetTargetProperty(timeAnimation, new PropertyPath("(ThicknessAnimation.Time)"));
             Storyboard.SetTarget(timeAnimation, timeAnimation); 
             return timeAnimation;
         }

         ///<summary>
         ///Silverlight's animation system is animating time from 0 to 1.  
         ///When time changes we update the thickness to be time
         ///percent between from and to 
         ///</summary>
         private static void OnTimeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
         {
             DoubleAnimation animation = (DoubleAnimation)sender;
             double time = GetTime(animation);
             Thickness from = (Thickness)sender.GetValue(FromProperty);
             Thickness to = (Thickness)sender.GetValue(ToProperty);
             DependencyProperty targetProperty = (DependencyProperty)sender.GetValue(TargetPropertyProperty);
             DependencyObject target = (DependencyObject)sender.GetValue(TargetProperty);
             target.SetValue(targetProperty, new Thickness((to.Left - from.Left) * time + from.Left,
             (to.Top - from.Top) * time + from.Top,
             (to.Right - from.Right) * time + from.Right,
             (to.Bottom - from.Bottom) * time + from.Bottom));
         } 

         public static double GetTime(DoubleAnimation animation)
         {
            return (double)animation.GetValue(TimeProperty);
         }

         public static void SetTime(DoubleAnimation animation, double value)
         {
            animation.SetValue(TimeProperty, value);
         }
    }
}

- 여기서 중요한 부분은 OnTimeChanged 함수이다. 이 함수로 들어온 DoubleAnimation으로 부터 설정한 애니메이션 정보를 얻은 다음에, Margin 값을 직접 수정하게 된다. (Margin의 Type은 Thickness)

- 이를 응용하면 애니메이션 적용이 힘든 다른 Property도 Custom Animation을 제작해 사용할 수 있다.


Posted by 벚꽃손님