后台生成动画

生成动画没有按照设想去工作,发现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结构,故而后台生成的动画代码就显得比较有必要了。

 

posted @ 2015-10-13 13:48  蘑菇mr  阅读(420)  评论(0编辑  收藏  举报