You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WPF项目中通过Style实现按钮点击涟漪动画效果

WPF按钮点击涟漪动画Style实现方案

直接上可复用的实现代码,把这段代码放到你的资源字典或者Window/UserControl的Resources里就能用:

<Style x:Key="RippleButtonStyle" TargetType="local:RippleButton">
    <Setter Property="Background" Value="#E0E0E0"/>
    <Setter Property="Foreground" Value="#333333"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Padding" Value="16,8"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:RippleButton">
                <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                    <!-- 按钮内容容器 -->
                    <ContentPresenter 
                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                        Margin="{TemplateBinding Padding}"/>
                    <!-- 涟漪动画元素 -->
                    <Ellipse x:Name="RippleEllipse" 
                             Fill="#80FFFFFF" 
                             Opacity="0"
                             RenderTransformOrigin="0.5,0.5"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="MouseDown">
                        <BeginStoryboard>
                            <Storyboard>
                                <!-- 设置涟漪初始位置为点击坐标 -->
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RippleEllipse"
                                                               Storyboard.TargetProperty="(Canvas.Left)">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MouseDownPosition.X}"/>
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RippleEllipse"
                                                               Storyboard.TargetProperty="(Canvas.Top)">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MouseDownPosition.Y}"/>
                                </DoubleAnimationUsingKeyFrames>
                                <!-- 涟漪缩放动画 -->
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RippleEllipse"
                                                               Storyboard.TargetProperty="Width">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="300"/>
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RippleEllipse"
                                                               Storyboard.TargetProperty="Height">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="300"/>
                                </DoubleAnimationUsingKeyFrames>
                                <!-- 涟漪淡出动画 -->
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RippleEllipse"
                                                               Storyboard.TargetProperty="Opacity">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="0.6"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="0"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <!-- 按钮按压状态背景变化 -->
                    <Trigger Property="IsPressed" Value="True">
                        <Setter TargetName="RootGrid" Property="Background" Value="#C0C0C0"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

配套代码说明

需要给Button添加自定义依赖属性来记录点击位置,新建一个类:

public class RippleButton : Button
{
    public static readonly DependencyProperty MouseDownPositionProperty =
        DependencyProperty.Register("MouseDownPosition", typeof(Point), typeof(RippleButton), new PropertyMetadata(new Point(0, 0)));

    public Point MouseDownPosition
    {
        get { return (Point)GetValue(MouseDownPositionProperty); }
        set { SetValue(MouseDownPositionProperty, value); }
    }

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        // 记录点击时相对于按钮的坐标
        MouseDownPosition = e.GetPosition(this);
    }
}

调整与使用

  • 可以修改动画的KeyTime(持续时长)、椭圆Fill颜色、最终Width/Height来适配不同按钮的尺寸和视觉需求
  • 在XAML中引用自定义按钮并应用Style:
<local:RippleButton Style="{StaticResource RippleButtonStyle}" Content="点击触发涟漪"/>

内容的提问来源于stack exchange,提问作者beiduoan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:17:17