基于WPF实现元旦祝福动画效果
作者:code_shenbing
本文介绍了如何在WPF中设计并实现一个元旦祝福动画,包括节日主题色彩、核心动画元素、交互体验等,通过XAML和C#代码,展示了如何使用WPF动画系统、3D图形和视觉效果,实现渐变显示、雪花飘落、烟花绽放等动画效果,感兴趣的小伙伴可以动手尝试一下
一、设计思路
在WPF中创建元旦祝福动画,我们将结合多种动画元素,打造一个生动、喜庆的节日效果。主要设计思路包括:
节日主题色彩:以红色、金色为主色调,象征新年的喜庆与希望
核心动画元素:
- 渐变显示的新年祝福文字
- 飘落的雪花/彩屑动画
- 绽放的烟花效果
- 3D旋转的"2026"年份数字
交互体验:支持用户点击触发特定动画效果
二、完整WPF实现
下面是完整的XAML和C#代码实现:
<Window
x:Class="YD_Animal.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:local="clr-namespace:YD_Animal"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="元旦快乐 2026"
Width="1000"
Height="700"
Background="Black"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>
<!-- 雪花样式 -->
<Style x:Key="SnowflakeStyle" TargetType="Ellipse">
<Setter Property="Width" Value="8" />
<Setter Property="Height" Value="8" />
<Setter Property="Fill" Value="White" />
<Setter Property="Opacity" Value="0.8" />
</Style>
<!-- 烟花粒子样式 -->
<Style x:Key="FireworkParticleStyle" TargetType="Ellipse">
<Setter Property="Width" Value="6" />
<Setter Property="Height" Value="6" />
<Setter Property="Opacity" Value="0.9" />
</Style>
</Window.Resources>
<Grid>
<!-- 背景渐变 -->
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Offset="0" Color="#0c0032" />
<GradientStop Offset="0.5" Color="#190061" />
<GradientStop Offset="1" Color="#240090" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<!-- 星星背景 -->
<Canvas x:Name="StarsCanvas" />
<!-- 雪花容器 -->
<Canvas x:Name="SnowCanvas" />
<!-- 烟花容器 -->
<Canvas x:Name="FireworksCanvas" />
<!-- 主内容区域 -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- 顶部祝福语 -->
<Viewport3D x:Name="Year3DViewport" Grid.Row="0">
<!-- 3D年份动画 -->
</Viewport3D>
<!-- 中央祝福文字 -->
<StackPanel
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock
x:Name="MainGreeting"
Margin="0,20"
HorizontalAlignment="Center"
FontSize="72"
FontWeight="Bold"
Foreground="Transparent"
Text="元旦快乐">
<TextBlock.Effect>
<DropShadowEffect
BlurRadius="20"
ShadowDepth="0"
Color="Gold" />
</TextBlock.Effect>
</TextBlock>
<TextBlock
x:Name="SubGreeting"
Margin="0,10"
HorizontalAlignment="Center"
FontSize="36"
Foreground="Transparent"
Text="新年新气象,好运常相伴">
<TextBlock.Effect>
<DropShadowEffect
BlurRadius="15"
ShadowDepth="0"
Color="LightCoral" />
</TextBlock.Effect>
</TextBlock>
</StackPanel>
<!-- 底部交互区域 -->
<StackPanel
Grid.Row="2"
Margin="0,0,0,50"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Orientation="Horizontal">
<Button
x:Name="FireworksButton"
Width="120"
Height="40"
Margin="10"
Background="#FF4081"
Click="FireworksButton_Click"
Content="绽放烟花"
FontWeight="Bold"
Foreground="White" />
<Button
x:Name="SnowButton"
Width="120"
Height="40"
Margin="10"
Background="#2196F3"
Click="SnowButton_Click"
Content="飘落雪花"
FontWeight="Bold"
Foreground="White" />
<Button
x:Name="ResetButton"
Width="120"
Height="40"
Margin="10"
Background="#4CAF50"
Click="ResetButton_Click"
Content="重置动画"
FontWeight="Bold"
Foreground="White" />
</StackPanel>
</Grid>
<!-- 倒计时显示 -->
<Border
x:Name="CountdownPanel"
Margin="0,20,0,0"
Padding="20,10"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Background="#80000000"
CornerRadius="10"
Visibility="Collapsed">
<TextBlock
x:Name="CountdownText"
FontSize="48"
FontWeight="Bold"
Foreground="White"
Text="3" />
</Border>
</Grid>
</Window>
后台代码:
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.Media.Media3D;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace YD_Animal;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Random random = new Random();
private List<Ellipse> snowflakes = new List<Ellipse>();
private List<Ellipse> fireworks = new List<Ellipse>();
private Storyboard mainStoryboard = new Storyboard();
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
CreateStarsBackground();
InitializeAnimations();
StartMainAnimation();
}
// 创建星空背景
private void CreateStarsBackground()
{
for (int i = 0; i < 150; i++)
{
Ellipse star = new Ellipse
{
Width = random.Next(1, 4),
Height = random.Next(1, 4),
Fill = Brushes.White,
Opacity = random.NextDouble() * 0.5 + 0.3
};
Canvas.SetLeft(star, random.NextDouble() * this.Width);
Canvas.SetTop(star, random.NextDouble() * this.Height);
StarsCanvas.Children.Add(star);
// 添加星星闪烁动画
DoubleAnimation opacityAnim = new DoubleAnimation
{
From = star.Opacity * 0.5,
To = star.Opacity,
Duration = TimeSpan.FromSeconds(random.NextDouble() * 2 + 1),
AutoReverse = true,
RepeatBehavior = RepeatBehavior.Forever
};
star.BeginAnimation(Ellipse.OpacityProperty, opacityAnim);
}
}
// 初始化主动画
private void InitializeAnimations()
{
// 主祝福文字渐变显示
ColorAnimation mainTextColorAnim = new ColorAnimation
{
From = Colors.Transparent,
To = Colors.Gold,
Duration = TimeSpan.FromSeconds(2),
BeginTime = TimeSpan.FromSeconds(0.5)
};
ColorAnimation subTextColorAnim = new ColorAnimation
{
From = Colors.Transparent,
To = Color.FromRgb(255, 105, 180), // 粉色
Duration = TimeSpan.FromSeconds(2),
BeginTime = TimeSpan.FromSeconds(1.5)
};
// 创建3D年份动画
Create3DYearAnimation();
// 添加到故事板
Storyboard.SetTarget(mainTextColorAnim, MainGreeting);
Storyboard.SetTargetProperty(mainTextColorAnim,
new PropertyPath("(TextBlock.Foreground).(SolidColorBrush.Color)"));
Storyboard.SetTarget(subTextColorAnim, SubGreeting);
Storyboard.SetTargetProperty(subTextColorAnim,
new PropertyPath("(TextBlock.Foreground).(SolidColorBrush.Color)"));
mainStoryboard.Children.Add(mainTextColorAnim);
mainStoryboard.Children.Add(subTextColorAnim);
// 添加文字抖动效果
AddTextJitterAnimation();
}
// 创建3D年份旋转动画
private void Create3DYearAnimation()
{
// 创建3D模型
Model3DGroup yearModel = new Model3DGroup();
// 创建数字"2026"的3D文本
for (int i = 0; i < 4; i++)
{
string digit = "2026"[i].ToString();
GeometryModel3D digitModel = Create3DText(digit,
new DiffuseMaterial(new SolidColorBrush(
Color.FromRgb((byte)(255 - i * 30), (byte)(200 - i * 20), 50))),
new Point3D(i * 2.5 - 3.75, 0, 0));
yearModel.Children.Add(digitModel);
}
// 设置3D相机
PerspectiveCamera camera = new PerspectiveCamera(
new Point3D(0, 0, 10),
new Vector3D(0, 0, -1),
new Vector3D(0, 1, 0), 45);
// 创建光源
AmbientLight ambientLight = new AmbientLight(Colors.White);
DirectionalLight directionalLight = new DirectionalLight(Colors.White,
new Vector3D(-1, -1, -1));
yearModel.Children.Add(ambientLight);
yearModel.Children.Add(directionalLight);
// 创建ModelVisual3D
ModelVisual3D modelVisual = new ModelVisual3D();
modelVisual.Content = yearModel;
// 添加到Viewport3D
Year3DViewport.Children.Add(modelVisual);
Year3DViewport.Camera = camera;
// 添加3D旋转动画
AxisAngleRotation3D rotation = new AxisAngleRotation3D(
new Vector3D(0, 1, 0), 0);
RotateTransform3D rotateTransform = new RotateTransform3D(rotation);
yearModel.Transform = rotateTransform;
DoubleAnimation rotateAnim = new DoubleAnimation
{
From = 0,
To = 360,
Duration = TimeSpan.FromSeconds(20),
RepeatBehavior = RepeatBehavior.Forever
};
rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, rotateAnim);
}
// 创建3D文字
private GeometryModel3D Create3DText(string text, Material material, Point3D position)
{
// 简化版:创建长方体代替真正的3D文字
MeshGeometry3D mesh = new MeshGeometry3D();
// 创建立方体的8个顶点
double size = 1.0;
Point3D[] points = new Point3D[]
{
new Point3D(-size, -size, -size),
new Point3D(size, -size, -size),
new Point3D(size, size, -size),
new Point3D(-size, size, -size),
new Point3D(-size, -size, size),
new Point3D(size, -size, size),
new Point3D(size, size, size),
new Point3D(-size, size, size)
};
// 添加顶点
foreach (var point in points)
{
mesh.Positions.Add(new Point3D(
point.X + position.X,
point.Y + position.Y,
point.Z + position.Z));
}
// 添加三角形面
int[][] triangles = new int[][]
{
new int[] {0, 1, 2}, new int[] {2, 3, 0}, // 前面
new int[] {1, 5, 6}, new int[] {6, 2, 1}, // 右面
new int[] {5, 4, 7}, new int[] {7, 6, 5}, // 后面
new int[] {4, 0, 3}, new int[] {3, 7, 4}, // 左面
new int[] {3, 2, 6}, new int[] {6, 7, 3}, // 上面
new int[] {4, 5, 1}, new int[] {1, 0, 4} // 下面
};
foreach (var triangle in triangles)
{
mesh.TriangleIndices.Add(triangle[0]);
mesh.TriangleIndices.Add(triangle[1]);
mesh.TriangleIndices.Add(triangle[2]);
}
return new GeometryModel3D(mesh, material);
}
// 添加文字抖动动画
private void AddTextJitterAnimation()
{
DoubleAnimationUsingKeyFrames jitterAnim = new DoubleAnimationUsingKeyFrames();
jitterAnim.Duration = TimeSpan.FromSeconds(10);
jitterAnim.RepeatBehavior = RepeatBehavior.Forever;
double baseY = 0;
for (int i = 0; i <= 100; i++)
{
double time = i * 0.1;
double offset = Math.Sin(time * 3) * 2 +
Math.Sin(time * 7) * 1;
jitterAnim.KeyFrames.Add(
new LinearDoubleKeyFrame(baseY + offset,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(time))));
}
Storyboard.SetTarget(jitterAnim, MainGreeting);
Storyboard.SetTargetProperty(jitterAnim,
new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));
// 初始化变换
MainGreeting.RenderTransform = new TranslateTransform();
mainStoryboard.Children.Add(jitterAnim);
}
// 开始主动画
private void StartMainAnimation()
{
// 开始倒计时
StartCountdown();
// 延迟开始主动画
DispatcherTimer timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(3.2)
};
timer.Tick += (s, e) =>
{
timer.Stop();
mainStoryboard.Begin();
StartSnowAnimation();
};
timer.Start();
}
// 开始倒计时
private void StartCountdown()
{
CountdownPanel.Visibility = Visibility.Visible;
int count = 3;
DispatcherTimer countdownTimer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1)
};
countdownTimer.Tick += (s, e) =>
{
if (count > 0)
{
CountdownText.Text = count.ToString();
// 添加缩放动画
ScaleTransform scale = new ScaleTransform(1, 1);
CountdownText.RenderTransform = scale;
DoubleAnimation scaleAnim = new DoubleAnimation
{
From = 3,
To = 1,
Duration = TimeSpan.FromSeconds(0.3)
};
scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnim);
scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnim);
count--;
}
else
{
countdownTimer.Stop();
CountdownPanel.Visibility = Visibility.Collapsed;
}
};
countdownTimer.Start();
}
// 雪花动画
private void StartSnowAnimation()
{
for (int i = 0; i < 100; i++)
{
CreateSnowflake();
}
}
private void CreateSnowflake()
{
Ellipse snowflake = new Ellipse
{
Width = random.Next(5, 15),
Height = random.Next(5, 15),
Fill = new RadialGradientBrush(
Colors.White,
Color.FromArgb(150, 255, 255, 255)),
Opacity = random.NextDouble() * 0.7 + 0.3
};
// 随机位置
double startX = random.NextDouble() * this.Width;
Canvas.SetLeft(snowflake, startX);
Canvas.SetTop(snowflake, -20);
SnowCanvas.Children.Add(snowflake);
snowflakes.Add(snowflake);
// 创建动画
DoubleAnimation fallAnim = new DoubleAnimation
{
To = this.Height + 20,
Duration = TimeSpan.FromSeconds(random.NextDouble() * 5 + 5)
};
DoubleAnimation xAnim = new DoubleAnimation
{
From = startX,
To = startX + random.NextDouble() * 100 - 50,
Duration = fallAnim.Duration,
AutoReverse = true
};
DoubleAnimation opacityAnim = new DoubleAnimation
{
From = snowflake.Opacity,
To = 0,
Duration = fallAnim.Duration
};
// 动画完成事件
fallAnim.Completed += (s, e) =>
{
SnowCanvas.Children.Remove(snowflake);
snowflakes.Remove(snowflake);
CreateSnowflake();
};
// 开始动画
snowflake.BeginAnimation(Canvas.TopProperty, fallAnim);
snowflake.BeginAnimation(Canvas.LeftProperty, xAnim);
snowflake.BeginAnimation(Ellipse.OpacityProperty, opacityAnim);
}
// 烟花按钮事件
private void FireworksButton_Click(object sender, RoutedEventArgs e)
{
LaunchFirework(random.Next(100, (int)this.Width - 100),
this.Height - 100);
}
// 发射烟花
private void LaunchFirework(double x, double y)
{
// 创建上升的火花
Ellipse spark = new Ellipse
{
Width = 8,
Height = 8,
Fill = Brushes.White,
Opacity = 1
};
Canvas.SetLeft(spark, x);
Canvas.SetTop(spark, this.Height);
FireworksCanvas.Children.Add(spark);
// 上升动画
DoubleAnimation riseAnim = new DoubleAnimation
{
To = y,
Duration = TimeSpan.FromSeconds(1)
};
riseAnim.Completed += (s, e) =>
{
FireworksCanvas.Children.Remove(spark);
CreateFireworkExplosion(x, y);
};
spark.BeginAnimation(Canvas.TopProperty, riseAnim);
}
// 创建烟花爆炸效果
private void CreateFireworkExplosion(double x, double y)
{
int particles = 30;
Color[] colors = { Colors.Red, Colors.Gold, Colors.Orange,
Colors.Pink, Colors.Cyan };
for (int i = 0; i < particles; i++)
{
Ellipse particle = new Ellipse
{
Width = 6,
Height = 6,
Fill = new SolidColorBrush(colors[random.Next(colors.Length)]),
Opacity = 0.9
};
Canvas.SetLeft(particle, x);
Canvas.SetTop(particle, y);
FireworksCanvas.Children.Add(particle);
fireworks.Add(particle);
// 计算随机方向
double angle = random.NextDouble() * Math.PI * 2;
double distance = random.NextDouble() * 100 + 50;
double endX = x + Math.Cos(angle) * distance;
double endY = y + Math.Sin(angle) * distance;
// 创建动画
DoubleAnimation xAnim = new DoubleAnimation
{
To = endX,
Duration = TimeSpan.FromSeconds(1)
};
DoubleAnimation yAnim = new DoubleAnimation
{
To = endY,
Duration = TimeSpan.FromSeconds(1)
};
DoubleAnimation opacityAnim = new DoubleAnimation
{
To = 0,
Duration = TimeSpan.FromSeconds(1)
};
// 动画完成事件
opacityAnim.Completed += (s, e) =>
{
FireworksCanvas.Children.Remove(particle);
fireworks.Remove(particle);
};
// 开始动画
particle.BeginAnimation(Canvas.LeftProperty, xAnim);
particle.BeginAnimation(Canvas.TopProperty, yAnim);
particle.BeginAnimation(Ellipse.OpacityProperty, opacityAnim);
}
}
// 雪花按钮事件
private void SnowButton_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 50; i++)
{
CreateSnowflake();
}
}
// 重置动画
private void ResetButton_Click(object sender, RoutedEventArgs e)
{
// 清除所有动画
mainStoryboard.Stop();
// 清除所有雪花
foreach (var snowflake in snowflakes.ToList())
{
SnowCanvas.Children.Remove(snowflake);
}
snowflakes.Clear();
// 清除所有烟花
foreach (var firework in fireworks.ToList())
{
FireworksCanvas.Children.Remove(firework);
}
fireworks.Clear();
// 重置文字颜色
MainGreeting.Foreground = new SolidColorBrush(Colors.Transparent);
SubGreeting.Foreground = new SolidColorBrush(Colors.Transparent);
// 重新开始动画
InitializeAnimations();
StartMainAnimation();
}
}运行效果:

