哔哩哔哩是什么| 甲状腺低回声结节是什么意思| 怀孕一个月出血是什么情况| 三月生日是什么星座| 令郎是什么意思| 氟哌酸又叫什么名字| 大便不成形用什么药| 刘亦菲原名叫什么| 笔芯是什么意思| 胜利在什么| 向日葵代表什么象征意义| 遗精频繁是什么原因| 越国在现在的什么地方| 3月24日是什么星座| 站久了腰疼是什么原因| ggo是什么意思| 什么门不能开| 脂肪肝有什么症状| 宫颈ecc是什么意思| 多吃蔬菜对身体有什么好处| 甲亢看什么科| 吃什么丰胸效果最好最快| 桂圆不能和什么一起吃| 什么情况下吃救心丸| 苦瓜汤为什么要放黄豆| 王字加一笔是什么字| 重阳节的习俗是什么| 双肾小结石是什么意思| baumwolle是什么面料| 没什么大不了| 刘邦和项羽是什么关系| 一什么树叶| 骨古头坏死吃什么药| 试纸什么时候用最准确| 日落胭脂红的下一句是什么| 过敏性紫癜是什么症状| 橙子是什么季节的水果| 5月24号是什么星座| 包饺子用什么面粉| 等不到天黑烟火不会太完美什么歌| 怀孕前三个月为什么不能告诉别人| 舒筋健腰丸为什么这么贵| 中耳炎什么症状| 隐士是什么意思| 门口放什么植物好风水| 小腿有血栓是什么症状| 春天的花开秋天的风是什么歌| 吃什么能生精和提高精子质量| 微针是什么美容项目| 结肠多发憩室是什么意思| 伏案工作是什么意思| 什么是偏头痛| hbsag阴性是什么意思| 经产妇是什么意思| 饭票是什么意思| 在什么中间| 来月经可以吃什么水果| 血余炭是什么制成的| 热火朝天是什么意思| oc是什么| 超声是什么检查| 夫妻都是a型血孩子是什么血型| 憔悴是什么意思| hpv73阳性是什么意思| 双甘油脂肪酸酯是什么| 挑疳积挑出来的是什么| 脊柱侧弯挂什么科| 家里有蜈蚣是什么原因| 金为什么克木| 高就是什么意思| 抉择是什么意思| 共建是什么意思| 狗狗哭了代表什么预兆| 双子座是什么象星座| 波字五行属什么| 私房照是什么| 男人为什么喜欢女人| 套作是什么意思| 鹿查什么部首| 悠悠什么意思| 龋齿是什么样子的图片| 面面俱到是什么意思| 驴打滚是什么意思| kick是什么意思| 怀女孩有什么征兆| 昭和是什么意思| 声带小结是什么意思| 阑尾粪石是什么| 香蕉补什么| 醋酸是什么东西| 妊娠反应什么时候开始| 胎发什么时候剃最合适| 马齿苋吃了有什么好处| 上午九点到十一点是什么时辰| 爰是什么意思| 为什么会感染幽门螺旋杆菌| 均质是什么意思| 白芷炖肉起什么作用| 附骨疽是什么病| 学兽医需要什么学历| 银耳和雪耳有什么区别| 吴字五行属什么| 脚心发凉是什么原因| 什么如什么什么| 憔悴是什么意思| 1969属什么生肖| 极光是什么| 什么水果对肝有好处| 洋气是什么意思| 橄榄色是什么颜色| 什么运动长高最快| 世界上最贵的狗是什么| 甲亢食疗吃什么| 脸上长痘是什么原因| 白细胞阳性什么意思| 有氧运动和无氧运动有什么区别| 血糖降不下来是什么原因导致| 什么是心率| 节育环嵌顿是什么意思| 头疼想吐是什么原因| 为什么老是做噩梦| 什么食物利尿效果最好| 红细胞高是什么原因| 女人肚子大是什么原因| 右肾小结石是什么意思| 石榴花什么时候开花| 投资公司是做什么的| 记性越来越差是什么原因| 癔症是什么| 肝区回声密集是什么意思| recipe什么意思| 青核桃皮的功效与作用是什么| 脸颊两边长痘痘是什么原因引起的| 腮腺炎吃什么药| 冠状沟有溃疡是什么病| 下面有味道用什么药| 心脏下面是什么器官| 潜水是什么意思| 舌头生疮是什么原因引起的| 什么叫非甾体抗炎药| 老年人喝什么蛋白粉好| 降结肠疼是什么原因| 宫颈管分离是什么意思| 梦见穿袜子是什么意思| 漂白粉是什么| 上梁不正下梁歪是什么意思| 蝙蝠长什么样| 魔鬼是什么意思| 猝死是什么原因造成的| 降血脂有什么好办法| 胆囊炎可以吃什么水果| 脾胃湿热吃什么药好| zn是什么元素| 什么是圆周率| 桂花是什么颜色| 电脑什么时候发明的| 额头长痘是什么原因| 什么是回避型依恋人格| 动脉ct主要检查什么| 蓁字五行属什么| 小脑萎缩吃什么药效果最好| 1974年是什么年| 在什么情况下最容易怀孕| 胆囊肿是什么病严重吗| 现在是什么时辰| 金匮肾气丸主治什么病| 什能组什么词| 不想吃饭没胃口是什么原因| 高潮是什么| 观音菩萨成道日是什么意思| 多吃青菜有什么好处| 吃什么药去体内湿气| 天干指的是什么| 白猫来家里有什么预兆| 梦见穿袜子是什么意思| 四川的耗儿鱼是什么鱼| 泡脚用什么东西泡最好| strong什么意思| 四季平安是什么生肖| 孩子肚脐眼下面疼是什么原因| york是什么牌子| 三伏天是什么| 龙凤呈祥的意思是什么| 小孩铅过高有什么症状| 一帘幽梦是什么意思| 下属是什么意思| 佟丽娅是什么民族| 间接胆红素高是什么意思| 松鼠喜欢吃什么食物| 经常梦遗是什么原因| 30年属什么生肖| 95年属什么生肖婚配表| 舌头有齿痕吃什么药| 唐宋元明清前面是什么| 护士需要什么学历| 孙耀威为什么被封杀| 跳蚤长什么样子| 高压氧舱治疗什么效果| 为什么喉咙总感觉有东西堵着| 成吉思汗属什么生肖| 刺猬喜欢吃什么食物| 一个三点水一个有读什么字| 咸鸭蛋不能和什么一起吃| 印度为什么用手吃饭| 什么是传染性软疣| 三伏天喝什么汤最好| 心脏支架最怕什么| 嘴皮发白是什么原因| 漏尿是什么原因引起的| 名什么中什么| 波奇饭是什么意思| 黄芪是什么样子的| 感冒发烧吃什么药比较好| 勇气是什么| 得乙肝的人有什么症状| 避孕套什么牌子好用又安全| 孽缘什么意思| 乙醇是什么东西| 日本投降是什么时候| mbc是什么意思| 复方氨酚烷胺片是什么药| 经期吃榴莲有什么好处和坏处| 是什么颜色| 睾丸痛吃什么消炎药| 肠道感染有什么症状| 雾霾是什么意思| 高铁不能带什么| 送镜子代表什么意思| 这是什么表情包| 载脂蛋白是什么意思| 血色素是什么意思| 下午5点多是什么时辰| 当归有什么作用和功效| 姓彭的女孩子取什么名字好| 劫是什么意思| 梦见龙是什么意思| 荷叶泡水喝有什么作用| 三价铁离子什么颜色| 此起彼伏是什么意思| 鱼泡是鱼的什么器官| 尿道炎症状吃什么药| 指什么门| 产检是什么意思| 男朋友过生日送什么礼物最有意义| 心火旺吃什么中药| 鱼蛋是什么| 什么茶降血压效果最好| 瘴气是什么意思| gbs是什么意思| 吃什么治便秘最有效| 心梗吃什么药效果好| 什么是妊娠| 舌头锯齿状是什么原因| 合欢树为什么叫鬼树| 欲钱知吃月饼是什么生肖| 5公里25分钟什么水平| 司空见惯是什么意思| 荣辱与共是什么意思| 老鹰代表什么生肖| 孙耀威为什么被雪藏| 神经是什么| 修面皮是什么皮| 交易是什么意思| 外阴瘙痒涂什么药膏| 百度

