WPF实现好看的Loading动画的示例代码

实现思路

框架使用大于等于.NET40

Visual Studio 2022;

项目使用 MIT 开源许可协议;

老板觉得公司系统等待动画转圈太简单,所以需要做一个稍微好看点的,就有这篇等待RingLoading动画

最外层使用Viewbox为父控件内部嵌套创建三组 Grid -> Ellipse 、 Border分别给它们指定不同的Angle从左侧开始 -135 225 54,做永久 Angle 动画;

  • PART_Ring1.RotateTransform.AngleFrom -135 到 -495
  • PART_Ring2.RotateTransform.AngleFrom 225 到 -585
  • PART_Ring3.RotateTransform.AngleFrom -54 到 -315

如何绘制;

对Ellipse的StrokeDashArray进行设置23 100就能达到效果;

Border 做为圆设置 Effect 可实现阴影效果;

实现代码

1)RingLoading.cs代码如下;

using System.Windows;
using System.Windows.Controls;

namespace WPFDevelopers.Controls
{
    public class RingLoading : Control
    {
        // Using a DependencyProperty as the backing store for IsStart.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsStartProperty =
            DependencyProperty.Register("IsStart", typeof(bool), typeof(RingLoading), new PropertyMetadata(default));

        // Using a DependencyProperty as the backing store for ProgressValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ProgressValueProperty =
            DependencyProperty.Register("ProgressValue", typeof(double), typeof(RingLoading),
                new PropertyMetadata(0d, OnProgressValueChangedCallBack));

        // Using a DependencyProperty as the backing store for Progress.  This enables animation, styling, binding, etc...
        internal static readonly DependencyProperty ProgressProperty =
            DependencyProperty.Register("Progress", typeof(string), typeof(RingLoading), new PropertyMetadata(default));

        // Using a DependencyProperty as the backing store for Maximum.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(RingLoading),
                new PropertyMetadata(100d, OnMaximumPropertyChangedCallBack));

        // Using a DependencyProperty as the backing store for Description.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DescriptionProperty =
            DependencyProperty.Register("Description", typeof(string), typeof(RingLoading),
                new PropertyMetadata(default));

        static RingLoading()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(RingLoading),
                new FrameworkPropertyMetadata(typeof(RingLoading)));
        }

        public bool IsStart
        {
            get => (bool)GetValue(IsStartProperty);
            set => SetValue(IsStartProperty, value);
        }

        public double ProgressValue
        {
            get => (double)GetValue(ProgressValueProperty);
            set => SetValue(ProgressValueProperty, value);
        }

        internal string Progress
        {
            get => (string)GetValue(ProgressProperty);
            set => SetValue(ProgressProperty, value);
        }

        public double Maximum
        {
            get => (double)GetValue(MaximumProperty);
            set => SetValue(MaximumProperty, value);
        }

        public string Description
        {
            get => (string)GetValue(DescriptionProperty);
            set => SetValue(DescriptionProperty, value);
        }

        private static void OnProgressValueChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is RingLoading control))
                return;

            if (!double.TryParse(e.NewValue?.ToString(), out var value))
                return;

            var progress = value / control.Maximum;
            control.SetCurrentValue(ProgressProperty, progress.ToString("P0"));
        }

        private static void OnMaximumPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is RingLoading control))
                return;

            if (!double.TryParse(e.NewValue?.ToString(), out var maxValue))
                return;

            if (maxValue <= 0)
                return;

            var progress = control.ProgressValue / maxValue;
            control.SetCurrentValue(ProgressProperty, progress.ToString("P0"));
        }
    }
}

