目标是显示应用程序正在工作的信息。因此,我正在寻找一种智能的实现示例,使用 WPF / MVVM 来创建一个加载旋转器。
@Menol发布的自定义Spinner存在一个小问题,即Spinner会向下和向右移动一个点的大小。我已经更新了代码,以便通过减去一半的点来补偿这个偏移量。
以下是更新后的代码:
private void initialSetup()
{
float horizontalCenter = (float)(SpinnerWidth / 2);
float verticalCenter = (float)(SpinnerHeight / 2);
float distance = (float)Math.Min(SpinnerHeight, SpinnerWidth) / 2;
float dotComp = (float)(EllipseSize / 2);
double angleInRadians = 44.8;
float cosine = (float)Math.Cos(angleInRadians);
float sine = (float)Math.Sin(angleInRadians);
EllipseN = newPos(left: horizontalCenter - dotComp, top: verticalCenter - distance - dotComp);
EllipseNE = newPos(left: horizontalCenter + (distance * cosine) - dotComp, top: verticalCenter - (distance * sine) - dotComp);
EllipseE = newPos(left: horizontalCenter + distance - dotComp, top: verticalCenter - dotComp);
EllipseSE = newPos(left: horizontalCenter + (distance * cosine) - dotComp, top: verticalCenter + (distance * sine) - dotComp);
EllipseS = newPos(left: horizontalCenter - dotComp, top: verticalCenter + distance - dotComp);
EllipseSW = newPos(left: horizontalCenter - (distance * cosine) - dotComp, top: verticalCenter + (distance * sine) - dotComp);
EllipseW = newPos(left: horizontalCenter - distance - dotComp, top: verticalCenter - dotComp);
EllipseNW = newPos(left: horizontalCenter - (distance * cosine) - dotComp, top: verticalCenter - (distance * sine) - dotComp);
}
CircularProgressBarBlue.xaml
<UserControl
x:Class="CircularProgressBarBlue"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent"
Name="progressBar">
<UserControl.Resources>
<Storyboard x:Key="spinning" >
<DoubleAnimation
Storyboard.TargetName="SpinnerRotate"
Storyboard.TargetProperty="(RotateTransform.Angle)"
From="0"
To="360"
RepeatBehavior="Forever"/>
</Storyboard>
</UserControl.Resources>
<Grid
x:Name="LayoutRoot"
Background="Transparent"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Image Source="C:\SpinnerImage\BlueSpinner.png" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image.RenderTransform>
<RotateTransform
x:Name="SpinnerRotate"
Angle="0"/>
</Image.RenderTransform>
</Image>
</Grid>
CircularProgressBarBlue.xaml.cs
using System;
using System.Windows;
using System.Windows.Media.Animation;
/// <summary>
/// Interaction logic for CircularProgressBarBlue.xaml
/// </summary>
public partial class CircularProgressBarBlue
{
private Storyboard _sb;
public CircularProgressBarBlue()
{
InitializeComponent();
StartStoryBoard();
IsVisibleChanged += CircularProgressBarBlueIsVisibleChanged;
}
void CircularProgressBarBlueIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (_sb == null) return;
if (e != null && e.NewValue != null && (((bool)e.NewValue)))
{
_sb.Begin();
_sb.Resume();
}
else
{
_sb.Stop();
}
}
void StartStoryBoard()
{
try
{
_sb = (Storyboard)TryFindResource("spinning");
if (_sb != null)
_sb.Begin();
}
catch
{ }
}
}
<Grid Width="100" Height="100">
<Ellipse Width="20" Height="20" Stroke="Gray" StrokeThickness="4">
<Ellipse.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="rotateTransform"
Storyboard.TargetProperty="Angle"
From="0" To="360"
Duration="0:0:1"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
<Ellipse.RenderTransform>
<RotateTransform x:Name="rotateTransform" CenterX="10" CenterY="10"/>
</Ellipse.RenderTransform>
</Ellipse>
<Grid Width="100" Height="100">
<Path Stroke="Gray" StrokeThickness="4" StrokeEndLineCap="Round">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="50,10">
<LineSegment Point="10,50" />
<LineSegment Point="50,90" />
<LineSegment Point="90,50" />
<LineSegment Point="50,10" />
</PathFigure>
</PathGeometry>
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="rotateTransform"
Storyboard.TargetProperty="Angle"
From="0" To="360"
Duration="0:0:1"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
<Path.RenderTransform>
<RotateTransform x:Name="rotateTransform" CenterX="50" CenterY="50" />
</Path.RenderTransform>
</Path>
使用应用于几何图形的动画技术,将所需的几何图形添加到路径(Path)中,并对其旋转变换(RotateTransform)进行0-360°的动画处理。
我的Spinner支持两种类型的Spinner:
而中心逻辑看起来像这样:
if(spinner.SpinnerType == SpinnerType.Ring)
{
double innerRad = spinner.Radius - spinner.ItemRadius;
Point center = new Point(0, 0);
grp.Children.Add(new EllipseGeometry( center, spinner.Radius, spinner.Radius));
grp.Children.Add(new EllipseGeometry(center, innerRad, innerRad));
return;
}
var points = GetPointsOnCircle( spinner.Diameter/ 2);
double r = spinner.ItemRadius;
foreach (var point in points)
{
grp.Children.Add(new EllipseGeometry(point, r, r));
r -= spinner.ContinuousSizeReduction;
}
使用方法如下:
<local:SpinnerControl Diameter="60" Fill="#FFE8B311"/>
这里是源代码!