老板加薪!看我做的 WPF Loading! - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yanjinhua
V2EX    .NET

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

  •  
  •   yanjinhua 2022-08-10 11:21:07 +08:00 5973 次点击
    这是一个创建于 1226 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    控件名:RingLoading

    作者:WPFDevelopersOrg

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

    • 框架使用大于等于.NET40
    • Visual Studio 2022;
    • 项目使用 MIT 开源许可协议;

    视频点我效果预览

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

    • 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> lt;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|码云

    34 条回复    2022-08-22 10:39:01 +08:00
    Terry05
        1
    Terry05  
       2022-08-10 11:26:22 +08:00
    emmmmmm……恕我没看懂
    y830CAa5nink4rUQ
        2
    y830CAa5nink4rUQ  
       2022-08-10 11:28:36 +08:00   1
    老板:这么丑?撤掉,换回上一版那个 GIF !
    runningowl
        3
    runningowl  
       2022-08-10 12:34:52 +08:00
    Lottie 不香么
    loopinfor
        4
    loopinfor  
       2022-08-10 12:40:02 +08:00
    这个 loading 效果过于另类了,应该不会有人真的用吧
    yanjinhua
        5
    yanjinhua  
    OP
       2022-08-10 13:15:26 +08:00
    yanjinhua
        6
    yanjinhua  
    OP
       2022-08-10 13:15:40 +08:00
    @loopinfor 哈哈哈
    yanjinhua
        7
    yanjinhua  
    OP
       2022-08-10 13:16:05 +08:00
    @DrX 没用 gif
    yanjinhua
        8
    yanjinhua  
    OP
       2022-08-10 13:16:44 +08:00
    @Terry05 呃呃呃呃呃
    wangyzj
        9
    wangyzj  
       2022-08-10 14:05:29 +08:00
    不够卷
    SeanTheSheep
        10
    SeanTheSheep  
       2022-08-10 14:05:48 +08:00
    逛 V 站一年了,第二次看到 WPF 相关的帖子,泪目了。
    yanjinhua
        11
    yanjinhua  
    OP
       2022-08-10 15:31:29 +08:00
    @wangyzj 正在努力
    yanjinhua
        12
    yanjinhua  
    OP
       2022-08-10 15:31:55 +08:00
    @SeanTheSheep 那么我很关心第一次的帖子 i
    20015jjw
        13
    20015jjw  
       2022-08-10 15:42:37 +08:00 via iPhone
    amazon 可能会喜欢你(雾
    sinnosong1
        14
    sinnosong1  
       2022-08-10 16:06:39 +08:00
    每行都能看懂,但是连起来就完全看不懂了,虽然我也写过 WPF ,一直都是入门状态的新手。。。
    yanjinhua
        15
    yanjinhua  
    OP
       2022-08-10 16:12:15 +08:00
    @sinnosong1 哈哈哈,好像懂了 但是又没完全懂
    yanjinhua
        16
    yanjinhua  
    OP
       2022-08-10 16:12:32 +08:00
    @20015jjw 我不懂了
    vone
        17
    vone  
       2022-08-10 16:24:57 +08:00   3
    当场开除!
    dcsuibian
        18
    dcsuibian  
       2022-08-10 16:43:54 +08:00
    现在 Electron 越来越多,对原生开发者也越来越敬重
    villivateur
        19
    villivateur  
       2022-08-10 16:47:06 +08:00
    star 了,准备在我丑得要命的上位机里面试下这个主题
    stoluoyu
        20
    stoluoyu  
       2022-08-10 16:49:15 +08:00
    精子有了,load 完不该进入卵子了么(大雾
    marcong95
        21
    marcong95  
       2022-08-10 17:10:38 +08:00
    其实只留一组,甚至把那个东西的头部删掉其实就好多了,最好圆弧的长度还能随着时间变长变短。。。。
    v2byy
        22
    v2byy  
       2022-08-10 17:45:58 +08:00
    就用 windows start 那个 loading 不香吗
    NGXDLK
        23
    NGXDLK  
       2022-08-10 18:00:18 +08:00
    @marcong95 还可以变粗变细,变直变弯
    lifeintools
        24
    lifeintools  
       2022-08-10 18:17:55 +08:00
    真好玩~
    xyx0826
        25
    xyx0826  
       2022-08-11 10:40:36 +08:00 via iPhone
    很酷诶...WPF 我用了一段时间但是完全没搞懂它的高级样式和动画,现在 winui 3 也出了,不知道该学哪个了
    yanjinhua
        26
    yanjinhua  
    OP
       2022-08-11 13:10:55 +08:00
    @vone 哈哈哈哈哈
    yanjinhua
        27
    yanjinhua  
    OP
       2022-08-11 13:11:32 +08:00
    @dcsuibian 现在确实都是使用 electron 。谢谢
    yanjinhua
        28
    yanjinhua  
    OP
       2022-08-11 13:12:16 +08:00
    @villivateur 欢迎使用哈,https://github.com/WPFDevelopersOrg 这个组织下都是关于 WPF 和 MAUI 的项目。有问题及时反馈哈。
    yanjinhua
        29
    yanjinhua  
    OP
       2022-08-11 13:13:03 +08:00
    @stoluoyu 哈哈哈哈,后期应该会增加任务完成关闭。
    yanjinhua
        30
    yanjinhua  
    OP
       2022-08-11 13:13:19 +08:00
    @NGXDLK 是这样的。
    yanjinhua
        31
    yanjinhua  
    OP
       2022-08-11 13:13:38 +08:00
    @lifeintools 可以复制源码魔改起来。
    yanjinhua
        32
    yanjinhua  
    OP
       2022-08-11 13:15:46 +08:00
    @xyx0826 maui 跨平台,win10 之前的系统。动画和高级样式多写几次就熟悉了。“https://github.com/WPFDevelopersOrg” 这个组织下 也有 maui 项目。
    ragnaroks
        33
    ragnaroks  
       2022-08-19 08:39:59 +08:00
    WPF 设置样式( StyleSetter )和动画( StoryBorad )太累了,我已经放弃了,现在都用网页做 UI ,通过 websocket 链接到本地
    yanjinhua
        34
    yanjinhua  
    OP
       2022-08-22 10:39:01 +08:00
    @ragnaroks 熟悉了就还好,也是不错的选择。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2949 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 13:46 PVG 21:46 LAX 05:46 JFK 08:46
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86