微信小程序开发——Skyline中Worklet动画

Skyline简单介绍

Skyline是微信小程序的新的渲染引擎,其相比于Webview引擎拥有更好的性能,同时也支持更多原生的新特性,比如Worklet动画、路由跳转的转场动画、共享元素动画、全局工具栏等,这些新特性都可以让小程序拥有更加丝滑的操作,以及转场。小编在此非常推荐大家去使用Skyline进行自己的小程序开发。

Skyline目前支持按页面去升级,也就是部分页面可以继续使用Webview,部分可以使用Skyline,具体的配置方法可以参考官方文档:Skyline 渲染引擎 / 从 WebView 迁移 / 起步

本文主要介绍如何使用Skyline的Worklet动画,让你的小程序交互性能更加流畅。

Skyline的线程模型

在讲Worklet动画之前,我们先了解下Skylilne的线程模型。不同于Webview的单线程模型,Skyline改成了双线程模型,将js逻辑、DOM树构建,CSS样式计算单独放到了AppService线程,简称JS线程,而应用样式、布局(Layout)和绘制(Paint)则放在一个渲染线程,简称UI线程,以下是其架构图:

分开成两个线程后,当有需要在JS线程计算动画的过程,而在UI线程进行展示,两者直接很难去协调同步,容易出现动画不流畅的问题。因此微信小程序就提供了Worklet动画来解决这个问题。

什么是Worklet动画

Worklet动画有两个核心概念,分别是Worklet函数,和Worklet共享变量。

Worklet函数

Worklet函数就是一种既可以在JS线程中运行,也可以在UI线程中运行的函数。

Worklet函数的定义就是在函数的顶部加上'worklet'字符串标志:

scss 复制代码
function someWorklet(greeting) {
  'worklet';
  console.log(greeting);
}

// 运行在 JS 线程
someWorklet('hello') // print: hello

// 运行在 UI 线程
wx.worklet.runOnUI(someWorklet)('hello') // print: [ui] hello

Worklet函数间可以直接相互调用:

javascript 复制代码
const name = 'worklet1'

function anotherWorklet() {
  'worklet';
  return 'hello ' + name;
}

// worklet 函数间可互相调用
function someWorklet() {
  'worklet';
  const greeting = anotherWorklet();
  console.log('another worklet says ', greeting);
}

wx.worklet.runOnUI(someWorklet)() // print: [ui] another worklet says hello worklet1

Worklet函数通过wx.worklet.runOnJS来调用普通函数:

scss 复制代码
function someFunc(greeting) {
  console.log('hello', greting);
}

function someWorklet() {
  'worklet'
  // 访问非 worklet 函数时,需使用 runOnJS
  // someFunc 运行在 JS 线程
  wx.worklet.runOnJS(someFunc)('js function')
}

wx.worklet.runOnUI(someWorklet)() // print: hello js function

需要注意的是,Worklet函数不能直接调用普通的函数,需要通过wx.worklet.runOnJS来运行普通的函数,让其在JS线程中运行。

Worklet共享变量

Worklet共享变量就是在JS线程中创建,并且可以在JS线程和UI线程中共享使用的变量。

scss 复制代码
const { shared, runOnUI } = wx.worklet

const offset = shared(0)
function someWorklet() {
  'worklet'
  console.log(offset.value) // print: 1
  // 在 UI 线程修改
  offset.value = 2
  console.log(offset.value) // print: 2
}
// 在 JS 线程修改
offset.value = 1

runOnUI(someWorklet)()

Worklet的实际使用场景

我们结合下前两节的Worklet函数和Worklet共享变量,看下在实际的使用场景。我们开头提到过,Worklet动画解决的就是动画函数在JS线程和UI线程之间协调时导致的卡顿问题。那么我们来看看这个问题是如何使用Worklet动画去解决的。

驱动动画

bash 复制代码
<view id="moved-box"></view>
<view id="btn" bind:tap="tap">点击驱动小球移动</view>
javascript 复制代码
Page({
  onLoad() {
    const offset = wx.worklet.shared(0)
    this.applyAnimatedStyle('#moved-box', () => {
      'worklet';
      return {
        transform: `translateX(${offset.value}px)`
      }
    })
    this._offset = offset
  },
  tap() {
    // 点击时修改 sharedValue 值,驱动小球移动
    this._offset.value = Math.random()
  }
})

当点击按钮 #btn 时,我们用随机数给 offset 进行赋值,小球会随之移动。

applyAnimatedStyle 接口的第二个参数 updater 为一个 worklet 函数,其捕获了共享变量 offset,当 offset 的值变化时,updater 会重新执行,并将返回的新 styleObject 应用到选中节点上。

当然,光看这个例子,跟用 setData 看好像没有什么区别。但当 worklet 动画和手势结合时,就产生了质变。

结合手势系统

ini 复制代码
<pan-gesture-handler onGestureEvent="handlepan">
  <view class="circle"></view>
</pan-gesture-handler>
ini 复制代码
Page({
  onLoad() {
    const offset = wx.worklet.shared(0);
    this.applyAnimatedStyle('.circle', () => {
      'worklet';
      return {
        transform: `translateX(${offset.value}px)`
      };
    });
    this._offset = offset;
  },
  handlepan(evt) {
    'worklet';
    if (evt.state === GestureState.ACTIVE) {
      this._offset.value += evt.deltaX;
    }
  }
});

当手指在 circle 节点上移动时,会产生平滑的拖动效果。handlepan 回调触发在 UI 线程时修改了 offset 的值,而offset值改变的时候会触发this.apppAnimatedStyle的updated函数,并修改.circle的style的transform的值,触发了circle 节点的移动,整个过程都是在UI线程中进行,没有JS线程和UI线程的切换,从而让动画更加的平滑顺畅。

手势系统中的回调handlepan必须是Worklet函数

关于手势系统,我们会在接下来的文章中详细介绍。

相关推荐
汤姆yu2 小时前
基于微信小程序的学校招生系统
微信小程序·小程序·招生小程序
一渊之隔12 小时前
微信小程序在用户拒绝授权后无法使用wx.opensetting再次获取定位授权
微信小程序·小程序
racerun16 小时前
微信小程序如何实现再多个页面共享数据
微信小程序·小程序
HERR_QQ2 天前
【unify】unify的微信小程序开发学习 (to be continued)
学习·微信小程序·小程序
mg6682 天前
微信小程序入门实例_____快速搭建一个快递查询小程序
微信小程序·小程序
程序员柳2 天前
基于微信小程序的校园二手交易平台、微信小程序校园二手商城源代码+数据库+使用说明,layui+微信小程序+Spring Boot
数据库·微信小程序·layui
Jyywww1212 天前
微信小程序学习笔记
笔记·学习·微信小程序
The_era_achievs_hero2 天前
微信小程序41~50
微信小程序·小程序
走,带你去玩3 天前
uniapp 微信小程序水印
微信小程序·小程序·uni-app
是一碗螺丝粉3 天前
🔥 微信H5视频自动播放终极秘籍:WeixinJSBridge竟是官方“通行证”?
微信小程序