zoukankan      html  css  js  c++  java
  • WPF触控程序开发(三)——类似IPhone相册的反弹效果

         用过IPhone的都知道,IPhone相册里,当图片放大到一定程度后,手指一放,会自动缩回,移动图片超出边框后手指一放,图片也会自动缩回,整个过程非常和谐、自然、精确,那么WPF能否做到呢,答案是肯定的。

         在没有现成的控件的情况下,只有自己做,你肯定想到做动画,WPF触屏开发提供了相应的功能来获取触控点的一些变化,这些变化的最佳消费者个人认为是Matrix。我们回想下做动画一般怎么做,比如给一个button做个宽度增5的动画,我们一般是定义一个DoubleAnimation,然后定义一个Sotryboard,然后用Sotryboard的静态方法SetTargetProperty设置UI对象和动画作用的依赖属性。按照这样的步骤,我们给UI的Matrix做动画,发现,找不到这样的一个类似DoubleAnimation的动画类,Matrix也没有类似Button.WidthProperty这样的依赖属性。也许你会说Matrix的属性OffsetX,M11什么的都是double类型,可以对其设置动画,但是Storyboard应用的对象必须是继承自DependencyProperty的,所以是不可能在Matrix的属性上设置动画的,唯一的解决方案是自己做一个类似于MatrixAnimation的东西。网上有人写过这样的动画类,如下:
        public class LinearMatrixAnimation : AnimationTimeline
        {
            public Matrix? From
            {
                set { SetValue(FromProperty, value); }
                get { return (Matrix)GetValue(FromProperty); }
            }
            public static DependencyProperty FromProperty = DependencyProperty.Register("From", typeof(Matrix?), typeof(LinearMatrixAnimation), new PropertyMetadata(null));
            public Matrix? To
            {
                set { SetValue(ToProperty, value); }
                get { return (Matrix)GetValue(ToProperty); }
            }
            public static DependencyProperty ToProperty = DependencyProperty.Register("To", typeof(Matrix?), typeof(LinearMatrixAnimation), new PropertyMetadata(null));
            public LinearMatrixAnimation()
            {
            }
            public LinearMatrixAnimation(Matrix from, Matrix to, Duration duration)
            {
                Duration = duration;
                From = from;
                To = to;
            }
            public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
            {
                if (animationClock.CurrentProgress == null)
                {
                    return null;
                }
                double progress = animationClock.CurrentProgress.Value;
                Matrix from = From ?? (Matrix)defaultOriginValue;
                if (To.HasValue)
                {
                    Matrix to = To.Value;
                    Matrix newMatrix = new Matrix(((to.M11 - from.M11) * progress) + from.M11, 0, 0, ((to.M22 - from.M22) * progress) + from.M22,
                                                  ((to.OffsetX - from.OffsetX) * progress) + from.OffsetX, ((to.OffsetY - from.OffsetY) * progress) + from.OffsetY);
                    return newMatrix;
                }
                return Matrix.Identity;
            }
            protected override System.Windows.Freezable CreateInstanceCore()
            {
                return new LinearMatrixAnimation();
            }
            public override System.Type TargetPropertyType
            {
                get { return typeof(Matrix); }
            }
        }
      有了这个类,我们就可以使用了:
    var animation = new LinearMatrixAnimation(oldMatrix, newMatrix, TimeSpan.FromSeconds(0.5));
    animation.AccelerationRatio = 0.3;
    animation.DecelerationRatio = 0.3;
      有了动画,只需要用UI的MatrixTransform启动动画即可,假设某个UI的MatrixTransform为matrixTransform,我们就可以启动了:
    matrixTransform.BeginAnimation(MatrixTransform.MatrixProperty, animation);
      有效果,但是貌似只能执行一次,执行完之后,后来无论怎样弄都没反应了,这是由于动画执行完后锁定了属性,网上也有人解决了,办法是在执行完动画之后做了点处理:
    public static void PlayMatrixTransformAnimation(MatrixTransform matrixTransform, Matrix newMatrix, TimeSpan timeSpan)
    {
      var animation = new LinearMatrixAnimation(matrixTransform.Matrix, newMatrix, TimeSpan.FromSeconds(0.5));
      animation.AccelerationRatio = 0.3;
      animation.DecelerationRatio = 0.3;
      animation.FillBehavior = FillBehavior.HoldEnd;
      animation.Completed += (sender, e) =>
      {
        //去除属性的动画绑定  
        matrixTransform.BeginAnimation(MatrixTransform.MatrixProperty, null);
        //将期望结果值保留  
        matrixTransform.Matrix = newMatrix;
      };
    
        //启动动画  
        matrixTransform.BeginAnimation(MatrixTransform.MatrixProperty, animation, HandoffBehavior.SnapshotAndReplace);
    }

      这样一来,仿IPhone的反弹效果就已经差不多了。其实这里是利用了UI的MatrixTransform做了动画,有人说不是有个MatrixAnimationUsingKeyFrames动画类吗,有兴趣的人可以继续探索下。

      鉴于大家的热情,我会把全部代码整理出来放到群文件共享里,敬请关注。

  • 相关阅读:
    SP笔记:交叉实现七行并成一行
    HTML tag 学习
    操作哈希表
    Efficient bipedal robots based on passivedynamic walkers
    Pushing People Around
    ZEROMOMENT PONTTHIRTY FIVE YEARS OF ITS LIFE

    Active Learning for RealTime Motion Controllers
    Accelerometerbased User Interfaces for the Control of a Physically Simulated Character
    Dynamic Response for Motion Capture Animation
  • 原文地址:https://www.cnblogs.com/zoexia/p/3731429.html
Copyright © 2011-2022 走看看