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)Data\Enum\NotifyIconInfoType.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\CloseWindowCommand.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\CloseWindowCommand.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\OpenLinkCommand.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\BorderCircularClipConverter.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\ColLayoutConverter.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\ColLayoutConverter.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\CornerRadiusSplitConverter.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.Interactivity")]
|
||||||
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Expression.Shapes")]
|
[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.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.Data")]
|
||||||
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Properties.Langs")]
|
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Properties.Langs")]
|
||||||
[assembly: XmlnsPrefix("https://handyorg.github.io/handycontrol", "hc")]
|
[assembly: XmlnsPrefix("https://handyorg.github.io/handycontrol", "hc")]
|
||||||
@@ -15,7 +15,7 @@ namespace HandyControl.Tools
|
|||||||
/// <param name="thickness"></param>
|
/// <param name="thickness"></param>
|
||||||
/// <param name="milliseconds"></param>
|
/// <param name="milliseconds"></param>
|
||||||
/// <returns></returns>
|
/// <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)))
|
return new ThicknessAnimation(thickness, new Duration(TimeSpan.FromMilliseconds(milliseconds)))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user