生成动画没有按照设想去工作,发现bug,是因为PropertyPath没有正确设置,正确设置之后正常工作了
简单介绍一下PropertyPath以及PropertyChain
动画是通过编写一个故事版根据故事版上的两个DoubleAnimation来播放的动画的
动画的细节在DoubleAnimation,Animation有很多种,下次有机会再详细说各种动画的特点及表现。
这里主要是一个TranslateTransform的Y轴变换动画,还有RotateTransfom的Angle改变的旋转动画组成的
/// <summary> /// 雪花 /// </summary> public class SnowFlower : Image { #region 字段 //完全随机数生成器 private readonly Random _random = RandomHelper.GetRandom(); #endregion #region 属性 /// <summary> /// 下落速度 /// </summary> public int GravitySpeed { get { return _random.Next(10, 20); } } /// <summary> /// 旋转速度 /// </summary> public int AngleSpeed { get { return _random.Next(1, 5); } } /// <summary> /// 起始的X坐标 /// </summary> public int StartX { get { return _random.Next(0, (int)SystemParameters.PrimaryScreenWidth); } } #endregion public SnowFlower() { Opacity = GetOpacity(); Source = GetSource(); Height = GetSize(); Width = Height; RenderTransformOrigin = new Point(0.5, 0.5); Margin = new Thickness(StartX, 0, 0, 0); HorizontalAlignment = HorizontalAlignment.Left; VerticalAlignment = VerticalAlignment.Top; RenderTransform = GetRenderTransform(); Loaded += SnowFlower_Loaded; } #region 动画 private void SnowFlower_Loaded(object sender, RoutedEventArgs e) { GetFallingStoryborad().Begin(); } //获取变换的信息 private static TransformGroup GetRenderTransform() { var result = new TransformGroup(); result.Children.Add(new RotateTransform()); result.Children.Add(new TranslateTransform()); return result; } //获取飘落动画故事版 private Storyboard GetFallingStoryborad() { var result = new Storyboard(); result.Children.Add(GetAngleAnimation()); result.Children.Add(GetFallingAnimation()); return result; } //属性链 private readonly object[] _propertyChain = { RenderTransformProperty, TransformGroup.ChildrenProperty, RotateTransform.AngleProperty, TranslateTransform.YProperty }; //获取旋转动画 private DoubleAnimation GetAngleAnimation() { var da = new DoubleAnimation { From = 0, To = 360, Duration = TimeSpan.FromSeconds(AngleSpeed), RepeatBehavior = RepeatBehavior.Forever }; //Storyboard.SetTargetProperty(da, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)")); Storyboard.SetTargetProperty(da, new PropertyPath("(0).(1)[0].(2)", _propertyChain)); Storyboard.SetTarget(da, this); return da; } //获取飘落动画 private DoubleAnimation GetFallingAnimation() { var da = new DoubleAnimation { From = 0, To = SystemParameters.PrimaryScreenHeight, Duration = TimeSpan.FromSeconds(GravitySpeed) }; Storyboard.SetTargetProperty(da, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.Y)")); Storyboard.SetTarget(da, this); return da; } #endregion //获取初始的透明度 private static double GetOpacity() { var result = (double)new Random().Next(1, 5); result = result / 10; return result; } //获取图像源 private static BitmapImage GetSource() { var result = new BitmapImage(); result.BeginInit(); result.UriSource = new Uri("/SnowEffect;component/Resource/SnowFlower.png", UriKind.RelativeOrAbsolute); result.EndInit(); return result; } //获取尺寸 private static double GetSize() { var result = (double)new Random().Next(20, 50); return result; } }
有一步其中导致动画没有出现的原因就是其中的PropertyPath没有正确赋值
这里的PropertyPath是与控件的RenderTransfrom有关的
其中的RenderTransform是由TransformGourp构成
而TramsformGroup的Children含有RotateTransform和TranslateTransform两个
这里有两种PropertyPath的设置方式
方法一:字符串
Storyboard.SetTargetProperty(da, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.Y)"));
方法二:属性链
Storyboard.SetTargetProperty(da, new PropertyPath("(0).(1)[0].(2)", _propertyChain));
代码比较简单易懂,这里就不赘述了。
总结一下:代码生成动画的步骤。
1:声明Animation,并设置Animation的基本属性
2:通过Storyboard的静态方法设置Target和TargetProperty
3:通过故事版来启用动画(其实也可以直接通过BeginAnimatoin,但是这是其他的方法,本质上没有太大的区别,但是故事版更好管理和组合,而BeginAnimation更加方便)
代码生成动画与前台界面生成动画没有什么本质上的区别,这里使用这个动画是为了能够更好的复用以及组合。
是一个单纯的类,不含有Xaml结构,故而后台生成的动画代码就显得比较有必要了。