WPF實(shí)現(xiàn)好看的Loading動(dòng)畫(huà)的示例代碼
實(shí)現(xiàn)思路
框架使用大于等于.NET40
;
Visual Studio 2022
;
項(xiàng)目使用 MIT 開(kāi)源許可協(xié)議;
老板覺(jué)得公司系統(tǒng)等待動(dòng)畫(huà)轉(zhuǎn)圈太簡(jiǎn)單,所以需要做一個(gè)稍微好看點(diǎn)的,就有這篇等待RingLoading動(dòng)畫(huà)
最外層使用Viewbox為父控件內(nèi)部嵌套創(chuàng)建三組 Grid -> Ellipse 、 Border
分別給它們指定不同的Angle從左側(cè)開(kāi)始 -135 225 54
,做永久 Angle 動(dòng)畫(huà);
- PART_Ring1.RotateTransform.Angle從
From -135
到-495
; - PART_Ring2.RotateTransform.Angle從
From 225
到-585
; - PART_Ring3.RotateTransform.Angle從
From -54
到-315
;
如何繪制;
對(duì)Ellipse的StrokeDashArray進(jìn)行設(shè)置23 100就能達(dá)到效果;
Border 做為圓設(shè)置 Effect 可實(shí)現(xiàn)陰影效果;
實(shí)現(xiàn)代碼
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實(shí)現(xiàn)好看的Loading動(dòng)畫(huà)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于WPF Loading動(dòng)畫(huà)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
WinForm中DefWndProc、WndProc與IMessageFilter的區(qū)別
這篇文章主要介紹了WinForm中DefWndProc、WndProc與IMessageFilter的區(qū)別,較為詳細(xì)的分析了WinForm的消息處理機(jī)制,需要的朋友可以參考下2014-08-08C#表達(dá)式中的動(dòng)態(tài)查詢(xún)?cè)斀狻咀g】
這篇文章主要給大家介紹了關(guān)于C#表達(dá)式中動(dòng)態(tài)查詢(xún)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01C#通過(guò)配置文件動(dòng)態(tài)修改web.config內(nèi)容的操作步驟
這篇文章主要介紹了C#通過(guò)配置文件動(dòng)態(tài)修改web.config內(nèi)容的操作步驟,文中通過(guò)圖文結(jié)合的方式介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-03-03C#實(shí)現(xiàn)SQL批量插入數(shù)據(jù)到表的方法
這篇文章主要介紹了C#實(shí)現(xiàn)SQL批量插入數(shù)據(jù)到表的方法,涉及C#批量操作SQL的相關(guān)技巧,需要的朋友可以參考下2016-04-04C#實(shí)現(xiàn)公式計(jì)算驗(yàn)證碼的示例詳解
現(xiàn)在很多的平臺(tái)已經(jīng)不使用普通的數(shù)字、字母等驗(yàn)證碼了,取而代之的是拼圖類(lèi)、選圖類(lèi)、旋轉(zhuǎn)類(lèi)或者計(jì)算類(lèi)的驗(yàn)證碼。本文將利用C#實(shí)現(xiàn)一個(gè)公式計(jì)算驗(yàn)證碼,感興趣的可以了解一下2022-10-10