ID #7812

WPF与缓动(一) N次缓动

如果我们希望制作的动画效果像现实生活中的运动一样平滑, 比如汽车的启动与停止总有一个加速或减速的过程, 那么我们有必要研究一下"缓动"

缓入: 速度逐渐增加的过程,比如汽车的启动

如果我们用曲线上的点的斜率表示速度,那么在数学上它对应了下面这样的曲线:

缓出:速度逐渐减小的过程,比如汽车的停止

在数学上它对应了下面的曲线

就加速运动而言, 根据以下位置与加速度等公式

我们可以得到,任意时刻的速度等于总的路程乘以当前时间与总时间的比值的平方, 而总的路程实际将相当与WPF中Animation的To与From的差值, 当前时间与总时间的比值实际上相当与WPF中animationClock.CurrentProgress.Value值.

除此之外,我们发现,曲线的指数越大,点的斜率变化越快,那么加速度也就越大.

有了这些知识,我们可以很好的模拟加速运动了

参考以下代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Media.Animation;
using System.Windows;

namespace EaseMoveDemo
{
public class EaseMoveAnimation : DoubleAnimationBase
{

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

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

public static readonly DependencyProperty PowerProperty = DependencyProperty.Register(
"Power", typeof(double?), typeof(EaseMoveAnimation), new PropertyMetadata(null));

public double? From
{
get
{
return (double?)this.GetValue(EaseMoveAnimation.FromProperty);
}
set
{
this.SetValue(EaseMoveAnimation.FromProperty, value);
}
}

public double? To
{
get
{
return (double?)this.GetValue(EaseMoveAnimation.ToProperty);
}
set
{
this.SetValue(EaseMoveAnimation.ToProperty, value);
}
}

/**//// <summary>
/// 幂指数,值越大,曲线上点的斜率越大,加速度越大,设置为5时效果较好
/// </summary>
public double? Power
{
get
{
return (double?)this.GetValue(EaseMoveAnimation.PowerProperty);
}
set
{
this.SetValue(EaseMoveAnimation.PowerProperty, value);
}
}

protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock animationClock)
{
double from = (this.From==null?defaultDestinationValue:(double)this.From);
double to = (this.To==null?defaultOriginValue:(double)this.To);
double delta = to - from;
double power = this.Power == null ? 2 : (double)this.Power;

//加速
return delta * Math.Pow(animationClock.CurrentProgress.Value, power) + from;
//return delta * Math.Pow(animationClock.CurrentProgress.Value, 1/power) + from;

//先加速后减速
//if (animationClock.CurrentProgress.Value < 0.5)
//{
//  return delta / 2 * Math.Pow(animationClock.CurrentProgress.Value * 2, power) + from;
/

本文配套源码


2011-07-02 09:55
阅读:
I'm VC , Just U know Y
本站部分文章来源于互联网,版权归原作者所有。

延伸阅读:

对WPF逻辑树概念的理解

WPF Bug清单之(10)——CheckBox在不同主题下具有不

【探索PowerShell 】【十五】引号与转义字符

WPF Bug清单之(11)——错位的RenderTransform动画

WPF Bug清单之(12)