同居财产被判还拒不执行 法院强制执行显威力

百度 美国很有可能对欧盟其他产品下手:比如汽车产业,将会严重冲击到德国;再比如机械制造和装备制造,也会对德国、法国、荷兰等国家造成严重影响。

小程序采用双线程架构,渲染线程(UI 线程)和逻辑线程(JS 线程)分离。JS 线程不会影响 UI 线程的动画表现,如滚动效果。但引入的问题是,UI 线程的事件发生后,需跨线程传递到 JS 线程,进而触发开发者回调,当做交互动画(如拖动元素)时,这种异步性会带来较大的延迟和不稳定。

worklet 动画正是为解决这类问题而诞生的,使得小程序可以做到类原生动画般的体验。

# 立即体验

使用 worklet 动画能力时确保以下两项:

  • 确保开发者工具右上角 > 详情 > 本地设置里的 将 JS 编译成 ES5 选项被勾选上 (代码包体积会少量增加)
  • worklet 动画相关接口仅在 Skyline 渲染模式下才能使用

首先,我们需要了解一些相关概念。

# 概念一:worklet 函数

一种声明在开发者代码中,可运行在 JS 线程或 UI 线程的函数,函数体顶部有 'worklet' 指令声明。

# worklet 函数定义

function someWorklet(greeting) {
  'worklet';
  console.log(greeting);
}

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

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

