当前位置: 首页 > news >正文

HarmonyOS7 双指缩放手势:PinchGesture 实现组件放大缩小

文章目录

    • 前言
    • 效果展示
    • 实现原理
      • PinchGesture 的工作方式
      • 缩放计算公式
    • 代码详解
      • 状态变量
      • 缩放组件
      • 重置和放大按钮
      • 完整代码
    • 常见问题
      • Q:缩放有没有极限?
      • Q:能不能只缩放一个方向?
      • Q:fingers 设为 3 能三指缩放吗?
    • 写在最后

前言

双指捏合缩放是触屏设备上最自然的手势之一——打开相册看照片,两指一撑就放大了。ArkUI 用PinchGesture来识别这个手势,提供缩放比例(scale)数据。

今天来实现一个基础的双指缩放效果,并加上重置和按钮放大功能。

效果展示

一个紫色的方块,上面写着"双指缩放"。用户用两根手指捏合或撑开,方块会跟着缩小或放大。方块上方实时显示当前缩放百分比。底部有"重置"和"放大"两个按钮。

实现原理

PinchGesture 的工作方式

PinchGesture检测两根手指之间的距离变化。当两指距离变大(撑开)时,scale> 1(放大);距离变小(捏合)时,scale< 1(缩小)。

初始两指距离 = D0 当前两指距离 = D1 scale = D1 / D0

跟 PanGesture 一样,PinchGesture 的scale也是相对于本次手势起点的相对值。所以在onActionEnd里需要保存当前的缩放值,下次缩放时在这个基础上累乘。

缩放计算公式

当前缩放值 = 上次缩放值 × 本次手势的 scale

代码详解

状态变量

@StatescaleValue:number=1// 当前缩放值@StatelastScale:number=1// 上次手势结束时的缩放值@StatescalePercent:string='100%'// 显示用百分比文本

缩放组件

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.scaleValue=this.lastScale*event.scalethis.scalePercent=Math.floor(this.scaleValue*100)+'%'}).onActionEnd(()=>{this.lastScale=this.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.scaleValue=1this.lastScale=1this.scalePercent='100%'})Button('放大').width('45%').height(40).backgroundColor('#9B59B6').borderRadius(10).fontColor('#FFFFFF').fontSize(14).onClick(()=>{this.scaleValue+=0.2this.lastScale=this.scaleValuethis.scalePercent=Math.floor(this.scaleValue*100)+'%'})}.width('100%').justifyContent(FlexAlign.SpaceBetween).margin({top:20})

重置把缩放值恢复到 1(100%),放大按钮每次增加 0.2(20%)。注意修改scaleValue后要同步更新lastScale

完整代码

@Entry@Componentstruct PinchGestureZoom{@StatescaleValue:number=1@StatelastScale:number=1@StatescalePercent:string='100%'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.scaleValue=this.lastScale*event.scalethis.scalePercent=Math.floor(this.scaleValue*100)+'%'}).onActionEnd(()=>{this.lastScale=this.scaleValue}))}.width(160).height(160)Row(){Button('重置').width('45%').height(40).backgroundColor('#E0E0E0').borderRadius(10).fontColor('#333333').fontSize(14).onClick(()=>{this.scaleValue=1;this.lastScale=1this.scalePercent='100%'})Button('放大').width('45%').height(40).backgroundColor('#9B59B6').borderRadius(10).fontColor('#FFFFFF').fontSize(14).onClick(()=>{this.scaleValue+=0.2;this.lastScale=this.scaleValuethis.scalePercent=Math.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 到 3x:

this.scaleValue=Math.max(0.5,Math.min(3,this.lastScale*event.scale))

Q:能不能只缩放一个方向?

可以。.scale({ x: this.scaleValue, y: 1 })就只缩放水平方向,垂直不变。但双指缩放通常是等比缩放,非等比缩放会让内容变形。

Q:fingers 设为 3 能三指缩放吗?

理论上可以,但三指操作在手机上很不方便,不建议使用。

写在最后

PinchGesture让缩放交互变得简单易实现。核心就是lastScale * event.scale的累乘计算,跟 PanGesture 的"上次位置 + 偏移"是同一套思路。

别忘了给缩放加上范围限制,不然用户两指一撑,组件就大到看不全了。

http://www.jsqmd.com/news/1233326/

相关文章:

  • 卫生巾哪家用户体验好? - 中媒介
  • 电机技术咨询哪家推荐? - 中媒介
  • 专利无效代理哪家专业? - 中媒介
  • 足球资讯自动化采集与本地化处理实践
  • 鸿蒙Flutter DecoratedBox装饰容器:前景与背景装饰
  • 市政工程保温胶水哪家效果好? - 中媒介
  • SpringBoot集成Activiti/Flowable工作流引擎与bpmnjs流程设计器实战
  • LangChain 之 【RAG简介、文档加载器、文本分割器】
  • 贵阳贵安数字应用场景案例解析与关键技术
  • 四川能做照片定制的蛋糕店 - 中媒介
  • 深入解析C2000 XINTF接口:DMA握手机制与精细化时序配置实战
  • IP68 防水插头线厂家哪家靠谱? - 中媒介
  • 快速理赔猕猴桃哪家好? - 中媒介
  • 企业工商信息查询API调用限制解析:QPS、缓存与数据边界
  • Zephyr RTOS环境变量配置指南:STM32F103C8T6实战详解
  • 基准测试工具之你不知道的两三事 | 5.什么是读写混合负载
  • 人体工程学设计儿童滑板车制造商 - 中媒介
  • BEV三维世界模型全解|全网独家复现Pillar/体素双建模方案,完善三维场景重建与时序预测,助力AGV、园区无人车精准预判避障、仿真训练量产落地
  • 二叉树数据结构详解:从基础概念到工程应用
  • GitHub中文插件:3分钟让GitHub界面全面中文化
  • 饮用水设备卡瓶故障怎么快速解决? - 中媒介
  • 【CMakeLists.txt的写法(基于ROS2)】
  • .NET企业级开发:架构设计与性能优化实战
  • CommitRecap:用Git提交历史生成技术叙事报告的CLI工具
  • docker核心概念
  • HarmonyOS7 旋转手势:RotationGesture 实现双指旋转组件
  • 塑身衣不会卷边哪家好? - 中媒介
  • 找冷链锁鲜靠谱的烤小肠批发商 - 中媒介
  • 推荐洗衣液贴牌全流程定制服务商 - 中媒介
  • 操作系统不支持压缩包内文件搜索怎么办?