三、动画效果说明
1. 主要动画效果
- 3D年份旋转:数字"2026"在3D空间中持续旋转
- 祝福文字渐变:"元旦快乐"和"新年新气象"文字从透明逐渐显现
- 文字抖动效果:主标题有轻微的上下抖动,增加生动感
- 星空背景:随机生成的星星带有闪烁效果
- 雪花飘落:点击按钮可触发雪花飘落效果
- 烟花绽放:点击按钮可在指定位置发射烟花
2. 交互功能
- 绽放烟花按钮:在随机位置发射烟花
- 飘落雪花按钮:增加雪花飘落数量
- 重置动画按钮:重置所有动画到初始状态
四、技术要点
1. WPF动画系统
- 使用
Storyboard管理复杂动画序列 - 利用
DoubleAnimation实现属性值动画 - 通过
KeyFrame动画创建更复杂的运动轨迹
2. 3D图形
- 使用WPF 3D功能创建旋转的年份数字
- 通过
Viewport3D、ModelVisual3D和GeometryModel3D构建3D场景
3. 视觉效果
- 利用
DropShadowEffect创建文字发光效果 - 通过渐变画刷创建丰富的色彩过渡
- 使用透明度动画实现淡入淡出效果
五、扩展建议
- 添加音效:可以为烟花和倒计时添加音效
- 更多祝福语:可以随机显示不同的元旦祝福语
- 用户自定义:允许用户输入自己的祝福语
- 导出功能:添加导出为视频或GIF的功能
- 响应式设计:适配不同窗口大小的布局
这个元旦祝福动画展示了WPF强大的动画和图形功能,通过代码和设计的结合,创造出既美观又有节日氛围的动画效果。您可以根据需要调整颜色、动画速度和其他参数,创建出独一无二的元旦祝福动画。
以上就是基于WPF实现元旦祝福动画效果的详细内容,更多关于WPF元旦祝福动画的资料请关注脚本之家其它相关文章!