# worklet 函数间相互调用

const name = 'skyline'

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 skyline

# 从 UI 线程调回到 JS 线程

function someFunc(greeting) {
  console.log('hello', greeting);
}

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

wx.worklet.runOnUI(someWorklet)() // print: hello skyline

# 概念二:共享变量

JS 线程创建,可在两个线程间同步的变量。

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)()

shared 函数创建的变量,我们称为 sharedValue 共享变量。用法上可类比 vue3 中的 ref,对它的读写都需要通过 .value 属性,但需注意的是它们并不是一个概念。sharedValue 的用途主要如下。

# 跨线程共享数据

worklet 函数捕获的外部变量,实际上会被序列化后生成在 UI 线程的拷贝,如下代码中, someWorklet 捕获了 obj 变量,尽管我们修改了 objname 属性,但在 someWorklet 声明的位置,obj 已经被序列化发送到了 UI 线程,因此后续的修改是无法同步的。

const obj = { name: 'skyline'}
function someWorklet() {
  'worklet'
  console.log(obj.name) // 输出的仍旧是 skyline
}
obj.name = 'change name'

wx.worklet.runOnUI(someWorklet)() 

sharedValue 就是用来在线程间同步状态变化的变量。

const { shared, runOnUI } = wx.worklet

const offset = shared(0)
function someWorklet() {
  'worklet'
  console.log(offset.value) // 输出的是新值 1
}
offset.value = 1

runOnUI(someWorklet)() 

# 驱动动画

worklet 函数和共享变量就是用来解决交互动画问题的。相关接口 applyAnimatedStyle 可通过页面/组件实例访问,接口文档参考

<view id="moved-box"></view>
<view id="btn" bind:tap="tap">点击驱动小球移动</view>
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 动画和手势结合时,就产生了质变。

# 示例用法

# 手势处理

<pan-gesture-handler onGestureEvent="handlepan">
  <view class="circle"></view>
</pan-gesture-handler>
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 的值,会在 UI 线程产生动画,不必再绕回到 JS 线程。

查看更多手势处理的示例代码

# 自定义动画曲线

<view id="moved-box"></view>
<view id="btn" bind:tap="tap">点击驱动小球移动</view>
const { shared, Easing, timing } = wx.worklet
Page({
  onLoad() {
    const offset = shared(0)
    this.applyAnimatedStyle('#moved-box', () => {
      'worklet';
      return {
        transform: `translateX(${offset.value}px)`
      }
    })
    this._offset = offset
  },
  tap() {
    /**
     * 目标值 300
     * 动画时长 200ms
     * 动画曲线 Easing.ease
     */
    this._offset.value = timing(300, {
      duration: 200,
      easing: Easing.ease
    })
  }
})

