TransitionSystem - Axvser/MinimalisticWPF GitHub Wiki
基于 State ( 状态 ) 的过渡自动加载框架,旨在为WPF动画提供极简的C#实现
- 过渡作用于属性而非依赖属性,更加灵活
- 线程安全的属性更新,即便过渡在非UI线程启动
- 帧计算模块可拆卸、自定义
- 提供接口以允许任何自定义类参与过渡
TransitionParams类 提供了表格中的内容以描述一个过渡
分类 | 成员/属性/事件 | 描述 |
---|---|---|
静态实例 | TransitionParams.Theme |
主题过渡效果的默认参数 |
TransitionParams.Hover |
悬停过渡效果的默认参数 | |
TransitionParams.Empty |
空过渡效果的默认参数 | |
效果参数 | FrameRate |
帧率,控制过渡效果的平滑度 |
Duration |
持续时间,控制过渡效果的总时长 | |
Acceleration |
加速度,控制过渡效果的速度变化 | |
IsAutoReverse |
是否自动反向播放过渡效果 | |
LoopTime |
循环次数,控制过渡效果的重复次数 | |
Priority |
优先级,控制过渡效果的调度优先级 | |
IsAsync |
是否异步执行过渡效果 | |
生命周期事件 | Awaked |
过渡效果初始化时触发的事件 |
Start |
过渡效果开始时触发的事件 | |
Update |
过渡效果每帧更新时触发的事件 | |
LateUpdate |
过渡效果每帧更新后触发的事件 | |
Canceled |
过渡效果被取消时触发的事件 | |
Completed |
过渡效果完成时触发的事件 | |
计算属性 | DeltaTime |
每帧的时间间隔,根据帧率计算 |
FrameCount |
总帧数,根据持续时间和帧率计算 | |
默认值 | DefaultFrameRate |
默认帧率 |
DefaultPriority |
默认优先级 | |
方法 | Clone() |
实现ICloneable 接口,调用DeepCopy()
|
提供原子过渡,一个元素仅运行一个最新激活的过渡
-
- 用 Fluent API 构建过渡
var control = new Grid();
control.Transition()
.SetProperty(x=>x.Background,Brushes.Red)
.SetParams((p) =>
{
p.Duration = 3;
p.IsAutoReverse = true;
p.LoopTime = 2;
})
.Start();
-
- 用 TransitionBoard 复用过渡
var control = new Grid();
var param = new TransitionParams()
{
Duration = 3,
IsAutoReverse = true,
LoopTime = 2,
};
var transition1 = Transition.Create<Grid>()
.SetProperty(x => x.Background, Brushes.Red)
.SetParams(param);
var transition2 = Transition.Create<Grid>()
.SetProperty(x => x.Width, 100)
.SetParams(param);
var transition = Transition.Create([transition1, transition2]);
control.BeginTransition(transition);
// Transition.Dispose(control);
提供非原子过渡,一个元素可以同时执行多个过渡,特别注意是使用 BeginTransitions 而不是 BeginTransition
var control = new Grid();
var param1 = new TransitionParams()
{
Duration = 3,
IsAutoReverse = true,
};
var param2 = new TransitionParams()
{
Duration = 1,
LoopTime = 15
};
var transition1 = Transition.Create<Grid>()
.SetProperty(x => x.Background, Brushes.Red)
.SetParams(param1);
var transition2 = Transition.Create<Grid>()
.SetProperty(x => x.Width, 100)
.SetProperty(x => x.Height, 100)
.SetParams(param2);
var schedulers = control.BeginTransitions(transition1, transition2);
// schedulers[0].Dispose();
// schedulers[1].Dispose();
构建过渡时,无论使用Fluent API还是TransitionBoard,均可替换指定属性的插值计算逻辑
public void LoadTransition()
{
var control = new Grid();
control.Transition()
.SetProperty(x => x.Background, Brushes.Red)
.SetParams(TransitionParams.Hover)
.SetCalculator(nameof(Grid.Background), Interpolate) // 将 Background 的插值逻辑覆写为自定义的插值逻辑 Interpolate
.Start();
}
public static List<object?> Interpolate(object? current, object? target, double steps)
{
List<object?> list = [];
// 实现自定义的插值逻辑
return list;
}
非WPF常见属性也可参与过渡自动生成,且由于依据你自定义插值逻辑执行过渡,效果而言可以很灵活
using MinimalisticWPF.StructuralDesign.Animator;
namespace DynamicTest_MinWpf
{
public class MyClass : IInterpolable
{
public List<object?> Interpolate(object? current, object? target, int steps)
{
// 要求你提供一个统一方法,计算从 current 到 target 的插值集合 , 总计 steps 个插值
// 发挥你的想象力,不仅仅是线性插值,一切皆有可能
}
}
}
基于过渡参数是一个引用类型,这在某些场景下可能导致意外的效果变动,尽管这种情况我没有遇到过,但是原则上必须提供这样的功能
var control1 = new Grid();
var control2 = new Grid();
var param = new TransitionParams()
{
Duration = 3,
IsAutoReverse = true,
LoopTime = 2,
};
var transition1 = Transition.Create<Grid>()
.SetProperty(x => x.Background, Brushes.Red)
.SetParams(param);
var transition2 = Transition.Create<Grid>()
.SetProperty(x => x.Width, 100)
.SetParams(param);
var transition = Transition.Create([transition1, transition2]);
var compile = Transition.Compile([transition1, transition2], param, null);
param.LoopTime = 10; // 假设在这里,过渡参数被意外地修改了
control1.BeginTransition(transition); // 循环 10次,受到引用类型的影响
control2.BeginTransition(compile); // 循环 2次,不受外部影响,不可修改