diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index 22182e67..58ada875 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -41,8 +41,13 @@ + + + + + diff --git a/src/Shared/HandyControl_Shared/Media/Animation/GeometryAnimation.cs b/src/Shared/HandyControl_Shared/Media/Animation/GeometryAnimation.cs index 7446d679..0edd36dd 100644 --- a/src/Shared/HandyControl_Shared/Media/Animation/GeometryAnimation.cs +++ b/src/Shared/HandyControl_Shared/Media/Animation/GeometryAnimation.cs @@ -1,17 +1,14 @@ -using System.Text; -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; using System.Windows; using System.Windows.Media; using System.Windows.Media.Animation; -using HandyControl.Tools.Extension; +using HandyControl.Tools; // ReSharper disable PossibleInvalidOperationException namespace HandyControl.Media.Animation { public class GeometryAnimation : GeometryAnimationBase { - private const string Rgx = @"[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?"; - private string[] _strings; private double[] _numbersFrom; @@ -42,16 +39,6 @@ namespace HandyControl.Media.Animation } } - private static void DecomposeValue(string geometryStr, out double[] arr) - { - var collection = Regex.Matches(geometryStr, Rgx); - arr = new double[collection.Count]; - for (var i = 0; i < collection.Count; i++) - { - arr[i] = collection[i].Value.Value(); - } - } - public GeometryAnimation(Geometry fromValue, Geometry toValue) : this() { From = fromValue; @@ -77,22 +64,6 @@ namespace HandyControl.Media.Animation protected override Freezable CreateInstanceCore() => new GeometryAnimation(); - private Geometry ConvertToGeometry(double[] arr) - { - var builder = new StringBuilder(_strings[0]); - for (var i = 0; i < _numbersAccumulator.Length; i++) - { - var s = _strings[i + 1]; - var n = arr[i]; - if (!double.IsNaN(n)) - { - builder.Append(n).Append(s); - } - } - - return Geometry.Parse(builder.ToString()); - } - protected override Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock) { if (_numbersAccumulator == null) @@ -100,14 +71,14 @@ namespace HandyControl.Media.Animation if (_numbersFrom == null) { var geometryStr = defaultOriginValue.ToString(); - DecomposeValue(geometryStr, out _numbersFrom); + AnimationHelper.DecomposeGeometryStr(geometryStr, out _numbersFrom); } if (_numbersTo == null) { var geometryStr = defaultDestinationValue.ToString(); - DecomposeValue(geometryStr, out _numbersTo); - _strings = Regex.Split(geometryStr, Rgx); + AnimationHelper.DecomposeGeometryStr(geometryStr, out _numbersTo); + _strings = Regex.Split(geometryStr, RegularPatterns.DigitsPattern); } UpdateValue(); @@ -146,7 +117,7 @@ namespace HandyControl.Media.Animation numbers[i] = accumulated[i] + _numbersFrom[i] + _numbersAccumulator[i] * progress; } - return ConvertToGeometry(numbers); + return AnimationHelper.ComposeGeometry(_strings, numbers); } public static readonly DependencyProperty FromProperty = DependencyProperty.Register( @@ -157,7 +128,7 @@ namespace HandyControl.Media.Animation var obj = (GeometryAnimation) d; if (e.NewValue is Geometry geometry) { - DecomposeValue(geometry.ToString(), out obj._numbersFrom); + AnimationHelper.DecomposeGeometryStr(geometry.ToString(), out obj._numbersFrom); obj.UpdateValue(); } } @@ -177,8 +148,8 @@ namespace HandyControl.Media.Animation if (e.NewValue is Geometry geometry) { var geometryStr = geometry.ToString(); - DecomposeValue(geometryStr, out obj._numbersTo); - obj._strings = Regex.Split(geometryStr, Rgx); + AnimationHelper.DecomposeGeometryStr(geometryStr, out obj._numbersTo); + obj._strings = Regex.Split(geometryStr, RegularPatterns.DigitsPattern); obj.UpdateValue(); } } diff --git a/src/Shared/HandyControl_Shared/Media/Animation/GeometryAnimationUsingKeyFrames.cs b/src/Shared/HandyControl_Shared/Media/Animation/GeometryAnimationUsingKeyFrames.cs new file mode 100644 index 00000000..1405806e --- /dev/null +++ b/src/Shared/HandyControl_Shared/Media/Animation/GeometryAnimationUsingKeyFrames.cs @@ -0,0 +1,34 @@ +using System.Collections; +using System.Windows; +using System.Windows.Markup; +using System.Windows.Media; +using System.Windows.Media.Animation; + +namespace HandyControl.Media.Animation +{ + [ContentProperty("KeyFrames")] + public class GeometryAnimationUsingKeyFrames : GeometryAnimationBase, IKeyFrameAnimation, IAddChild + { + protected override Freezable CreateInstanceCore() + { + throw new System.NotImplementedException(); + } + + protected override Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, + AnimationClock animationClock) + { + throw new System.NotImplementedException(); + } + + public IList KeyFrames { get; set; } + public void AddChild(object value) + { + throw new System.NotImplementedException(); + } + + public void AddText(string text) + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Media/Animation/GeometryKeyFrame.cs b/src/Shared/HandyControl_Shared/Media/Animation/GeometryKeyFrame.cs index 0f743acc..e0a4efb4 100644 --- a/src/Shared/HandyControl_Shared/Media/Animation/GeometryKeyFrame.cs +++ b/src/Shared/HandyControl_Shared/Media/Animation/GeometryKeyFrame.cs @@ -2,6 +2,7 @@ using System.Windows; using System.Windows.Media; using System.Windows.Media.Animation; +using HandyControl.Tools; public abstract class GeometryKeyFrame : Freezable, IKeyFrame { @@ -12,12 +13,12 @@ public abstract class GeometryKeyFrame : Freezable, IKeyFrame protected GeometryKeyFrame(Geometry value) { - Value = value; + AnimationHelper.DecomposeGeometryStr(value.ToString(), out var arr); + Value = arr; } - protected GeometryKeyFrame(Geometry value, KeyTime keyTime) + protected GeometryKeyFrame(Geometry value, KeyTime keyTime) : this(value) { - Value = value; KeyTime = keyTime; } @@ -33,18 +34,20 @@ public abstract class GeometryKeyFrame : Freezable, IKeyFrame object IKeyFrame.Value { get => Value; - set => Value = (Geometry)value; + set => Value = (double[])value; } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( - "Value", typeof(Geometry), typeof(GeometryKeyFrame), new PropertyMetadata(default(Geometry))); + "Value", typeof(Geometry), typeof(GeometryKeyFrame), new PropertyMetadata(default(double[]))); - public Geometry Value + public double[] Value { - get => (Geometry) GetValue(ValueProperty); + get => (double[]) GetValue(ValueProperty); set => SetValue(ValueProperty, value); } + protected string[] Strings { get; set; } + public Geometry InterpolateValue(Geometry baseValue, double keyFrameProgress) { if (keyFrameProgress < 0.0 || keyFrameProgress > 1.0) diff --git a/src/Shared/HandyControl_Shared/Media/Animation/LinearGeometryKeyFrame.cs b/src/Shared/HandyControl_Shared/Media/Animation/LinearGeometryKeyFrame.cs new file mode 100644 index 00000000..af2b2d2a --- /dev/null +++ b/src/Shared/HandyControl_Shared/Media/Animation/LinearGeometryKeyFrame.cs @@ -0,0 +1,56 @@ +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Animation; +using HandyControl.Expression.Drawing; +using HandyControl.Tools; + +namespace HandyControl.Media.Animation +{ + public class LinearGeometryKeyFrame : GeometryKeyFrame + { + private double[] _baseValues; + + public LinearGeometryKeyFrame() + { + + } + + public LinearGeometryKeyFrame(Geometry value) : base(value) + { + + } + + public LinearGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime) + { + + } + + protected override Freezable CreateInstanceCore() => new LinearDoubleKeyFrame(); + + protected override Geometry InterpolateValueCore(Geometry baseValue, double keyFrameProgress) + { + if (_baseValues == null) + { + AnimationHelper.DecomposeGeometryStr(baseValue.ToString(), out _baseValues); + } + + if (MathHelper.IsVerySmall(keyFrameProgress)) + { + return baseValue; + } + + if (MathHelper.AreClose(keyFrameProgress, 1)) + { + return AnimationHelper.ComposeGeometry(Strings, Value); + } + + var accumulated = new double[Value.Length]; + for (var i = 0; i < Value.Length; i++) + { + accumulated[i] = _baseValues[i] + (Value[i] - _baseValues[i]) * keyFrameProgress; + } + + return AnimationHelper.ComposeGeometry(Strings, accumulated); + } + } +} diff --git a/src/Shared/HandyControl_Shared/Tools/Helper/AnimationHelper.cs b/src/Shared/HandyControl_Shared/Tools/Helper/AnimationHelper.cs index b1004d67..30851a16 100644 --- a/src/Shared/HandyControl_Shared/Tools/Helper/AnimationHelper.cs +++ b/src/Shared/HandyControl_Shared/Tools/Helper/AnimationHelper.cs @@ -1,6 +1,10 @@ using System; +using System.Text; +using System.Text.RegularExpressions; using System.Windows; +using System.Windows.Media; using System.Windows.Media.Animation; +using HandyControl.Tools.Extension; namespace HandyControl.Tools { @@ -36,5 +40,31 @@ namespace HandyControl.Tools EasingFunction = new PowerEase { EasingMode = EasingMode.EaseInOut } }; } + + internal static void DecomposeGeometryStr(string geometryStr, out double[] arr) + { + var collection = Regex.Matches(geometryStr, RegularPatterns.DigitsPattern); + arr = new double[collection.Count]; + for (var i = 0; i < collection.Count; i++) + { + arr[i] = collection[i].Value.Value(); + } + } + + internal static Geometry ComposeGeometry(string[] strings, double[] arr) + { + var builder = new StringBuilder(strings[0]); + for (var i = 0; i < arr.Length; i++) + { + var s = strings[i + 1]; + var n = arr[i]; + if (!double.IsNaN(n)) + { + builder.Append(n).Append(s); + } + } + + return Geometry.Parse(builder.ToString()); + } } } \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Tools/RegularPatterns.cs b/src/Shared/HandyControl_Shared/Tools/RegularPatterns.cs index 4ff94eb6..7226a6b0 100644 --- a/src/Shared/HandyControl_Shared/Tools/RegularPatterns.cs +++ b/src/Shared/HandyControl_Shared/Tools/RegularPatterns.cs @@ -89,7 +89,7 @@ /// /// 计算性质数字正则匹配 /// - public const string DigitsPattern = @"^[+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)([eE][+-]?[0-9]+)?$"; + public const string DigitsPattern = @"[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?"; /// /// 正整数正则匹配