老板加薪!看我做的 WPF Loading !!!
控件名:RingLoading
作者:WPFDevelopersOrg
原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal
.NET40
;Visual Studio 2022
;Grid -> Ellipse 、Border
分别给它们指定不同的Angle从左侧开始 -135 225 54
,做永久 Angle 动画;From -135
到 -495
;From 225
到 -585
;From -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>
RingLoading|Github
RingLoading|码云
RingLoading.xaml|Github
RingLoading.xaml|码云
1
Terry05 2022-08-10 11:26:22 +08:00
emmmmmm……恕我没看懂
|
2
y830CAa5nink4rUQ 2022-08-10 11:28:36 +08:00 1
老板:这么丑?撤掉,换回上一版那个 GIF !
|
3
runningowl 2022-08-10 12:34:52 +08:00
Lottie 不香么
|
4
loopinfor 2022-08-10 12:40:02 +08:00
这个 loading 效果过于另类了,应该不会有人真的用吧
|
5
yanjinhua OP @runningowl 香
|
9
wangyzj 2022-08-10 14:05:29 +08:00
不够卷
|
10
SeanTheSheep 2022-08-10 14:05:48 +08:00
逛 V 站一年了,第二次看到 WPF 相关的帖子,泪目了。
|
12
yanjinhua OP @SeanTheSheep 那么我很关心第一次的帖子 i😊
|
13
20015jjw 2022-08-10 15:42:37 +08:00 via iPhone
amazon 可能会喜欢你(雾
|
14
sinnosong1 2022-08-10 16:06:39 +08:00
每行都能看懂,但是连起来就完全看不懂了,虽然我也写过 WPF ,一直都是入门状态的新手。。。
|
15
yanjinhua OP @sinnosong1 哈哈哈,好像懂了 但是又没完全懂
|
17
vone 2022-08-10 16:24:57 +08:00 3
当场开除!
|
18
dcsuibian 2022-08-10 16:43:54 +08:00
现在 Electron 越来越多,对原生开发者也越来越敬重
|
19
villivateur 2022-08-10 16:47:06 +08:00
star 了,准备在我丑得要命的上位机里面试下这个主题
|
20
stoluoyu 2022-08-10 16:49:15 +08:00
精子有了,load 完不该进入卵子了么(大雾
|
21
marcong95 2022-08-10 17:10:38 +08:00
其实只留一组,甚至把那个东西的头部删掉其实就好多了,最好圆弧的长度还能随着时间变长变短。。。。
|
22
v2byy 2022-08-10 17:45:58 +08:00
就用 windows start 那个 loading 不香吗
|
24
lifeintools 2022-08-10 18:17:55 +08:00
真好玩~
|
25
xyx0826 2022-08-11 10:40:36 +08:00 via iPhone
很酷诶...WPF 我用了一段时间但是完全没搞懂它的高级样式和动画,现在 winui 3 也出了,不知道该学哪个了
|
28
yanjinhua OP @villivateur 欢迎使用哈,https://github.com/WPFDevelopersOrg 这个组织下都是关于 WPF 和 MAUI 的项目。有问题及时反馈哈。
|
31
yanjinhua OP @lifeintools 可以复制源码魔改起来。
|
32
yanjinhua OP @xyx0826 maui 跨平台,win10 之前的系统。动画和高级样式多写几次就熟悉了。“https://github.com/WPFDevelopersOrg” 这个组织下 也有 maui 项目。
|
33
ragnaroks 2022-08-19 08:39:59 +08:00
WPF 设置样式( StyleSetter )和动画( StoryBorad )太累了,我已经放弃了,现在都用网页做 UI ,通过 websocket 链接到本地
|