1# PinchGesture 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @jiangtao92--> 5<!--Designer: @piggyguy--> 6<!--Tester: @songyanhong--> 7<!--Adviser: @HelloCrease--> 8 9用于触发捏合手势,触发捏合手势的最少手指为2指,最大为5指,最小识别距离为5vp。 10 11> **说明:** 12> 13> 从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 14> 15> 在捏合手势触发成功后,需要抬起所有手指,重新按下进行捏合才能再次触发捏合手势。 16 17 18## 接口 19 20### PinchGesture 21 22PinchGesture(value?: { fingers?: number; distance?: number }) 23 24继承自[GestureInterface\<T>](ts-gesture-common.md#gestureinterfacet11),设置捏合手势事件。 25 26**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 27 28**系统能力:** SystemCapability.ArkUI.ArkUI.Full 29 30**参数:** 31 32| 参数名 | 类型 | 必填 | 说明 | 33| -------- | -------- | -------- | -------- | 34| value | { fingers?: number; distance?: number } | 否 | 设置捏合手势事件参数。<br> - fingers:触发捏合的最少手指数, 最小为2指,最大为5指。<br/>默认值:2 <br/>触发手势手指可以多于fingers数目,但只有先落下的与fingers相同数目的手指参与手势计算。<br> - distance:最小识别距离,单位为vp。<br/>默认值:5 <br/>**说明:** <br/>取值范围:[0, +∞)。当识别距离的值小于等于0时,会被转化为默认值。 | 35 36### PinchGesture<sup>15+</sup> 37 38PinchGesture(options?: PinchGestureHandlerOptions) 39 40设置捏合手势事件。与[PinchGesture](#pinchgesture-1)相比,options参数新增了对isFingerCountLimited参数,表示是否检查触摸屏幕的手指数量。 41 42**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 43 44**系统能力:** SystemCapability.ArkUI.ArkUI.Full 45 46**参数:** 47 48| 参数名 | 类型 | 必填 | 说明 | 49| -------- | -------- | -------- | -------- | 50| options | [PinchGestureHandlerOptions](./ts-gesturehandler.md#pinchgesturehandleroptions) | 否 | 捏合手势处理器配置参数。 | 51 52 53## 事件 54 55> **说明:** 56> 57> 在[GestureEvent](ts-gesture-common.md#gestureevent对象说明)的fingerList元素中,手指索引编号与位置相对应,即fingerList[index]的id为index。对于先按下但未参与当前手势触发的手指,fingerList中对应的位置为空。建议优先使用fingerInfos。 58 59### onActionStart 60 61onActionStart(event: (event: GestureEvent) => void) 62 63Pinch手势识别成功回调。 64 65**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 66 67**系统能力:** SystemCapability.ArkUI.ArkUI.Full 68 69**参数:** 70 71| 参数名 | 类型 | 必填 | 说明 | 72| ------ | ------------------------------------------ | ---- | ---------------------------- | 73| event | (event: [GestureEvent](ts-gesture-common.md#gestureevent对象说明)) => void | 是 | 手势事件回调函数。 | 74 75### onActionUpdate 76 77onActionUpdate(event: (event: GestureEvent) => void) 78 79Pinch手势移动过程中回调。 80 81**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 82 83**系统能力:** SystemCapability.ArkUI.ArkUI.Full 84 85**参数:** 86 87| 参数名 | 类型 | 必填 | 说明 | 88| ------ | ------------------------------------------ | ---- | ---------------------------- | 89| event | (event: [GestureEvent](ts-gesture-common.md#gestureevent对象说明)) => void | 是 | 手势事件回调函数。 | 90 91### onActionEnd 92 93onActionEnd(event: (event: GestureEvent) => void) 94 95Pinch手势识别成功,手指抬起后触发回调。 96 97**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 98 99**系统能力:** SystemCapability.ArkUI.ArkUI.Full 100 101**参数:** 102 103| 参数名 | 类型 | 必填 | 说明 | 104| ------ | ------------------------------------------ | ---- | ---------------------------- | 105| event | (event: [GestureEvent](ts-gesture-common.md#gestureevent对象说明)) => void | 是 | 手势事件回调函数。 | 106 107### onActionCancel 108 109onActionCancel(event: () => void) 110 111Pinch手势识别成功,接收到触摸取消事件触发回调。返回手势事件信息。 112 113**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 114 115**系统能力:** SystemCapability.ArkUI.ArkUI.Full 116 117**参数:** 118 119| 参数名 | 类型 | 必填 | 说明 | 120| ------ | ------------------------------------------ | ---- | ---------------------------- | 121| event | () => void | 是 | 手势事件回调函数。 | 122 123### onActionCancel<sup>18+</sup> 124 125onActionCancel(event: Callback\<GestureEvent\>) 126 127Pinch手势识别成功,接收到触摸取消事件触发回调。返回手势事件信息。 128 129**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 130 131**系统能力:** SystemCapability.ArkUI.ArkUI.Full 132 133**参数:** 134 135| 参数名 | 类型 | 必填 | 说明 | 136| ------ | ------------------------------------------ | ---- | ---------------------------- | 137| event | Callback\<[GestureEvent](ts-gesture-common.md#gestureevent对象说明)> | 是 | 手势事件回调函数。 | 138 139## 示例 140 141### 示例1(实现简单缩放) 142 143该示例通过配置PinchGesture实现了三指捏合手势的识别。 144 145```ts 146// xxx.ets 147@Entry 148@Component 149struct PinchGestureExample { 150 @State scaleValue: number = 1; 151 @State pinchValue: number = 1; 152 @State pinchX: number = 0; 153 @State pinchY: number = 0; 154 155 build() { 156 Column() { 157 Column() { 158 Text('PinchGesture scale:\n' + this.scaleValue) 159 Text('PinchGesture center:\n(' + this.pinchX + ',' + this.pinchY + ')') 160 } 161 .height(200) 162 .width(300) 163 .padding(20) 164 .border({ width: 3 }) 165 .margin({ top: 100 }) 166 .scale({ x: this.scaleValue, y: this.scaleValue, z: 1 }) 167 // 三指捏合触发该手势事件 168 .gesture( 169 PinchGesture({ fingers: 3 }) 170 .onActionStart((event: GestureEvent) => { 171 console.info('Pinch start') 172 }) 173 .onActionUpdate((event: GestureEvent) => { 174 if (event) { 175 this.scaleValue = this.pinchValue * event.scale 176 this.pinchX = event.pinchCenterX 177 this.pinchY = event.pinchCenterY 178 } 179 }) 180 .onActionEnd((event: GestureEvent) => { 181 this.pinchValue = this.scaleValue 182 console.info('Pinch end') 183 }) 184 ) 185 }.width('100%') 186 } 187} 188``` 189 190  191 192### 示例2(实现图片跟手缩放) 193 194该示例通过配置PinchGesture实现了图片的跟手缩放效果。 195 196```ts 197// xxx.ets 198import { UIContext, display, matrix4 } from '@kit.ArkUI'; 199 200@Entry 201@Component 202struct PinchGestureExample { 203 private uiContext: UIContext = new UIContext(); 204 private contentWidth: number = 0; 205 private contentHeight: number = 0; 206 private scaleMin: number = 0.3; 207 private scaleMax: number = 30.0; 208 private screenWidth: number = 0; 209 private screenHeight: number = 0; 210 @State pntX: number = 0; 211 @State pntY: number = 0; 212 @State curScale: number = 1; 213 @State preScale: number = 1; 214 @State offsetX: number = 0; 215 @State offsetY: number = 0; 216 @State matrix: matrix4.Matrix4Transit = matrix4.identity() 217 .translate({ x: this.offsetX, y: this.offsetY }) 218 .scale({ x: this.curScale, y: this.curScale }); 219 220 public updateMatrix(): void { 221 this.matrix = matrix4.identity() 222 .scale({ x: this.curScale, y: this.curScale }) 223 .translate({ x: this.uiContext.vp2px(this.offsetX), y: this.uiContext.vp2px(this.offsetY) }); 224 } 225 226 aboutToAppear(): void { 227 this.uiContext = this.getUIContext(); 228 let screenSize = display.getDefaultDisplaySync(); 229 this.screenWidth = this.uiContext.px2vp(screenSize.width); 230 this.screenHeight = this.uiContext.px2vp(screenSize.height); 231 } 232 233 build() { 234 Column() { 235 // $r('app.media.img')需要替换为开发者所需的图像资源文件。 236 Image($r('app.media.img')) 237 .objectFit(ImageFit.Contain) 238 .draggable(false) 239 .onComplete((event) => { 240 this.contentWidth = this.uiContext.px2vp(event!.contentWidth); 241 this.contentHeight = this.uiContext.px2vp(event!.contentHeight); 242 }) 243 .transform(this.matrix) 244 } 245 // 双指捏合触发该手势事件 246 .gesture( 247 PinchGesture({ fingers: 2 }) 248 .onActionStart((event: GestureEvent) => { 249 // 图片本次缩放前展示大小 250 const displayWidth = this.contentWidth * this.curScale; 251 const displayHeight = this.contentHeight * this.curScale; 252 // 图片本次缩放前左上角顶点 253 const left = (this.screenWidth - displayWidth) / 2 + this.offsetX; 254 const top = (this.screenHeight - displayHeight) / 2 + this.offsetY; 255 // 本次缩放前手指终点相对图片左上角顶点尺寸占图片展示尺寸的百分比 256 this.pntX = (event.pinchCenterX - left) / displayWidth; 257 this.pntY = (event.pinchCenterY - top) / displayHeight; 258 // 图片本次缩放前的缩放比例 259 this.preScale = this.curScale; 260 }) 261 .onActionUpdate((event: GestureEvent) => { 262 // 目标缩放比 263 this.curScale = this.preScale * event.scale; 264 let targetDisplayWidth = this.contentWidth * this.curScale; 265 let targetDisplayHeight = this.contentHeight * this.curScale; 266 // 本次缩放前手指中点在本次缩放后的坐标 267 const pointX = (this.screenWidth - targetDisplayWidth) / 2 + targetDisplayWidth * this.pntX; 268 const pointY = (this.screenHeight - targetDisplayHeight) / 2 + targetDisplayHeight * this.pntY; 269 // 将pointX、pointY移动到缩放后的手指中点,需要移动的距离 270 this.offsetX = event.pinchCenterX - pointX; 271 this.offsetY = event.pinchCenterY - pointY; 272 this.updateMatrix(); 273 }) 274 .onActionEnd((event: GestureEvent) => { 275 if (this.curScale < this.scaleMin || this.curScale > this.scaleMax) { 276 this.curScale = 1; 277 this.offsetX = 0; 278 this.offsetY = 0; 279 this.updateMatrix(); 280 } 281 }) 282 ) 283 } 284} 285``` 286 287  288