WPF学习(动画)

文章目录

  • [一、图像变换 RenderTransform](#一、图像变换 RenderTransform)
      • 1、常见变换类型
      • [2、`RenderTransform` 的核心作用](#2、RenderTransform 的核心作用)
      • [3、`RenderTransform` 的使用方式](#3、RenderTransform 的使用方式)
      • [4、与 `LayoutTransform` 的对比](#4、与 LayoutTransform 的对比)
      • 5、在动画中的应用
  • [二、 滚动的椭圆](#二、 滚动的椭圆)
  • 三、Storyboard放置位置
      • [1. **元素的 `Resources` 集合**](#1. 元素的 Resources 集合)
      • [2. **控件模板(`ControlTemplate`)或数据模板(`DataTemplate`)中**](#2. 控件模板(ControlTemplate)或数据模板(DataTemplate)中)
      • [3. **窗口(`Window`)或页面(`Page`)的资源**](#3. 窗口(Window)或页面(Page)的资源)
      • [4. **应用程序资源(`App.xaml`)**](#4. 应用程序资源(App.xaml)
      • [5. **代码动态创建**](#5. 代码动态创建)
      • 选择建议
        • [示例代码: 旋转的按钮](#示例代码: 旋转的按钮)

一、图像变换 RenderTransform

在WPF中,RenderTransform 是一个重要的属性,用于对UI元素进行变换(Transformation) ,即在不改变元素实际位置和大小的情况下,改变其视觉呈现效果。常见的变换包括旋转、缩放、平移和倾斜
Render:使成为某种状态,使成为

1、常见变换类型

WPF提供了多种变换类,每种对应不同的效果:

变换类 作用 关键属性
RotateTransform 旋转元素 Angle(旋转角度,单位:度)
ScaleTransform 缩放元素 ScaleXScaleY(水平/垂直缩放比例)
TranslateTransform 平移元素(相对移动) XY(平移距离)
SkewTransform 倾斜元素 AngleXAngleY(水平/垂直倾斜角度)
MatrixTransform 自定义矩阵变换(高级用法) Matrix(变换矩阵)

2、RenderTransform 的核心作用

  1. 视觉效果增强

    通过变换可以创建动画、特效或调整元素的显示方式,而不影响布局系统。

    例如:旋转按钮、放大图像、倾斜文本等。

  2. 独立于布局

    变换只影响元素的渲染结果,不会改变元素在布局中的位置或占用空间。

    例如:将按钮旋转45度后,它仍占据原来的矩形区域。

  3. 组合多种变换

    可以通过 TransformGroup 组合多个变换,按顺序应用效果。

3、RenderTransform 的使用方式

  1. 单一变换示例(旋转)
xml 复制代码
<Button Content="旋转按钮" Width="100" Height="30">
    <Button.RenderTransform>
        <RotateTransform Angle="45" CenterX="50" CenterY="15" />
    </Button.RenderTransform>
</Button>
  • CenterXCenterY:指定旋转中心点(相对于元素左上角)。
  1. 组合变换示例(缩放 + 旋转)
xml 复制代码
<Ellipse Width="50" Height="50" Fill="Blue">
    <Ellipse.RenderTransform>
        <TransformGroup>
            <ScaleTransform ScaleX="1.5" ScaleY="0.8" />
            <RotateTransform Angle="30" />
        </TransformGroup>
    </Ellipse.RenderTransform>
</Ellipse>
  • 变换按顺序应用:先缩放,再旋转。

4、与 LayoutTransform 的对比

WPF中还有一个 LayoutTransform 属性,两者的区别如下:

属性 作用范围 对布局的影响 性能
RenderTransform 仅影响元素的渲染结果 不影响布局(占位不变) 较高(仅重绘)
LayoutTransform 影响元素的布局计算 改变元素占用空间 较低(触发布局更新)

5、在动画中的应用

RenderTransform 常与动画结合使用,实现动态效果。例如:

xml 复制代码
<Button Content="动画按钮" Width="100">
    <Button.RenderTransform>
        <RotateTransform x:Name="buttonRotate" Angle="0" />
    </Button.RenderTransform>
</Button>

<!-- 动画定义 -->
<Storyboard x:Key="RotateAnimation">
    <DoubleAnimation 
        Storyboard.TargetName="buttonRotate"
        Storyboard.TargetProperty="Angle"
        From="0" To="360" Duration="0:0:2"
        RepeatBehavior="Forever" />
</Storyboard>

六、注意事项

  1. 变换中心(Center)

    多数变换需要指定中心点(如旋转、缩放),默认值为 (0, 0)(元素左上角)。合理设置中心点可避免元素"漂移"。

  2. 性能考虑

    频繁使用复杂变换(尤其是 MatrixTransform)可能影响性能,建议适度使用。

  3. 坐标系

    变换基于元素自身的坐标系,而非父容器或全局坐标系。

总结
RenderTransform 是WPF中实现元素视觉变换的核心机制,通过它可以轻松创建旋转、缩放、平移等效果,为UI增添动态和交互性。结合动画系统,更能实现复杂的视觉过渡效果。

二、 滚动的椭圆

示例代码

xml 复制代码
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Ellipse Center 动画示例" Height="300" Width="400">
    <Grid>
                <!-- 定义动画资源 -->
                <Grid.Resources>
                    <Storyboard x:Key="RollingAnimation" RepeatBehavior="Forever">
                        <!-- 水平移动动画 -->
                        <DoubleAnimation 
                    Storyboard.TargetName="MyEllipse"
                    Storyboard.TargetProperty="(Canvas.Left)"
                    From="0" To="300" Duration="0:0:5"
                    AutoReverse="True" />

                        <!-- 旋转动画 - 模拟滚动效果 -->
                        <DoubleAnimation 
                    Storyboard.TargetName="EllipseRotateTransform"
                    Storyboard.TargetProperty="Angle"
                    From="0" To="360" Duration="0:0:1"
                    RepeatBehavior="Forever" />
                    </Storyboard>
                </Grid.Resources>

                <!-- 触发动画 -->
                <Grid.Triggers>
                    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                        <BeginStoryboard Storyboard="{StaticResource RollingAnimation}" />
                    </EventTrigger>
                </Grid.Triggers>

                <!-- 椭圆路径 -->
                <Canvas>
                    <Path Grid.Row="1" Stroke="red" StrokeThickness="2" x:Name="MyEllipse" Canvas.Left="0" Canvas.Top="100">
                        <Path.RenderTransform>
                            <RotateTransform x:Name="EllipseRotateTransform" CenterX="100" CenterY="100" />
                        </Path.RenderTransform>
                        <Path.Data>
                            <EllipseGeometry Center="100,100" RadiusX="50" RadiusY="20"/>
                        </Path.Data>
                    </Path>
                </Canvas>
            </Grid>
        </Window>

三、Storyboard放置位置

在WPF(Windows Presentation Foundation)中,Storyboard 是用于定义和控制动画的对象。它可以放在多个不同的位置,具体取决于你的使用场景和动画的作用范围。以下是常见的几种放置位置及其适用情况:

1. 元素的 Resources 集合

Storyboard 定义在元素的资源字典中,使其仅对该元素及其子元素可用。这种方式适合局部动画,例如按钮点击效果、控件加载动画等。

示例(按钮悬停动画)

xml 复制代码
<Button Content="Hover Me">
    <Button.Resources>
        <Storyboard x:Key="HoverStoryboard">
            <DoubleAnimation
                Storyboard.TargetProperty="Opacity"
                From="1.0" To="0.7" Duration="0:0:0.3"
                AutoReverse="True"/>
        </Storyboard>
    </Button.Resources>
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.MouseEnter">
            <BeginStoryboard Storyboard="{StaticResource HoverStoryboard}"/>
        </EventTrigger>
    </Button.Triggers>
</Button>

2. 控件模板(ControlTemplate)或数据模板(DataTemplate)中

当需要为自定义控件或数据项定义动画时,可以将 Storyboard 放在模板的资源中。这种方式适合封装在控件内部的动画逻辑。

示例(自定义按钮模板动画)

xml 复制代码
<Style TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border x:Name="border" Background="{TemplateBinding Background}">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Resources>
                    <Storyboard x:Key="PressAnimation">
                        <ColorAnimation
                            Storyboard.TargetName="border"
                            Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                            To="LightBlue" Duration="0:0:0.2"/>
                    </Storyboard>
                </ControlTemplate.Resources>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="Button.PreviewMouseDown">
                        <BeginStoryboard Storyboard="{StaticResource PressAnimation}"/>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

3. 窗口(Window)或页面(Page)的资源

Storyboard 定义在窗口或页面的资源字典中,使其对整个窗口或页面内的所有元素可用。这种方式适合应用于多个控件的共享动画。

示例(窗口级别的共享动画)

xml 复制代码
<Window.Resources>
    <Storyboard x:Key="FadeInStoryboard">
        <DoubleAnimation
            Storyboard.TargetProperty="Opacity"
            From="0" To="1" Duration="0:0:0.5"/>
    </Storyboard>
</Window.Resources>

<StackPanel>
    <Button Content="Animate" 
            Click="Button_Click"/>
    <TextBlock x:Name="message" Text="Hello"/>
</StackPanel>

在代码-behind中启动动画:

csharp 复制代码
private void Button_Click(object sender, RoutedEventArgs e) {
    Storyboard sb = (Storyboard)FindResource("FadeInStoryboard");
    Storyboard.SetTarget(sb, message);
    sb.Begin();
}

4. 应用程序资源(App.xaml

对于全局共享的动画(如全局过渡效果、应用程序启动动画),可以将 Storyboard 定义在应用程序的资源字典中。

示例(应用程序级别的动画)

xml 复制代码
<Application.Resources>
    <Storyboard x:Key="GlobalHighlightAnimation">
        <ColorAnimation
            Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)"
            To="Yellow" Duration="0:0:0.5" AutoReverse="True"/>
    </Storyboard>
</Application.Resources>

5. 代码动态创建

在某些情况下(如需要动态生成动画参数),可以在代码中动态创建 Storyboard 并应用到元素上。

示例(动态创建动画)

csharp 复制代码
// 创建动画
DoubleAnimation animation = new DoubleAnimation {
    From = 0,
    To = 100,
    Duration = TimeSpan.FromSeconds(1)
};

// 创建 Storyboard 并设置目标属性
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(animation);
Storyboard.SetTargetProperty(animation, new PropertyPath(Button.WidthProperty));
Storyboard.SetTarget(animation, myButton);

// 启动动画
storyboard.Begin();

选择建议

  • 局部动画:放在元素资源或模板中。
  • 共享动画:放在窗口/页面资源或应用程序资源中。
  • 动态动画:在代码中创建。

无论放在何处,确保 Storyboard 的作用范围与动画的使用场景相匹配,以提高代码的可维护性和复用性。

示例代码: 旋转的按钮

鼠标放到上面会自动旋转

xml 复制代码
<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Button Content="动画按钮" Width="100" Height="60">
            <Button.RenderTransform>
                <RotateTransform x:Name="buttonRotate" Angle="0" />
            </Button.RenderTransform>
            <Button.Resources>
                <Storyboard x:Key="RotateAnimation">
                    <DoubleAnimation 
        Storyboard.TargetName="buttonRotate"
        Storyboard.TargetProperty="Angle"
        From="0" To="360" Duration="0:0:6"
        RepeatBehavior="Forever" />
                </Storyboard>

            </Button.Resources>
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.MouseEnter">
                    <BeginStoryboard Storyboard="{StaticResource RotateAnimation}"/>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </Grid>
</Window>
相关推荐
Scout-leaf2 天前
WPF新手村教程(三)—— 路由事件
c#·wpf
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意4 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码4 天前
嵌入式学习路线
学习
毛小茛4 天前
计算机系统概论——校验码
学习
babe小鑫4 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms4 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下4 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。4 天前
2026.2.25监控学习
学习
im_AMBER4 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode