# worklet animation
Mini Program uses a two-threaded architecture, the rendering thread (UI Threads) and logical threads (JS Threads) separated.JS
Threads do not affect the UI
An animated representation of a thread, such as a scrolling effect. But the problem with the introduction,UI
After the event of a thread occurs, it needs to be passed across threads to JS
Thread, which in turn triggers developer callbacks as interactive animations (such as dragging elements), this asynchrony causes significant latency and instability.
worklet
Animation is born to solve such problems, so that the Mini Program can achieve a similar experience of native animation.
# Experience immediately
use worklet
Animation ability when ensuring the following two:
- Make sure the top right corner of the developer tools > details > In the local settings.
will JS Compiled into ES5
The option is checked on (The code package volume increases slightly) - worklet The animation-related interface is available only in
Skyline
Can be used in rendering mode
First, we need to understand some related concepts.
# Concept 1:worklet
function
A declaration in developer code that can be run on the JS
Thread or UI
Thread's function, the top of the function body has 'worklet'
Directive statement.
# worklet Function definition
function someWorklet(greeting) {
'worklet'
console.log(greeting)
}
// Running in the JS Thread
someWorklet('hello') // print: hello
// Running in the UI Thread
wx.worklet.runOnUI(someWorklet)('hello') // print: [ui] hello
# worklet Call each other function
const Name = Skyline
function anotherWorklet() {
'worklet'
return 'hello ' + Name
}
// worklet Functions can call each other
function someWorklet() {
'worklet'
const greeting = anotherWorklet()
console.log('another worklet says ', greeting)
}
wx.worklet.runOnUI(someWorklet)() // print: [ui] another worklet says hello skyline
# from UI Thread back to the JS Thread
function someFunc(greeting) {
console.log('hello', greeting)
}
function someWorklet() {
'worklet'
// Access to non worklet Function, you need to use the runOnJS
// someFunc Running in the JS Thread
runOnJS(someFunc)(Skyline )
}
wx.worklet.runOnUI(someWorklet)() // print: hello skyline
# Concept 2: Shared variables
in JS
Thread creates variables that can be synchronized between two threads.
const { shared, RunOnUI } = wx.worklet
const offset = shared(0)
function someWorklet() {
'worklet'
console.log(offset.value) // print: 1
// in UI Thread modification
offset.value = 2
console.log(offset.value) // print: 2
}
// in JS Thread modification
offset.value = 1
RunOnUI(someWorklet)()
by shared
The variable created by the function, which we call sharedValue
Shared variables. Analogy in usage Vue3
to hit the target ref
, read and write to it need to be passed .value
Properties, but it is important to note that they are not a concept.sharedValue
The main uses are as follows.
# Shared data across threads
by worklet
The external variables captured by the function are actually serialized and generated in the UI
A copy of the thread, in the following code, someWorklet
Captured the obj
Variables, even though we modified the obj
of Name
Properties, but in the someWorklet
Position of the statement,obj
Has been serialized and sent to the UI
Thread, so subsequent modifications cannot be synchronized.
const obj = { name: skyline}
function someWorklet() {
'worklet'
console.log(obj.name) // The output is still skyline
}
obj.name = 'change name'
wx.worklet.runOnUI(someWorklet)()
sharedValue
Is used to synchronize the change of state between threads.
const { shared, RunOnUI } = wx.worklet
const offset = shared(0)
function someWorklet() {
'worklet'
console.log(offset.value) // The output is a new value. 1
}
offset.value = 1
RunOnUI(someWorklet)()
# Drive animation
worklet
Functions and shared variables are used to solve the interactive animation problem. Related interface applyAnimatedStyle
Available through the page/Component Instance Access,[Interface Documentation Reference](https://developers.weixin.qq.com/miniprogram/dev/Reference/api/Component.html#ApplyAnimatedStyle- Parameter Definitions)。
<view id="moved-box"></view>
<view id="btn" bind:tap="tap" >Click to drive the ball to move</view>
Page({
onLoad() {
const offset = wx.worklet.shared(0)
this.applyAnimatedStyle('#moved-box', () => {
'worklet'
return {
transform: `translateX(${offset.value}px)`
}
})
this._offset = offset
},
tap() {
// Modify when clicked sharedValue Value, driving the ball to move
this._offset.value = Math.random()
}
})
When the button is clicked #Btn
When we use random numbers to offset
And the ball moves.
applyAnimatedStyle
The second parameter of the interface updater
For a worklet
Function that captures the shared variable offset
, When offset
When the value of theupdater
Will be re-executed and will return the new styleObject
Applied to the selected node.
Of course, just look at this example, with the setData
It doesn't seem to make a difference. But when worklet
Animation andgestureWhen combined, there is a qualitative change.
# Example usage
# Gesture processing
<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
},
handlebar (possibly ) {
'worklet'
if (evt.state === GestureState.ACTIVE) {
this._offset.value += if possible deltaX
}
}
})
When the finger is circle
When you move on a node, it produces a smooth drag effect.handlebar
The callback trigger is UI
Thread, at the same time we modified the offset
The value of, will be in UI
Thread to produce animation, there is no need to go back to the JS
Thread.
See more sample code for gesture processing
# Custom Animation Curves
<view id="moved-box"></view>
<view id="btn" bind:tap="tap" >Click to drive the ball to move</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() {
/**
* Target value 300
* Animation duration 200ms
* Animation curve Easing.ease
*/
this._offset.value = Timing(300, {
duration: 200,
easing: Easing.ease
})
}
})
Built-in such as Timing
、spring
Developers can customize animation curves, and can combine and repeat different animation types to form interlaced animation.
See More Different Animation Types Usage
See more sample code for a slow function
# Related interface
Basic type shared、 derived、cancelAnimation
Slow function Easing
Page Instance Method [applyAnimatedStyle](https://developers.weixin.qq.com/miniprogram/dev/Reference/api/Component.html#ApplyAnimatedStyle- Parameter Definitions)、[clearAniamtedStyle](https://developers.weixin.qq.com/miniprogram/dev/Reference/api/Component.html#ClearAnimatedStyle- Parameter Definitions)
# Note
worklet
There are some limitations on calling inside the function to be aware of
- page/Defined in the component instance
worklet
Type callback function, internal accesswx
The interface on therunOnJS
Transferred back toJS
Thread. worklet
The external variable referenced by the function, the object type will beObject.freeze
Frozen, which requires direct access to specific properties on the object.
<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'
// Very important!!!
// const { msg } = this.data
// By deconstructing this.data access MSG, at this time this.data Will be Object.freeze Freezing, can lead to setData Unable to take effect
// And by this.data.msg It will not freeze. this.data
const msg = `hello ${this.data.msg}`
// Very important!!!
// Page method Must be passed this.methodName.bind(this) access
const showModal = this.showModal.bind(this)
// Scenario 1: Return JS Thread
runOnJS(showModal)(msg)
// Scene 2: Animation Completion Callback JS Thread
const toValue = 100
Timing(toValue, { duration: 300 }, () => {
'worklet'
runOnJS(showModal)(msg)
})
// Scenario 3: Call others worklet function
this.doSomething()
},
doSomething() {
'worklet'
},
showModal(msg) {
wx.showModal({
title: msg // title: hello skyline
})
},
})