前年看了一点WPF二维动画的开发,通过对各种Transform和Animation的组合,可以设计出各种非常炫的动画效果,我是个艺术白痴,所以就不敢奢望设计出多么好的动画效果。但是,我却在想一个问题,如果我们可以提供一个WPF动画库,任何WPF应用程序都可以非常轻松的重用该动画库里面的动画,那应该是比较爽的一件事。既然有了想法,那就试试,结果还真被我捣鼓出一点小东西出来,写出来跟大家分享一下。
基本思路:
1. 接口尽可能简单,只需要制定要执行动画的控件和动画的类型即可。
2. 根据动画类型来决定对应的Storyboard和Transform。
3. 根据动画类型决定Transform的位置、大小等。
4. Storyboard和Transform保存在独立的ResourceDictionary中,动态加载。
5. 将AnimationProvider设计为单件,避免多份使用。
代码很简单,大概如下,有兴趣跑起来就可以用。
using System;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows;
usingSystem.Windows.Media.Animation;
usingSystem.Windows.Media;
namespace YmyCodes.Controls
{
public enum AnimationTypes
{
Rotate1,
Rotate2,
}
public class AnimationProvider
{
private AnimationProvider()
{
m_AnimationStoryboards = new ResourceDictionary();
m_AnimationStoryboards.Source = new Uri("/YmyCodes.Controls;component/Themes/Animation.xaml",
UriKind.RelativeOrAbsolute);
}
private staticAnimationProvider m_Instance = null;
private ResourceDictionarym_AnimationStoryboards;
public staticAnimationProvider Instance
{
get
{
if(m_Instance == null)
{
m_Instance = new AnimationProvider();
}
returnm_Instance;
}
}
public boolDoStoryboard(FrameworkElement ele, AnimationTypes aniType, ActioncompleteCallback = null)
{
Transform grpBack =ele.RenderTransform;
TransformGroup grp =GetTransformGroup(aniType, ele.ActualWidth, ele.ActualHeight);
ele.RenderTransform = grp;
Storyboard sb =GetStoryboard(aniType);
if (sb != null)
{
Storyboard.SetTarget(sb,ele);
sb.Completed += new EventHandler((obj,arg) =>
{
ele.RenderTransform =grpBack;
if(completeCallback != null)
{
completeCallback();
}
});
sb.Begin();
returntrue;
}
return false;
}
private TransformGroupGetTransformGroup(AnimationTypes aniType, double width, doubleheight)
{
switch (aniType)
{
caseAnimationTypes.Rotate1:
caseAnimationTypes.Rotate2:
TransformGroupgrp = (m_AnimationStoryboards["Rotate1TranGroup"]as TransformGroup).Clone();
ScaleTransformscaleTran = grp.Children[0] as ScaleTransform;
scaleTran.CenterX = width /2;
scaleTran.CenterY = width /2;
RotateTransformrotateTran = grp.Children[1] as RotateTransform;
rotateTran.CenterX = height/ 2;
rotateTran.CenterY = height/ 2;
returngrp;
default:
returnnull;
}
}
private StoryboardGetStoryboard(AnimationTypes aniType)
{
switch (aniType)
{
caseAnimationTypes.Rotate1:
return(m_AnimationStoryboards["Rotate1Storyboard"]as Storyboard).Clone();
caseAnimationTypes.Rotate2:
return(m_AnimationStoryboards["Rotate2Storyboard"]as Storyboard).Clone();
default:
returnnull;
}
}
}
}
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TransformGroup x:Key="Rotate1TranGroup">
<ScaleTransform ScaleX="1" ScaleY="1"/>
<RotateTransform Angle="0"/>
</TransformGroup>
<Storyboard x:Key="Rotate1Storyboard">
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0.2" To="1" Duration="0:0:2.5">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
From="70" To="0" Duration="0:0:2">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
From="0" To="1" Duration="0:0:2"
AccelerationRatio="1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
From="0" To="1" Duration="0:0:2"
AccelerationRatio="1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
To="0.98" BeginTime="0:0:2" Duration="0:0:0.05"
DecelerationRatio="1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
To="0.98" BeginTime="0:0:2" Duration="0:0:0.05"
DecelerationRatio="1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
To="1" BeginTime="0:0:2.05" Duration="0:0:0.2"
AccelerationRatio="1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
To="1" BeginTime="0:0:2.05" Duration="0:0:0.2"
AccelerationRatio="1">
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="Rotate2Storyboard">
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
To="360" Duration="0:0:1.5">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:3">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
To="0" Duration="0:0:1.5" AccelerationRatio="1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
To="0" Duration="0:0:1.5" AccelerationRatio="1">
</DoubleAnimation>
</Storyboard>
</ResourceDictionary>