2)RingLoading.xaml代码如下

 <Style TargetType="controls:RingLoading" BasedOn="{StaticResource ControlBasicStyle}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="controls:RingLoading">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="PART_Resource_Storyboard" RepeatBehavior="Forever">
                            <DoubleAnimation To="-495" Duration="0:0:1.5" Storyboard.TargetName="PART_Ring1"  Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/>
                            <DoubleAnimation To="585" Duration="0:0:1.5" Storyboard.TargetName="PART_Ring2"  Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/>
                            <DoubleAnimation To="-315" Duration="0:0:1.5" Storyboard.TargetName="PART_Ring3"  Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/>
                        </Storyboard>
                    </ControlTemplate.Resources>

                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>

                        <Viewbox HorizontalAlignment="Center" VerticalAlignment="Center" >
                            <Border Padding="10" Width="100" Height="100" >
                                <Grid>
                                    <Grid x:Name="PART_Ring1" Width="60" Height="60" HorizontalAlignment="Center" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5">
                                        <Grid.RenderTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="-135"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Grid.RenderTransform>
                                        <Ellipse Stroke="Red" StrokeThickness="2" StrokeDashArray="23 100" RenderTransformOrigin="0.5,0.5"/>
                                        <Border Width="10" Height="10" CornerRadius="10" Background="Red" HorizontalAlignment="Right" Margin="0,0,-4,0">
                                            <Border.Effect>
                                                <DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="Red"/>
                                            </Border.Effect>
                                        </Border>
                                    </Grid>

                                    <Grid x:Name="PART_Ring2" Width="60" Height="60" HorizontalAlignment="Left" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5">
                                        <Grid.RenderTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="225"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Grid.RenderTransform>
                                        <Ellipse Stroke="Purple" StrokeThickness="2" StrokeDashArray="23 100"/>
                                        <Border Width="10" Height="10" CornerRadius="10" Background="Purple" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,-4">
                                            <Border.Effect>
                                                <DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="Purple"/>
                                            </Border.Effect>
                                        </Border>
                                    </Grid>

                                    <Grid x:Name="PART_Ring3" Width="60" Height="60" HorizontalAlignment="Right" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5">
                                        <Grid.RenderTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="45"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Grid.RenderTransform>
                                        <Ellipse Stroke="#0fb8b2" StrokeThickness="2" StrokeDashArray="23 100"/>
                                        <Border Width="10" Height="10" CornerRadius="10" Background="#0fb8b2" HorizontalAlignment="Right" Margin="0,0,-4,0">
                                            <Border.Effect>
                                                <DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="#0fb8b2"/>
                                            </Border.Effect>
                                        </Border>
                                    </Grid>
                                </Grid>
                            </Border>
                        </Viewbox>

                        <StackPanel Grid.Row="1" Grid.ColumnSpan="2" Margin="10">
                            <TextBlock HorizontalAlignment="Center" Text="Loading..." Margin="0,0,0,15"/>
                            <TextBlock HorizontalAlignment="Center" Text="{TemplateBinding Description}" Margin="0,0,0,15"/>
                            <TextBlock HorizontalAlignment="Center" Text="{TemplateBinding Progress}" FontSize="{StaticResource TitleFontSize}"
                                       FontWeight="Bold"/>
                        </StackPanel>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsStart" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource PART_Resource_Storyboard}" x:Name="PART_BeginStoryboard"/>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <StopStoryboard BeginStoryboardName="PART_BeginStoryboard"/>
                            </Trigger.ExitActions>
                        </Trigger>

                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

3)RingLoadingExample.xaml代码如下

<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.RingLoadingExample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"
             xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <wpfdev:RingLoading IsStart="true"
                            Width="400" Height="400"
                            Description="WPFDevelopers" Foreground="Black" ProgressValue="50"/>
    </Grid>
</UserControl>

以上就是WPF实现好看的Loading动画的示例代码的详细内容,更多关于WPF Loading动画的资料请关注我们其它相关文章!

(0)