内置如 timingspring 等常见动画方式的封装方法,开发者可自定义动画曲线,同时可对不同的动画类型进行组合、重复,形成交织动画。

查看更多不同动画类型用法

查看更多缓动函数的示例代码

# 相关接口

# 注意事项

worklet 函数内部有一些调用上的限制需要留意

  1. 页面/组件实例中定义的 worklet 类型回调函数,内部访问 wx 上的接口,可按如下方式,通过 runOnJS 调回到 JS 线程。
  2. worklet 函数引用的外部变量,对象类型将被 Object.freeze 冻结,使用时需直接访问对象上具体的属性。
<tap-gesture-handler onGestureEvent="handleTap">
  <view class="circle" >showModal</view>
</tap-gesture-handler>
const { runOnJS, timing } = wx.worklet
Page({
  data: {
    msg: 'Skyline'
  },
  onLoad() {
    const toValue = 100
    const showModal = this.showModal.bind(this)
    timing(toValue, { duration: 300 }, () => {
      'worklet'
      runOnJS(showModal)(msg)
    })
  },
  handleTap() {
    'worklet'

    // 非常重要!!!
    // const { msg } = this.data
    // 通过解构 this.data 访问 msg,此时 this.data 将被 Object.freeze 冻结,会导致 setData 无法生效
    // 而通过 this.data.msg 则不会冻结 this.data
    const msg = `hello ${this.data.msg}`

    // 非常重要!!!
    // Page method 必须通过 this.methodName.bind(this) 访问
    const showModal = this.showModal.bind(this)
    
    // 场景一:返回 JS 线程
    runOnJS(showModal)(msg)

    // 场景二:动画完成回调里返回 JS 线程
    const toValue = 100
    timing(toValue, { duration: 300 }, () => {
      'worklet'
      runOnJS(showModal)(msg)
    })

    // 场景三:调用其它 worklet 函数
    this.doSomething()
  },
  doSomething() {
    'worklet'
  },
  showModal(msg) {
    wx.showModal({
      title: msg // title: hello skyline
    })
  },
})
墨池为什么不爱柔嘉了 abob是什么药 青霉素主治什么病 未时是什么时候 半年抛是什么意思
丙烯颜料用什么洗掉 姜还是老的辣是什么意思 一个口一个我念什么 此刻朋友这杯酒最珍贵是什么歌 为什么不建议割鼻息肉
胎盘粘连是什么原因造成的 霉菌性阴炎是什么原因引起的女 12月21日是什么星座 父母都是b型血孩子是什么血型 摩羯座是什么动物
美容行业五行属什么 襁褓是什么意思 轮状病毒吃什么药 介入超声是什么意思 散片是什么意思
黄体回声是什么意思hcv8jop4ns2r.cn 望穿秋水的意思是什么hcv9jop4ns8r.cn 你最喜欢的食物是什么hcv8jop0ns4r.cn 三色线分别代表什么hcv7jop6ns2r.cn 9月28号什么星座hcv9jop0ns7r.cn
水淀粉是什么东西hcv7jop9ns4r.cn 笑靥如花什么意思hcv9jop5ns3r.cn 植物神经紊乱中医叫什么病hcv9jop3ns4r.cn 优生优育是什么意思hcv8jop6ns4r.cn 南辕北辙是什么意思hcv9jop7ns0r.cn
守株待兔是什么意思gangsutong.com 壮阳吃什么补最快最好hcv7jop7ns0r.cn 站点是什么意思hcv9jop6ns2r.cn 中耳炎吃什么消炎药hcv8jop6ns9r.cn 前列腺炎吃什么药好hcv8jop9ns2r.cn
焦虑症应该挂什么科室hcv8jop0ns7r.cn 巴特是什么意思hcv7jop5ns4r.cn 完蛋是什么意思hcv9jop3ns4r.cn 论文检索号是什么hcv8jop7ns5r.cn 606是什么意思hcv8jop0ns8r.cn
百度