实现效果

今天以一个交互式小球的例子跟大家分享一下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)

WPF中动画教程(DoubleAnimation的基本使用)的更多相关文章

  1. WPF利用动画实现圆形进度条

    原文:WPF利用动画实现圆形进度条 这是我的第一篇随笔,最近因为工作需要,开始学习WPF相关技术,自己想实现以下圆形进度条的效果,逛了园子发现基本都是很久以前的文章,实现方式一般都是GDI实现的,想到 ...

  2. WPF中的动画——(三)时间线(TimeLine)

    WPF中的动画——(三)时间线(TimeLine) 时间线(TimeLine)表示时间段. 它提供的属性可以让控制该时间段的长度.开始时间.重复次数.该时间段内时间进度的快慢等等.在WPF中内置了如下 ...

  3. WPF异步载入图片,附带载入中动画

    原文:WPF异步载入图片,附带载入中动画 WPF异步载入图片,附带载入中动画 最近,在做一个WPF项目.项目中有一个需求,就是以列表的方式显示出项目图片.这些图片有的存在于互联网上,有的存在于本地磁盘 ...

  4. WPF中的DoubleAnimation

    原文:WPF中的DoubleAnimation WPF中的DoubleAnimation                                                         ...

  5. (转载)WPF中的动画——(一)基本概念

    http://www.cnblogs.com/TianFang/p/4050845.html WPF的一个特点就是支持动画,我们可以非常容易的实现漂亮大方的界面.首先,我们来复习一下动画的基本概念.计 ...

  6. WPF中的动画

    动画无疑是WPF中最吸引人的特色之一,其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互.这里我们讨论一下故事板. 在WPF中我们采用Storyboard(故事板)的方式来编写动画,为了对St ...

  7. WPF中的动画——(一)基本概念

    WPF的一个特点就是支持动画,我们可以非常容易的实现漂亮大方的界面.首先,我们来复习一下动画的基本概念.计算机中的动画一般是定格动画,也称之为逐帧动画,它通过每帧不同的图像连续播放,从而欺骗眼和脑产生 ...

  8. 【WPF学习笔记】[转]周银辉之WPF中的动画 && 晓风影天之wpf动画——new PropertyPath属性链

    (一)WPF中的动画 动画无疑是WPF中最吸引人的特色之一,其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互.这里我们讨论一下故事板. 在WPF中我们采用Storyboard(故事板)的方式 ...

  9. WPF中自动增加行(动画)的TextBox

    原文:WPF中自动增加行(动画)的TextBox WPF中自动增加行(动画)的TextBox WPF中的Textbox控件是可以自动换行的,只要设置TextWrapping属性为"Wrap& ...

  10. WPF中的PathAnimation(路径动画)

    原文:WPF中的PathAnimation(路径动画) WPF中的PathAnimation(路径动画)                                                 ...

随机推荐

  1. Redis 缓存过期删除/淘汰策略分析

    Redis 缓存过期删除/淘汰策略分析 Redis 缓存删除 Redis 键过期删除,定期删除(主动)和惰性删除(被动) Redis 内存不足时,缓存淘汰策略 key 键过期删除 我们用 redis ...

  2. 【Android逆向】脱壳项目frida_dump 原理分析

    脱dex核心文件dump_dex.js 核心函数 function dump_dex() { var libart = Process.findModuleByName("libart.so ...

  3. linux下安装nginx(编译安装)及反向代理及负载均衡

    首先卸载掉之前用yum命令下载的nginx yum remove nginx 安装nginx需要的依赖库 yum install -y gcc patch libffi-devel python-de ...

  4. 【八股cover#2】CPP语法 Q&A与知识点

    CPP语法 Q&A与知识点 简历cover 1.熟练使用C的指针应用及内存管理 指针与引用的区别 指针是一个存储地址的变量,可以有多级,可以为空,并且在初始化后可以改变指向: 引用是原变量的别 ...

  5. 【Azure 应用服务】遇见“无法创建hybrid connection for App Service”的解决办法

    Hybrid Connection (混合连接) 在两个联网应用程序之间启用了双向.请求-响应和二进制流通信以及简单的数据报流.通过混合连接,可以实现应用部署在公网环境中,而数据库保存在本地私网环境中 ...

  6. 2023 年值得一读的技术文章 | NebulaGraph 技术社区

    在之前的产品篇,我们了解到了 NebulaGraph 内核及周边工具在 2023 年经历了什么样的变化.伴随着这些特性的变更和上线,在[文章]博客分类中,一篇篇的博文记录下了这些功能背后的设计思考和研 ...

  7. Python基础之程序与用户交互

    [一]Python基础之程序与用户交互 [一]程序如何与用户交互 用户通过input命令在窗口内与输入就可以让用户和窗口进行交流 input接受的所有数据类型都是 str 类型 username = ...

  8. Spring事务(二)-@Transactional注解

    上一节说了Spring的事务配置,其中,声明式事务配置里有5种配置方式, @Transactional注解应该是最为常用的一种方式了.这一节就说说@Transactional注解. @Transact ...

  9. 一个简单的spdlog使用示例

    目录 引用源码 封装Log头文件 使用方法 spdlog是一个开源.跨平台.无依赖.只有头文件的C++11日志库,网上介绍的文章有很多这里就不过多的介绍了,GitHub链接:https://githu ...

  10. 玩转Vue3之深入理解响应式编程

    前言 Vue 3是一个功能强大的前端框架,它引入了一些令人兴奋的新特性,其中最引人注目的是ref和reactive.这两个API是Vue 3中响应式编程的核心,本文将深入探讨它们的用法和差异. 什么是 ...