WPF弹性惯性效果应用

Posted qiaoke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF弹性惯性效果应用相关的知识,希望对你有一定的参考价值。

WPF弹性、惯性效果。已发布在了一些网站,都是这里写的

代码改编自微软示例代码库
// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the

// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

就3个函数

/// </summary>
    /// <param name="translation_control">需动画的组件</param>
    /// <param name="mode">模式:0-弹性,2-惯性</param>
    /// <param name="orientation">方向:0-正向,1-反向</param>
    /// <param name="axis">轴:0-左右,1-上下</param>
    /// <param name="delay">延时</param>
    /// <param name="_begin">开始动画位置</param>
    /// <param name="_end">结束动画位置</param>
    /// <param name="amplitude">振幅</param>
    /// <param name="suppression">硬度</param>
    public void Translation(FrameworkElement translation_control, int mode, int orientation, int axis, double delay, double _begin, double _end, double amplitude = 8, double suppression = 3)
 
 
 
    /// </summary>
    /// <param name="main">在哪个Grid内</param>
    /// <param name="width">组件宽度</param>
    /// <param name="height">组件高度</param>
    /// <param name="direction">方向:0-横向,1-纵向</param>
    /// <param name="rotate_control">组件</param>
    /// <param name="begin_angel">起始角度</param>
    /// <param name="timeDelay">延时</param>
    public CushionRotate(Grid main, double width, double height, int direction, UserControl rotate_control, double begin_angel, double timeDelay)
 
    /// </summary>
    /// <param name="mode">模式:0-弹性,1-惯性</param>
    /// <param name="amplitude">振幅</param>
    /// <param name="suppression">硬度</param>
    public void Rotate(int mode, double amplitude = 8, double suppression = 3)

 

效果如图

技术图片

 

基本代码

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

public class BounceDoubleAnimation : DoubleAnimationBase
{
    public enum EdgeBehaviorEnum
    {
        EaseIn, EaseOut, EaseInOut
    }

    public static readonly DependencyProperty EdgeBehaviorProperty =
        DependencyProperty.Register("EdgeBehavior",
            typeof(EdgeBehaviorEnum),
            typeof(BounceDoubleAnimation),
            new PropertyMetadata(EdgeBehaviorEnum.EaseInOut));

    public static readonly DependencyProperty BouncesProperty =
        DependencyProperty.Register("Bounces",
            typeof(int),
            typeof(BounceDoubleAnimation),
            new PropertyMetadata(5));

    public static readonly DependencyProperty BouncinessProperty =
        DependencyProperty.Register("Bounciness",
            typeof(double),
            typeof(BounceDoubleAnimation),
            new PropertyMetadata(3.0));

    public static readonly DependencyProperty FromProperty =
        DependencyProperty.Register("From",
            typeof(double?),
            typeof(BounceDoubleAnimation),
            new PropertyMetadata(null));

    public static readonly DependencyProperty ToProperty =
        DependencyProperty.Register("To",
            typeof(double?),
            typeof(BounceDoubleAnimation),
            new PropertyMetadata(null));

    public EdgeBehaviorEnum EdgeBehavior
    {
        get
        {
            return (EdgeBehaviorEnum)GetValue(EdgeBehaviorProperty);
        }
        set
        {
            SetValue(EdgeBehaviorProperty, value);
        }
    }

    public int Bounces
    {
        get
        {
            return (int)GetValue(BouncesProperty);
        }
        set
        {
            if (value > 0)
            {
                SetValue(BouncesProperty, value);
            }
            else
            {
                throw new ArgumentException("can‘t set the bounces to " + value);
            }
        }
    }

    public double Bounciness
    {
        get
        {
            return (double)GetValue(BouncinessProperty);
        }
        set
        {
            if (value > 0)
            {
                SetValue(BouncinessProperty, value);
            }
            else
            {
                throw new ArgumentException("can‘t set the bounciness to " + value);
            }
        }
    }

