微信小程序 Worklet 动画是一种高性能的动画技术,通过沟通主线程与UI线程来提高了动画的流畅性和响应性。当然动画既要流畅还应该可控。要做到可控则需要满足两个必要的动作,绑定与解绑
绑定元素、动画属性与shared变量
小程序简单的demo示例如下
// 一秒钟位移100px像素动画
const x = wx.worklet.shared(0)
x.value = wx.worklet.timing(100, {duration: 1000})
this.applyAnimatedStyle('.box', ()=>{
"worklet"
return {
transform: `translate3d(${x.value}px, 0, 0)`
}
})
通过APIapplyAnimatedStyle将shared变量和元素绑定,使用(timing, spring)等算法变更shared值驱动元素生成动画效果。如上例中通过timing算法动态更新x的值产生元素的水平位移操作
解除绑定
查看官方文档,发现可以使用clearAnimatedStyle来解绑状态
this.clearAnimatedStyle('.box', styleIds, () => {
console.log('animatedStyle 已清除绑定')
})
官方描述为
清除选中节点上所有绑定的 animatedStyle,需要注意的是样式并不会重置,只是解除了依赖关系
完蛋,似乎解绑了,又似乎没有解绑。可以理解为元素并没有归位。涉及到上例中的box元素在x轴运动100PX后没有恢复初始状态0上。
会有什么问题
在box元素需要做连续队列动画,或步进动画时会出现比较严重的问题,又当涉及到rotate, skew,transform-origin等动画动作时会因为基准没有还原,或者基准还原被动画化了而出现动画失真。想要的效果出现了诡异的运动轨迹
如在我最近整理完成的小程序wAnimate动画库中,第6例和15例涉及到transform-origin(元素中心点)的变更,是一定要还原初始位置
解决方法
涉及到多效果切换,在开发wAnimate小程序时,还原的问题折腾了好长时间。显然 clearAnimatedStyle解决不了问题,再去仔细翻阅官方文档,暂时的解决方法是在reset方法中通过applyAnimatedStyleAPI归位元素状态,目前来看没有问题
先来看官方API描述,图1 可以设定为sync/async,
flush的描述为
默认情况下,新的样式会在下一个渲染时间片上生效(性能更好),设置 flush: sync 可使得在当前渲染时间片上生效
// reset方法
this.applyAnimatedStyle(element, ()=>{
"worklet"
return {
opacity: 1,
transform: `rotate(0) skew(0) translate3d(0, 0, 0, 0) scale(1)`,
transformOrigin: "50% 50%"
}
}, {
immediate: true,
flush: 'sync' // 一定设置为同步状态
}, (res) => {
// console.log('========= 对象还原');
})
ok,既然flush可以在当前时间片上执行动作,即它可以将数据和元素状态同步执行,我们只要在reset方法时去触发更新就好了。现在来看reset方法执行后效果如预期,后续动画效果正常。
这里吐槽一下,微信小程序 worklet 动画的translateZ效果与浏览器效果差异较大,有些翻滚效果较难实现,希望后续会有变化吧