更新记录
1.0.0(2026-10-24)
更新日志
1.0.0(2026-10-24)
- 支持双指捏合缩放(以两指中点为缩放中心)与单指拖动
- 支持边界限制与缩放范围控制(minScale / maxScale)
- 支持双击快速缩放 / 重置(enableDoubleTap / doubleTapScale)
- 支持 swiper 兼容模式(swiperCompatible),未放大不拦截手势
- 支持长文本查看场景(minScale 可低至 0.5 总览全文)
- 提供 @change 事件(ZoomPanState 共享类型)与 reset / setScale / getState 方法
- 多端适配:App(Android/iOS)、微信小程序、H5
平台兼容性
uni-app x(4.41)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| √ | √ | √ | √ | - | √ |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| × | × | × | √ |
ZoomPanView 双指缩放单指拖动组件(uni-app x 多端)
基于 uni-app x(uvue/UTS)的双指捏合缩放 + 单指拖动组件,一份代码适配 App(Android/iOS)、微信小程序、H5。
功能特性
- 双指缩放:支持双指捏合缩放,缩放中心基于两指中点
- 单指拖动:缩放后支持单指拖动内容(双指抬起一指后可无缝继续拖动)
- 边界限制:拖动时自动限制边界,防止内容超出可视区域;缩小时自动回中
- 缩放范围控制:可配置最小和最大缩放比例
- 双击缩放:支持双击快速缩放/重置,围绕点击点放大
- swiper 兼容:
swiper-compatible模式下未放大时不拦截手势,swiper 正常翻页;放大后拖动不带动 swiper - 动画过渡:双击/重置/设置缩放比例时平滑过渡,手势进行中实时跟手
- 类型共享:内置
ZoomPanState共享类型(uts),@change事件强类型回调
快速开始
组件位于 uni_modules/bjx-zoom-pan-view/components/zoom-pan-view/,uni_modules 支持 easycom,无需 import 直接使用:
<template>
<view class="container">
<zoom-pan-view>
<image src="/static/logo.png" mode="aspectFit" style="width:100%;height:100%;"></image>
</zoom-pan-view>
</view>
</template>
Props 属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| minScale | Number | 1 | 最小缩放比例 |
| maxScale | Number | 3 | 最大缩放比例 |
| initialScale | Number | 1 | 初始缩放比例 |
| enableZoom | Boolean | true | 是否启用缩放功能 |
| enablePan | Boolean | true | 是否启用拖动功能 |
| animationDuration | Number | 300 | 缩放动画时长(毫秒) |
| enableDoubleTap | Boolean | true | 是否启用双击缩放 |
| doubleTapScale | Number | 2 | 双击缩放比例 |
| allowPageScroll | Boolean | true | H5 端是否允许页面滚动(false 时阻止默认滚动) |
| swiperCompatible | Boolean | false | swiper 兼容模式(见下文) |
事件
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| @change | 缩放或拖动状态改变时触发 | state: ZoomPanState(scale/translateX/translateY) |
监听事件需导入共享类型:
import { ZoomPanState } from '@/uni_modules/bjx-zoom-pan-view/components/zoom-pan-view/zoom-pan-state.uts'
// methods 中
onChange(s: ZoomPanState) {
console.log('scale:', s.scale, 'x:', s.translateX, 'y:', s.translateY)
}
方法
通过 ref 调用(uni-app x 官方方式 $refs + $callMethod):
<zoom-pan-view ref="zpv">...</zoom-pan-view>
import { ComponentPublicInstance } from 'vue'
// 重置到初始状态
(this.$refs['zpv'] as ComponentPublicInstance).$callMethod('reset')
// 设置缩放比例
(this.$refs['zpv'] as ComponentPublicInstance).$callMethod('setScale', 2)
// 获取当前状态
(this.$refs['zpv'] as ComponentPublicInstance).$callMethod('getState')
在 swiper 中使用
设置 :swiper-compatible="true":
- 未放大(scale = 1)时组件不拦截手势,swiper 左右滑动正常翻页
- 放大后(scale > 1)或双指捏合中,组件消费手势,拖动内容不会带动 swiper
- 双指捏合过程中自动锁定,避免缩放与翻页冲突
<swiper>
<swiper-item>
<zoom-pan-view :swiper-compatible="true" :min-scale="0.5" :max-scale="4">
<!-- 长文本或图片内容 -->
</zoom-pan-view>
</swiper-item>
</swiper>
长文本查看建议
长文本内容超出可视区域时,建议将 min-scale 设为 0.5:先縮小总览全文,再双击/捏合放大、拖动阅读细节。
注意事项
- 容器尺寸:确保父容器有明确的宽高,组件会自动通过
createSelectorQuery获取容器尺寸(失败时回退窗口尺寸) - 内容适配:建议内容使用
aspectFit模式以保持比例;边界计算假设内容在 scale=1 时铺满容器 - uni-app x 仅支持 vue3,本项目为 uvue/UTS 实现,不支持 vue2 / uni-app 老项目(.vue)
- 复杂事件参数:
@change的对象参数依赖zoom-pan-state.uts共享类型,请勿在页面中自行声明同形 type 替代导入 will-change在 App 端原生渲染下无意义,未包含
技术实现
- 使用
touchstart、touchmove、touchend、touchcancel事件处理手势 - 通过
transform: translate() scale()实现缩放和位移,缩放围绕内容中心(与焦点保持公式t' = t·r + (f−c)(1−r)配合) - 拖动边界按
(scale−1)×容器宽高/2动态计算 - 缩放中心跟随两指中点 / 双击点击点
- swiper 兼容模式通过
stopPropagation()按需拦截冒泡实现

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 112
赞赏 1
下载 12710922
赞赏 1957
赞赏
京公网安备:11010802035340号