凑合用吧,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;
}
}

1060

被折叠的 条评论
为什么被折叠?



