Skip to content

panZoom 拖拽缩放指令

让任意 DOM 元素具备类似图片查看器的拖拽平移 + 缩放交互,支持鼠标拖拽、滚轮缩放、双指缩放与双击放大等手势。

安装与引入

按需导入(推荐)

ts
import { VPanZoom } from '@cuixingjian/cui-utils'

全局注册

ts
import { createApp } from 'vue'
import { VPanZoom } from '@cuixingjian/cui-utils'

const app = createApp(App)
app.directive('pan-zoom', VPanZoom)
app.mount('#app')

局部注册

vue
<script setup lang="ts">
import { VPanZoom as vPanZoom } from '@cuixingjian/cui-utils'
</script>

<template>
  <div v-pan-zoom>
    <img src="image.jpg" />
  </div>
</template>

效果演示

交互式演示

拖拽平移图片,滚轮缩放,双击放大。

使用代码

基本用法:

vue
<template>
  <div v-pan-zoom>
    <img src="image.jpg" />
  </div>
</template>

自定义缩放范围:

vue
<template>
  <div v-pan-zoom="{ minScale: 0.5, maxScale: 5 }">
    <img src="image.jpg" />
  </div>
</template>

禁用拖拽:

vue
<template>
  <div v-pan-zoom="{ drag: false }">
    <img src="image.jpg" />
  </div>
</template>

API 说明

指令值类型

类型说明示例
boolean启用/禁用指令v-pan-zoom="true"
Object传入配置对象v-pan-zoom="{ minScale: 0.5 }"

配置选项 (PanZoomOptions)

参数类型默认值说明
disabledbooleanfalse是否禁用指令
dragbooleantrue是否允许拖拽平移
zoomOnWheelbooleantrue是否允许滚轮缩放
zoomOnPinchbooleantrue是否允许双指缩放
doubleClickZoombooleantrue是否允许双击缩放
minScalenumber0.5最小缩放倍率
maxScalenumber4最大缩放倍率
initialScalenumber1初始缩放倍率
initialXnumber0初始 X 位移(px)
initialYnumber0初始 Y 位移(px)
wheelZoomSpeednumber0.0025滚轮缩放灵敏度
doubleClickStepnumber1.35双击时的放大倍率
onTransform(state: { scale, x, y }) => void变换回调

注意事项

缩放中心

所有缩放操作都以图片当前显示位置的中心点为基准:

  • 滚轮缩放:以图片中心点缩放
  • 双击缩放:以图片中心点放大
  • 双指缩放:以图片中心点缩放

交互方式

  • 鼠标拖拽:平移内容
  • 滚轮:缩放内容
  • 双击:放大内容
  • 双指捏合:缩放内容(移动端)

容器要求

  • 建议设置固定宽高
  • 使用 overflow: hidden 隐藏超出部分
  • 图片建议设置 pointer-events: none

最佳实践

  • 自动设置 touch-action: none 防止滚动冲突
  • 不会覆盖已有的 transform 变换
  • 支持实时状态回调

源码展示

展开查看完整源码
ts
import type { Directive } from 'vue'
import { withInstallDirective } from '../install'

export interface PanZoomOptions {
  disabled?: boolean
  drag?: boolean
  zoomOnWheel?: boolean
  zoomOnPinch?: boolean
  doubleClickZoom?: boolean
  minScale?: number
  maxScale?: number
  initialScale?: number
  initialX?: number
  initialY?: number
  wheelZoomSpeed?: number
  doubleClickStep?: number
  onTransform?: (state: { scale: number; x: number; y: number }) => void
}

// 详见 packages/utils/directives/panZoom.ts
export const VPanZoom = withInstallDirective(panZoom, 'pan-zoom')