C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > WPF元旦祝福动画

基于WPF实现元旦祝福动画效果

作者:code_shenbing

本文介绍了如何在WPF中设计并实现一个元旦祝福动画,包括节日主题色彩、核心动画元素、交互体验等,通过XAML和C#代码,展示了如何使用WPF动画系统、3D图形和视觉效果,实现渐变显示、雪花飘落、烟花绽放等动画效果,感兴趣的小伙伴可以动手尝试一下

一、设计思路

在WPF中创建元旦祝福动画,我们将结合多种动画元素,打造一个生动、喜庆的节日效果。主要设计思路包括:

节日主题色彩:以红色、金色为主色调,象征新年的喜庆与希望

核心动画元素

交互体验:支持用户点击触发特定动画效果

二、完整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. 主要动画效果

2. 交互功能

四、技术要点

1. WPF动画系统

2. 3D图形

3. 视觉效果

五、扩展建议

  1. 添加音效:可以为烟花和倒计时添加音效
  2. 更多祝福语:可以随机显示不同的元旦祝福语
  3. 用户自定义:允许用户输入自己的祝福语
  4. 导出功能:添加导出为视频或GIF的功能
  5. 响应式设计:适配不同窗口大小的布局

这个元旦祝福动画展示了WPF强大的动画和图形功能,通过代码和设计的结合,创造出既美观又有节日氛围的动画效果。您可以根据需要调整颜色、动画速度和其他参数,创建出独一无二的元旦祝福动画。

以上就是基于WPF实现元旦祝福动画效果的详细内容,更多关于WPF元旦祝福动画的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文