HarmonyOS7 双指缩放手势:PinchGesture 实现组件放大缩小 📅 2026/7/21 7:38:57 文章目录前言效果展示实现原理PinchGesture 的工作方式缩放计算公式代码详解状态变量缩放组件重置和放大按钮完整代码常见问题Q缩放有没有极限Q能不能只缩放一个方向Qfingers 设为 3 能三指缩放吗写在最后前言双指捏合缩放是触屏设备上最自然的手势之一——打开相册看照片两指一撑就放大了。ArkUI 用PinchGesture来识别这个手势提供缩放比例scale数据。今天来实现一个基础的双指缩放效果并加上重置和按钮放大功能。效果展示一个紫色的方块上面写着双指缩放。用户用两根手指捏合或撑开方块会跟着缩小或放大。方块上方实时显示当前缩放百分比。底部有重置和放大两个按钮。实现原理PinchGesture 的工作方式PinchGesture检测两根手指之间的距离变化。当两指距离变大撑开时scale 1放大距离变小捏合时scale 1缩小。初始两指距离 D0 当前两指距离 D1 scale D1 / D0跟 PanGesture 一样PinchGesture 的scale也是相对于本次手势起点的相对值。所以在onActionEnd里需要保存当前的缩放值下次缩放时在这个基础上累乘。缩放计算公式当前缩放值 上次缩放值 × 本次手势的 scale代码详解状态变量StatescaleValue:number1// 当前缩放值StatelastScale:number1// 上次手势结束时的缩放值StatescalePercent:string100%// 显示用百分比文本缩放组件Column(){Column(){Text(双指缩放).fontSize(18).fontColor(#FFFFFF).margin({bottom:4})Text(Pinch me).fontSize(12).fontColor(#FFFFFF).opacity(0.8)}.width(100%).height(100%).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).backgroundColor(#9B59B6).borderRadius(16).scale({x:this.scaleValue,y:this.scaleValue}).gesture(PinchGesture({fingers:2}).onActionUpdate((event:GestureEvent){this.scaleValuethis.lastScale*event.scalethis.scalePercentMath.floor(this.scaleValue*100)%}).onActionEnd((){this.lastScalethis.scaleValue}))}.width(160).height(160)关键 API.scale({ x: this.scaleValue, y: this.scaleValue })— 设置组件的缩放比例X 和 Y 同时缩放保持等比PinchGesture({ fingers: 2 })— 需要两根手指触发event.scale— 本次手势的缩放比例重置和放大按钮Row(){Button(重置).width(45%).height(40).backgroundColor(#E0E0E0).borderRadius(10).fontColor(#333333).fontSize(14).onClick((){this.scaleValue1this.lastScale1this.scalePercent100%})Button(放大).width(45%).height(40).backgroundColor(#9B59B6).borderRadius(10).fontColor(#FFFFFF).fontSize(14).onClick((){this.scaleValue0.2this.lastScalethis.scaleValuethis.scalePercentMath.floor(this.scaleValue*100)%})}.width(100%).justifyContent(FlexAlign.SpaceBetween).margin({top:20})重置把缩放值恢复到 1100%放大按钮每次增加 0.220%。注意修改scaleValue后要同步更新lastScale。完整代码EntryComponentstruct PinchGestureZoom{StatescaleValue:number1StatelastScale:number1StatescalePercent:string100%build(){Column(){Column(){Text(缩放手势).fontSize(16).fontWeight(FontWeight.Bold).margin({bottom:16})Text(当前缩放:${this.scalePercent}).fontSize(18).fontWeight(FontWeight.Bold).fontColor(#4D96FF).margin({bottom:20})Column(){Column(){Text(双指缩放).fontSize(18).fontColor(#FFFFFF).margin({bottom:4})Text(Pinch me).fontSize(12).fontColor(#FFFFFF).opacity(0.8)}.width(100%).height(100%).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).backgroundColor(#9B59B6).borderRadius(16).scale({x:this.scaleValue,y:this.scaleValue}).gesture(PinchGesture({fingers:2}).onActionUpdate((event:GestureEvent){this.scaleValuethis.lastScale*event.scalethis.scalePercentMath.floor(this.scaleValue*100)%}).onActionEnd((){this.lastScalethis.scaleValue}))}.width(160).height(160)Row(){Button(重置).width(45%).height(40).backgroundColor(#E0E0E0).borderRadius(10).fontColor(#333333).fontSize(14).onClick((){this.scaleValue1;this.lastScale1this.scalePercent100%})Button(放大).width(45%).height(40).backgroundColor(#9B59B6).borderRadius(10).fontColor(#FFFFFF).fontSize(14).onClick((){this.scaleValue0.2;this.lastScalethis.scaleValuethis.scalePercentMath.floor(this.scaleValue*100)%})}.width(100%).justifyContent(FlexAlign.SpaceBetween).margin({top:20})}.width(100%).padding(24).backgroundColor(#FFFFFF).borderRadius(12).alignItems(HorizontalAlign.Center)}.width(100%).height(100%).backgroundColor(#F5F6FA).padding(16)}}常见问题Q缩放有没有极限默认没有——scale可以无限累乘。实际项目中通常需要限制范围比如 0.5x 到 3xthis.scaleValueMath.max(0.5,Math.min(3,this.lastScale*event.scale))Q能不能只缩放一个方向可以。.scale({ x: this.scaleValue, y: 1 })就只缩放水平方向垂直不变。但双指缩放通常是等比缩放非等比缩放会让内容变形。Qfingers 设为 3 能三指缩放吗理论上可以但三指操作在手机上很不方便不建议使用。写在最后PinchGesture让缩放交互变得简单易实现。核心就是lastScale * event.scale的累乘计算跟 PanGesture 的上次位置 偏移是同一套思路。别忘了给缩放加上范围限制不然用户两指一撑组件就大到看不全了。