    public double? From
    {
        get
        {
            return (double?)GetValue(FromProperty);
        }
        set
        {

            SetValue(FromProperty, value);

        }
    }

    public double? To
    {
        get
        {
            return (double?)GetValue(ToProperty);
        }
        set
        {

            SetValue(ToProperty, value);

        }
    }

    protected override double GetCurrentValueCore(
        double defaultOriginValue,
        double defaultDestinationValue,
        AnimationClock clock)
    {
        double returnValue;
        double start = From != null ? (double)From : defaultOriginValue;
        double delta = To != null ? (double)To - start : defaultOriginValue - start;

        switch (this.EdgeBehavior)
        {
            case EdgeBehaviorEnum.EaseIn:
                returnValue = easeIn(clock.CurrentProgress.Value, start, delta, Bounciness, Bounces);
                break;
            case EdgeBehaviorEnum.EaseOut:
                returnValue = easeOut(clock.CurrentProgress.Value, start, delta, Bounciness, Bounces);
                break;
            case EdgeBehaviorEnum.EaseInOut:
            default:
                returnValue = easeInOut(clock.CurrentProgress.Value, start, delta, Bounciness, Bounces);
                break;
        }
        return returnValue;
    }

    protected override Freezable CreateInstanceCore()
    {

        return new BounceDoubleAnimation();
    }

    private static double easeOut(double timeFraction, double start, double delta, double bounciness, int bounces)
    {
        double returnValue = 0.0;
        returnValue = Math.Abs(Math.Pow((1 - timeFraction), bounciness)
                      * Math.Cos(2 * Math.PI * timeFraction * bounces));
        returnValue = delta - (returnValue * delta);
        returnValue += start;
        return returnValue;

    }
    private static double easeIn(double timeFraction, double start, double delta, double bounciness, int bounces)
    {
        double returnValue = 0.0;
        returnValue = Math.Abs(Math.Pow((timeFraction), bounciness)
                      * Math.Cos(2 * Math.PI * timeFraction * bounces));
        returnValue = returnValue * delta;
        returnValue += start;
        return returnValue;
    }
    private static double easeInOut(double timeFraction, double start, double delta, double bounciness, int bounces)
    {
        double returnValue = 0.0;

        if (timeFraction <= 0.5)
        {
            returnValue = easeIn(timeFraction * 2, start, delta / 2, bounciness, bounces);
        }
        else
        {
            returnValue = easeOut((timeFraction - 0.5) * 2, start, delta / 2, bounciness, bounces);
            returnValue += delta / 2;
        }
        return returnValue;
    }
}

/// <summary>
/// 
/// </summary>

public class BackDoubleAnimation : DoubleAnimationBase
{
    public enum EdgeBehaviorEnum
    {
        EaseIn, EaseOut, EaseInOut
    }

    public static readonly DependencyProperty EdgeBehaviorProperty =
        DependencyProperty.Register("EdgeBehavior", typeof(EdgeBehaviorEnum), typeof(BackDoubleAnimation), new PropertyMetadata(EdgeBehaviorEnum.EaseIn));

    public static readonly DependencyProperty AmplitudeProperty =
        DependencyProperty.Register("Amplitude", typeof(double), typeof(BackDoubleAnimation), new PropertyMetadata(4.0));

    public static readonly DependencyProperty SuppressionProperty =
        DependencyProperty.Register("Suppression", typeof(double), typeof(BackDoubleAnimation), new PropertyMetadata(2.0));

    public static readonly DependencyProperty FromProperty =
        DependencyProperty.Register("From",
            typeof(double?),
            typeof(BackDoubleAnimation),
            new PropertyMetadata(null));

    public static readonly DependencyProperty ToProperty =
        DependencyProperty.Register("To",
            typeof(double?),
            typeof(BackDoubleAnimation),
            new PropertyMetadata(null));

