# Gesture system
In business development, we often need to listen to nodes touch
Event that handles drag and drop and zoom related logic. Because Skyline
Using a two-thread architecture, in such interactive animation, there will be a large asynchronous delay, which can be referred to wxs Responding to Events。
Skyline
in wxs
The code runs on the JS
Thread, while events are generated in the UI
Thread. Therefore, wxs animation
Performance has been reduced, in order to improve the effect of the interactive experience of the Mini Program, we have built a number of gesture components. The advantages of using gesture components include
- Avoid listening to developers
touch
Events, calculate the complex steps of gesture logic on your own - The gesture component directly in the
UI
Thread response, avoiding the need to pass to theJS
Delays caused by threads
# Effect display
The following figure demonstrates the use of gestures, negotiation gestures to achieve the drag ball, half-screen pop-up gesture drag off, segmented half-screen and other effects.Click to see more Skyline Example。
Scan code Mini Program examples, respectively, to experience Basic gesture
and Negotiation gesture
New features
# Gesture component
Component name | Trigger timing |
---|---|
<tap-gesture-handler> | Triggered when clicked |
<double-tap-gesture-handler> | Triggered when double-click |
<scale-gesture-handler> | Triggered when multi-finger scaling |
<force-press-gesture-handler> | iPhone Equipment re-triggered on time |
<pan-gesture-handler > | Drag (Horizontal/Longitudinal) when triggered |
<vertical-drag-gesture-handler> | Triggered when longitudinal sliding |
<horizontal-drag-gesture-handler > | Triggered when lateral sliding |
<long-press-gesture-handler> | Long time trigger |
# Working principle
Gesture component is virtual component, the real response to the event is its direct child node. In the code below, we give container
The node adds two types of gesture listening.
- When swiping horizontally across the screen,
horizontal drag
The callback of the gesture node will be triggered - When swiping lengthwise on the screen,
vertical-drag
The callback of the gesture node will be triggered.
<horizontal-drag-gesture-handler >
<vertical-drag-gesture-handler>
<view id="container"></view>
</vertical-drag-gesture-handler>
</horizontal-drag-gesture-handler >
When you touch the screen, the rendering engine recognizes gestures from the inside out, and when one of the listeners meets the criteria, the rest of the listeners fail. As in scroll-view
When you add a longitudinal gesture monitor internally, it will block scroll-view
Inside the gesture listener, resulting in an inability to swipe.
<scrol-view>
<vertical-drag-gesture-handler>
<view id="container"></view>
</vertical-drag-gesture-handler>
</scroll-view>
It's important to note,pan
The ratio of determining conditions for type vertical-drag
To be loose, so when sliding lengthwise,vertical-drag
Will respond, and pan
Will fail. When sliding horizontally,pan
Type will respond.
<vertical-drag-gesture-handler>
<pan-gesture-handler >
<view id="container"></view>
</pan-gesture-handler >
</vertical-drag-gesture-handler>
# Common attributes
attribute | type | Default value | Required | Introductions |
---|---|---|---|---|
tag | string | nothing | no | Component identity when declaring gesture negotiation |
worklet:ongesture | eventhandler | nothing | no | Gesture Processing Callback |
worklet:should-response-on-move | callback | nothing | no | Whether the gesture responds during finger movement |
worklet:should-accept-gesture | callback | nothing | no | Whether gestures should be recognized |
simultaneous-handlers | Array<string> | [] | no | Declare gesture nodes that can be triggered simultaneously |
native-view | string | nothing | no | Native node type for proxy |
native-view
The supported enumeration values are scroll-view
and swiper
When scrolling the container lengthwise, use the <vertical-drag-gesture-handler>
The gesture component represents the internal gesture, and when scrolling horizontally, the <horizontal-drag-gesture-handler >
。
eventhandler
The type is an event callback, with no return valuecallback
A type is a callback function that the developer registers with the component and is executed at the appropriate time to read the return value.- All callbacks can only pass in one worklet Callback
# Event callback parameter
# worklet:should-response-on-move
Parameters returned pointerEvent
The fields are as follows. Callback each time the touch moves, returning the false
The corresponding gesture component cannot receive the move
Events.
attribute | type | Introductions |
---|---|---|
identifier | number | Touch Object's unique identifier |
type | string | Type of event |
deltaX | number | Last time, x Axis moving coordinates |
deltaY | number | Last time, Y Axis moving coordinates |
clientX | number | Contact with respect to the left edge of the visible visual X coordinate |
clientY | number | Contact with respect to the upper edge of the visible visual Y coordinate |
radiusX | number | Returns the horizontal axis of the smallest ellipse capable of surrounding the contact area (X axis) radius |
radiusY | number | Returns the vertical axis of the smallest ellipse capable of surrounding the contact area (Y axis) radius |
RotationAngle | number | Returns an angle value representing the value described above by radiusX and radiusY The ellipse described needs to be rotated clockwise in order to cover the contact area between the user and the plane as accurately as possible |
force | number | The user's pressure on the touch plane |
timeStamp | number | The time stamp triggered by the event |
Page({
shouldResponseOnMove(pointerEvent) {
'worklet'
return false
}
})
# worklet:should-accept-gesture
The usage is as follows. Frame gesture recognition takes effect when it calls back, and it is up to the developer to decide whether the gesture takes effect. with Pan
Hand gestures, for example.
Enter when you touch screen State.Possible
Status,shouldAcceptGesture
return false
After entering State.CANCELLED
Status, Return true
After entering State.Begin
Status, can continue to receive formalities move
Events.
Page({
shouldAcceptGesture() {
'worklet'
return false
}
})
# worklet:ongesture
The parameters returned by different types of gesture components are as follows
# tap / double-tap
attribute | type | Introductions |
---|---|---|
state | number | Gesture state |
absoluteX | number | Relative to the global X coordinate |
absoluteY | number | Relative to the global Y coordinate |
# pan / vertical-drag / horizontal drag
attribute | type | Introductions |
---|---|---|
state | number | Gesture state |
absoluteX | number | Relative to the global X coordinate |
absoluteY | number | Relative to the global Y coordinate |
deltaX | number | Last time, x Axis moving coordinates |
deltaY | number | Last time, Y Axis moving coordinates |
velocityX | number | The lateral speed of the finger as it leaves the screen (pixel per second) |
velocityY | number | The vertical speed of the finger as it leaves the screen (pixel per second) |
# scale
attribute | type | Introductions |
---|---|---|
state | number | Gesture state |
focalX | number | Center point with respect to the global X coordinate |
focalY | number | Center point with respect to the global Y coordinate |
focalDeltaX | number | Relative to the last time, the center point in the X Axis moving coordinates |
focalDeltaY | number | Relative to the last time, the center point in the Y Axis moving coordinates |
scale | number | Magnified or reduced ratio |
horizontalScale | number | scale The transverse component of |
verticalScale | number | scale The longitudinal component of the |
rotation | number | Angle of swing (in radians) |
velocityX | number | The lateral speed of the finger as it leaves the screen (pixel per second) |
velocityY | number | The vertical speed of the finger as it leaves the screen (pixel per second) |
pointerCount | number | Number of fingers tracked |
- When multiple fingers slide,
focalX
andfocalY
Coordinates for a central focus of a plurality of touch points - When one finger slides,
pointerCount = 1
, the same effect at this timepan-gesture-handler
,scale
The gesture ispan
Of the superset.
# long-press
attribute | type | Introductions |
---|---|---|
state | number | Gesture state |
absoluteX | number | Relative to the global X coordinate |
absoluteY | number | Relative to the global Y coordinate |
translationX | number | Relative to the initial touch point of the X Axis offset |
translationY | number | Relative to the initial touch point of the Y Axis offset |
velocityX | number | The lateral speed of the finger as it leaves the screen (pixel per second) |
velocityY | number | The vertical speed of the finger as it leaves the screen (pixel per second) |
# force-press
attribute | type | Introductions |
---|---|---|
state | number | Gesture state |
absoluteX | number | Relative to the global X coordinate |
absoluteY | number | Relative to the global Y coordinate |
pressure | number | Pressure size |
# Gesture state
All gestures worklet:ongesture
The callback will always return a state
Status field.
enum State {
// Gesture not recognized
POSSIBLE = 0,
// Gesture recognized
BEGIN = 1,
// Continuous gesture active state
ACTIVE = 2,
// Gesture termination
END = 3,
// Gesture cancellation
CANCELLED = 4,
}
We divide gestures into two types:
- Discrete Gestures:
tap
anddouble-tap
, Triggered Only Once - Continuous gestures: Other types of gesture components, finger dragging triggers multiple times
tap-gesture-handler
Returned by the gesture component state
Always for 1。
pan-gesture-handler
The gesture component during a complete drag,state
Will change in the following manner
- When your finger touches the screen,
state = 0
- Moving a short distance,
pan
When the gesture determination is in effect,state = 1
- Keep moving,
state = 2
- Finger off the screen
state = 3
Because nested gestures conflict (only one final decision is recognized), successive gestures state
The changes may have the following scenarios, the developer needs according to the state
Value to handle some exceptional cases.
POSSIBLE -> BEGIN -> ACTIVE -> END
Normal flowPOSSIBLE -> BEGIN -> ACTIVE -> CANCELLED
Advance interruptionPOSSIBLE -> CANCELLED
Gesture not recognized
Not all continuous gestures have POSSIBLE
Status, such as scale-gesture-handler
Gesture component, when the two fingers touch and let go,state
The changes are as follows:
- Two-fingered touch screen,
state = 1, pointerCount = 2
- Double finger magnification operation,
state = 2, pointerCount = 2
- Two fingers off the screen,
state = 3, pointerCount = 1
♪ and then we'll call it back a.state = 1, pointerCount = 1
b.state = 2, pointerCount = 1
c.state = 3, pointerCount = 0
# Note
- The gesture component is available only in
Skyline
Can be used in rendering mode - The gesture component is a virtual component and will not be laid out.
style
、class
Is invalid. - A gesture component can contain only one direct child node, otherwise it is not valid
- The parent component style of a gesture component directly affects its children
- The callback function of the gesture component must be declared as
worklet
function - Gestures are different from ordinary
touch
Event, will not proceed to bubble - Of the gesture component.
eventhandler / callback
Must be declared asworklet
Function, the callback in theUI
Thread Trigger
# Methods of Use
# sample code
Preview the effect in developer tools
# Chaining API init Function sample code
Preview the effect in developer tools
# Example 1: Listen for drag gestures
<pan-gesture-handler on-gesture-event="handlePan">
<view></view>
</pan-gesture-handler >
Page({
handlePan (possibly ) {
"worklet"
console.log(evt.translateX)
},
})
# Example 2: Listening for nested gestures
<horizontal-drag-gesture-handler on-gesture-event="handleHorizontalDrag">
<vertical-drag-gesture-handler on-gesture-event="handleVerticalDrag">
<view class="circle">one-way drag</view>
</vertical-drag-gesture-handler>
</horizontal-drag-gesture-handler >
# Example 3: Proxy native component internal gestures
for <scroll-view>
and <swiper>
Such a scrolling container internally handles scrolling operations based on gestures. Compared to web
,skyline
Provides a lower level access mechanism, so that in some complex interactions, you can do more granular, phased control.
<vertical-drag-gesture-handler
native-view="scroll-view"
should-response-on-move="shouldScrollViewResponse"
should-accept-gesture="shouldScrollViewAccept"
on-gesture-event="handleGesture"
>
<scroll-view
scroll-y
type="list"
adjust-deceleration-velocity="adjustDecelerationVelocity"
bindscroll="handleScroll"
>
<view class="item" wx:for="{{list}}">
<view class="avatar" />
<view class="comment" />
</view>
</scroll-view>
</vertical-drag-gesture-handler>
Rolling lengthwise <scroll-view>
For example, you can use <vertical-drag-gesture-handler>
Gesture components, and declare that native-view="scroll-view"
To represent their internal gestures.
# Rolling events
When the list is scrolled, the event callback of the gesture component and the <scroll-view>
of scroll
Event callbacks are triggered, and they differ in that:
scroll
Events are triggered only when rolling, when the top/After the bottom, no more callbackson-gesture-event
Gesture callbacks trigger when the finger is swiped across the screen until the hand is released
# Gesture control
In the previous introduction to continuous gesture states, we know that gestures have their own recognition process. for example vertical-drag
Gesture, when the finger touches for POSSIBLE
State, moves a short distance before being recognized as BEGIN
State, at which time the gesture is said to be recognized (theACCEPT
)。
# 1. Gesture recognition
should-accept-gesture
Property allows the developer to register a callback
, and returns a boolean value that participates in theGesture recognitionOf the process. When returning false
When the touch gesture is no longer in effect, the associated <scroll-view>
Components cannot be scrolled either.
# 2. Event distribution
should-response-on-move
Property allows the developer to register a callback
, and returns a boolean value that participates in theEvent distributionOf the process. When returning false
When, when move
Of the events are no longer distributed, the associated <scroll-view>
No, keep rolling. This callback will continue to trigger as the finger moves and can be changed at any time to control the scroll container to continue/Pause scrolling.
Page({
// Here to return False, then scroll-view Unable to scroll
// should-accept-gesture Will trigger once at the beginning of gesture recognition.
// should-response-on-move Was in the move Constantly triggered in the process
shouldScrollViewAccept() {
'worklet'
return true
},
// Here to return False, then scroll-view Unable to scroll
shouldScrollViewResponse(pointerEvent) {
'worklet'
return true
},
// Specifies the decay rate when the finger slides away from the rolling assembly
adjustDecelerationVelocity(velocity) {
'worklet'
return velocity
},
// scroll-view After scrolling to the border, slide your finger, scroll Events are no longer triggered
handleScroll (possibly ) {
'worklet'
},
// scroll-view After scrolling to the border, the finger slides and the gesture callback still triggers
handleGesture (possibly ) {
'worklet'
},
})
# Example 4: Gesture Negotiation
In some cases, we will encounterGesture conflictAs the code below shows, there are nested <vertical-drag-gesture-handler>
Components. We hope that Outer
The gesture component to handle the longitudinal drag,Inner
The gesture component handles the scrolling of the list, but actually only Inner
The gesture callback is triggered.
Nested gesture components of the same type, when the inner gesture recognition, the outer gesture components will not be recognized.
<vertical-drag-gesture-handler tag="outer">
<vertical-drag-gesture-handler tag="inner" native-view="scroll-view">
<scroll-view scroll-y></scroll-view>
</vertical-drag-gesture-handler>
</vertical-drag-gesture-handler>
But the above scenario is very common, such as WeChat Channels comment list, the list of scrolling and the entire comment section of the link is very smooth. Gesture negotiation mechanism is used to solve this problem, and it is also very simple to use.simultaneous-handlers
Property declares that multiple gestures can be triggered at the same time.
<vertical-drag-gesture-handler tag="outer" simultaneous-handlers= ["inner"]}}">
<vertical-drag-gesture-handler tag="inner" simultaneous-handlers= ["outer"]}}" native-view="scroll-view">
<scroll-view scroll-y></scroll-view>
</vertical-drag-gesture-handler>
</vertical-drag-gesture-handler>
At this time,Outer
and Inner
Of the gesture component. on-gesture-event
Callbacks will be triggered in turn, in combination with the aboveGesture controlPrinciple, can achieve the desired effect. Full Code ReferenceExample Demo。