1. 动画实现基础:从CSS到JavaScript,再到Skyline
做小程序开发这么多年,我最大的感受就是,动画做得好不好,直接决定了用户愿不愿意留下来。一个流畅的动画,能让用户觉得你的产品“很高级”、“很跟手”;而一个卡顿、掉帧的动画,哪怕功能再强大,用户也会觉得“这玩意儿有点糙”。微信小程序因为运行在微信这个“超级App”里面,它的性能边界其实比我们想象的要复杂。今天,我就从一个老开发者的角度,跟你聊聊怎么在小程序里玩转动画,从最基础的CSS动画,到需要精细控制的JavaScript动画,再到微信新出的“大杀器”Skyline引擎,咱们一步步来拆解。
1.1 CSS动画:简单高效的“快枪手”
对于大多数简单的过渡效果,比如按钮点击的反馈、页面的淡入淡出、元素的轻微移动,CSS动画绝对是你的首选。它就像一把“快枪手”,上手快,性能好,浏览器(或者说小程序的内核)能对它进行很好的优化。
为什么CSS动画性能好? 核心在于,现代浏览器会把应用了CSS transform 和 opacity 动画的元素单独拎出来,放到一个叫“合成层”的地方。这个层可以直接用GPU来绘制,跳过了中间复杂的布局计算和绘制过程。所以,你看到元素在平滑移动,其实只是GPU在不停地合成一张张图片,效率非常高。
我刚开始做小程序的时候,就踩过一个坑。当时要实现一个图标从小变大的动画,我顺手就写了 width 和 height 的过渡。结果在低端安卓机上,动画卡得像幻灯片。后来才明白,修改 width/height 会触发整个页面的“重排”(Reflow),浏览器要重新计算所有元素的位置和大小,开销巨大。正确的做法是使用 transform: scale()。
/* 错误示范:性能杀手 */
.bad-animation {
width: 100rpx;
height: 100rpx;
transition: width 0.3s, height 0.3s;
}
.bad-animation.active {
width: 150rpx;
height: 150rpx;
}
/* 正确示范:GPU加速,丝般顺滑 */
.good-animation {
width: 100rpx;
height: 100rpx;
transform: scale(1);
transition: transform 0.3s;
}
.good-animation.active {
transform: scale(1.5);
}
除了 transform,opacity(透明度)的变化也是高性能的。你可以放心地用它们来实现淡入淡出效果。但记住一个原则:能不用 left/top/margin 做动画就不用。这些属性同样会触发重排。CSS动画的语法很简单,用 @keyframes 定义关键帧,或者用 transition 定义过渡。我个人的习惯是,简单的状态切换用 transition,复杂的多段动画用 @keyframes。
1.2 JavaScript动画:掌控一切的“指挥家”
CSS动画虽好,但有个硬伤:它不够“智能”。你很难在动画播放到一半的时候暂停,或者根据用户的手势实时改变动画的轨迹。这时候,就需要请出我们的“指挥家”——JavaScript动画了。
微信小程序官方提供了 wx.createAnimation 这个API,它是对底层动画能力的一个封装,用起来很方便。你可以创建一个动画实例,然后链式调用各种动画方法(比如旋转、平移、缩放),最后调用 .step() 表示这一组动画定义结束,再通过 setData 将动画数据应用到WXML模板上。
Page({
data: {
animationData: {}
},
onReady: function() {
// 创建一个动画实例,指定时长和缓动函数
const animation = wx.createAnimation({
duration: 1000,
timingFunction: 'ease-out',
delay: 200,
transformOrigin: '50% 50%'
});
// 链式调用,定义动画:先向右移动100px,同时旋转360度
animation.translateX(100).rotate(360).step();
// 导出动画数据,并设置到data中,触发视图层渲染
this.setData({
animationData: animation.export()
});
}
})
在WXML中,用 animation 属性绑定这个数据:
<view animation="{
{animationData}}">我会动起来</view>
wx.createAnimation 适合大多数有明确起止状态的动画。但是,如果你要做的是跟随用户手指拖拽的动画,比如那个经典的左滑删除,它就力不从心了。因为你需要实时获取触摸点的坐标,并立即更新视图的位置。这时候,就得用更原始但也更强大的方式:直接操作数据,结合 transform: translateX。
实测下来,这种“数据驱动视图”的方式,配合 transform,在流畅度上是最好的。你会在后面的实践案例里看到具体代码。这里我想强调的是,JavaScript动画的核心思想是 “在requestAnimationFrame回调中更新状态”。requestAnimationFrame 会告诉浏览器:“请在下次重绘之前调用我这个函数”。这样能保证你的动画更新频率和屏幕刷新率同步(通常是60Hz),避免不必要的计算和丢帧。虽然 wx.createAnimation 内部可能已经用了,但自己手写复杂交互时,这个概念一定要有。
1.3 Skyline引擎:高性能动画的“新舞台”
如果说传统的WebView渲染像是在一个老旧的剧院里表演,那Skyline引擎就像是给你换到了一个现代化的、设备顶级的音乐厅。这是微信团队为小程序打造的一个全新的高性能渲染引擎,它的目标就是解决复杂界面和高级交互下的卡顿问题。
Skyline不是一种新的动画API,而是一个新的底层渲染环境。你的CSS和JavaScript动画代码可能不需要大改,但在Skyline上跑起来,感觉会完全不一样。最大的区别在于线程模型。传统WebView中,JavaScript逻辑、样式计算、布局、绘制、合成等任务,很容易在主线程上互相打架,导致阻塞。Skyline引擎优化了这一点,让渲染管线的效率更高。
我最早体验Skyline是在一个图片瀑布流的小程序里,传统WebView下,快速滑动时白屏和卡顿很明显。切换到Skyline(需要在项目配置中手动开启)后,同样的代码,滚动顺滑了很多,图片加载和定位的响应也更快了。这对于动画来说意味着什么?意味着更稳定的帧率。特别是那些涉及大量元素同时运动、或者需要频繁更新视图的动画,在Skyline上掉帧的概率会大大降低。
启用Skyline很简单,在 app.json 中配置 "renderer": "skyline" 即可。但要注意,它目前还处于持续迭代阶段,有些旧的组件或API可能支持度不够完善。我的建议是,对于新项目,尤其是预期会有复杂交互和动画的项目,可以果断


2533

被折叠的 条评论
为什么被折叠?



