目录
(2)MVVM模式下,通过预先设置的条件关系,让控件自动加载动画效果
前言:
WPF的storyboard、visualstate是强劲的动画工具,但个人觉得XAML写起来不舒服,特别是动画效果特别复杂时,光是看着前端代码界面就晕了,加上最近有在学习Unity,觉得Unity的Animator实现动画很轻松,于是就产生了手写一个状态机的想法,截至文章发布,类库已经更新到了1.5.2版本,可以在详细内容中通过链接访问github或nuget查看文档
Ⅰ效果演示:
(1)为100×100的控件加载动画(控件名为GD)
private RotateTransform rotateTransform = new RotateTransform(-280, 50, 50);
private TranslateTransform translateTransform = new TranslateTransform(-100, -50);
private ScaleTransform scaleTransform = new ScaleTransform(2, 2, 50, 50);
private void GD_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
GD.StateMachineTransfer()
.Add(x => x.RenderTransform, rotateTransform, translateTransform, scaleTransform)
.Add(x => x.Opacity, 0.2)
.Add(x => x.CornerRadius,new CornerRadius(15))
.Set((x) =>
{
x.Duration = 0.4;
x.Completed = () =>
{
Notification.Message("过渡完成 √");
};
})
.Start();
}
这个示例中,让GD同时实现了旋转、平移、缩放、透明度、边框圆滑度的渐变动画,持续时间为0.4秒,动画结束时弹出一个模态窗口提示动画完成。
可以试着用WPF原生方法写一下这段动画,然后对比使用这个类库,类库需求的代码量是会少很多,且结构会很清晰;原生方法性能更为强劲、稳定;
还有至关重要的一点,状态机支持对【任何类型】的【任何类型受支持的属性的值】进行渐变,而不局限于控件,它还提供了一个接口,允许任何【自定义的类型】作为【属性】参与到状态机渐变中。
(2)MVVM模式下,通过预先设置的条件关系,让控件自动加载动画效果
- 鼠标进入控件时,令其背景透明度过渡为0.2
- 鼠标离开控件时,令其背景透明度过渡为0
<UserControl.DataContext>
<local:MButtonViewModel x:Name="ViewModel"/>
</UserControl.DataContext>
public partial class MButton : UserControl
{
public MButton()
{
InitializeComponent();
this.StateMachineLoading(ViewModel);
}
}
public class MButtonViewModel : ViewModelBase<MButtonViewModel, MButtonModel>
{
public MButtonViewModel() { }
public static State Start = State.FromObject(new MButtonViewModel())
.SetName("defualt")
.SetProperty(x => x.HoverBackgroundOpacity, 0)
.ToState();
public static State MouseIn = State.FromObject(new MButtonViewModel())
.SetName("mouseInside")
.SetProperty(x => x.HoverBackgroundOpacity, 0.2)
.ToState();
public StateVector<MButtonViewModel> ConditionA { get; set; } = StateVector<MButtonViewModel>.Create()
.AddCondition(x => x.IsMouseInside, MouseIn, (x) => { x.Duration = 0.2; })
.AddCondition(x => !x.IsMouseInside, Start, (x) => { x.Duration = 0.2; });
public override bool IsMouseInside
{
get => base.IsMouseInside;
set
{
base.IsMouseInside = value;
OnConditionsChecked();
//鼠标进出控件时修改IsMouseInside
//IsMouseInside被修改时检查是否满足条件,若满足,则切换State
}
}
}
这里使得控件的背景板的透明度绑定为ViewModel内定义的HoverBackgroundOpacity属性, 随后你便可以设置两个State记录控件ViewModel在鼠标悬停和非悬停下的状态值,接着用一个StateVector定义【在ViewModel满足何种条件时,自动过渡至哪个Sate】的对照关系,于是该控件已经可以自动加载悬停/非悬停动画了!这就和Unity的Animator有些使用方式上的相似了。
(3)生命周期支持
依旧是像Unity那样,在状态机运行渐变效果时,你可通过设置如下委托丰富过程中的行为
Ⅱ实现原理:
1.反射
实现不需要已知起始值,只需要知道最终值,就可以从当前状态渐变至最终状态
2.★ 线性插值
对任何类型的指定属性做出平滑的修改, 那么视觉上的确是一个丝滑的动画
3.图形变换矩阵
Transform变换本质是从一个矩阵渐变至另一个矩阵