WPF中动画教程(DoubleAnimation的基本使用)

简介: WPF中动画教程(DoubleAnimation的基本使用)

实现效果

今天以一个交互式小球的例子跟大家分享一下wpf动画中DoubleAnimation的基本使用。该小球会移动到我们鼠标左键或右键点击的地方。

该示例的实现效果如下所示:

页面设计

xaml如下所示:

<Window x:Class="AnimationDemo.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:AnimationDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <DockPanel>
        <Border x:Name="_containerBorder" Background="Transparent">
            <Ellipse x:Name="_interactiveEllipse"
         Fill="Lime"
         Stroke="Black"
         StrokeThickness="2.0"
         Width="25"
         Height="25"
         HorizontalAlignment="Left"
         VerticalAlignment="Top" />
        </Border>
    </DockPanel>
</Window>

就是在DockPanel中包含一个Border,在Border中包含一个圆形。

页面设计的效果如下所示:

一些设置

相关设置的cs代码如下所示:

public partial class MainWindow : Window
 {
     private readonly TranslateTransform _interactiveTranslateTransform;
     public MainWindow()
     {
         InitializeComponent();
         _interactiveTranslateTransform = new TranslateTransform();
         _interactiveEllipse.RenderTransform =
             _interactiveTranslateTransform;
         _containerBorder.MouseLeftButtonDown +=
            border_mouseLeftButtonDown;
         _containerBorder.MouseRightButtonDown +=
             border_mouseRightButtonDown;
     }
private readonly TranslateTransform _interactiveTranslateTransform;

首先声明了一个私有的只读的TranslateTransform类型的对象_interactiveTranslateTransform,然后在MainWindow的构造函数中赋值。

_interactiveTranslateTransform = new TranslateTransform();

TranslateTransform是什么?有什么作用呢?

它的基本结构:

//
 // 摘要:
 //     Translates (moves) an object in the 2-D x-y coordinate system.
 public sealed class TranslateTransform : Transform
 {
     public static readonly DependencyProperty XProperty;
  
     public static readonly DependencyProperty YProperty;
     public TranslateTransform();
   
     public TranslateTransform(double offsetX, double offsetY);
     public override Matrix Value { get; }
   
     public double X { get; set; }
  
     public double Y { get; set; }
     public TranslateTransform Clone();
 
     public TranslateTransform CloneCurrentValue();
     protected override Freezable CreateInstanceCore();
 }

TranslateTransform 是 WPF 中的一个类,它表示一个 2D 平移变换。这个类是 Transform 类的派生类,用于在 2D 平面上移动(平移)对象。

TranslateTransform 类有两个主要的属性:X 和 Y,它们分别表示在 X 轴和 Y 轴上的移动距离。例如,如果你设置 X 为 100 和 Y 为 200,那么应用这个变换的元素将会向右移动 100 像素,向下移动 200 像素。

_interactiveEllipse.RenderTransform =
             _interactiveTranslateTransform;

_interactiveEllipse元素的RenderTransform属性设置为_interactiveTranslateTransform

RenderTransform属性用于获取或设置影响 UIElement 呈现位置的转换信息。

_containerBorder.MouseLeftButtonDown +=
    border_mouseLeftButtonDown;
 _containerBorder.MouseRightButtonDown +=
     border_mouseRightButtonDown;

这是在注册_containerBorder的鼠标左键点击事件与鼠标右键点击事件。

注意当Border这样写时,不会触发鼠标点击事件:

<Border x:Name="_containerBorder">

这是因为在 WPF 中,Border 控件的背景默认是透明的,这意味着它不会接收鼠标事件。当你设置了背景颜色后,Border 控件就会开始接收鼠标事件,因为它现在有了一个可见的背景。

如果你希望 Border 控件在没有背景颜色的情况下也能接收鼠标事件,你可以将背景设置为透明色。这样,虽然背景看起来是透明的,但它仍然会接收鼠标事件。

可以这样设置:

<Border x:Name="_containerBorder" Background="Transparent">

鼠标点击事件处理程序

以鼠标左键点击事件处理程序为例,进行说明:

private void border_mouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  {
      var clickPoint = Mouse.GetPosition(_containerBorder);
      // Set the target point so the center of the ellipse
      // ends up at the clicked point.
      var targetPoint = new Point
      {
          X = clickPoint.X - _interactiveEllipse.Width / 2,
          Y = clickPoint.Y - _interactiveEllipse.Height / 2
      };
      // Animate to the target point.
      var xAnimation =
          new DoubleAnimation(targetPoint.X,
              new Duration(TimeSpan.FromSeconds(4)));
      _interactiveTranslateTransform.BeginAnimation(
          TranslateTransform.XProperty, xAnimation, HandoffBehavior.SnapshotAndReplace);
      var yAnimation =
          new DoubleAnimation(targetPoint.Y,
              new Duration(TimeSpan.FromSeconds(4)));
      _interactiveTranslateTransform.BeginAnimation(
          TranslateTransform.YProperty, yAnimation, HandoffBehavior.SnapshotAndReplace);
      // Change the color of the ellipse.
      _interactiveEllipse.Fill = Brushes.Lime;
  }

重点是:

// Animate to the target point.
      var xAnimation =
          new DoubleAnimation(targetPoint.X,
              new Duration(TimeSpan.FromSeconds(4)));
      _interactiveTranslateTransform.BeginAnimation(
          TranslateTransform.XProperty, xAnimation, HandoffBehavior.SnapshotAndReplace);
      var yAnimation =
          new DoubleAnimation(targetPoint.Y,
              new Duration(TimeSpan.FromSeconds(4)));
      _interactiveTranslateTransform.BeginAnimation(
          TranslateTransform.YProperty, yAnimation, HandoffBehavior.SnapshotAndReplace);

DoubleAnimation类的介绍:

DoubleAnimation 是 WPF 中的一个类,它用于创建从一个 double 值到另一个 double 值的动画。这个类是 AnimationTimeline 类的派生类,它可以用于任何接受 double 类型的依赖属性。

DoubleAnimation 类有几个重要的属性:

• From:动画的起始值。

• To:动画的结束值。

• By:动画的增量值,用于从 From 值增加或减少。

• Duration:动画的持续时间。

• AutoReverse:一个布尔值,指示动画是否在到达 To 值后反向运行回 From 值。

• RepeatBehavior:定义动画的重复行为,例如,它可以设置为无限重复或重复特定的次数。

var xAnimation =
          new DoubleAnimation(targetPoint.X,
              new Duration(TimeSpan.FromSeconds(4)));

我们使用的是这种形式的重载:

设置了一个要达到的double类型值与达到的时间,这里设置为了4秒。

_interactiveTranslateTransform.BeginAnimation(
          TranslateTransform.XProperty, xAnimation, HandoffBehavior.SnapshotAndReplace);

• _interactiveTranslateTransform.BeginAnimation:这是 BeginAnimation 方法的调用,它开始一个动画,该动画会改变一个依赖属性的值。在这个例子中,改变的是 _interactiveTranslateTransform 对象的 X 属性。

• TranslateTransform.XProperty:这是 TranslateTransform 类的 X 依赖属性。这个属性表示在 X 轴上的移动距离。

• xAnimation:这是一个 DoubleAnimation 对象,它定义了动画的目标值和持续时间。在这个例子中,动画的目标值是鼠标点击的位置,持续时间是 4 秒。

• HandoffBehavior.SnapshotAndReplace:这是 HandoffBehavior 枚举的一个值,它定义了当新动画开始时,如何处理正在进行的动画。SnapshotAndReplace 表示新动画将替换旧动画,并从旧动画当前的值开始。

全部代码

xaml:

<Window x:Class="AnimationDemo.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:AnimationDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <DockPanel>
        <Border x:Name="_containerBorder" Background="Transparent">
            <Ellipse x:Name="_interactiveEllipse"
         Fill="Lime"
         Stroke="Black"
         StrokeThickness="2.0"
         Width="25"
         Height="25"
         HorizontalAlignment="Left"
         VerticalAlignment="Top" />
        </Border>
    </DockPanel>
</Window>

cs:

using System.Text;
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.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace AnimationDemo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly TranslateTransform _interactiveTranslateTransform;
        public MainWindow()
        {
            InitializeComponent();
            _interactiveTranslateTransform = new TranslateTransform();
            _interactiveEllipse.RenderTransform =
                _interactiveTranslateTransform;
            _containerBorder.MouseLeftButtonDown +=
               border_mouseLeftButtonDown;
            _containerBorder.MouseRightButtonDown +=
                border_mouseRightButtonDown;
        }
        private void border_mouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var clickPoint = Mouse.GetPosition(_containerBorder);
            // Set the target point so the center of the ellipse
            // ends up at the clicked point.
            var targetPoint = new Point
            {
                X = clickPoint.X - _interactiveEllipse.Width / 2,
                Y = clickPoint.Y - _interactiveEllipse.Height / 2
            };
            // Animate to the target point.
            var xAnimation =
                new DoubleAnimation(targetPoint.X,
                    new Duration(TimeSpan.FromSeconds(4)));
            _interactiveTranslateTransform.BeginAnimation(
                TranslateTransform.XProperty, xAnimation, HandoffBehavior.SnapshotAndReplace);
            var yAnimation =
                new DoubleAnimation(targetPoint.Y,
                    new Duration(TimeSpan.FromSeconds(4)));
            _interactiveTranslateTransform.BeginAnimation(
                TranslateTransform.YProperty, yAnimation, HandoffBehavior.SnapshotAndReplace);
            // Change the color of the ellipse.
            _interactiveEllipse.Fill = Brushes.Lime;
        }
        private void border_mouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            // Find the point where the use clicked.
            var clickPoint = Mouse.GetPosition(_containerBorder);
            // Set the target point so the center of the ellipse
            // ends up at the clicked point.
            var targetPoint = new Point
            {
                X = clickPoint.X - _interactiveEllipse.Width / 2,
                Y = clickPoint.Y - _interactiveEllipse.Height / 2
            };
            // Animate to the target point.
            var xAnimation =
                new DoubleAnimation(targetPoint.X,
                    new Duration(TimeSpan.FromSeconds(4)));
            _interactiveTranslateTransform.BeginAnimation(
                TranslateTransform.XProperty, xAnimation, HandoffBehavior.Compose);
            var yAnimation =
                new DoubleAnimation(targetPoint.Y,
                    new Duration(TimeSpan.FromSeconds(4)));
            _interactiveTranslateTransform.BeginAnimation(
                TranslateTransform.YProperty, yAnimation, HandoffBehavior.Compose);
            // Change the color of the ellipse.
            _interactiveEllipse.Fill = Brushes.Orange;
        }
    }
}

