WPF的一个Loading动画

凑合用吧,wpf的loading动画挺多的,好不容易自己写了点得记下来。

记在别的地方还容易找不到,就记在这里吧。。

先放几个图,gif弄起来太麻烦了,我直接截图吧,1-》2-》3-》1-》2-》3这样看,眨眼补帧就好。

xaml:

    <Style TargetType="{x:Type cc:Loading}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type cc:Loading}">
                    <Border>
                        <Border.Resources>
                            <Storyboard x:Key="BaseEllipseAnimation" RepeatBehavior="Forever">
                                <!-- 透明度动画 -->
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="1" />
                                    <SplineDoubleKeyFrame KeyTime="0:0:1" Value="0.8" />
                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="1" />
                                </DoubleAnimationUsingKeyFrames>

                                <!-- 宽度动画 -->
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)">
                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="{Binding Diameter,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                    <SplineDoubleKeyFrame KeyTime="0:0:1" Value="5" />
                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="{Binding Diameter,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                </DoubleAnimationUsingKeyFrames>

                                <!-- 高度动画 -->
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)">
                                    <SplineDoubleKeyFrame KeyTime="0:0:0" Value="{Binding Diameter,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                    <SplineDoubleKeyFrame KeyTime="0:0:1" Value="5" />
                                    <SplineDoubleKeyFrame KeyTime="0:0:2" Value="{Binding Diameter,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Key="EllipseAnimation1" BeginTime="0:0:0.0">
                                <StaticResource ResourceKey="BaseEllipseAnimation"/>
                            </Storyboard>
                            <Storyboard x:Key="EllipseAnimation2" BeginTime="0:0:0.25">
                                <StaticResource ResourceKey="BaseEllipseAnimation"/>
                            </Storyboard>
                            <Storyboard x:Key="EllipseAnimation3" BeginTime="0:0:0.5">
                                <StaticResource ResourceKey="BaseEllipseAnimation"/>
                            </Storyboard>
                            <Storyboard x:Key="EllipseAnimation4" BeginTime="0:0:0.75">
                                <StaticResource ResourceKey="BaseEllipseAnimation"/>
                            </Storyboard>
                            <Storyboard x:Key="EllipseAnimation5" BeginTime="0:0:1.0">
                                <StaticResource ResourceKey="BaseEllipseAnimation"/>
                            </Storyboard>
                            <Storyboard x:Key="EllipseAnimation6" BeginTime="0:0:1.25">
                                <StaticResource ResourceKey="BaseEllipseAnimation"/>
                            </Storyboard>
                            <Storyboard x:Key="EllipseAnimation7" BeginTime="0:0:1.50">
                                <StaticResource ResourceKey="BaseEllipseAnimation"/>
                            </Storyboard>
                            <Storyboard x:Key="EllipseAnimation8" BeginTime="0:0:1.75">
                                <StaticResource ResourceKey="BaseEllipseAnimation"/>
                            </Storyboard>
                        </Border.Resources>
                        <Border.Background>
                            <SolidColorBrush Color="Black" Opacity=".8" />
                        </Border.Background>
                        <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
                            <StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
                                <cc:CirclePanel HorizontalAlignment="Center">
                                    <cc:CirclePanel.Resources>
                                        <Style TargetType="{x:Type Border}">
                                            <Setter Property="Width" Value="{Binding Size, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                            <Setter Property="Height" Value="{Binding Size, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                        </Style>
                                        <Style TargetType="{x:Type Ellipse}">
                                            <Setter Property="Margin" Value="0" />
                                            <Setter Property="Width" Value="{Binding Diameter,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                            <Setter Property="Height" Value="{Binding Diameter,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                            <Setter Property="Fill" Value="{Binding FillBrush,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                        </Style>
                                    </cc:CirclePanel.Resources>
                                    <Border>
                                        <Ellipse Name="e1" >
                                            <Ellipse.Triggers>
                                                <EventTrigger RoutedEvent="Ellipse.Loaded">
                                                    <BeginStoryboard Storyboard="{StaticResource EllipseAnimation1}"/>
                                                </EventTrigger>
                                            </Ellipse.Triggers>
                                        </Ellipse>
                                    </Border>
                                    <Border>
                                        <Ellipse Name="e2">
                                            <Ellipse.Triggers>
                                                <EventTrigger RoutedEvent="Ellipse.Loaded">
                                                    <BeginStoryboard Storyboard="{StaticResource EllipseAnimation2}"/>
                                                </EventTrigger>
                                            </Ellipse.Triggers>
                                        </Ellipse>
                                    </Border>
                                    <Border>
                                        <Ellipse Name="e3" >
                                            <Ellipse.Triggers>
                                                <EventTrigger RoutedEvent="Ellipse.Loaded">
                                                    <BeginStoryboard Storyboard="{StaticResource EllipseAnimation3}"/>
                                                </EventTrigger>
                                            </Ellipse.Triggers>
                                        </Ellipse>
                                    </Border>
                                    <Border>
                                        <Ellipse Name="e4" >
                                            <Ellipse.Triggers>
                                                <EventTrigger RoutedEvent="Ellipse.Loaded">
                                                    <BeginStoryboard Storyboard="{StaticResource EllipseAnimation4}"/>
                                                </EventTrigger>
                                            </Ellipse.Triggers>
                                        </Ellipse>
                                    </Border>
                                    <Border>
                                        <Ellipse Name="e5" >
                                            <Ellipse.Triggers>
                                                <EventTrigger RoutedEvent="Ellipse.Loaded">
                                                    <BeginStoryboard Storyboard="{StaticResource EllipseAnimation5}"/>
                                                </EventTrigger>
                                            </Ellipse.Triggers>
                                        </Ellipse>
                                    </Border>
                                    <Border>
                                        <Ellipse Name="e6" >
                                            <Ellipse.Triggers>
                                                <EventTrigger RoutedEvent="Ellipse.Loaded">
                                                    <BeginStoryboard Storyboard="{StaticResource EllipseAnimation6}"/>
                                                </EventTrigger>
                                            </Ellipse.Triggers>
                                        </Ellipse>
                                    </Border>
                                    <Border>
                                        <Ellipse Name="e7" >
                                            <Ellipse.Triggers>
                                                <EventTrigger RoutedEvent="Ellipse.Loaded">
                                                    <BeginStoryboard Storyboard="{StaticResource EllipseAnimation7}"/>
                                                </EventTrigger>
                                            </Ellipse.Triggers>
                                        </Ellipse>
                                    </Border>
                                    <Border>
                                        <Ellipse Name="e8" >
                                            <Ellipse.Triggers>
                                                <EventTrigger RoutedEvent="Ellipse.Loaded">
                                                    <BeginStoryboard Storyboard="{StaticResource EllipseAnimation8}"/>
                                                </EventTrigger>
                                            </Ellipse.Triggers>
                                        </Ellipse>
                                    </Border>
                                </cc:CirclePanel>

                                <TextBlock Foreground="White" Text="{Binding Text, RelativeSource={RelativeSource Mode=TemplatedParent}}" Margin="0,30,0,5" />
                            </StackPanel>
                        </Border>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

cs:

internal class Loading : UserControl
{
    public static readonly DependencyProperty SizeProperty =
        DependencyProperty.Register(nameof(Size), typeof(double), typeof(Loading), new PropertyMetadata(5.0, OnSizePropertyChanged));

    private static void OnSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is Loading loading)
        {
            loading.Diameter = (double)e.NewValue / 2d;
        }
    }

    public double Size
    {
        get { return (double)GetValue(SizeProperty); }
        set { SetCurrentValue(SizeProperty, value); }
    }

    public double Diameter { get; set; }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register(nameof(Text), typeof(string), typeof(Loading), new PropertyMetadata(null, OnTextPropertyChanged));

    private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is Loading loading)
        {
            loading.Text = e.NewValue as string;
        }
    }

    public string Text
    {
        get { return (string)GetValue(SizeProperty); }
        set { SetCurrentValue(TextProperty, value); }
    }


    public static readonly DependencyProperty FillBrushProperty =
        DependencyProperty.Register(nameof(FillBrush), typeof(System.Windows.Media.Brush), typeof(Loading), new PropertyMetadata(Brushes.Blue));

    public System.Windows.Media.Brush FillBrush
    {
        get { return (System.Windows.Media.Brush)GetValue(FillBrushProperty); }
        set { SetCurrentValue(FillBrushProperty, value); }
    }

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

}

