WPF中创建一个矩形圆角动画

WPF 中内置了好几种动画,大多数场景可以坐到开箱即用,不过并没有内置 CornerRadiusAnimation ,本文将会介绍怎么实现一个 CornerRadiusAnimation 动画,实现 BorderCornerRadius 属性动画效果。

动画类 CornerRadiusAnimation

WPF 中,所有的动画都是继承于 AnimationTimeline 类型,我们自定义的 CornerRadiusAnimation 类也应该继承于该类。

public class CornerRadiusAnimation : AnimationTimeline
{
    
}

照猫画虎,在动画中,我们需要定义一个 From ,一个 To ,用来表示动画的初始状态和结束状态,我们的动画是应用于 CornerRadius 属性,那 FromTo 都应该是 CornerRadius 类型。然后注册对应的依赖属性,用于在 xaml 中进行绑定。

public CornerRadius From
{
    get => (CornerRadius)GetValue(FromProperty);
    set => SetValue(FromProperty, value);
}

public static readonly DependencyProperty FromProperty = DependencyProperty.Register("From", typeof(CornerRadius), typeof(CornerRadiusAnimation));

public CornerRadius To
{
    get => (CornerRadius)GetValue(ToProperty);
    set => SetValue(ToProperty, value);   
}

public static readonly DependencyProperty ToProperty = DependencyProperty.Register("To", typeof(CornerRadius), typeof(CornerRadiusAnimation));

接下来,我们要对基类的属性和方法进行重写, TargetPropertyType 属性用来定义我们的动画需要作用的类型,CreateInstanceCore() 方法实现了创建动画实例,GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock) 方法实现了当前的值,在动画播放时会被重复调用,达到动画效果。

public override Type TargetPropertyType => typeof(CornerRadius);


public override Freezable CreateInstanceCore(){
    return new CornerRadiusAnimation();
}


public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
{
    if(animationClock.CurrentProgress == null)
    {
        return From;
    }

    double progress = animationClock.CurrentProgress.Value;

    return new CornerRadius(
        From.TopLeft + (To.TopLeft = From.TopLeft) * progress,
        From.TopRight + (To.TopRight = From.TopRight ) * progress,
        From.BottomRight + (To.BottomRight = From.BottomRight ) * progress,
        From.BottomLeft + (To.BottomLeft = From.BottomLeft ) * progress
    );
}

使用

XAML

xaml 中定义一个 Border 控件,设置初始状态下的 CornerRadius 属性值,在资源中引入我们写好的 CornerRadiusAnimation ,设置 FromTo 属性值,这里设置为 0 和 30,预期结果是 Border 控件的会从直角矩形慢慢变成圆角矩形。

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Storyboard x:Key="CornerRadiusAnimation">
            <local:CornerRadiusAnimation Storyboard.TargetProperty="(Border.CornerRadius)" 
                                         Storyboard.TargetName="MyBorder" 
                                         From="0,0,0,0" To="30,30,30,30" 
                                         Duration="0:0:2" />
        </Storyboard>
    </Window.Resources>
    <Grid>
        <Border x:Name="MyBorder" Width="200" Height="200" Background="LightBlue" CornerRadius="0,0,0,0">
        </Border>
        <Button Content="播放" Margin="0,0,0,20" Click="Button_Click"/>
    </Grid>
</Window>

C#

在窗体的后台代码中,我们来实现 Button_Click 事件,在事件中调用动画对象的 Begin() 方法进行播放。

using System.Windows;
using System.Windows.Media.Animation;

namespace WpfApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Storyboard sb = (Storyboard)this.Resources["CornerRadiusAnimation"];
            sb.Begin();
        }
    }
}
发布时间:2024-11-27