WPF与缓动(一) N次缓动

                                                             WPF与缓动(一)  N次缓动
                                                                                       周银辉

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

缓入: 速度逐渐增加的过程,比如汽车的启动
如果我们用曲线上的点的斜率表示速度,那么在数学上它对应了下面这样的曲线:
easeIn.PNG
缓出:速度逐渐减小的过程,比如汽车的停止
在数学上它对应了下面的曲线
easeOut.PNG
就加速运动而言,  根据以下位置与加速度等公式
formula2.PNG
我们可以得到,任意时刻的速度等于总的路程乘以当前时间与总时间的比值的平方, 而总的路程实际将相当与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;
            
//}
            
//return delta / 2 * Math.Pow((animationClock.CurrentProgress.Value - 0.5) * 2, 1/power) + delta / 2 + from;
        }



        
protected override System.Windows.Freezable CreateInstanceCore()
        
{
            
return new EaseMoveAnimation();
        }

    }

}


下载源代码



posted @ 2007-05-16 18:18 周银辉 阅读(3221) 评论(10) 编辑 收藏

 回复 引用 查看   
#1楼 2007-05-16 18:34 yyww      
你这个公式也写的太那个啥了。。。
 回复 引用 查看   
#2楼[楼主] 2007-05-16 19:36 周银辉      
呵呵,将就将就...
 回复 引用 查看   
#3楼 2007-05-16 19:36 bearhunter      
wpf的效率感觉太低哦,没多少动作cpu耗用率就好高了

看这里 https://***

 回复 引用 查看   
#4楼 2007-05-16 20:54 Adrian.      
太可爱了....
 回复 引用 查看   
#5楼 2007-05-16 22:49 过江      
ding
 回复 引用   
#6楼 2007-05-16 22:52 yayx
公式极其可爱.........

Animation里面自带了几个属性,能实现类似的功能~
SpeedRatio AccelerationRatio DecelerationRatio 速度,加速度,负加速度~

 回复 引用 查看   
#7楼[楼主] 2007-05-17 10:21 周银辉      
<!-- This example shows how to use the AccelerationRatio and
DecelerationRatio properties of timelines
to make animations speed up or slow down as they progress. -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SampleControls="SampleControls"
WindowTitle="Acceleration and Deceleration Example">
<StackPanel Margin="20">

<Rectangle Name="nonAcceleratedOrDeceleratedRectangle" Fill="#9933FF"
Width="10" Height="20" HorizontalAlignment="Left" />

<Rectangle Name="acceleratedRectangle" Fill="#3333FF"
Width="10" Height="20" HorizontalAlignment="Left" />

<Rectangle Name="deceleratedRectangle" Fill="#33FF66"
Width="10" Height="20" HorizontalAlignment="Left" />

<Rectangle Name="acceleratedAndDeceleratedRectangle" Fill="#CCFF33"
Width="10" Height="20" HorizontalAlignment="Left" />

<!-- Create a button to start the animations. -->
<Button Margin="0,30,0,0" HorizontalAlignment="Left"
Content="Start Animations">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>

<!-- 没有加速度与减速度. -->
<DoubleAnimation
Storyboard.TargetName="nonAcceleratedOrDeceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
Duration="0:0:10" From="20" To="400" />

<!-- 时间线的40%用于加速,从0加速到最大速度 -->
<DoubleAnimation
Storyboard.TargetName="acceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
AccelerationRatio="0.4" Duration="0:0:10" From="20" To="400" />

<!-- 时间线的60%用于减速,从最大速度减速到0 -->
<DoubleAnimation
Storyboard.TargetName="deceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
DecelerationRatio="0.6" Duration="0:0:10" From="20" To="400" />

<!-- 时间线的40%用于加速,从0加速到最大速度,时间线的60%用于减速,从最大速度减速到0.
加速度和减速度同时设置时,它们的总和应该小于等于1 -->
<DoubleAnimation
Storyboard.TargetName="acceleratedAndDeceleratedRectangle"
Storyboard.TargetProperty="(Rectangle.Width)"
AccelerationRatio="0.4" DecelerationRatio="0.6" Duration="0:0:10" From="20" To="400" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>

 回复 引用 查看   
#8楼[楼主] 2007-05-17 10:33 周银辉      
不过感觉Animation自带的是二次缓动,加减速效果在视觉上不是很明显,使用文章中的方法可以实现N次缓动让效果更明显,Demo中的就是5次缓动(这里的"次"表示函数中的幂指数)
 回复 引用 查看   
#9楼 2009-05-16 08:27 sps.shareach.com      
楼主多来点动画算法, 我数学太差了, 呵呵
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 748952 4/IWuUtlUJQ=