Files
HandyControl/src/Shared/HandyControl_Shared/Controls/Loading/LoadingCircle.cs
T
NaBian 04eb5cf73a fixed a bug of Loading
Storyboard will not pause if IsRunning is asigned a value of false in xaml
2021-03-30 00:05:24 +08:00

214 lines
8.1 KiB
C#

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
namespace HandyControl.Controls
{
public class LoadingCircle : LoadingBase
{
public static readonly DependencyProperty DotOffSetProperty = DependencyProperty.Register(
"DotOffSet", typeof(double), typeof(LoadingCircle),
new FrameworkPropertyMetadata(20.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double DotOffSet
{
get => (double) GetValue(DotOffSetProperty);
set => SetValue(DotOffSetProperty, value);
}
public static readonly DependencyProperty NeedHiddenProperty = DependencyProperty.Register(
"NeedHidden", typeof(bool), typeof(LoadingCircle),
new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.AffectsRender));
public bool NeedHidden
{
get => (bool) GetValue(NeedHiddenProperty);
set => SetValue(NeedHiddenProperty, ValueBoxes.BooleanBox(value));
}
static LoadingCircle()
{
DotSpeedProperty.OverrideMetadata(typeof(LoadingCircle),
new FrameworkPropertyMetadata(6.0, FrameworkPropertyMetadataOptions.AffectsRender));
DotDelayTimeProperty.OverrideMetadata(typeof(LoadingCircle),
new FrameworkPropertyMetadata(220.0, FrameworkPropertyMetadataOptions.AffectsRender));
}
protected sealed override void UpdateDots()
{
var dotCount = DotCount;
var dotInterval = DotInterval;
var dotSpeed = DotSpeed;
var dotDelayTime = DotDelayTime;
var needHidden = NeedHidden;
if (dotCount < 1) return;
PrivateCanvas.Children.Clear();
//定义动画
Storyboard = new Storyboard
{
RepeatBehavior = RepeatBehavior.Forever
};
//创建圆点
for (var i = 0; i < dotCount; i++)
{
var border = CreateBorder(i, dotInterval, needHidden);
var framesMove = new DoubleAnimationUsingKeyFrames
{
BeginTime = TimeSpan.FromMilliseconds(dotDelayTime * i)
};
var subAngle = -dotInterval * i;
//开始位置
var frame0 = new LinearDoubleKeyFrame
{
Value = 0 + subAngle,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero)
};
//开始位置到第一次匀速开始
var frame1 = new EasingDoubleKeyFrame
{
EasingFunction = new PowerEase
{
EasingMode = EasingMode.EaseOut
},
Value = 180 + subAngle,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (0.75 / 7)))
};
//第一次匀速开始到第一次匀速结束
var frame2 = new LinearDoubleKeyFrame
{
Value = 180 + DotOffSet + subAngle,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (2.75 / 7)))
};
//第一次匀速结束到匀加速结束
var frame3 = new EasingDoubleKeyFrame
{
EasingFunction = new PowerEase
{
EasingMode = EasingMode.EaseIn
},
Value = 360 + subAngle,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (3.5 / 7)))
};
//匀加速结束到匀减速结束
var frame4 = new EasingDoubleKeyFrame
{
EasingFunction = new PowerEase
{
EasingMode = EasingMode.EaseOut
},
Value = 540 + subAngle,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (4.25 / 7)))
};
//匀减速结束到第二次匀速结束
var frame5 = new LinearDoubleKeyFrame
{
Value = 540 + DotOffSet + subAngle,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (6.25 / 7)))
};
//第二次匀速结束到匀加速结束
var frame6 = new EasingDoubleKeyFrame
{
EasingFunction = new PowerEase
{
EasingMode = EasingMode.EaseIn
},
Value = 720 + subAngle,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed))
};
framesMove.KeyFrames.Add(frame0);
framesMove.KeyFrames.Add(frame1);
framesMove.KeyFrames.Add(frame2);
framesMove.KeyFrames.Add(frame3);
framesMove.KeyFrames.Add(frame4);
framesMove.KeyFrames.Add(frame5);
framesMove.KeyFrames.Add(frame6);
Storyboard.SetTarget(framesMove, border);
Storyboard.SetTargetProperty(framesMove, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"));
Storyboard.Children.Add(framesMove);
if (NeedHidden)
{
//隐藏一段时间
var frame7 = new DiscreteObjectKeyFrame
{
Value = Visibility.Collapsed,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed))
};
var frame8 = new DiscreteObjectKeyFrame
{
Value = Visibility.Collapsed,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed + 0.4))
};
var frame9 = new DiscreteObjectKeyFrame
{
Value = Visibility.Visible,
KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero)
};
var framesVisibility = new ObjectAnimationUsingKeyFrames
{
BeginTime = TimeSpan.FromMilliseconds(dotDelayTime * i)
};
framesVisibility.KeyFrames.Add(frame9);
framesVisibility.KeyFrames.Add(frame7);
framesVisibility.KeyFrames.Add(frame8);
Storyboard.SetTarget(framesVisibility, border);
Storyboard.SetTargetProperty(framesVisibility, new PropertyPath("(UIElement.Visibility)"));
Storyboard.Children.Add(framesVisibility);
}
PrivateCanvas.Children.Add(border);
}
Storyboard.Begin();
if (!IsRunning)
{
Storyboard.Pause();
}
}
private Border CreateBorder(int index, double dotInterval, bool needHidden)
{
var ellipse = CreateEllipse(index);
ellipse.HorizontalAlignment = HorizontalAlignment.Center;
ellipse.VerticalAlignment = VerticalAlignment.Bottom;
var rt = new RotateTransform
{
Angle = -dotInterval * index
};
var myTransGroup = new TransformGroup();
myTransGroup.Children.Add(rt);
var border = new Border
{
RenderTransformOrigin = new Point(0.5, 0.5),
RenderTransform = myTransGroup,
Child = ellipse,
Visibility = needHidden ? Visibility.Collapsed : Visibility.Visible
};
border.SetBinding(WidthProperty, new Binding("Width") { Source = this });
border.SetBinding(HeightProperty, new Binding("Height") { Source = this });
return border;
}
}
}