相关推荐

  • WPF实现倒计时转场动画效果

    代码如下 一.创建 CountdownTimer.xaml 继承ContentControl代码如下. using System; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windo

  • 超炫酷的WPF实现Loading控件效果

    Win8系统的Loading效果还是很不错的,网上也有人用CSS3等技术实现,研究了一下,并打算用WPF自定义一个Loading控件实现类似的效果,并可以让用户对Loading的颗粒(Particle)背景颜色进行自定义,话不多说,直接上代码: 1.用VS2012新建一个WPF的用户控件库项目WpfControlLibraryDemo,VS自动生成如下结构: 2.删除UserControl1.xaml,并新建一个Loading的CustomControl(不是UserControl),如下图所示

  • WPF实现流光动画特效

    一.代码 <Window.Resources> <!--外--> <Storyboard x:Key="Storyboard1" RepeatBehavior="Forever"> <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(LinearGradientBrush.StartPoint)" Storybo

  • c# WPF中自定义加载时实现带动画效果的Form和FormItem

    背景 今天我们来谈一下我们自定义的一组WPF控件Form和FormItem,然后看一下如何自定义一组完整地组合WPF控件,在我们很多界面显示的时候我们需要同时显示文本.图片并且我们需要将这些按照特定的顺序整齐的排列在一起,这样的操作当然通过定义Grid和StackPanel然后组合在一起当然也是可以的,我们的这一组控件就是将这个过程组合到一个Form和FormItem中间去,从而达到这样的效果,我们首先来看看这组控件实现的效果. 一 动画效果 看了这个效果之后我们来看看怎么来使用Form和For

  • 基于WPF实现控件轮廓跑马灯动画效果

    代码如下 一.创建EdgeLight.xaml代码如下. <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                     xmlns:controls="c

  • WPF实现好看的Loading动画的示例代码

    实现思路 框架使用大于等于.NET40: Visual Studio 2022; 项目使用 MIT 开源许可协议: 老板觉得公司系统等待动画转圈太简单,所以需要做一个稍微好看点的,就有这篇等待RingLoading动画 最外层使用Viewbox为父控件内部嵌套创建三组 Grid -> Ellipse . Border分别给它们指定不同的Angle从左侧开始 -135 225 54,做永久 Angle 动画: PART_Ring1.RotateTransform.Angle从From -135 到

  • 使用numpngw和matplotlib生成png动画的示例代码

    在matplotlib官网看到了第三方库numpngw的简介,利用该库作为插件可以辅助matplotlib生成png动画. numpngw概述 numpngw库可生成PNG静态图像和PNG动画. 通过write_png函数可以将 numpy保存为PNG 文件. 通过 write_apng 函数可以将数组序列保存为 PNG 动画(APNG)文件 . 通过AnimatedPNGWriter类可以将Matplotlib 保存为PNG动画文件. numpngw库的依赖包是numpy和setuptools

  • Android动画系列之帧动画和补间动画的示例代码

    Android 提供三种动画:帧动画.补间动画和属性动画,本篇文章介绍帧动画以及补间动画的使用,属性动画的使用将在后面的文章中分享,那就来复习一下这两种动画的使用吧. FrameAnimation FrameAnimation 即逐帧动画,通俗来说就是按照图片动作顺序依次播放来形成动画,创建 FrameAnimation 可用 xml 定义也可直接使用代码创建. xml创建帧动画 在 res/drawable 文件夹下创建一个 drawable 文件,使用 animation-list 标签,具

  • Android绘制平移动画的示例代码

    目录 1.具体操作步骤 2.具体实施 创建ImageView 创建ObjectAnimator对象 3.具体实例 activity_main.xml MainActivity.java 1.具体操作步骤 创建ImageView对象 创建ObjectAnimator对象 通过ofFloat方法实现平移 2.具体实施 创建ImageView <ImageView android:id="@+id/car" android:layout_width="wrap_content

  • WPF实现文本描边+外发光效果的示例代码

    解决思路: (1)描边效果可以将文本字符串用GDI+生成Bitmap,然后转成BitmapImage,再用WPF的Image控件显示. (2)外发光效果用WPF自带的Effect实现 代码: using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.IO; namespace TextHighLighthDemo { public clas

  • vue实现数字变换动画的示例代码

    最近开发项目的时候有个屏保的部分,就几个数字觉得过于单调,索性加点特效在里边,UI图数字部分如下: emmm.所以加了个数字动态变动的效果 一开始直接在网上copy了一份.但是部分功能不太能满足需求 ,so,改动了部分,完美实现 改动部分: 1.数字不需要千位符,但是为了防止以后要有 所以加了个参数判断,默认是没有的 2.数字整数变动 3.组件改为行内元素,能更好的兼容页面样式 4.第二次数字变动在上次的数字累加 5.添加监听器防止页面不更新的情况 代码如下: <template> <s

  • Android利用贝塞尔曲线绘制动画的示例代码

    目录 彩虹系列 弹簧动画 复杂立体感动画 总结 前面我们花了几篇介绍了贝塞尔曲线的原理和绘制贝塞尔曲线,着实让我们见识到了贝塞尔曲线的美.好奇心驱使我想看看贝塞尔曲线动起来会是什么样?本篇就借由动画驱动贝塞尔曲线绘制看看动起来的贝塞尔曲线什么效果. 彩虹系列 通过动画控制绘制的结束点,就可以让贝塞尔曲线动起来.例如下面的动图展示的效果,看起来像搭了一个滑滑梯一样.实际上就是用7条贝塞尔曲线实现的,我们使用了 Animation 对象的值来控制绘制的结束点,从而实现了对应的动画效果. 具体源码如下

  • Android Flutter制作交错动画的示例代码

    目录 前言 动画解析 编码实现 总结 前言 之前一篇我们讲了 Flutter组合动画实现的方式 —— 交错动画.借助 GIF 和绘图技巧是可以做到类似 GIF 那种效果的.本篇我们来一个应用实例,我们让轮子在草地滚动着前进,而且还能粘上“绿色的草”,运行效果如下动画所示. 动画解析 上面实现的效果实际上由三个动画组成: 轮子前进的动画 轮子滚动 轮子的边缘颜色渐变(由黑色变成绿色) 这三个动画是同时进行的,因此需要使用到交错动画,即使用一个 AnimationController来控制三个 Tw

  • WPF实现环(圆)形菜单的示例代码

    目录 前言 实现代码 1.CircularMenuItemCustomControl.cs 2.CircularMenuItemCustomControlStyle.xaml 3.MainWindow.xaml 4.MainWindow.xaml.cs 前言 需要实现环(圆)形菜单. 效果预览(更多效果请下载源码体验): 实现代码 1.CircularMenuItemCustomControl.cs using System; using System.Collections.Generic;

  • WPF模拟实现Gitee泡泡菜单的示例代码

    WPF实现 Gitee泡泡菜单 框架使用大于等于.NET40: Visual Studio 2022; 项目使用 MIT 开源许可协议: 需要实现泡泡菜单需要使用Canvas画布进行添加内容: 保证颜色随机,位置不重叠: 点击泡泡获得当前泡泡的值: 实现代码 1) BubblleCanvas.cs 代码如下: using System.Windows; using System.Windows.Controls; using WPFDevelopers.Helpers; using WPFDev

随机推荐