    public EdgeBehaviorEnum EdgeBehavior
    {
        get
        {
            return (EdgeBehaviorEnum)GetValue(EdgeBehaviorProperty);
        }
        set
        {
            SetValue(EdgeBehaviorProperty, value);
        }
    }

    public double Amplitude
    {
        get
        {
            return (double)GetValue(AmplitudeProperty);
        }
        set
        {
            SetValue(AmplitudeProperty, value);
        }
    }

    public double Suppression
    {
        get
        {
            return (double)GetValue(SuppressionProperty);
        }
        set
        {
            SetValue(SuppressionProperty, value);
        }
    }

    public double? From
    {
        get
        {
            return (double?)GetValue(FromProperty);
        }
        set
        {

            SetValue(FromProperty, value);

        }
    }

    public double? To
    {
        get
        {
            return (double?)GetValue(ToProperty);
        }
        set
        {

            SetValue(ToProperty, value);

        }
    }

    protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock clock)
    {
        double returnValue;
        double start = From != null ? (double)From : defaultOriginValue;
        double delta = To != null ? (double)To - start : defaultOriginValue - start;
        switch (this.EdgeBehavior)
        {
            case EdgeBehaviorEnum.EaseIn:
                returnValue = easeIn(clock.CurrentProgress.Value, start, delta, Amplitude, Suppression);
                break;
            case EdgeBehaviorEnum.EaseOut:
                returnValue = easeOut(clock.CurrentProgress.Value, start, delta, Amplitude, Suppression);
                break;
            case EdgeBehaviorEnum.EaseInOut:
            default:
                returnValue = easeInOut(clock.CurrentProgress.Value, start, delta, Amplitude, Suppression);
                break;
        }
        return returnValue;
    }

    protected override Freezable CreateInstanceCore()
    {

        return new BackDoubleAnimation();
    }


    private static double easeOut(double timeFraction, double start, double delta, double amplitude, double suppression)
    {
        double returnValue = 0.0;
        double frequency = 0.5;

        returnValue = Math.Pow((timeFraction), suppression)
                      * amplitude * Math.Sin(2 * Math.PI * timeFraction * frequency) + timeFraction;
        returnValue = (returnValue * delta);
        returnValue += start;
        return returnValue;
    }

    private static double easeIn(double timeFraction, double start, double delta, double amplitude, double suppression)
    {
        double returnValue = 0.0;
        double frequency = 0.5;

        returnValue = Math.Pow((1 - timeFraction), suppression)
                      * amplitude * Math.Sin(2 * Math.PI * timeFraction * frequency) * -1 + timeFraction;
        returnValue = (returnValue * delta);
        returnValue += start;
        return returnValue;
    }

    private static double easeInOut(double timeFraction, double start, double delta, double amplitude, double suppression)
    {
        double returnValue = 0.0;

        if (timeFraction <= 0.5)
        {
            return easeIn(timeFraction * 2, start, delta / 2, amplitude, suppression);
        }
        else
        {
            returnValue = easeOut((timeFraction - 0.5) * 2, start, delta / 2, amplitude, suppression);
            returnValue += (delta / 2);
        }
        return returnValue;
    }
}

 

例如旋转惯性

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;

public class CushionRotate
{
    private AxisAngleRotation3D axisAngleRotation;
    private double b_angel, delay;

