mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
Implementing a new animation execution mechanism
This commit is contained in:
parent
03422c53a6
commit
28abd64b04
@ -2,6 +2,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Media.Transformation;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Primitives;
|
namespace AtomUI.Controls.Primitives;
|
||||||
|
|
||||||
@ -9,10 +10,10 @@ public class MotionActorControl : Decorator
|
|||||||
{
|
{
|
||||||
#region 公共属性定义
|
#region 公共属性定义
|
||||||
|
|
||||||
public static readonly StyledProperty<ITransform?> MotionTransformProperty =
|
public static readonly StyledProperty<TransformOperations?> MotionTransformProperty =
|
||||||
AvaloniaProperty.Register<MotionActorControl, ITransform?>(nameof(MotionTransform));
|
AvaloniaProperty.Register<MotionActorControl, TransformOperations?>(nameof(MotionTransform));
|
||||||
|
|
||||||
public ITransform? MotionTransform
|
public TransformOperations? MotionTransform
|
||||||
{
|
{
|
||||||
get => GetValue(MotionTransformProperty);
|
get => GetValue(MotionTransformProperty);
|
||||||
set => SetValue(MotionTransformProperty, value);
|
set => SetValue(MotionTransformProperty, value);
|
||||||
@ -58,6 +59,7 @@ public class MotionActorControl : Decorator
|
|||||||
|
|
||||||
ChildProperty.Changed
|
ChildProperty.Changed
|
||||||
.AddClassHandler<MotionActorControl>((x, _) => x.HandleChildChanged());
|
.AddClassHandler<MotionActorControl>((x, _) => x.HandleChildChanged());
|
||||||
|
AffectsRender<MotionActorControl>(MotionTransformProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleLayoutTransformChanged(AvaloniaPropertyChangedEventArgs e)
|
private void HandleLayoutTransformChanged(AvaloniaPropertyChangedEventArgs e)
|
||||||
@ -108,7 +110,7 @@ public class MotionActorControl : Decorator
|
|||||||
}
|
}
|
||||||
|
|
||||||
_transformation = matrix;
|
_transformation = matrix;
|
||||||
_matrixTransform.Matrix = matrix;
|
_matrixTransform.Matrix = FilterScaleTransform(matrix);
|
||||||
// New transform means re-layout is necessary
|
// New transform means re-layout is necessary
|
||||||
InvalidateMeasure();
|
InvalidateMeasure();
|
||||||
}
|
}
|
||||||
@ -130,6 +132,17 @@ public class MotionActorControl : Decorator
|
|||||||
matrix.M32);
|
matrix.M32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Matrix FilterScaleTransform(Matrix matrix)
|
||||||
|
{
|
||||||
|
return new Matrix(
|
||||||
|
1.0,
|
||||||
|
matrix.M12,
|
||||||
|
matrix.M21,
|
||||||
|
1.0,
|
||||||
|
matrix.M31,
|
||||||
|
matrix.M32);
|
||||||
|
}
|
||||||
|
|
||||||
protected override Size ArrangeOverride(Size finalSize)
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
{
|
{
|
||||||
if (MotionTransformRoot == null || MotionTransform == null)
|
if (MotionTransformRoot == null || MotionTransform == null)
|
||||||
@ -184,7 +197,6 @@ public class MotionActorControl : Decorator
|
|||||||
|
|
||||||
protected override Size MeasureOverride(Size availableSize)
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
{
|
{
|
||||||
Console.WriteLine(MotionTransform);
|
|
||||||
if (MotionTransformRoot == null || MotionTransform == null)
|
if (MotionTransformRoot == null || MotionTransform == null)
|
||||||
{
|
{
|
||||||
return base.MeasureOverride(availableSize);
|
return base.MeasureOverride(availableSize);
|
||||||
|
@ -6,7 +6,7 @@ using Avalonia.Styling;
|
|||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.Controls.Utils;
|
||||||
|
|
||||||
public static partial class MotionFactory
|
internal static partial class MotionFactory
|
||||||
{
|
{
|
||||||
public static MotionConfig BuildCollapseMotion(Direction direction, TimeSpan duration, Easing? easing = null,
|
public static MotionConfig BuildCollapseMotion(Direction direction, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Animation;
|
using Avalonia.Animation;
|
||||||
|
using Avalonia.Media.Transformation;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.Controls.Utils;
|
||||||
|
|
||||||
public record MotionConfig
|
internal record MotionConfig
|
||||||
{
|
{
|
||||||
public RelativePoint RenderTransformOrigin { get; }
|
public RelativePoint RenderTransformOrigin { get; }
|
||||||
public IList<Animation> Animations { get; }
|
public IList<Animation> Animations { get; }
|
||||||
@ -13,4 +14,36 @@ public record MotionConfig
|
|||||||
RenderTransformOrigin = renderTransformOrigin;
|
RenderTransformOrigin = renderTransformOrigin;
|
||||||
Animations = animations;
|
Animations = animations;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static partial class MotionFactory
|
||||||
|
{
|
||||||
|
static TransformOperations BuildScaleTransform(double scaleX, double scaleY)
|
||||||
|
{
|
||||||
|
var builder = new TransformOperations.Builder(1);
|
||||||
|
builder.AppendScale(scaleX, scaleY);
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
static TransformOperations BuildScaleTransform(double scale)
|
||||||
|
{
|
||||||
|
return BuildScaleTransform(scale, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TransformOperations BuildScaleXTransform(double scale)
|
||||||
|
{
|
||||||
|
return BuildScaleTransform(scale, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TransformOperations BuildScaleYTransform(double scale)
|
||||||
|
{
|
||||||
|
return BuildScaleTransform(1.0, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TransformOperations BuildTranslateTransform(double offsetX, double offsetY)
|
||||||
|
{
|
||||||
|
var builder = new TransformOperations.Builder(1);
|
||||||
|
builder.AppendTranslate(offsetX, offsetY);
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,24 +1,26 @@
|
|||||||
using Avalonia;
|
using AtomUI.Controls.Primitives;
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.Controls.Utils;
|
||||||
|
|
||||||
public static class MotionInvoker
|
internal static class MotionInvoker
|
||||||
{
|
{
|
||||||
public static void Invoke(Control target,
|
public static void Invoke(MotionActorControl target,
|
||||||
MotionConfig motionConfig,
|
MotionConfig motionConfig,
|
||||||
Action? aboutToStart = null,
|
Action? aboutToStart = null,
|
||||||
Action? completedAction = null)
|
Action? completedAction = null)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
{
|
{
|
||||||
using var originRestore = new RenderTransformOriginRestore(target);
|
using var originRestore = new RenderTransformOriginRestore(target);
|
||||||
target.RenderTransformOrigin = motionConfig.RenderTransformOrigin;
|
target.RenderTransformOrigin = motionConfig.RenderTransformOrigin;
|
||||||
if (aboutToStart != null)
|
if (aboutToStart != null)
|
||||||
{
|
{
|
||||||
aboutToStart();
|
aboutToStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var animation in motionConfig.Animations)
|
foreach (var animation in motionConfig.Animations)
|
||||||
{
|
{
|
||||||
await animation.RunAsync(target);
|
await animation.RunAsync(target);
|
||||||
@ -42,7 +44,7 @@ internal class RenderTransformOriginRestore : IDisposable
|
|||||||
_target = target;
|
_target = target;
|
||||||
_origin = target.RenderTransformOrigin;
|
_origin = target.RenderTransformOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_target.RenderTransformOrigin = _origin;
|
_target.RenderTransformOrigin = _origin;
|
||||||
|
@ -4,7 +4,7 @@ using Avalonia.Media.Transformation;
|
|||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.Controls.Utils;
|
||||||
|
|
||||||
public class MotionTransformOptionsAnimator : InterpolatingAnimator<TransformOperations>
|
internal class MotionTransformOptionsAnimator : InterpolatingAnimator<TransformOperations>
|
||||||
{
|
{
|
||||||
public override TransformOperations Interpolate(double progress, TransformOperations oldValue, TransformOperations newValue)
|
public override TransformOperations Interpolate(double progress, TransformOperations oldValue, TransformOperations newValue)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@ using Avalonia.Styling;
|
|||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.Controls.Utils;
|
||||||
|
|
||||||
public static partial class MotionFactory
|
internal static partial class MotionFactory
|
||||||
{
|
{
|
||||||
public static MotionConfig BuildMoveDownInMotion(double offset, TimeSpan duration, Easing? easing = null,
|
public static MotionConfig BuildMoveDownInMotion(double offset, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
using Avalonia;
|
using AtomUI.Controls.Primitives;
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Animation;
|
using Avalonia.Animation;
|
||||||
using Avalonia.Animation.Easings;
|
using Avalonia.Animation.Easings;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Media.Transformation;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.Controls.Utils;
|
||||||
|
|
||||||
public static partial class MotionFactory
|
internal static partial class MotionFactory
|
||||||
{
|
{
|
||||||
public static MotionConfig BuildSlideUpInMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfig BuildSlideUpInMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new QuinticEaseOut();
|
easing ??= new CubicEaseOut();
|
||||||
var animations = new List<Animation>();
|
var animations = new List<Animation>();
|
||||||
RelativePoint transformOrigin = default;
|
RelativePoint transformOrigin = default;
|
||||||
var animation = new Animation
|
var animation = new Animation
|
||||||
@ -32,36 +34,14 @@ public static partial class MotionFactory
|
|||||||
Value = 0.0
|
Value = 0.0
|
||||||
};
|
};
|
||||||
startFrame.Setters.Add(opacitySetter);
|
startFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
var scaleYSetter = new Setter
|
var scaleYSetter = new Setter
|
||||||
{
|
{
|
||||||
Property = ScaleTransform.ScaleYProperty,
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
Value = 0.1
|
Value = BuildScaleYTransform(0.01) // // 不知道为啥设置成 0.0, 子元素渲染不正常
|
||||||
};
|
};
|
||||||
startFrame.Setters.Add(scaleYSetter);
|
startFrame.Setters.Add(scaleYSetter);
|
||||||
}
|
}
|
||||||
animation.Children.Add(startFrame);
|
animation.Children.Add(startFrame);
|
||||||
|
|
||||||
var middleFrame = new KeyFrame
|
|
||||||
{
|
|
||||||
Cue = new Cue(0.9)
|
|
||||||
};
|
|
||||||
{
|
|
||||||
var opacitySetter = new Setter
|
|
||||||
{
|
|
||||||
Property = Visual.OpacityProperty,
|
|
||||||
Value = 0.2
|
|
||||||
};
|
|
||||||
middleFrame.Setters.Add(opacitySetter);
|
|
||||||
|
|
||||||
var scaleYSetter = new Setter
|
|
||||||
{
|
|
||||||
Property = ScaleTransform.ScaleYProperty,
|
|
||||||
Value = 0.9
|
|
||||||
};
|
|
||||||
middleFrame.Setters.Add(scaleYSetter);
|
|
||||||
}
|
|
||||||
animation.Children.Add(middleFrame);
|
|
||||||
|
|
||||||
var endFrame = new KeyFrame
|
var endFrame = new KeyFrame
|
||||||
{
|
{
|
||||||
@ -76,8 +56,8 @@ public static partial class MotionFactory
|
|||||||
endFrame.Setters.Add(opacitySetter);
|
endFrame.Setters.Add(opacitySetter);
|
||||||
var scaleYSetter = new Setter
|
var scaleYSetter = new Setter
|
||||||
{
|
{
|
||||||
Property = ScaleTransform.ScaleYProperty,
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
Value = 1.0
|
Value = BuildScaleYTransform(1.0)
|
||||||
};
|
};
|
||||||
endFrame.Setters.Add(scaleYSetter);
|
endFrame.Setters.Add(scaleYSetter);
|
||||||
}
|
}
|
||||||
@ -91,7 +71,7 @@ public static partial class MotionFactory
|
|||||||
public static MotionConfig BuildSlideUpOutMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfig BuildSlideUpOutMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new QuinticEaseIn();
|
easing ??= new CubicEaseIn();
|
||||||
var animations = new List<Animation>();
|
var animations = new List<Animation>();
|
||||||
RelativePoint transformOrigin = default;
|
RelativePoint transformOrigin = default;
|
||||||
var animation = new Animation
|
var animation = new Animation
|
||||||
@ -115,33 +95,12 @@ public static partial class MotionFactory
|
|||||||
|
|
||||||
var scaleYSetter = new Setter
|
var scaleYSetter = new Setter
|
||||||
{
|
{
|
||||||
Property = ScaleTransform.ScaleYProperty,
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
Value = 1.0
|
Value = BuildScaleYTransform(1.0)
|
||||||
};
|
};
|
||||||
startFrame.Setters.Add(scaleYSetter);
|
startFrame.Setters.Add(scaleYSetter);
|
||||||
}
|
}
|
||||||
animation.Children.Add(startFrame);
|
animation.Children.Add(startFrame);
|
||||||
|
|
||||||
var middleFrame = new KeyFrame
|
|
||||||
{
|
|
||||||
Cue = new Cue(0.9)
|
|
||||||
};
|
|
||||||
{
|
|
||||||
var opacitySetter = new Setter
|
|
||||||
{
|
|
||||||
Property = Visual.OpacityProperty,
|
|
||||||
Value = 0.2
|
|
||||||
};
|
|
||||||
middleFrame.Setters.Add(opacitySetter);
|
|
||||||
|
|
||||||
var scaleYSetter = new Setter
|
|
||||||
{
|
|
||||||
Property = ScaleTransform.ScaleYProperty,
|
|
||||||
Value = 0.9
|
|
||||||
};
|
|
||||||
middleFrame.Setters.Add(scaleYSetter);
|
|
||||||
}
|
|
||||||
animation.Children.Add(middleFrame);
|
|
||||||
|
|
||||||
var endFrame = new KeyFrame
|
var endFrame = new KeyFrame
|
||||||
{
|
{
|
||||||
@ -156,8 +115,8 @@ public static partial class MotionFactory
|
|||||||
endFrame.Setters.Add(opacitySetter);
|
endFrame.Setters.Add(opacitySetter);
|
||||||
var scaleYSetter = new Setter
|
var scaleYSetter = new Setter
|
||||||
{
|
{
|
||||||
Property = ScaleTransform.ScaleYProperty,
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
Value = 0.0
|
Value = BuildScaleYTransform(0.0)
|
||||||
};
|
};
|
||||||
endFrame.Setters.Add(scaleYSetter);
|
endFrame.Setters.Add(scaleYSetter);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user