发现少了个CirclePanel.cs;补一下:
 


    public class CirclePanel : Panel
    {
        public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register("Radius", typeof(double), typeof(CirclePanel), new PropertyMetadata(0.0, new PropertyChangedCallback(OnValueChanged)));
        public double Radius
        {
            get => Convert.ToDouble(GetValue(RadiusProperty));
            set => SetValue(RadiusProperty, value);
        }


        private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as CirclePanel).Radius = Convert.ToDouble(e.NewValue);
            (d as CirclePanel).InvalidateArrange();
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            double MaxElementWidth = 0;
            foreach (UIElement item in Children)
            {
                //给定子控件的可用空间
                item.Measure(availableSize);
                MaxElementWidth = Math.Max(item.DesiredSize.Width, MaxElementWidth);
            }
            double PanelWidth = 2 * this.Radius + 2 * MaxElementWidth;
            double width = Math.Min(PanelWidth, availableSize.Width);
            double height = Math.Min(PanelWidth, availableSize.Height);
            return new Size(width, height);
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            double Degree = 0;
            double DegreeSrep = (double)360 / this.Children.Count;
            double X = this.DesiredSize.Width / 2;
            double Y = this.DesiredSize.Height / 2;
            foreach (UIElement Item in Children)
            {
                //角度转弧度
                double angle = Math.PI * Degree / 180.0;
                //转换为直角坐标系 r*cos
                double x = Math.Cos(angle) * this.Radius;
                //转换为直角坐标系 r*sin
                double y = Math.Sin(angle) * this.Radius;
                RotateTransform rotate = new RotateTransform();
                rotate.Angle = Degree;
                rotate.CenterX = 0;
                rotate.CenterY = 0;
                Item.RenderTransform = rotate;
                //决定子控件的位置和大小
                Item.Arrange(new Rect(X + x, Y + y, Item.DesiredSize.Width, this.DesiredSize.Height));
                Degree += DegreeSrep;
            }
            return finalSize;
        }

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值