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
其他阅读

C#中new和override的区别

在C#编程语言中,new 和 override 是两个重要的关键字,它们用于控制类成员方法的行为。在面向对象编程(OOP)中,理解这两个关键字的区别和用法,对于编写清晰、可维护和高效的代码至关重要。

查看原文

使用表达式树来提高反射的性能

反射是C#中一种常用的技术,反射提供了动态创建和访问对象的基础,但是反射在带来了极强的灵活性的同时,也带了极大的性能损耗,本文就介绍通过表达式树来提高反射过程中的性能。

查看原文

Nginx配置反向代理和负载均衡

Nginx是一个流行的Web容器,作为服务的入口,使用反向代理和负载均衡,达到隐藏和保护内部服务安全的作用,本文会描述Nginx反向代理和负载均衡的配置。

查看原文

Web前端中实现一个拖动效果

在原生客户端开发中,窗口拖动是一个比较常用的操作。今天把这个效果在网页客户端中实现以下,文章记录一下效果。

查看原文

Winform中设置控件边框

本文将会介绍在Winform中如何设置控件的边框,可应用于Form和Panel等。

查看原文