老板加薪!看我做的WPF Loading!!!

老板加薪!看我做的WPF Loading!!!

控件名:RingLoading

作者:WPFDevelopersOrg

原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用大于等于.NET40

  • Visual Studio 2022;

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

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

视频效果预览👉https://www.zhihu.com/zvideo/1540649421552779264

  • 最外层使用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
  • 如何绘制;

老板加薪!看我做的WPF Loading!!!

  • EllipseStrokeDashArray进行设置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> 

RingLoading|Github
RingLoading|码云
RingLoading.xaml|Github
RingLoading.xaml|码云

发表评论

相关文章