    public CushionRotate(Grid main, double width, double height, int direction, UserControl rotate_control, double begin_angel, double timeDelay)
    {
        delay = timeDelay;
        b_angel = begin_angel;

        double Mesh_Width = width / 2;
        double Mesh_Height = height / 2;

        Viewport3D viewport3D = new Viewport3D();
        PerspectiveCamera perspectiveCamera = new PerspectiveCamera()
        {
            Position = new Point3D(0, 0, width * 2),
            LookDirection = new Vector3D(0, 0, -1),
            NearPlaneDistance = 100
        };
        viewport3D.Camera = perspectiveCamera;
        ContainerUIElement3D containerUIElement3D = new ContainerUIElement3D();
        DiffuseMaterial diffuseMaterial = new DiffuseMaterial();
        Viewport2DVisual3D.SetIsVisualHostMaterial(diffuseMaterial, true);
        MeshGeometry3D meshGeometry3D = new MeshGeometry3D()
        {
            TriangleIndices = new Int32Collection(new int[] { 0, 1, 2, 0, 2, 3 }),
            TextureCoordinates = new PointCollection(new Point[] { new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0) }),
            Positions = new Point3DCollection(new Point3D[] {
                    new Point3D(-Mesh_Width, Mesh_Height, 0), new Point3D(-Mesh_Width, -Mesh_Height, 0),
                    new Point3D(Mesh_Width, -Mesh_Height, 0), new Point3D(Mesh_Width, Mesh_Height, 0)
                })
        };
        Viewport2DVisual3D viewport2DVisual3D = new Viewport2DVisual3D()
        {
            Geometry = meshGeometry3D,
            Visual = rotate_control,
            Material = diffuseMaterial
        };
        PointCollection Direction;
        Vector3D vector3D;
        if (direction == 0)
        {
            Direction = new PointCollection(new Point[] { new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0) });
            vector3D = new Vector3D(0, 1, 0);
        }
        else
        {
            Direction = new PointCollection(new Point[] { new Point(1, 1), new Point(1, 0), new Point(0, 0), new Point(0, 1) });
            vector3D = new Vector3D(1, 0, 0);
        }
        containerUIElement3D.Children.Add(viewport2DVisual3D);
        axisAngleRotation = new AxisAngleRotation3D()
        {
            Angle = begin_angel,
            Axis = vector3D
        };
        RotateTransform3D rotateTransform3D = new RotateTransform3D()
        {
            Rotation = axisAngleRotation
        };
        containerUIElement3D.Transform = rotateTransform3D;
        ModelVisual3D modelVisual3D = new ModelVisual3D()
        {
            Content = new DirectionalLight(Colors.Transparent, new Vector3D(0, 0, -1))
        };
        viewport3D.Children.Add(containerUIElement3D);
        viewport3D.Children.Add(modelVisual3D);
        main.Children.Add(viewport3D);
    }

    public void Rotate(int mode, double amplitude = 8, double suppression = 3)
    {
        if (mode == 0)
        {
            BounceDoubleAnimation bounceDoubleAnimation = new BounceDoubleAnimation()
            {
                From = b_angel,
                To = 0,
                Duration = new Duration(TimeSpan.Parse("0:0:" + delay.ToString())),
                EdgeBehavior = BounceDoubleAnimation.EdgeBehaviorEnum.EaseOut,
            };
            axisAngleRotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, bounceDoubleAnimation);
        }

        if (mode == 1)
        {
            BackDoubleAnimation backDoubleAnimation = new BackDoubleAnimation()
            {
                From = b_angel,
                To = 0,
                Duration = new Duration(TimeSpan.Parse("0:0:" + delay.ToString())),
                EdgeBehavior = BackDoubleAnimation.EdgeBehaviorEnum.EaseOut,
                Amplitude = amplitude,
                Suppression = suppression,
            };
            axisAngleRotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, backDoubleAnimation);
        }
    }
}

 

整例下载及代码下载:

https://pan.baidu.com/s/129O9eYXF8zJ8eJYDDpI4LQ

以上是关于WPF弹性惯性效果应用的主要内容,如果未能解决你的问题,请参考以下文章

android ScrollView 滑动特效 怎么做成iphone那样有惯性弹性!

WPF实用小工具

WPF 加强记忆

物理学的 H5 应用:模拟惯性滑动

ScrollView惯性效果手动,iOS,Swift

c# wpf代码怎么嵌入EXE应用程序?