實(shí)現(xiàn)效果
今天以一個(gè)交互式小球的例子跟大家分享一下wpf動(dòng)畫中DoubleAnimation
的基本使用。該小球會(huì)移動(dòng)到我們鼠標(biāo)左鍵或右鍵點(diǎn)擊的地方。
該示例的實(shí)現(xiàn)效果如下所示:

頁面設(shè)計(jì)
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
中包含一個(gè)Border
,在Border
中包含一個(gè)圓形。
頁面設(shè)計(jì)的效果如下所示:

一些設(shè)置
相關(guān)設(shè)置的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;
首先聲明了一個(gè)私有的只讀的TranslateTransform
類型的對(duì)象_interactiveTranslateTransform
,然后在MainWindow的構(gòu)造函數(shù)中賦值。
_interactiveTranslateTransform = new TranslateTransform();
TranslateTransform
是什么?有什么作用呢?

它的基本結(jié)構(gòu):
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 中的一個(gè)類,它表示一個(gè) 2D 平移變換。這個(gè)類是 Transform 類的派生類,用于在 2D 平面上移動(dòng)(平移)對(duì)象。
TranslateTransform 類有兩個(gè)主要的屬性:X 和 Y,它們分別表示在 X 軸和 Y 軸上的移動(dòng)距離。例如,如果你設(shè)置 X 為 100 和 Y 為 200,那么應(yīng)用這個(gè)變換的元素將會(huì)向右移動(dòng) 100 像素,向下移動(dòng) 200 像素。
_interactiveEllipse.RenderTransform =
_interactiveTranslateTransform;
將 _interactiveEllipse
元素的RenderTransform
屬性設(shè)置為_interactiveTranslateTransform
。

RenderTransform
屬性用于獲取或設(shè)置影響 UIElement 呈現(xiàn)位置的轉(zhuǎn)換信息。
_containerBorder.MouseLeftButtonDown +=
border_mouseLeftButtonDown;
_containerBorder.MouseRightButtonDown +=
border_mouseRightButtonDown;
這是在注冊(cè)_containerBorder
的鼠標(biāo)左鍵點(diǎn)擊事件與鼠標(biāo)右鍵點(diǎn)擊事件。


注意當(dāng)Border這樣寫時(shí),不會(huì)觸發(fā)鼠標(biāo)點(diǎn)擊事件:
<Border x:Name="_containerBorder">
這是因?yàn)樵?WPF 中,Border 控件的背景默認(rèn)是透明的,這意味著它不會(huì)接收鼠標(biāo)事件。當(dāng)你設(shè)置了背景顏色后,Border 控件就會(huì)開始接收鼠標(biāo)事件,因?yàn)樗F(xiàn)在有了一個(gè)可見的背景。
如果你希望 Border 控件在沒有背景顏色的情況下也能接收鼠標(biāo)事件,你可以將背景設(shè)置為透明色。這樣,雖然背景看起來是透明的,但它仍然會(huì)接收鼠標(biāo)事件。
可以這樣設(shè)置:
<Border x:Name="_containerBorder" Background="Transparent">
鼠標(biāo)點(diǎn)擊事件處理程序
以鼠標(biāo)左鍵點(diǎn)擊事件處理程序?yàn)槔?,進(jìn)行說明:
private void border_mouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var clickPoint = Mouse.GetPosition(_containerBorder);
var targetPoint = new Point
{
X = clickPoint.X - _interactiveEllipse.Width / 2,
Y = clickPoint.Y - _interactiveEllipse.Height / 2
};
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);
_interactiveEllipse.Fill = Brushes.Lime;
}
重點(diǎn)是:
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 中的一個(gè)類,它用于創(chuàng)建從一個(gè) double 值到另一個(gè) double 值的動(dòng)畫。這個(gè)類是 AnimationTimeline 類的派生類,它可以用于任何接受 double 類型的依賴屬性。
DoubleAnimation 類有幾個(gè)重要的屬性:
? From:動(dòng)畫的起始值。
? To:動(dòng)畫的結(jié)束值。
? By:動(dòng)畫的增量值,用于從 From 值增加或減少。
? Duration:動(dòng)畫的持續(xù)時(shí)間。
? AutoReverse:一個(gè)布爾值,指示動(dòng)畫是否在到達(dá) To 值后反向運(yùn)行回 From 值。
? RepeatBehavior:定義動(dòng)畫的重復(fù)行為,例如,它可以設(shè)置為無限重復(fù)或重復(fù)特定的次數(shù)。
var xAnimation =
new DoubleAnimation(targetPoint.X,
new Duration(TimeSpan.FromSeconds(4)));
我們使用的是這種形式的重載:

設(shè)置了一個(gè)要達(dá)到的double類型值與達(dá)到的時(shí)間,這里設(shè)置為了4秒。
_interactiveTranslateTransform.BeginAnimation(
TranslateTransform.XProperty, xAnimation, HandoffBehavior.SnapshotAndReplace);

? _interactiveTranslateTransform.BeginAnimation:這是 BeginAnimation 方法的調(diào)用,它開始一個(gè)動(dòng)畫,該動(dòng)畫會(huì)改變一個(gè)依賴屬性的值。在這個(gè)例子中,改變的是 _interactiveTranslateTransform 對(duì)象的 X 屬性。
? TranslateTransform.XProperty:這是 TranslateTransform 類的 X 依賴屬性。這個(gè)屬性表示在 X 軸上的移動(dòng)距離。
? xAnimation:這是一個(gè) DoubleAnimation 對(duì)象,它定義了動(dòng)畫的目標(biāo)值和持續(xù)時(shí)間。在這個(gè)例子中,動(dòng)畫的目標(biāo)值是鼠標(biāo)點(diǎn)擊的位置,持續(xù)時(shí)間是 4 秒。
? HandoffBehavior.SnapshotAndReplace:這是 HandoffBehavior 枚舉的一個(gè)值,它定義了當(dāng)新動(dòng)畫開始時(shí),如何處理正在進(jìn)行的動(dòng)畫。SnapshotAndReplace 表示新動(dòng)畫將替換舊動(dòng)畫,并從舊動(dòng)畫當(dāng)前的值開始。
全部代碼
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
{
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);
var targetPoint = new Point
{
X = clickPoint.X - _interactiveEllipse.Width / 2,
Y = clickPoint.Y - _interactiveEllipse.Height / 2
};
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);
_interactiveEllipse.Fill = Brushes.Lime;
}
private void border_mouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
var clickPoint = Mouse.GetPosition(_containerBorder);
var targetPoint = new Point
{
X = clickPoint.X - _interactiveEllipse.Width / 2,
Y = clickPoint.Y - _interactiveEllipse.Height / 2
};
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);
_interactiveEllipse.Fill = Brushes.Orange;
}
}
}
實(shí)現(xiàn)效果:

轉(zhuǎn)自https://www.cnblogs.com/mingupupu/p/18108029
該文章在 2025/3/19 8:58:21 編輯過