diff --git a/HandyControl/Controls/Other/AnimationPath.cs b/HandyControl/Controls/Other/AnimationPath.cs index ff126038..054dd802 100644 --- a/HandyControl/Controls/Other/AnimationPath.cs +++ b/HandyControl/Controls/Other/AnimationPath.cs @@ -5,6 +5,8 @@ using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using HandyControl.Data; +using HandyControl.Expression.Drawing; +using HandyControl.Tools.Extension; namespace HandyControl.Controls { @@ -17,6 +19,11 @@ namespace HandyControl.Controls /// private Storyboard _storyboard; + /// + /// 路径长度 + /// + private double _pathLength; + /// /// 路径 /// @@ -47,8 +54,7 @@ namespace HandyControl.Controls /// 路径长度 /// public static readonly DependencyProperty PathLengthProperty = DependencyProperty.Register( - "PathLength", typeof(double), typeof(AnimationPath), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, - OnPropertiesChanged)); + "PathLength", typeof(double), typeof(AnimationPath), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, OnPropertiesChanged)); /// /// 路径长度 @@ -146,34 +152,47 @@ namespace HandyControl.Controls remove => RemoveHandler(CompletedEvent, value); } + /// + /// 更新路径 + /// private void UpdatePath() { if (!Duration.HasTimeSpan || !IsPlaying) return; - StrokeDashOffset = PathLength; + + _pathLength = PathLength > 0 ? PathLength : Data.GetTotalLength(new Size(ActualWidth, ActualHeight), StrokeThickness); + + if (MathHelper.IsVerySmall(_pathLength)) return; + + StrokeDashOffset = _pathLength; StrokeDashArray = new DoubleCollection(new List { - PathLength, - PathLength + _pathLength, + _pathLength }); //定义动画 + if (_storyboard != null) + { + _storyboard.Stop(); + _storyboard.Completed -= Storyboard_Completed; + } _storyboard = new Storyboard { RepeatBehavior = RepeatBehavior }; - _storyboard.Completed += (s, e) => RaiseEvent(new RoutedEventArgs(CompletedEvent)); + _storyboard.Completed += Storyboard_Completed; var frames = new DoubleAnimationUsingKeyFrames(); //开始位置 var frame0 = new LinearDoubleKeyFrame { - Value = PathLength, + Value = _pathLength, KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero) }; //结束位置 var frame1 = new LinearDoubleKeyFrame { - Value = -PathLength, + Value = -_pathLength, KeyTime = KeyTime.FromTimeSpan(Duration.TimeSpan) }; frames.KeyFrames.Add(frame0); @@ -185,5 +204,7 @@ namespace HandyControl.Controls _storyboard.Begin(); } + + private void Storyboard_Completed(object sender, EventArgs e) => RaiseEvent(new RoutedEventArgs(CompletedEvent)); } } \ No newline at end of file diff --git a/HandyControl/HandyControl.csproj b/HandyControl/HandyControl.csproj index 4f14d102..ea3ec290 100644 --- a/HandyControl/HandyControl.csproj +++ b/HandyControl/HandyControl.csproj @@ -182,6 +182,7 @@ + diff --git a/HandyControl/Tools/Extension/GeometryExtension.cs b/HandyControl/Tools/Extension/GeometryExtension.cs new file mode 100644 index 00000000..1121bbca --- /dev/null +++ b/HandyControl/Tools/Extension/GeometryExtension.cs @@ -0,0 +1,50 @@ +using System; +using System.Windows; +using System.Windows.Media; +using HandyControl.Expression.Drawing; + +namespace HandyControl.Tools.Extension +{ + public static class GeometryExtension + { + /// + /// 获取路径总长度 + /// + /// + /// + public static double GetTotalLength(this Geometry geometry) + { + if (geometry == null) return 0; + + var pathGeometry = PathGeometry.CreateFromGeometry(geometry); + pathGeometry.GetPointAtFractionLength(1e-4, out var point, out _); + var length = (pathGeometry.Figures[0].StartPoint - point).Length * 1e+4; + + return length; + } + + /// + /// 获取路径总长度 + /// + /// + /// + /// + /// + public static double GetTotalLength(this Geometry geometry, Size size, double strokeThickness = 1) + { + if (geometry == null) return 0; + + if (MathHelper.IsVerySmall(size.Width) || MathHelper.IsVerySmall(size.Height)) return 0; + + var length = GetTotalLength(geometry); + var sw = geometry.Bounds.Width / size.Width; + var sh = geometry.Bounds.Height / size.Height; + var min = Math.Min(sw, sh); + + if (MathHelper.IsVerySmall(min) || MathHelper.IsVerySmall(strokeThickness)) return 0; + + length /= min; + return length / strokeThickness; + } + } +} \ No newline at end of file diff --git a/HandyControlDemo/UserControl/Controls/AnimationPathDemoCtl.xaml b/HandyControlDemo/UserControl/Controls/AnimationPathDemoCtl.xaml index 378c4c43..a01db604 100644 --- a/HandyControlDemo/UserControl/Controls/AnimationPathDemoCtl.xaml +++ b/HandyControlDemo/UserControl/Controls/AnimationPathDemoCtl.xaml @@ -4,6 +4,8 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"> - + + +