更新记录

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() 按需拦截冒泡实现

更新日志

见 changelog.md

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。