mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
Refactor Badge motion
This commit is contained in:
parent
6f37d63bdb
commit
a97994a132
@ -1,6 +1,7 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media.Transformation;
|
||||
using Avalonia.Threading;
|
||||
|
||||
@ -16,7 +17,7 @@ internal class AbstractMotion : IMotion
|
||||
public Easing Easing { get; }
|
||||
public FillMode PropertyValueFillMode { get; }
|
||||
|
||||
public AbstractMotion(TimeSpan duration, Easing? easing = null, FillMode fillMode = FillMode.None)
|
||||
public AbstractMotion(TimeSpan duration, Easing? easing = null, FillMode fillMode = FillMode.Forward)
|
||||
{
|
||||
Animations = new List<Animation>();
|
||||
Duration = duration;
|
||||
@ -38,7 +39,7 @@ internal class AbstractMotion : IMotion
|
||||
{
|
||||
aboutToStart();
|
||||
}
|
||||
|
||||
actor.NotifyMotionPreStart();
|
||||
NotifyPreStart();
|
||||
|
||||
foreach (var animation in Animations)
|
||||
@ -50,7 +51,7 @@ internal class AbstractMotion : IMotion
|
||||
{
|
||||
completedAction();
|
||||
}
|
||||
|
||||
actor.NotifyMotionCompleted();
|
||||
NotifyCompleted();
|
||||
});
|
||||
}
|
||||
@ -140,4 +141,21 @@ internal class AbstractMotion : IMotion
|
||||
};
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
|
||||
internal class RenderTransformOriginRestore : IDisposable
|
||||
{
|
||||
RelativePoint _origin;
|
||||
Control _target;
|
||||
|
||||
public RenderTransformOriginRestore(Control target)
|
||||
{
|
||||
_target = target;
|
||||
_origin = target.RenderTransformOrigin;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_target.RenderTransformOrigin = _origin;
|
||||
}
|
||||
}
|
@ -1,208 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.MotionScene;
|
||||
|
||||
internal static partial class MotionFactory
|
||||
{
|
||||
public static MotionConfig BuildCollapseMotion(Direction direction, TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
{
|
||||
easing ??= new CubicEaseOut();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var isHorizontal = direction == Direction.Left || direction == Direction.Right;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 1.0
|
||||
};
|
||||
startFrame.Setters.Add(opacitySetter);
|
||||
if (isHorizontal)
|
||||
{
|
||||
var scaleXSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleXTransform(1.0)
|
||||
};
|
||||
startFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleYTransform(1.0)
|
||||
};
|
||||
startFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
}
|
||||
animation.Children.Add(startFrame);
|
||||
|
||||
var endFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 0.0
|
||||
};
|
||||
endFrame.Setters.Add(opacitySetter);
|
||||
if (isHorizontal)
|
||||
{
|
||||
var scaleXSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleXTransform(0.0)
|
||||
};
|
||||
endFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleYTransform(0.0)
|
||||
};
|
||||
endFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
|
||||
if (direction == Direction.Left)
|
||||
{
|
||||
transformOrigin = new RelativePoint(1, 0.5, RelativeUnit.Relative);
|
||||
}
|
||||
else if (direction == Direction.Right)
|
||||
{
|
||||
transformOrigin = new RelativePoint(0, 0.5, RelativeUnit.Relative);
|
||||
}
|
||||
else if (direction == Direction.Top)
|
||||
{
|
||||
transformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
|
||||
}
|
||||
else
|
||||
{
|
||||
transformOrigin = new RelativePoint(0.5, 0.0, RelativeUnit.Relative);
|
||||
}
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
}
|
||||
|
||||
public static MotionConfig BuildExpandMotion(Direction direction, TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
{
|
||||
easing ??= new CubicEaseIn();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var isHorizontal = direction == Direction.Left || direction == Direction.Right;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 0.0
|
||||
};
|
||||
startFrame.Setters.Add(opacitySetter);
|
||||
if (isHorizontal)
|
||||
{
|
||||
var scaleXSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleXTransform(0.01)
|
||||
};
|
||||
startFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleYTransform(0.01)
|
||||
};
|
||||
startFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
}
|
||||
animation.Children.Add(startFrame);
|
||||
|
||||
var endFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 1.0
|
||||
};
|
||||
endFrame.Setters.Add(opacitySetter);
|
||||
if (isHorizontal)
|
||||
{
|
||||
var scaleXSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleXTransform(1.0)
|
||||
};
|
||||
endFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleYTransform(1.0)
|
||||
};
|
||||
endFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
}
|
||||
|
||||
animation.Children.Add(endFrame);
|
||||
|
||||
if (direction == Direction.Left)
|
||||
{
|
||||
transformOrigin = new RelativePoint(1.0, 0.5, RelativeUnit.Relative);
|
||||
}
|
||||
else if (direction == Direction.Right)
|
||||
{
|
||||
transformOrigin = new RelativePoint(0.0, 0.5, RelativeUnit.Relative);
|
||||
}
|
||||
else if (direction == Direction.Top)
|
||||
{
|
||||
transformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
|
||||
}
|
||||
else
|
||||
{
|
||||
transformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
|
||||
}
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ internal class CollapseMotion : AbstractMotion
|
||||
public CollapseMotion(Direction direction,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseOut(), fillMode)
|
||||
{
|
||||
Direction = direction;
|
||||
@ -115,7 +115,7 @@ internal class ExpandMotion : AbstractMotion
|
||||
public ExpandMotion(Direction direction,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseIn(), fillMode)
|
||||
{
|
||||
Direction = direction;
|
||||
|
96
src/AtomUI.Base/MotionScene/FadeMotions.cs
Normal file
96
src/AtomUI.Base/MotionScene/FadeMotions.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.MotionScene;
|
||||
|
||||
internal class FadeInMotion : AbstractMotion
|
||||
{
|
||||
public FadeInMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new LinearEasing(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Configure()
|
||||
{
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 0.0
|
||||
};
|
||||
startFrame.Setters.Add(opacitySetter);
|
||||
}
|
||||
animation.Children.Add(startFrame);
|
||||
|
||||
var endFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 1.0
|
||||
};
|
||||
endFrame.Setters.Add(opacitySetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class FadeOutMotion : AbstractMotion
|
||||
{
|
||||
public FadeOutMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new LinearEasing(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Configure()
|
||||
{
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 1.0
|
||||
};
|
||||
startFrame.Setters.Add(opacitySetter);
|
||||
}
|
||||
animation.Children.Add(startFrame);
|
||||
|
||||
var endFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 0.0
|
||||
};
|
||||
endFrame.Setters.Add(opacitySetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
@ -30,6 +30,13 @@ internal class MotionActorControl : Decorator
|
||||
|
||||
public Control? MotionTransformRoot => Child;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共事件定义
|
||||
|
||||
public event EventHandler? PreStart;
|
||||
public event EventHandler? Completed;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@ -394,4 +401,14 @@ internal class MotionActorControl : Decorator
|
||||
{
|
||||
return (a.Width + AcceptableDelta < b.Width) || (a.Height + AcceptableDelta < b.Height);
|
||||
}
|
||||
|
||||
internal virtual void NotifyMotionPreStart()
|
||||
{
|
||||
PreStart?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal virtual void NotifyMotionCompleted()
|
||||
{
|
||||
Completed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Media.Transformation;
|
||||
|
||||
namespace AtomUI.MotionScene;
|
||||
|
||||
internal record MotionConfig
|
||||
{
|
||||
public RelativePoint RenderTransformOrigin { get; }
|
||||
public IList<Animation> Animations { get; }
|
||||
|
||||
public MotionConfig(RelativePoint renderTransformOrigin, IList<Animation> animations)
|
||||
{
|
||||
RenderTransformOrigin = renderTransformOrigin;
|
||||
Animations = animations;
|
||||
}
|
||||
}
|
||||
|
||||
internal static partial class MotionFactory
|
||||
{
|
||||
public static TransformOperations BuildScaleTransform(double scaleX, double scaleY)
|
||||
{
|
||||
var builder = new TransformOperations.Builder(1);
|
||||
builder.AppendScale(scaleX, scaleY);
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
public static TransformOperations BuildScaleTransform(double scale)
|
||||
{
|
||||
return BuildScaleTransform(scale, scale);
|
||||
}
|
||||
|
||||
public static TransformOperations BuildScaleXTransform(double scale)
|
||||
{
|
||||
return BuildScaleTransform(scale, 1.0);
|
||||
}
|
||||
|
||||
public static TransformOperations BuildScaleYTransform(double scale)
|
||||
{
|
||||
return BuildScaleTransform(1.0, scale);
|
||||
}
|
||||
|
||||
public static TransformOperations BuildTranslateTransform(double offsetX, double offsetY)
|
||||
{
|
||||
var builder = new TransformOperations.Builder(1);
|
||||
builder.AppendTranslate(offsetX, offsetY);
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
public static TransformOperations BuildTranslateScaleAndTransform(double scaleX, double scaleY, double offsetX, double offsetY)
|
||||
{
|
||||
var builder = new TransformOperations.Builder(2);
|
||||
builder.AppendScale(scaleX, scaleY);
|
||||
builder.AppendTranslate(offsetX, offsetY);
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using System.Reactive.Disposables;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace AtomUI.MotionScene;
|
||||
@ -7,43 +6,74 @@ namespace AtomUI.MotionScene;
|
||||
internal static class MotionInvoker
|
||||
{
|
||||
public static void Invoke(MotionActorControl actor,
|
||||
MotionConfig motionConfig,
|
||||
AbstractMotion motion,
|
||||
Action? aboutToStart = null,
|
||||
Action? completedAction = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
Dispatcher.UIThread.Invoke(async () =>
|
||||
{
|
||||
using var originRestore = new RenderTransformOriginRestore(actor);
|
||||
actor.RenderTransformOrigin = motionConfig.RenderTransformOrigin;
|
||||
if (aboutToStart != null)
|
||||
{
|
||||
aboutToStart();
|
||||
}
|
||||
|
||||
foreach (var animation in motionConfig.Animations)
|
||||
{
|
||||
await animation.RunAsync(actor, cancellationToken);
|
||||
}
|
||||
|
||||
if (completedAction != null)
|
||||
{
|
||||
completedAction();
|
||||
}
|
||||
await motion.RunAsync(actor, aboutToStart, completedAction, cancellationToken);
|
||||
});
|
||||
}
|
||||
|
||||
public static async Task InvokeAsync(MotionActorControl actor,
|
||||
AbstractMotion motion,
|
||||
Action? aboutToStart = null,
|
||||
Action? completedAction = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
await motion.RunAsync(actor, aboutToStart, completedAction, cancellationToken);
|
||||
}
|
||||
|
||||
public static void InvokeInPopupLayer(SceneMotionActorControl actor,
|
||||
MotionConfig motionConfig,
|
||||
AbstractMotion motion,
|
||||
Action? aboutToStart = null,
|
||||
Action? completedAction = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
SceneLayer? sceneLayer = PrepareSceneLayer(actor);
|
||||
|
||||
Dispatcher.UIThread.Invoke(async () =>
|
||||
{
|
||||
await InvokeInPopupLayerAsync(actor, motion, aboutToStart, completedAction, cancellationToken);
|
||||
});
|
||||
}
|
||||
|
||||
private static SceneLayer PrepareSceneLayer(SceneMotionActorControl actor)
|
||||
|
||||
public static async Task InvokeInPopupLayerAsync(SceneMotionActorControl actor,
|
||||
AbstractMotion motion,
|
||||
Action? aboutToStart = null,
|
||||
Action? completedAction = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
SceneLayer sceneLayer = PrepareSceneLayer(motion, actor);
|
||||
var compositeDisposable = new CompositeDisposable();
|
||||
compositeDisposable.Add(Disposable.Create(sceneLayer, (state) =>
|
||||
{
|
||||
Dispatcher.UIThread.Invoke(async () =>
|
||||
{
|
||||
await Task.Delay(300);
|
||||
sceneLayer.Hide();
|
||||
sceneLayer.Dispose();
|
||||
});
|
||||
}));
|
||||
var ghost = actor.GetAnimatableGhost();
|
||||
sceneLayer.SetMotionTarget(ghost);
|
||||
actor.NotifyMotionTargetAddedToScene(ghost);
|
||||
sceneLayer.Show();
|
||||
sceneLayer.Topmost = true;
|
||||
actor.NotifySceneShowed();
|
||||
|
||||
await motion.RunAsync(actor, aboutToStart, () =>
|
||||
{
|
||||
if (completedAction is not null)
|
||||
{
|
||||
completedAction();
|
||||
}
|
||||
|
||||
compositeDisposable.Dispose();
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
private static SceneLayer PrepareSceneLayer(AbstractMotion motion, SceneMotionActorControl actor)
|
||||
{
|
||||
if (actor.SceneParent is null)
|
||||
{
|
||||
@ -54,24 +84,7 @@ internal static class MotionInvoker
|
||||
// TODO 这里除了 Popup 这种顶层元素以外,还会不会有其他的顶层元素种类
|
||||
// 暂时先处理 Popup 这种情况
|
||||
var sceneLayer = new SceneLayer(actor.SceneParent, actor.SceneParent.PlatformImpl!.CreatePopup()!);
|
||||
actor.NotifySceneLayerCreated(sceneLayer);
|
||||
actor.NotifySceneLayerCreated(motion, sceneLayer);
|
||||
return sceneLayer;
|
||||
}
|
||||
}
|
||||
|
||||
internal class RenderTransformOriginRestore : IDisposable
|
||||
{
|
||||
RelativePoint _origin;
|
||||
Control _target;
|
||||
|
||||
public RenderTransformOriginRestore(Control target)
|
||||
{
|
||||
_target = target;
|
||||
_origin = target.RenderTransformOrigin;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_target.RenderTransformOrigin = _origin;
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ internal class MoveDownInMotion : AbstractMotion
|
||||
public MoveDownInMotion(double offset,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new QuinticEaseOut(), fillMode)
|
||||
{
|
||||
Offset = offset;
|
||||
@ -97,7 +97,7 @@ internal class MoveDownOutMotion : AbstractMotion
|
||||
public MoveDownOutMotion(double offset,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new QuinticEaseIn(), fillMode)
|
||||
{
|
||||
Offset = offset;
|
||||
@ -182,7 +182,7 @@ internal class MoveUpInMotion : AbstractMotion
|
||||
public MoveUpInMotion(double offset,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new QuinticEaseOut(), fillMode)
|
||||
{
|
||||
Offset = offset;
|
||||
@ -266,7 +266,7 @@ internal class MoveUpOutMotion : AbstractMotion
|
||||
public MoveUpOutMotion(double offset,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new QuinticEaseIn(), fillMode)
|
||||
{
|
||||
Offset = offset;
|
||||
@ -360,7 +360,7 @@ internal class MoveLeftInMotion : AbstractMotion
|
||||
public MoveLeftInMotion(double offset,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new QuinticEaseOut(), fillMode)
|
||||
{
|
||||
Offset = offset;
|
||||
@ -447,7 +447,7 @@ internal class MoveLeftOutMotion : AbstractMotion
|
||||
public MoveLeftOutMotion(double offset,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new QuinticEaseIn(), fillMode)
|
||||
{
|
||||
Offset = offset;
|
||||
@ -530,7 +530,7 @@ internal class MoveRightInMotion : AbstractMotion
|
||||
public MoveRightInMotion(double offset,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new QuinticEaseOut(), fillMode)
|
||||
{
|
||||
Offset = offset;
|
||||
@ -615,7 +615,7 @@ internal class MoveRightOutMotion : AbstractMotion
|
||||
public MoveRightOutMotion(double offset,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new QuinticEaseIn(), fillMode)
|
||||
{
|
||||
Offset = offset;
|
||||
|
@ -6,6 +6,8 @@ namespace AtomUI.MotionScene;
|
||||
|
||||
internal class SceneMotionActorControl : MotionActorControl
|
||||
{
|
||||
public event EventHandler? SceneShowed;
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
/// <summary>
|
||||
@ -25,12 +27,17 @@ internal class SceneMotionActorControl : MotionActorControl
|
||||
{
|
||||
return _ghost ?? this;
|
||||
}
|
||||
|
||||
protected virtual Point CalculateTopLevelGhostPosition()
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在这个接口中,Actor 根据自己的需求对 sceneLayer 进行设置,主要就是位置和大小
|
||||
/// </summary>
|
||||
/// <param name="sceneLayer"></param>
|
||||
public virtual void NotifySceneLayerCreated(SceneLayer sceneLayer)
|
||||
public virtual void NotifySceneLayerCreated(AbstractMotion motion, SceneLayer sceneLayer)
|
||||
{
|
||||
var ghost = GetAnimatableGhost();
|
||||
|
||||
@ -46,9 +53,9 @@ internal class SceneMotionActorControl : MotionActorControl
|
||||
motionTargetSize = ghost.DesiredSize;
|
||||
}
|
||||
|
||||
// var sceneSize = _motion.CalculateSceneSize(motionTargetSize);
|
||||
// var scenePosition = _motion.CalculateScenePosition(motionTargetSize, CalculateGhostPosition());
|
||||
// sceneLayer.MoveAndResize(scenePosition, sceneSize);
|
||||
var sceneSize = motion.CalculateSceneSize(motionTargetSize);
|
||||
var scenePosition = motion.CalculateScenePosition(motionTargetSize, CalculateTopLevelGhostPosition());
|
||||
sceneLayer.MoveAndResize(scenePosition, sceneSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -61,11 +68,8 @@ internal class SceneMotionActorControl : MotionActorControl
|
||||
Canvas.SetTop(motionTarget, 0);
|
||||
}
|
||||
|
||||
internal virtual void NotifyMotionStarted()
|
||||
{
|
||||
}
|
||||
|
||||
internal virtual void NotifyMotionCompleted()
|
||||
public virtual void NotifySceneShowed()
|
||||
{
|
||||
SceneShowed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
@ -5,21 +5,18 @@ using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.MotionScene;
|
||||
|
||||
internal static partial class MotionFactory
|
||||
internal class SlideUpInMotion : AbstractMotion
|
||||
{
|
||||
public static MotionConfig BuildSlideUpInMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
public SlideUpInMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseOut(), fillMode)
|
||||
{
|
||||
easing ??= new CubicEaseOut();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Configure()
|
||||
{
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -59,25 +56,24 @@ internal static partial class MotionFactory
|
||||
endFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SlideUpOutMotion : AbstractMotion
|
||||
{
|
||||
public SlideUpOutMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseIn(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildSlideUpOutMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new CubicEaseIn();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -118,25 +114,24 @@ internal static partial class MotionFactory
|
||||
endFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SlideDownInMotion : AbstractMotion
|
||||
{
|
||||
public SlideDownInMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseOut(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildSlideDownInMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new CubicEaseOut();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -177,25 +172,24 @@ internal static partial class MotionFactory
|
||||
endFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SlideDownOutMotion : AbstractMotion
|
||||
{
|
||||
public SlideDownOutMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseIn(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildSlideDownOutMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new CubicEaseIn();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -236,25 +230,24 @@ internal static partial class MotionFactory
|
||||
endFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SlideLeftInMotion : AbstractMotion
|
||||
{
|
||||
public SlideLeftInMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseOut(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildSlideLeftInMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new CubicEaseOut();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -295,25 +288,24 @@ internal static partial class MotionFactory
|
||||
endFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SlideLeftOutMotion : AbstractMotion
|
||||
{
|
||||
public SlideLeftOutMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseIn(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildSlideLeftOutMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new CubicEaseIn();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -354,25 +346,82 @@ internal static partial class MotionFactory
|
||||
endFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SlideRightInMotion : AbstractMotion
|
||||
{
|
||||
public SlideRightInMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseOut(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildSlideRightInMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new CubicEaseOut();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
Cue = new Cue(0.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 1.0
|
||||
};
|
||||
startFrame.Setters.Add(opacitySetter);
|
||||
|
||||
var scaleXSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleXTransform(1.0)
|
||||
};
|
||||
startFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
animation.Children.Add(startFrame);
|
||||
|
||||
var endFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 0.0
|
||||
};
|
||||
endFrame.Setters.Add(opacitySetter);
|
||||
var scaleXSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleXTransform(0.0)
|
||||
};
|
||||
endFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
RenderTransformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SlideRightOutMotion : AbstractMotion
|
||||
{
|
||||
public SlideRightOutMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CubicEaseIn(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Configure()
|
||||
{
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -413,68 +462,8 @@ internal static partial class MotionFactory
|
||||
endFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
|
||||
public static MotionConfig BuildSlideRightOutMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
{
|
||||
easing ??= new CubicEaseIn();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 1.0
|
||||
};
|
||||
startFrame.Setters.Add(opacitySetter);
|
||||
|
||||
var scaleXSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleXTransform(1.0)
|
||||
};
|
||||
startFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
animation.Children.Add(startFrame);
|
||||
|
||||
var endFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1.0)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 0.0
|
||||
};
|
||||
endFrame.Setters.Add(opacitySetter);
|
||||
var scaleXSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = BuildScaleXTransform(0.0)
|
||||
};
|
||||
endFrame.Setters.Add(scaleXSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -6,21 +6,18 @@ using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Controls.Badge;
|
||||
|
||||
internal static class BadgeMotionFactory
|
||||
internal class BadgeZoomBadgeInMotion : AbstractMotion
|
||||
{
|
||||
public static MotionConfig BuildBadgeZoomBadgeInMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
public BadgeZoomBadgeInMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new ExponentialEaseOut(), fillMode)
|
||||
{
|
||||
easing ??= new ExponentialEaseOut();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Configure()
|
||||
{
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -36,7 +33,7 @@ internal static class BadgeMotionFactory
|
||||
var transformSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = MotionFactory.BuildScaleTransform(0.0)
|
||||
Value = BuildScaleTransform(0.01)
|
||||
};
|
||||
startFrame.Setters.Add(transformSetter);
|
||||
}
|
||||
@ -57,30 +54,29 @@ internal static class BadgeMotionFactory
|
||||
var transformSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = MotionFactory.BuildScaleTransform(1.0)
|
||||
Value = BuildScaleTransform(1.0)
|
||||
};
|
||||
endFrame.Setters.Add(transformSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class BadgeZoomBadgeOutMotion : AbstractMotion
|
||||
{
|
||||
public BadgeZoomBadgeOutMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new ExponentialEaseIn(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildBadgeZoomBadgeOutMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new ExponentialEaseIn();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -96,7 +92,7 @@ internal static class BadgeMotionFactory
|
||||
var transformSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = MotionFactory.BuildScaleTransform(1.0)
|
||||
Value = BuildScaleTransform(1.0)
|
||||
};
|
||||
startFrame.Setters.Add(transformSetter);
|
||||
}
|
||||
@ -117,30 +113,29 @@ internal static class BadgeMotionFactory
|
||||
var transformSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = MotionFactory.BuildScaleTransform(0.0)
|
||||
Value = BuildScaleTransform(0.01)
|
||||
};
|
||||
endFrame.Setters.Add(transformSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class CountBadgeNoWrapperZoomBadgeInMotion : AbstractMotion
|
||||
{
|
||||
public CountBadgeNoWrapperZoomBadgeInMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CircularEaseOut(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildCountBadgeNoWrapperZoomBadgeInMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new CircularEaseOut();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -156,7 +151,7 @@ internal static class BadgeMotionFactory
|
||||
var transformSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = MotionFactory.BuildScaleTransform(0.0, 0.0)
|
||||
Value = BuildScaleTransform(0.01, 0.01)
|
||||
};
|
||||
startFrame.Setters.Add(transformSetter);
|
||||
}
|
||||
@ -177,30 +172,29 @@ internal static class BadgeMotionFactory
|
||||
var transformSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = MotionFactory.BuildScaleTransform(1.0, 1.0)
|
||||
Value = BuildScaleTransform(1.0, 1.0)
|
||||
};
|
||||
endFrame.Setters.Add(transformSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class CountBadgeNoWrapperZoomBadgeOutMotion : AbstractMotion
|
||||
{
|
||||
public CountBadgeNoWrapperZoomBadgeOutMotion(TimeSpan duration,
|
||||
Easing? easing = null,
|
||||
FillMode fillMode = FillMode.Forward)
|
||||
: base(duration, easing ?? new CircularEaseIn(), fillMode)
|
||||
{
|
||||
}
|
||||
|
||||
public static MotionConfig BuildCountBadgeNoWrapperZoomBadgeOutMotion(TimeSpan duration, Easing? easing = null,
|
||||
FillMode fillMode = FillMode.None)
|
||||
protected override void Configure()
|
||||
{
|
||||
easing ??= new CircularEaseIn();
|
||||
var animations = new List<Animation>();
|
||||
RelativePoint transformOrigin = default;
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = fillMode
|
||||
};
|
||||
|
||||
var animation = CreateAnimation();
|
||||
var startFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.0)
|
||||
@ -216,7 +210,7 @@ internal static class BadgeMotionFactory
|
||||
var transformSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = MotionFactory.BuildScaleTransform(1.0, 1.0)
|
||||
Value = BuildScaleTransform(1.0, 1.0)
|
||||
};
|
||||
startFrame.Setters.Add(transformSetter);
|
||||
}
|
||||
@ -237,14 +231,14 @@ internal static class BadgeMotionFactory
|
||||
var transformSetter = new Setter
|
||||
{
|
||||
Property = MotionActorControl.MotionTransformProperty,
|
||||
Value = MotionFactory.BuildScaleTransform(0.0, 0.0)
|
||||
Value = BuildScaleTransform(0.01, 0.01)
|
||||
};
|
||||
endFrame.Setters.Add(transformSetter);
|
||||
}
|
||||
animation.Children.Add(endFrame);
|
||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||
|
||||
animations.Add(animation);
|
||||
return new MotionConfig(transformOrigin, animations);
|
||||
Animations.Add(animation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Media;
|
||||
@ -231,9 +230,8 @@ internal class CountBadgeAdorner : TemplatedControl
|
||||
if (_indicatorMotionActor is not null)
|
||||
{
|
||||
_indicatorMotionActor.IsVisible = false;
|
||||
var zoomBadgeInMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeInMotion(MotionDuration, null,
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeInMotionConfig, () =>
|
||||
var motion = new BadgeZoomBadgeInMotion(MotionDuration);
|
||||
MotionInvoker.Invoke(_indicatorMotionActor, motion, () =>
|
||||
{
|
||||
_indicatorMotionActor.IsVisible = true;
|
||||
}, null, _motionCancellationTokenSource!.Token);
|
||||
@ -244,12 +242,11 @@ internal class CountBadgeAdorner : TemplatedControl
|
||||
{
|
||||
if (_indicatorMotionActor is not null)
|
||||
{
|
||||
var zoomBadgeOutMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeOutMotion(MotionDuration, null,
|
||||
FillMode.Forward);
|
||||
var motion = new BadgeZoomBadgeOutMotion(MotionDuration);
|
||||
_motionCancellationTokenSource?.Cancel();
|
||||
_motionCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeOutMotionConfig, null, () =>
|
||||
MotionInvoker.Invoke(_indicatorMotionActor, motion, null, () =>
|
||||
{
|
||||
completedAction();
|
||||
}, _motionCancellationTokenSource.Token);
|
||||
|
@ -15,13 +15,13 @@ internal class DotBadgeAdorner : TemplatedControl
|
||||
public static readonly StyledProperty<IBrush?> BadgeDotColorProperty =
|
||||
AvaloniaProperty.Register<DotBadgeAdorner, IBrush?>(
|
||||
nameof(BadgeDotColor));
|
||||
|
||||
|
||||
public static readonly DirectProperty<DotBadgeAdorner, DotBadgeStatus?> StatusProperty =
|
||||
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, DotBadgeStatus?>(
|
||||
nameof(Status),
|
||||
o => o.Status,
|
||||
(o, v) => o.Status = v);
|
||||
|
||||
|
||||
internal IBrush? BadgeDotColor
|
||||
{
|
||||
get => GetValue(BadgeDotColorProperty);
|
||||
@ -73,7 +73,7 @@ internal class DotBadgeAdorner : TemplatedControl
|
||||
get => GetValue(OffsetProperty);
|
||||
set => SetValue(OffsetProperty, value);
|
||||
}
|
||||
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly StyledProperty<TimeSpan> MotionDurationProperty =
|
||||
@ -85,9 +85,9 @@ internal class DotBadgeAdorner : TemplatedControl
|
||||
get => GetValue(MotionDurationProperty);
|
||||
set => SetValue(MotionDurationProperty, value);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private MotionActorControl? _indicatorMotionActor;
|
||||
private CancellationTokenSource? _motionCancellationTokenSource;
|
||||
|
||||
@ -109,28 +109,23 @@ internal class DotBadgeAdorner : TemplatedControl
|
||||
if (_indicatorMotionActor is not null)
|
||||
{
|
||||
_indicatorMotionActor.IsVisible = false;
|
||||
var zoomBadgeInMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeInMotion(MotionDuration, null,
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeInMotionConfig, () =>
|
||||
{
|
||||
_indicatorMotionActor.IsVisible = true;
|
||||
}, null, _motionCancellationTokenSource!.Token);
|
||||
_motionCancellationTokenSource?.Cancel();
|
||||
_motionCancellationTokenSource = new CancellationTokenSource();
|
||||
var motion = new BadgeZoomBadgeInMotion(MotionDuration, null, FillMode.Forward);
|
||||
MotionInvoker.Invoke(_indicatorMotionActor, motion, () => _indicatorMotionActor.IsVisible = true,
|
||||
null, _motionCancellationTokenSource.Token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ApplyHideMotion(Action completedAction)
|
||||
{
|
||||
if (_indicatorMotionActor is not null)
|
||||
{
|
||||
var zoomBadgeOutMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeOutMotion(MotionDuration, null,
|
||||
FillMode.Forward);
|
||||
_motionCancellationTokenSource?.Cancel();
|
||||
_motionCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeOutMotionConfig, null, () =>
|
||||
{
|
||||
completedAction();
|
||||
}, _motionCancellationTokenSource.Token);
|
||||
_motionCancellationTokenSource = new CancellationTokenSource();
|
||||
var motion = new BadgeZoomBadgeOutMotion(MotionDuration, null, FillMode.Forward);
|
||||
MotionInvoker.Invoke(_indicatorMotionActor, motion, null, () => completedAction(),
|
||||
_motionCancellationTokenSource.Token);
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,7 +140,7 @@ internal class DotBadgeAdorner : TemplatedControl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SetupBadgeColor()
|
||||
{
|
||||
if (Status is not null)
|
||||
@ -190,6 +185,7 @@ internal class DotBadgeAdorner : TemplatedControl
|
||||
offsetY -= dotSize.Height / 3;
|
||||
_indicatorMotionActor.Arrange(new Rect(new Point(offsetX, offsetY), dotSize));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -199,16 +195,16 @@ internal class DotBadgeAdorner : TemplatedControl
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
adornerLayer.Children.Remove(this);
|
||||
|
||||
|
||||
AdornerLayer.SetAdornedElement(this, adorned);
|
||||
AdornerLayer.SetIsClipEnabled(this, false);
|
||||
adornerLayer.Children.Add(this);
|
||||
|
||||
|
||||
_motionCancellationTokenSource?.Cancel();
|
||||
_motionCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
_motionCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
ApplyShowMotion();
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Automation.Peers;
|
||||
using Avalonia.Controls;
|
||||
@ -308,9 +307,8 @@ public class CollapseItem : HeaderedContentControl, ISelectable
|
||||
}
|
||||
|
||||
InAnimating = true;
|
||||
var slideDownInMotionConfig = MotionFactory.BuildSlideUpInMotion(MotionDuration, new CubicEaseOut(),
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_motionActor, slideDownInMotionConfig, () =>
|
||||
var motion = new SlideUpInMotion(MotionDuration, new CubicEaseOut());
|
||||
MotionInvoker.Invoke(_motionActor, motion, () =>
|
||||
{
|
||||
_motionActor.SetCurrentValue(IsVisibleProperty, true);
|
||||
}, () =>
|
||||
@ -333,9 +331,8 @@ public class CollapseItem : HeaderedContentControl, ISelectable
|
||||
}
|
||||
|
||||
InAnimating = true;
|
||||
var slideDownOutMotionConfig = MotionFactory.BuildSlideUpOutMotion(MotionDuration, new CubicEaseIn(),
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_motionActor, slideDownOutMotionConfig, null, () =>
|
||||
var motion = new SlideUpOutMotion(MotionDuration, new CubicEaseIn());
|
||||
MotionInvoker.Invoke(_motionActor, motion, null, () =>
|
||||
{
|
||||
_motionActor.SetCurrentValue(IsVisibleProperty, false);
|
||||
InAnimating = false;
|
||||
|
@ -4,7 +4,6 @@ using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
@ -194,6 +193,7 @@ public class Expander : AvaloniaExpander
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsExpanded = !IsExpanded;
|
||||
};
|
||||
}
|
||||
@ -294,6 +294,7 @@ public class Expander : AvaloniaExpander
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsExpanded = !IsExpanded;
|
||||
}
|
||||
}
|
||||
@ -311,52 +312,46 @@ public class Expander : AvaloniaExpander
|
||||
CollapseItemContent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ExpandItemContent()
|
||||
{
|
||||
if (_motionActor is null || _animating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!_enableAnimation)
|
||||
{
|
||||
_motionActor.IsVisible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_animating = true;
|
||||
var expandMotionConfig = MotionFactory.BuildExpandMotion(DirectionFromExpandDirection(ExpandDirection),
|
||||
var motion = new ExpandMotion(DirectionFromExpandDirection(ExpandDirection),
|
||||
MotionDuration,
|
||||
new CubicEaseOut(),
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_motionActor, expandMotionConfig, () =>
|
||||
{
|
||||
_motionActor.SetCurrentValue(IsVisibleProperty, true);
|
||||
}, () =>
|
||||
{
|
||||
_animating = false;
|
||||
});
|
||||
new CubicEaseOut());
|
||||
MotionInvoker.Invoke(_motionActor, motion, () => { _motionActor.SetCurrentValue(IsVisibleProperty, true); },
|
||||
() => { _animating = false; });
|
||||
}
|
||||
|
||||
|
||||
private void CollapseItemContent()
|
||||
{
|
||||
if (_motionActor is null || _animating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_enableAnimation)
|
||||
{
|
||||
_motionActor.IsVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_animating = true;
|
||||
var slideDownOutMotionConfig = MotionFactory.BuildCollapseMotion(DirectionFromExpandDirection(ExpandDirection),
|
||||
var motion = new CollapseMotion(DirectionFromExpandDirection(ExpandDirection),
|
||||
MotionDuration,
|
||||
new CubicEaseIn(),
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_motionActor, slideDownOutMotionConfig, null, () =>
|
||||
new CubicEaseIn());
|
||||
MotionInvoker.Invoke(_motionActor, motion, null, () =>
|
||||
{
|
||||
_motionActor.SetCurrentValue(IsVisibleProperty, false);
|
||||
_animating = false;
|
||||
@ -371,6 +366,8 @@ public class Expander : AvaloniaExpander
|
||||
ExpandDirection.Up => Direction.Top,
|
||||
ExpandDirection.Right => Direction.Right,
|
||||
ExpandDirection.Down => Direction.Bottom,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(expandDirection), expandDirection,
|
||||
"Invalid value for ExpandDirection")
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
@ -198,9 +197,8 @@ public class MessageCard : TemplatedControl
|
||||
if (_motionActor is not null)
|
||||
{
|
||||
_motionActor.IsVisible = false;
|
||||
var moveUpInMotionConfig = MotionFactory.BuildMoveUpInMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_motionActor, moveUpInMotionConfig, () =>
|
||||
var motion = new MoveUpInMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseOut());
|
||||
MotionInvoker.Invoke(_motionActor, motion, () =>
|
||||
{
|
||||
_motionActor.IsVisible = true;
|
||||
});
|
||||
@ -211,9 +209,8 @@ public class MessageCard : TemplatedControl
|
||||
{
|
||||
if (_motionActor is not null)
|
||||
{
|
||||
var moveUpOutMotionConfig = MotionFactory.BuildMoveUpOutMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_motionActor, moveUpOutMotionConfig, null, () =>
|
||||
var motion = new MoveUpOutMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseIn());
|
||||
MotionInvoker.Invoke(_motionActor, motion, null, () =>
|
||||
{
|
||||
IsClosed = true;
|
||||
});
|
||||
|
@ -87,7 +87,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<bool> IsCheckedProperty =
|
||||
AvaloniaProperty.Register<NavMenuItem, bool>(nameof(IsChecked));
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="Level"/> property.
|
||||
/// </summary>
|
||||
@ -182,6 +182,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
}
|
||||
|
||||
private bool _hasSubMenu;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether the <see cref="NavMenuItem"/> has a submenu.
|
||||
/// </summary>
|
||||
@ -190,8 +191,9 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
get => _hasSubMenu;
|
||||
set => SetAndRaise(HasSubMenuProperty, ref _hasSubMenu, value);
|
||||
}
|
||||
|
||||
|
||||
private int _level;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the level/indentation of the item.
|
||||
/// </summary>
|
||||
@ -208,7 +210,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
|
||||
/// <inheritdoc/>
|
||||
bool INavMenuItem.IsPointerOverSubMenu => _popup?.IsPointerOverPopup ?? false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者设置菜单项的 Key
|
||||
/// </summary>
|
||||
@ -243,91 +245,96 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
|
||||
internal static readonly StyledProperty<double> ActiveBarWidthProperty =
|
||||
NavMenu.ActiveBarWidthProperty.AddOwner<NavMenuItem>();
|
||||
|
||||
|
||||
internal static readonly StyledProperty<double> ActiveBarHeightProperty =
|
||||
NavMenu.ActiveBarHeightProperty.AddOwner<NavMenuItem>();
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, double> EffectiveActiveBarWidthProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, double>(nameof(EffectiveActiveBarWidth),
|
||||
o => o.EffectiveActiveBarWidth,
|
||||
o => o.EffectiveActiveBarWidth,
|
||||
(o, v) => o.EffectiveActiveBarWidth = v);
|
||||
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, double> EffectivePopupMinWidthProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, double>(nameof(EffectivePopupMinWidth),
|
||||
o => o.EffectivePopupMinWidth,
|
||||
o => o.EffectivePopupMinWidth,
|
||||
(o, v) => o.EffectivePopupMinWidth = v);
|
||||
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, double> PopupMinWidthProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, double>(nameof(PopupMinWidth),
|
||||
o => o.PopupMinWidth,
|
||||
o => o.PopupMinWidth,
|
||||
(o, v) => o.PopupMinWidth = v);
|
||||
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, NavMenuMode> ModeProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, NavMenuMode>(nameof(Mode),
|
||||
o => o.Mode,
|
||||
o => o.Mode,
|
||||
(o, v) => o.Mode = v);
|
||||
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, TimeSpan> OpenCloseMotionDurationProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, TimeSpan>(nameof(OpenCloseMotionDuration),
|
||||
o => o.OpenCloseMotionDuration,
|
||||
o => o.OpenCloseMotionDuration,
|
||||
(o, v) => o.OpenCloseMotionDuration = v);
|
||||
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, bool> HasSubMenuProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, bool>(nameof(HasSubMenu),
|
||||
o => o.HasSubMenu,
|
||||
o => o.HasSubMenu,
|
||||
(o, v) => o.HasSubMenu = v);
|
||||
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, double> InlineItemIndentUnitProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, double>(nameof(InlineItemIndentUnit),
|
||||
o => o.InlineItemIndentUnit,
|
||||
o => o.InlineItemIndentUnit,
|
||||
(o, v) => o.InlineItemIndentUnit = v);
|
||||
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, bool> IsDarkStyleProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, bool>(nameof(IsDarkStyle),
|
||||
o => o.IsDarkStyle,
|
||||
o => o.IsDarkStyle,
|
||||
(o, v) => o.IsDarkStyle = v);
|
||||
|
||||
|
||||
internal double ActiveBarWidth
|
||||
{
|
||||
get => GetValue(ActiveBarWidthProperty);
|
||||
set => SetValue(ActiveBarWidthProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal double ActiveBarHeight
|
||||
{
|
||||
get => GetValue(ActiveBarHeightProperty);
|
||||
set => SetValue(ActiveBarHeightProperty, value);
|
||||
}
|
||||
|
||||
|
||||
private double _effectiveActiveBarWidth;
|
||||
|
||||
internal double EffectiveActiveBarWidth
|
||||
{
|
||||
get => _effectiveActiveBarWidth;
|
||||
set => SetAndRaise(EffectiveActiveBarWidthProperty, ref _effectiveActiveBarWidth, value);
|
||||
}
|
||||
|
||||
|
||||
private double _effectivePopupMinWidth;
|
||||
|
||||
internal double EffectivePopupMinWidth
|
||||
{
|
||||
get => _effectivePopupMinWidth;
|
||||
set => SetAndRaise(EffectivePopupMinWidthProperty, ref _effectivePopupMinWidth, value);
|
||||
}
|
||||
|
||||
|
||||
private double _popupMinWidth;
|
||||
|
||||
internal double PopupMinWidth
|
||||
{
|
||||
get => _popupMinWidth;
|
||||
set => SetAndRaise(PopupMinWidthProperty, ref _popupMinWidth, value);
|
||||
}
|
||||
|
||||
|
||||
private TimeSpan _openCloseMotionDuration;
|
||||
|
||||
internal TimeSpan OpenCloseMotionDuration
|
||||
{
|
||||
get => _openCloseMotionDuration;
|
||||
set => SetAndRaise(OpenCloseMotionDurationProperty, ref _openCloseMotionDuration, value);
|
||||
}
|
||||
|
||||
|
||||
private NavMenuMode _mode;
|
||||
|
||||
internal NavMenuMode Mode
|
||||
{
|
||||
get => _mode;
|
||||
@ -341,7 +348,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
get => _inlineItemIndentUnit;
|
||||
set => SetAndRaise(InlineItemIndentUnitProperty, ref _inlineItemIndentUnit, value);
|
||||
}
|
||||
|
||||
|
||||
private bool _isDarkStyle;
|
||||
|
||||
internal bool IsDarkStyle
|
||||
@ -349,7 +356,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
get => _isDarkStyle;
|
||||
set => SetAndRaise(IsDarkStyleProperty, ref _isDarkStyle, value);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共事件定义
|
||||
@ -437,7 +444,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
private EventHandler CanExecuteChangedHandler => _canExecuteChangeHandler ??= new(CanExecuteChanged);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
internal static PlatformKeyGestureConverter KeyGestureConverter = new();
|
||||
|
||||
/// <summary>
|
||||
@ -472,7 +479,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
AffectsRender<MenuItem>(BackgroundProperty);
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Opens the submenu.
|
||||
/// </summary>
|
||||
@ -488,6 +495,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetCurrentValue(IsSubMenuOpenProperty, true);
|
||||
}
|
||||
|
||||
@ -506,6 +514,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetCurrentValue(IsSubMenuOpenProperty, false);
|
||||
}
|
||||
|
||||
@ -549,7 +558,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
}
|
||||
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
|
||||
|
||||
Level = CalculateDistanceFromLogicalParent<NavMenu>(this) - 1;
|
||||
|
||||
(var command, var parameter) = (Command, CommandParameter);
|
||||
@ -568,7 +577,8 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
}
|
||||
|
||||
_isEmbeddedInMenu = parent?.FindLogicalAncestorOfType<INavMenu>(true) != null;
|
||||
TokenResourceBinder.CreateTokenBinding(this, InlineItemIndentUnitProperty, NavMenuTokenResourceKey.InlineItemIndentUnit);
|
||||
TokenResourceBinder.CreateTokenBinding(this, InlineItemIndentUnitProperty,
|
||||
NavMenuTokenResourceKey.InlineItemIndentUnit);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -637,7 +647,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
protected virtual void OnSubmenuOpened(RoutedEventArgs e)
|
||||
{
|
||||
var menuItem = e.Source as NavMenuItem;
|
||||
|
||||
|
||||
if (menuItem != null && menuItem.Parent == this)
|
||||
{
|
||||
// TODO 我们在这里对模式做一个区分, Inline 暂时不互斥关闭,后面有时间看是否加一个互斥的标记
|
||||
@ -649,7 +659,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
{
|
||||
child.IsSubMenuOpen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -683,13 +693,15 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
SetupItemIcon();
|
||||
if (Mode == NavMenuMode.Inline)
|
||||
{
|
||||
_childItemsLayoutTransform = e.NameScope.Find<MotionActorControl>(InlineNavMenuItemTheme.ChildItemsLayoutTransformPart);
|
||||
_childItemsLayoutTransform =
|
||||
e.NameScope.Find<MotionActorControl>(InlineNavMenuItemTheme.ChildItemsLayoutTransformPart);
|
||||
if (_childItemsLayoutTransform is not null)
|
||||
{
|
||||
_childItemsLayoutTransform.SetCurrentValue(MotionActorControl.IsVisibleProperty, IsSubMenuOpen);
|
||||
}
|
||||
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(this, OpenCloseMotionDurationProperty, GlobalTokenResourceKey.MotionDurationSlow);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(this, OpenCloseMotionDurationProperty,
|
||||
GlobalTokenResourceKey.MotionDurationSlow);
|
||||
}
|
||||
|
||||
if (Transitions is null)
|
||||
@ -710,7 +722,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
|
||||
Icon.IconMode = IconMode.Active;
|
||||
}
|
||||
|
||||
|
||||
private void HandleHeaderFrameExit(object? sender, PointerEventArgs args)
|
||||
{
|
||||
if (!IsDarkStyle || Icon is null || HasSubMenu)
|
||||
@ -726,7 +738,6 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
{
|
||||
Icon.IconMode = IconMode.Normal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void UpdateDataValidation(
|
||||
@ -847,6 +858,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
{
|
||||
HeaderChanged(change);
|
||||
}
|
||||
|
||||
if (change.Property == ParentProperty)
|
||||
{
|
||||
UpdatePseudoClasses();
|
||||
@ -878,7 +890,8 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
else if (change.Property == ModeProperty)
|
||||
{
|
||||
SetupItemContainerTheme(true);
|
||||
} else if (change.Property == ItemCountProperty)
|
||||
}
|
||||
else if (change.Property == ItemCountProperty)
|
||||
{
|
||||
HasSubMenu = ItemCount > 0;
|
||||
}
|
||||
@ -901,22 +914,32 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
if (Icon is not null && Icon is PathIcon menuItemIcon)
|
||||
{
|
||||
BindUtils.RelayBind(this, IsEnabledProperty, menuItemIcon, PathIcon.IsEnabledProperty);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.WidthProperty, NavMenuTokenResourceKey.ItemIconSize);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.HeightProperty, NavMenuTokenResourceKey.ItemIconSize);
|
||||
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.WidthProperty,
|
||||
NavMenuTokenResourceKey.ItemIconSize);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.HeightProperty,
|
||||
NavMenuTokenResourceKey.ItemIconSize);
|
||||
|
||||
if (IsDarkStyle)
|
||||
{
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.NormalFilledBrushProperty, NavMenuTokenResourceKey.DarkItemColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.SelectedFilledBrushProperty, NavMenuTokenResourceKey.DarkItemSelectedColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.ActiveFilledBrushProperty, NavMenuTokenResourceKey.DarkItemHoverColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.DisabledFilledBrushProperty, NavMenuTokenResourceKey.DarkItemDisabledColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.NormalFilledBrushProperty,
|
||||
NavMenuTokenResourceKey.DarkItemColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.SelectedFilledBrushProperty,
|
||||
NavMenuTokenResourceKey.DarkItemSelectedColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.ActiveFilledBrushProperty,
|
||||
NavMenuTokenResourceKey.DarkItemHoverColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.DisabledFilledBrushProperty,
|
||||
NavMenuTokenResourceKey.DarkItemDisabledColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.NormalFilledBrushProperty, NavMenuTokenResourceKey.ItemColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.SelectedFilledBrushProperty, NavMenuTokenResourceKey.ItemSelectedColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.ActiveFilledBrushProperty, NavMenuTokenResourceKey.ItemHoverColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.DisabledFilledBrushProperty, NavMenuTokenResourceKey.ItemDisabledColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.NormalFilledBrushProperty,
|
||||
NavMenuTokenResourceKey.ItemColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.SelectedFilledBrushProperty,
|
||||
NavMenuTokenResourceKey.ItemSelectedColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.ActiveFilledBrushProperty,
|
||||
NavMenuTokenResourceKey.ItemHoverColor);
|
||||
TokenResourceBinder.CreateTokenBinding(menuItemIcon, PathIcon.DisabledFilledBrushProperty,
|
||||
NavMenuTokenResourceKey.ItemDisabledColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -928,6 +951,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
{
|
||||
width = _horizontalFrame.Bounds.Width;
|
||||
}
|
||||
|
||||
EffectiveActiveBarWidth = ActiveBarWidth * width;
|
||||
}
|
||||
|
||||
@ -967,7 +991,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
Focusable = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void UpdatePseudoClasses()
|
||||
{
|
||||
PseudoClasses.Set(TopLevelPC, IsTopLevel);
|
||||
@ -1041,7 +1065,8 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
RaiseEvent(new RoutedEventArgs(SubmenuOpenedEvent));
|
||||
PseudoClasses.Add(StdPseudoClass.Open);
|
||||
OpenInlineItem();
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
PseudoClasses.Remove(StdPseudoClass.Open);
|
||||
CloseInlineItem();
|
||||
@ -1055,6 +1080,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
{
|
||||
item.TryUpdateCanExecute();
|
||||
}
|
||||
|
||||
RaiseEvent(new RoutedEventArgs(SubmenuOpenedEvent));
|
||||
PseudoClasses.Add(StdPseudoClass.Open);
|
||||
}
|
||||
@ -1065,7 +1091,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal void OpenInlineItem()
|
||||
{
|
||||
if (_childItemsLayoutTransform is not null)
|
||||
@ -1074,20 +1100,15 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_animating = true;
|
||||
var slideDownInMotionConfig = MotionFactory.BuildSlideUpInMotion(_openCloseMotionDuration, new CubicEaseOut(),
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_childItemsLayoutTransform, slideDownInMotionConfig, () =>
|
||||
{
|
||||
_childItemsLayoutTransform.SetCurrentValue(IsVisibleProperty, true);
|
||||
}, () =>
|
||||
{
|
||||
_animating = false;
|
||||
});
|
||||
var motion = new SlideUpInMotion(_openCloseMotionDuration, new CubicEaseOut());
|
||||
MotionInvoker.Invoke(_childItemsLayoutTransform, motion,
|
||||
() => { _childItemsLayoutTransform.SetCurrentValue(IsVisibleProperty, true); },
|
||||
() => { _animating = false; });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal void CloseInlineItem()
|
||||
{
|
||||
if (_childItemsLayoutTransform is not null)
|
||||
@ -1096,11 +1117,10 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_animating = true;
|
||||
var slideDownOutMotionConfig = MotionFactory.BuildSlideUpOutMotion(_openCloseMotionDuration, new CubicEaseIn(),
|
||||
FillMode.Forward);
|
||||
MotionInvoker.Invoke(_childItemsLayoutTransform, slideDownOutMotionConfig, null, () =>
|
||||
var motion = new SlideUpOutMotion(_openCloseMotionDuration, new CubicEaseIn());
|
||||
MotionInvoker.Invoke(_childItemsLayoutTransform, motion, null, () =>
|
||||
{
|
||||
_childItemsLayoutTransform.SetCurrentValue(IsVisibleProperty, false);
|
||||
_animating = false;
|
||||
@ -1173,7 +1193,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void SetupItemContainerTheme(bool force = false)
|
||||
{
|
||||
if (ItemContainerTheme is null || force)
|
||||
@ -1181,11 +1201,13 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
_itemContainerThemeDisposable?.Dispose();
|
||||
if (Mode == NavMenuMode.Inline)
|
||||
{
|
||||
_itemContainerThemeDisposable = TokenResourceBinder.CreateGlobalResourceBinding(this, ItemContainerThemeProperty, InlineNavMenuItemTheme.ID);
|
||||
_itemContainerThemeDisposable =
|
||||
TokenResourceBinder.CreateGlobalResourceBinding(this, ItemContainerThemeProperty,
|
||||
InlineNavMenuItemTheme.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void PrepareContainerForItemOverride(Control element, object? item, int index)
|
||||
{
|
||||
base.PrepareContainerForItemOverride(element, item, index);
|
||||
@ -1221,7 +1243,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
ItemsPanel = new FuncTemplate<Panel?>(() => new StackPanel());
|
||||
RefreshContainers();
|
||||
}
|
||||
|
||||
|
||||
private static int CalculateDistanceFromLogicalParent<T>(ILogical? logical, int @default = -1) where T : class
|
||||
{
|
||||
var result = 0;
|
||||
@ -1247,5 +1269,4 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
var targetRect = new Rect(offset, targetFrame.Bounds.Size);
|
||||
return targetRect.Contains(point);
|
||||
}
|
||||
|
||||
}
|
@ -240,30 +240,30 @@ public class NotificationCard : ContentControl
|
||||
return;
|
||||
}
|
||||
|
||||
MotionConfig? motionConfig;
|
||||
AbstractMotion? motion = default;
|
||||
if (Position == NotificationPosition.TopLeft || Position == NotificationPosition.BottomLeft)
|
||||
{
|
||||
motionConfig = MotionFactory.BuildMoveLeftInMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
motion = new MoveLeftInMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
FillMode.Forward);
|
||||
}
|
||||
else if (Position == NotificationPosition.TopRight || Position == NotificationPosition.BottomRight)
|
||||
{
|
||||
motionConfig = MotionFactory.BuildMoveRightInMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
motion = new MoveRightInMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
FillMode.Forward);
|
||||
}
|
||||
else if (Position == NotificationPosition.TopCenter)
|
||||
{
|
||||
motionConfig = MotionFactory.BuildMoveUpInMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
motion = new MoveUpInMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
FillMode.Forward);
|
||||
}
|
||||
else
|
||||
{
|
||||
motionConfig = MotionFactory.BuildMoveDownInMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
motion = new MoveDownInMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseOut(),
|
||||
FillMode.Forward);
|
||||
}
|
||||
|
||||
_motionActor.IsVisible = false;
|
||||
MotionInvoker.Invoke(_motionActor, motionConfig, () =>
|
||||
MotionInvoker.Invoke(_motionActor, motion, () =>
|
||||
{
|
||||
_motionActor.IsVisible = true;
|
||||
});
|
||||
@ -275,29 +275,29 @@ public class NotificationCard : ContentControl
|
||||
{
|
||||
return;
|
||||
}
|
||||
MotionConfig? motionConfig;
|
||||
AbstractMotion? motion = default;
|
||||
if (Position == NotificationPosition.TopLeft || Position == NotificationPosition.BottomLeft)
|
||||
{
|
||||
motionConfig = MotionFactory.BuildMoveLeftOutMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
motion = new MoveLeftOutMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
FillMode.Forward);
|
||||
}
|
||||
else if (Position == NotificationPosition.TopRight || Position == NotificationPosition.BottomRight)
|
||||
{
|
||||
motionConfig = MotionFactory.BuildMoveRightOutMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
motion = new MoveRightOutMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
FillMode.Forward);
|
||||
}
|
||||
else if (Position == NotificationPosition.TopCenter)
|
||||
{
|
||||
motionConfig = MotionFactory.BuildMoveUpOutMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
motion = new MoveUpOutMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
FillMode.Forward);
|
||||
}
|
||||
else
|
||||
{
|
||||
motionConfig = MotionFactory.BuildMoveDownOutMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
motion = new MoveDownOutMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseIn(),
|
||||
FillMode.Forward);
|
||||
}
|
||||
|
||||
MotionInvoker.Invoke(_motionActor, motionConfig, null, () =>
|
||||
MotionInvoker.Invoke(_motionActor, motion, null, () =>
|
||||
{
|
||||
IsClosed = true;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user