add basic codes
This commit is contained in:
1 parent
b27391b88c
commit
814bfc2d64
5 files changed
+282
-1
No files matched your search
@@ -41,6 +41,8 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\NotifyIconInfoType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\CloseWindowCommand.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\OpenLinkCommand.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Media\Animation\GeometryAnimation.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Media\Animation\GeometryAnimationBase.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\BorderCircularClipConverter.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\ColLayoutConverter.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\CornerRadiusSplitConverter.cs" />
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using HandyControl.Tools.Extension;
|
||||
// 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;
|
||||
|
||||
private double[] _numbersTo;
|
||||
|
||||
private double[] _numbersAccumulator;
|
||||
|
||||
private double[][] _keyValues;
|
||||
|
||||
private bool _isAnimationFunctionValid;
|
||||
|
||||
public GeometryAnimation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GeometryAnimation(string fromValue, string toValue) : this()
|
||||
{
|
||||
From = Geometry.Parse(fromValue);
|
||||
To = Geometry.Parse(toValue);
|
||||
}
|
||||
|
||||
private void UpdateValue()
|
||||
{
|
||||
if (_numbersFrom == null || _numbersTo == null || _numbersFrom.Length != _numbersTo.Length) return;
|
||||
|
||||
_numbersAccumulator = new double[_numbersFrom.Length];
|
||||
for (var i = 0; i < _numbersFrom.Length; i++)
|
||||
{
|
||||
_numbersAccumulator[i] = _numbersTo[i] - _numbersFrom[i];
|
||||
}
|
||||
}
|
||||
|
||||
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<double>();
|
||||
}
|
||||
}
|
||||
|
||||
public GeometryAnimation(Geometry fromValue, Geometry toValue) : this()
|
||||
{
|
||||
From = fromValue;
|
||||
To = toValue;
|
||||
}
|
||||
|
||||
public GeometryAnimation(Geometry fromValue, Geometry toValue, Duration duration) : this()
|
||||
{
|
||||
From = fromValue;
|
||||
To = toValue;
|
||||
Duration = duration;
|
||||
}
|
||||
|
||||
public GeometryAnimation(Geometry fromValue, Geometry toValue, Duration duration, FillBehavior fillBehavior) : this()
|
||||
{
|
||||
From = fromValue;
|
||||
To = toValue;
|
||||
Duration = duration;
|
||||
FillBehavior = fillBehavior;
|
||||
}
|
||||
|
||||
public new GeometryAnimation Clone() => (GeometryAnimation)base.Clone();
|
||||
|
||||
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 (!_isAnimationFunctionValid)
|
||||
{
|
||||
ValidateAnimationFunction();
|
||||
}
|
||||
|
||||
var progress = animationClock.CurrentProgress.Value;
|
||||
|
||||
var easingFunction = EasingFunction;
|
||||
if (easingFunction != null)
|
||||
{
|
||||
progress = easingFunction.Ease(progress);
|
||||
}
|
||||
|
||||
var accumulated = new double[_numbersAccumulator.Length];
|
||||
var foundation = new double[_numbersAccumulator.Length];
|
||||
|
||||
var from = _keyValues[0];
|
||||
|
||||
if (IsAdditive)
|
||||
{
|
||||
foundation = new double[_numbersAccumulator.Length];
|
||||
}
|
||||
|
||||
|
||||
if (IsCumulative)
|
||||
{
|
||||
var currentRepeat = (double)(animationClock.CurrentIteration - 1);
|
||||
|
||||
if (currentRepeat > 0.0)
|
||||
{
|
||||
accumulated = new double[_numbersAccumulator.Length];
|
||||
for (var i = 0; i < _numbersAccumulator.Length; i++)
|
||||
{
|
||||
accumulated[i] = _numbersAccumulator[i] * currentRepeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var numbers = new double[_numbersAccumulator.Length];
|
||||
|
||||
for (var i = 0; i < _numbersAccumulator.Length; i++)
|
||||
{
|
||||
numbers[i] = foundation[i] + accumulated[i] + from[i] + _numbersAccumulator[i] * progress;
|
||||
}
|
||||
|
||||
return ConvertToGeometry(numbers);
|
||||
}
|
||||
|
||||
private void ValidateAnimationFunction()
|
||||
{
|
||||
_keyValues = null;
|
||||
|
||||
_keyValues = new double[2][];
|
||||
_keyValues[0] = _numbersFrom;
|
||||
_keyValues[1] = _numbersTo;
|
||||
|
||||
_isAnimationFunctionValid = true;
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FromProperty = DependencyProperty.Register(
|
||||
"From", typeof(Geometry), typeof(GeometryAnimation), new PropertyMetadata(default(Geometry), OnFromChanged));
|
||||
|
||||
private static void OnFromChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var obj = (GeometryAnimation) d;
|
||||
if (e.NewValue is Geometry geometry)
|
||||
{
|
||||
DecomposeValue(geometry.ToString(), out obj._numbersFrom);
|
||||
obj.UpdateValue();
|
||||
}
|
||||
}
|
||||
|
||||
public Geometry From
|
||||
{
|
||||
get => (Geometry)GetValue(FromProperty);
|
||||
set => SetValue(FromProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ToProperty = DependencyProperty.Register(
|
||||
"To", typeof(Geometry), typeof(GeometryAnimation), new PropertyMetadata(default(Geometry), OnToChanged));
|
||||
|
||||
private static void OnToChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var obj = (GeometryAnimation)d;
|
||||
if (e.NewValue is Geometry geometry)
|
||||
{
|
||||
var geometryStr = geometry.ToString();
|
||||
DecomposeValue(geometryStr, out obj._numbersTo);
|
||||
obj._strings = Regex.Split(geometryStr, Rgx);
|
||||
obj.UpdateValue();
|
||||
}
|
||||
}
|
||||
|
||||
public Geometry To
|
||||
{
|
||||
get => (Geometry)GetValue(ToProperty);
|
||||
set => SetValue(ToProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register(
|
||||
"EasingFunction", typeof(IEasingFunction), typeof(GeometryAnimation), new PropertyMetadata(default(IEasingFunction)));
|
||||
|
||||
public IEasingFunction EasingFunction
|
||||
{
|
||||
get => (IEasingFunction)GetValue(EasingFunctionProperty);
|
||||
set => SetValue(EasingFunctionProperty, value);
|
||||
}
|
||||
|
||||
public bool IsAdditive
|
||||
{
|
||||
get => (bool)GetValue(IsAdditiveProperty);
|
||||
set => SetValue(IsAdditiveProperty, value);
|
||||
}
|
||||
|
||||
public bool IsCumulative
|
||||
{
|
||||
get => (bool)GetValue(IsCumulativeProperty);
|
||||
set => SetValue(IsCumulativeProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
|
||||
namespace HandyControl.Media.Animation
|
||||
{
|
||||
public abstract class GeometryAnimationBase : AnimationTimeline
|
||||
{
|
||||
public new GeometryAnimationBase Clone()
|
||||
{
|
||||
return (GeometryAnimationBase)base.Clone();
|
||||
}
|
||||
|
||||
public sealed override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
|
||||
{
|
||||
if (defaultOriginValue == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(defaultOriginValue));
|
||||
}
|
||||
if (defaultDestinationValue == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(defaultDestinationValue));
|
||||
}
|
||||
return GetCurrentValue((Geometry)defaultOriginValue, (Geometry)defaultDestinationValue, animationClock);
|
||||
}
|
||||
|
||||
public override Type TargetPropertyType
|
||||
{
|
||||
get
|
||||
{
|
||||
ReadPreamble();
|
||||
|
||||
return typeof(Geometry);
|
||||
}
|
||||
}
|
||||
|
||||
public Geometry GetCurrentValue(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
|
||||
{
|
||||
ReadPreamble();
|
||||
|
||||
if (animationClock == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(animationClock));
|
||||
}
|
||||
|
||||
if (animationClock.CurrentState == ClockState.Stopped)
|
||||
{
|
||||
return defaultDestinationValue;
|
||||
}
|
||||
|
||||
return GetCurrentValueCore(defaultOriginValue, defaultDestinationValue, animationClock);
|
||||
}
|
||||
|
||||
protected abstract Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Interactivity")]
|
||||
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Expression.Shapes")]
|
||||
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Expression.Media")]
|
||||
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Media.Animation")]
|
||||
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Data")]
|
||||
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Properties.Langs")]
|
||||
[assembly: XmlnsPrefix("https://handyorg.github.io/handycontrol", "hc")]
|
||||
@@ -15,7 +15,7 @@ namespace HandyControl.Tools
|
||||
/// <param name="thickness"></param>
|
||||
/// <param name="milliseconds"></param>
|
||||
/// <returns></returns>
|
||||
public static ThicknessAnimation CreateAnimation(Thickness thickness = default(Thickness), double milliseconds = 200)
|
||||
public static ThicknessAnimation CreateAnimation(Thickness thickness = default, double milliseconds = 200)
|
||||
{
|
||||
return new ThicknessAnimation(thickness, new Duration(TimeSpan.FromMilliseconds(milliseconds)))
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user