WPF触控程序开发(三)——相似IPhone相册的反弹效果

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

     在没有现成的控件的状况下,只有本身作,你确定想到作动画,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动画类吗,有兴趣的人能够继续探索下。动画

  鉴于你们的热情,我会把所有代码整理出来放到群文件共享里,敬请关注。spa

相关文章
相关标签/搜索