WPF实现动画的方式:
- 基于计时器的动画
建立一个定时器,然后根据其频率循环调用函数或者一个事件处理函数,在这个函数中可以手工更新目标属性,直到达到最终值,这时可以停止计时器。
案例:
效果图:
XAML:
<Window x:Class="WpfDispatcherTimerAnimation.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfDispatcherTimerAnimation" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Ellipse Name="rectangle" Height="20" Width="20" Fill="Aquamarine"/>
<Button Content="开启动画" Click="ButtonBase_OnClick" Height="30" Width="90" Grid.Row="1"/>
</Grid>
</Window>
C#代码:
using System;
using System.Windows;
using System.Windows.Threading;
namespace WpfDispatcherTimerAnimation
{ /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window {
public MainWindow()
{
InitializeComponent();
}
/// <summary> /// 长方形减小计时器 /// </summary>
DispatcherTimer dispatcherTimerDecrease = new DispatcherTimer();
/// <summary> ///
长方形增大计时器 ///
</summary>
DispatcherTimer dispatcherTimerIncrease = new DispatcherTimer(); /// <summary>
/// 按钮点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { dispatcherTimerIncrease.Interval = TimeSpan.FromMilliseconds(30); dispatcherTimerIncrease.Tick += dispatcherTimerIncrease_Tick; dispatcherTimerIncrease.Start(); dispatcherTimerDecrease.Interval = TimeSpan.FromMilliseconds(30); dispatcherTimerDecrease.Tick += DispatcherTimerDecrease_Tick; }
/// <summary>
/// 增加计时器事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DispatcherTimerDecrease_Tick(object sender, EventArgs e)
{ if (rectangle.Width < 20 || rectangle.Height < 20)
{ (sender as DispatcherTimer).Stop();
dispatcherTimerIncrease.Start();
}
else if (rectangle.Width >= 20 || rectangle.Height >= 20)
{ rectangle.Width -= 5; rectangle.Height -= 5; }
}
/// <summary>
/// 减少计时器事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dispatcherTimerIncrease_Tick(object sender, EventArgs e)
{ if (rectangle.Width < 200 || rectangle.Height < 200)
{ rectangle.Width += 5; rectangle.Height += 5; }
else if (rectangle.Width >= 200 || rectangle.Height >= 200)
{
(sender as DispatcherTimer).Stop();
dispatcherTimerDecrease.Start();
}
}
}
}
2.基于桢的动画
由CompositionTarget类来完成,它提供了一个回调函数(Rendering的事件处理函数),WPF会在每次界面刷新时调用该回调函数。CompositionTarget的刷新率与窗体保持一致,因此很难人工控制动画的快慢。
案例:
效果图:
XAML:
<Window x:Class="Wpf基于桢的动画.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf基于桢的动画" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Ellipse Name="ellipse" Height="20" Width="20" Fill="Aquamarine"/>
<Button Grid.Row="1" Content="开启动画" Height="30" Width="90" Click="ButtonBase_OnClick" />
</Grid>
</Window>
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace Wpf基于桢的动画
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
CompositionTarget.Rendering+=new EventHandler(CompositionTarget_Rendering);
}
private void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (ellipse.Width < 200 || ellipse.Height < 200)
{
ellipse.Width += 5;
ellipse.Height += 5;
}
else if (ellipse.Width >= 200 || ellipse.Height >= 200)
{
CompositionTarget.Rendering-=new EventHandler(CompositionTarget_Rendering);
}
}
}
}
3.基于属性的动画
用一个DoubleAnimation类制定起始值(From=“”)、终点值To=“”、时间(Duration=“0:0:2.7”),以及动画结束应该(FillBehavior=”Stop”)。设置好之后该矩形调用BeginAnimation方法开始实现动画,BeginAnimation制定需要应用动画的属性和创建的DoubleAnimation。
案例:
效果图:
XAML:
<Window x:Class="Wpf基于属性的动画.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf基于属性的动画" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
<Grid >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Ellipse Name="ellipse" Height="20" Width="20" Fill="Aquamarine"/>
<Button Grid.Row="1" Content="开启动画" Height="30" Width="90" Click="ButtonBase_OnClick" />
</Grid>
</Window>
C#:
using System; using System.Windows; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace Wpf基于属性的动画
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{ public MainWindow() { InitializeComponent(); }
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{ DoubleAnimation doubleAnimation=new DoubleAnimation();
doubleAnimation.From = 20;
doubleAnimation.To = 200;
doubleAnimation.Duration = TimeSpan.FromMilliseconds(10000); doubleAnimation.FillBehavior = FillBehavior.Stop; ellipse.BeginAnimation(Ellipse.WidthProperty,doubleAnimation);
DoubleAnimation doubleAnimation1 = new DoubleAnimation();
doubleAnimation1.From = 20;
doubleAnimation1.To = 200;
doubleAnimation1.Duration = TimeSpan.FromMilliseconds(10000); doubleAnimation1.FillBehavior = FillBehavior.Stop; ellipse.BeginAnimation(Ellipse.HeightProperty, doubleAnimation);
}
}
}