• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# PinchGesture
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @jiangtao92-->
5<!--Designer: @piggyguy-->
6<!--Tester: @songyanhong-->
7<!--Adviser: @HelloCrease-->
8
9**PinchGesture** is used to trigger a pinch gesture, which requires two to five fingers with a minimum 5 vp distance between the fingers.
10
11>  **NOTE**
12>
13>  This gesture is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
14>
15>  After a pinch gesture is successfully triggered, all fingers must be lifted and pressed again to trigger the pinch gesture again.
16
17
18## APIs
19
20### PinchGesture
21
22PinchGesture(value?: { fingers?: number, distance?: number })
23
24Sets the parameters for the pinch gesture.
25
26**Atomic service API**: This API can be used in atomic services since API version 11.
27
28**System capability**: SystemCapability.ArkUI.ArkUI.Full
29
30**Parameters**
31
32| Name| Type| Mandatory| Description|
33| -------- | -------- | -------- | -------- |
34| value | { fingers?: number, distance?: number } | No| Parameters for the pinch gesture.<br> - **fingers**: minimum number of fingers to trigger a pinch. The value ranges from 2 to 5.<br>Default value: **2**<br>While more fingers than the minimum number can be pressed to trigger the gesture, only the first fingers of the minimum number participate in gesture calculation.<br> - **distance**: minimum recognition distance, in vp.<br>Default value: **5**<br>**NOTE**<br>Value range: [0, +∞). If the value is less than or equal to 0, it will be converted to the default value.|
35
36### PinchGesture<sup>15+</sup>
37
38PinchGesture(options?: PinchGestureHandlerOptions)
39
40Sets the parameters for the pinch gesture. Compared with [PinchGesture](#pinchgesture-1), this API adds the **isFingerCountLimited** parameter to **options**, which determines whether to enforce the exact number of fingers touching the screen.
41
42**Atomic service API**: This API can be used in atomic services since API version 15.
43
44**System capability**: SystemCapability.ArkUI.ArkUI.Full
45
46**Parameters**
47
48| Name| Type| Mandatory| Description|
49| -------- | -------- | -------- | -------- |
50| options | [PinchGestureHandlerOptions](./ts-uigestureevent.md#pinchgesturehandleroptions) | No| Parameters of the pinch gesture handler.|
51
52
53## Events
54
55>  **NOTE**
56>
57>  In **fingerList** of [GestureEvent](ts-gesture-settings.md#gestureevent), the index of a finger corresponds to its position, that is, the ID of a finger in **fingerList[index]** refers to its index. If a finger is pressed first and does not participate in triggering of the current gesture, its position in **fingerList** is left empty. You are advised to use **fingerInfos** when possible.
58
59### onActionStart
60
61onActionStart(event: (event: GestureEvent) => void)
62
63Triggered when a pinch gesture is recognized.
64
65**Atomic service API**: This API can be used in atomic services since API version 11.
66
67**System capability**: SystemCapability.ArkUI.ArkUI.Full
68
69**Parameters**
70
71| Name| Type                                      | Mandatory| Description                        |
72| ------ | ------------------------------------------ | ---- | ---------------------------- |
73| event  | (event: [GestureEvent](ts-gesture-settings.md#gestureevent)) => void | Yes  | Callback for the pinch event.|
74
75### onActionUpdate
76
77onActionUpdate(event: (event: GestureEvent) => void)
78
79Triggered when the user moves the finger in the pinch gesture on the screen.
80
81**Atomic service API**: This API can be used in atomic services since API version 11.
82
83**System capability**: SystemCapability.ArkUI.ArkUI.Full
84
85**Parameters**
86
87| Name| Type                                      | Mandatory| Description                        |
88| ------ | ------------------------------------------ | ---- | ---------------------------- |
89| event  |  (event: [GestureEvent](ts-gesture-settings.md#gestureevent)) => void | Yes  | Callback for the pinch event.|
90
91### onActionEnd
92
93onActionEnd(event: (event: GestureEvent) => void)
94
95Triggered when the fingers used for the pinch gesture are lifted.
96
97**Atomic service API**: This API can be used in atomic services since API version 11.
98
99**System capability**: SystemCapability.ArkUI.ArkUI.Full
100
101**Parameters**
102
103| Name| Type                                      | Mandatory| Description                     |
104| ------ | ------------------------------------------ | ---- | ---------------------------- |
105| event  |  (event: [GestureEvent](ts-gesture-settings.md#gestureevent)) => void | Yes  | Callback for the pinch event.|
106
107### onActionCancel
108
109onActionCancel(event: () => void)
110
111Triggered when a tap cancellation event is received after the pinch gesture is recognized. Gesture event information is returned.
112
113**Atomic service API**: This API can be used in atomic services since API version 11.
114
115**System capability**: SystemCapability.ArkUI.ArkUI.Full
116
117**Parameters**
118
119| Name| Type                                      | Mandatory| Description                     |
120| ------ | ------------------------------------------ | ---- | ---------------------------- |
121| event  |  () => void | Yes  | Callback for the pinch event.|
122
123### onActionCancel<sup>18+</sup>
124
125onActionCancel(event: Callback\<GestureEvent\>)
126
127Triggered when a tap cancellation event is received after the pinch gesture is recognized. Gesture event information is returned.
128
129**Atomic service API**: This API can be used in atomic services since API version 18.
130
131**System capability**: SystemCapability.ArkUI.ArkUI.Full
132
133**Parameters**
134
135| Name| Type                                      | Mandatory| Description                        |
136| ------ | ------------------------------------------ | ---- | ---------------------------- |
137| event  |  Callback\<[GestureEvent](ts-gesture-settings.md#gestureevent)> | Yes  | Callback for the pinch event.|
138
139## Attributes
140
141**System capability**: SystemCapability.ArkUI.ArkUI.Full
142
143| Name| Type   | Read-Only| Optional| Description                                       |
144| ----  | ------| -----| -----|----------------------------------- |
145| tag<sup>12+</sup>   | string  | No| No| Tag for the pinch gesture. It is used to distinguish the gesture during custom gesture recognition.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
146| allowedTypes<sup>14+</sup> | No| No| Array\<[SourceTool](ts-gesture-settings.md#sourcetool9)> | Allowed event input types for the pinch gesture.<br>**Atomic service API**: This API can be used in atomic services since API version 14.|
147
148## Example
149
150### Example 1: Implementing Simple Scaling
151
152This example demonstrates the recognition of a three-finger pinch gesture using **PinchGesture**.
153
154```ts
155// xxx.ets
156@Entry
157@Component
158struct PinchGestureExample {
159  @State scaleValue: number = 1;
160  @State pinchValue: number = 1;
161  @State pinchX: number = 0;
162  @State pinchY: number = 0;
163
164  build() {
165    Column() {
166      Column() {
167        Text('PinchGesture scale:\n' + this.scaleValue)
168        Text('PinchGesture center:\n(' + this.pinchX + ',' + this.pinchY + ')')
169      }
170      .height(200)
171      .width(300)
172      .padding(20)
173      .border({ width: 3 })
174      .margin({ top: 100 })
175      .scale({ x: this.scaleValue, y: this.scaleValue, z: 1 })
176      // The gesture event is triggered by pinching three fingers together.
177      .gesture(
178      PinchGesture({ fingers: 3 })
179        .onActionStart((event: GestureEvent) => {
180          console.info('Pinch start')
181        })
182        .onActionUpdate((event: GestureEvent) => {
183          if (event) {
184            this.scaleValue = this.pinchValue * event.scale
185            this.pinchX = event.pinchCenterX
186            this.pinchY = event.pinchCenterY
187          }
188        })
189        .onActionEnd((event: GestureEvent) => {
190          this.pinchValue = this.scaleValue
191          console.info('Pinch end')
192        })
193      )
194    }.width('100%')
195  }
196}
197```
198
199 ![en-us_image_0000001174582848](figures/en-us_image_0000001174582848.png)
200
201### Example 2: Implementing Image Scaling with Finger Tracking
202
203This example demonstrates how to implement image scaling with finger tracking by configuring **PinchGesture**.
204
205```ts
206// xxx.ets
207import { UIContext, display, matrix4 } from '@kit.ArkUI';
208
209@Entry
210@Component
211struct PinchGestureExample {
212  private uiContext: UIContext = new UIContext();
213  private contentWidth: number = 0;
214  private contentHeight: number = 0;
215  private scaleMin: number = 0.3;
216  private scaleMax: number = 30.0;
217  private screenWidth: number = 0;
218  private screenHeight: number = 0;
219  @State pntX: number = 0;
220  @State pntY: number = 0;
221  @State curScale: number = 1;
222  @State preScale: number = 1;
223  @State offsetX: number = 0;
224  @State offsetY: number = 0;
225  @State matrix: matrix4.Matrix4Transit = matrix4.identity()
226    .translate({ x: this.offsetX, y: this.offsetY })
227    .scale({ x: this.curScale, y: this.curScale });
228
229  public updateMatrix(): void {
230    this.matrix = matrix4.identity()
231      .scale({ x: this.curScale, y: this.curScale })
232      .translate({ x: this.uiContext.vp2px(this.offsetX), y: this.uiContext.vp2px(this.offsetY) });
233  }
234
235  aboutToAppear(): void {
236    this.uiContext = this.getUIContext();
237    let screenSize = display.getDefaultDisplaySync();
238    this.screenWidth = this.uiContext.px2vp(screenSize.width);
239    this.screenHeight = this.uiContext.px2vp(screenSize.height);
240  }
241
242  build() {
243    Column() {
244      // Replace $r('app.media.img') with the image resource file you use.
245      Image($r('app.media.img'))
246        .objectFit(ImageFit.Contain)
247        .draggable(false)
248        .onComplete((event) => {
249          this.contentWidth = this.uiContext.px2vp(event!.contentWidth);
250          this.contentHeight = this.uiContext.px2vp(event!.contentHeight);
251        })
252        .transform(this.matrix)
253    }
254    // The gesture event is triggered by a two-finger pinch.
255    .gesture(
256      PinchGesture({ fingers: 2 })
257        .onActionStart((event: GestureEvent) => {
258          // Displayed size of the image before scaling
259          const displayWidth = this.contentWidth * this.curScale;
260          const displayHeight = this.contentHeight * this.curScale;
261          // Upper left corner coordinates before scaling
262          const left = (this.screenWidth - displayWidth) / 2 + this.offsetX;
263          const top = (this.screenHeight - displayHeight) / 2 + this.offsetY;
264          // Relative position (as a percentage) of the pinch center relative to the upper left corner of the displayed image
265          this.pntX = (event.pinchCenterX - left) / displayWidth;
266          this.pntY = (event.pinchCenterY - top) / displayHeight;
267          // Scale factor before the current operation
268          this.preScale = this.curScale;
269        })
270        .onActionUpdate((event: GestureEvent) => {
271          // Target scale factor
272          this.curScale = this.preScale * event.scale;
273          let targetDisplayWidth = this.contentWidth * this.curScale;
274          let targetDisplayHeight = this.contentHeight * this.curScale;
275          // Coordinates of the pinch center after scaling
276          const pointX = (this.screenWidth - targetDisplayWidth) / 2 + targetDisplayWidth * this.pntX;
277          const pointY = (this.screenHeight - targetDisplayHeight) / 2 + targetDisplayHeight * this.pntY;
278          // Offset required to align the calculated point (pointX, pointY) with the actual pinch center after scaling
279          this.offsetX = event.pinchCenterX - pointX;
280          this.offsetY = event.pinchCenterY - pointY;
281          this.updateMatrix();
282        })
283        .onActionEnd((event: GestureEvent) => {
284          if (this.curScale < this.scaleMin || this.curScale > this.scaleMax) {
285            this.curScale = 1;
286            this.offsetX = 0;
287            this.offsetY = 0;
288            this.updateMatrix();
289          }
290        })
291    )
292  }
293}
294```
295
296 ![image_pinch](figures/image_pinch.gif)
297