实现效果:

参考

1、Microsoft Learn:培养开拓职业生涯新机遇的技能

2、WPF-Samples/Animation/LocalAnimations/InteractiveAnimationExample.cs at main · microsoft/WPF-Samples (github.com)

目录
相关文章
|
3月前
|
算法 C# Windows
不可不知的WPF动画(Animation)
【9月更文挑战第19天】在 WPF(Windows Presentation Foundation)中,动画能为应用程序增添生动性和交互性。主要类型包括线性动画和关键帧动画,可针对依赖属性和自定义属性操作。触发方式有事件触发和自动触发,支持暂停、恢复及停止控制。合理使用这些功能并注意性能优化,可创建引人入胜的用户界面。
|
4月前
|
C# UED 开发者
WPF与性能优化:掌握这些核心技巧,让你的应用从卡顿到丝滑,彻底告别延迟,实现响应速度质的飞跃——从布局到动画全面剖析与实例演示
【8月更文挑战第31天】本文通过对比优化前后的方法,详细探讨了提升WPF应用响应速度的策略。文章首先分析了常见的性能瓶颈,如复杂的XAML布局、耗时的事件处理、不当的数据绑定及繁重的动画效果。接着,通过具体示例展示了如何简化XAML结构、使用后台线程处理事件、调整数据绑定设置以及利用DirectX优化动画,从而有效提升应用性能。通过这些优化措施,WPF应用将更加流畅,用户体验也将得到显著改善。
306 1
|
4月前
|
C# UED 开发者
WPF动画大揭秘:掌握动画技巧,让你的界面动起来,告别枯燥与乏味!
【8月更文挑战第31天】在WPF应用开发中,动画能显著提升用户体验,使其更加生动有趣。本文将介绍WPF动画的基础知识和实现方法,包括平移、缩放、旋转等常见类型,并通过示例代码展示如何使用`DoubleAnimation`创建平移动画。此外,还将介绍动画触发器的使用,帮助开发者更好地控制动画效果,提升应用的吸引力。
230 0
|
4月前
|
存储 C# 数据格式
WPF动画教程(PointAnimationUsingPath的使用)
WPF动画教程(PointAnimationUsingPath的使用)
57 0
|
7月前
|
C#
WPF —— 动画缩放变换
`ScaleTransform`用于二维x-y坐标系中对象的缩放,可沿X或Y轴调整。在故事板中,通过RenderTransform.ScaleX和ScaleY属性控制缩放。示例代码展示了如何设置按钮的RenderTransformOrigin、Background等属性,并通过LayoutTransform应用ScaleTransform。当鼠标进入按钮时,EventTrigger启动DoubleAnimation实现X和Y轴的缩放动画。最后,展示了如何将动画集成到自定义按钮样式中。
192 0
|
C#
WPF技术之动画系列-上下运动
本例子展现动画小球上下循环运动
228 0
|
C# 索引
WPF简单模拟QQ登录背景动画
原文:WPF简单模拟QQ登录背景动画 介绍 之所以说是简单模拟,是因为我不知道QQ登录背景动画是怎么实现的.这里是通过一些办法把它简化了,做成了类似的效果 效果图   大体思路 首先把背景看成是一个4行8列的点的阵距,X轴Y轴都是距离70.
1276 0
|
C#
WPF中的PathAnimation(路径动画)
原文:WPF中的PathAnimation(路径动画)                                   WPF中的PathAnimation(路径动画)                                                               周...
1439 0
|
API C# 索引
WPF中的动画——(一)基本概念
原文:WPF中的动画——(一)基本概念 WPF的一个特点就是支持动画,我们可以非常容易的实现漂亮大方的界面。首先,我们来复习一下动画的基本概念。计算机中的动画一般是定格动画,也称之为逐帧动画,它通过每帧不同的图像连续播放,从而欺骗眼和脑产生动画效果。
1082 0
|
C# 测试技术
WPF中的动画——(二)From/To/By 动画
原文:WPF中的动画——(二)From/To/By 动画 我们所实现的的动画中,很大一部分是让一个属性在起始值和结束值之间变化,例如,我在前文中实现的改变宽度的动画:     var widthAnimation = new DoubleAnimation()    {        From = 0,        To = 320,        Duration = TimeSpan.
1011 0