Appearance
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)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| disabled | boolean | false | 是否禁用指令 |
| drag | boolean | true | 是否允许拖拽平移 |
| zoomOnWheel | boolean | true | 是否允许滚轮缩放 |
| zoomOnPinch | boolean | true | 是否允许双指缩放 |
| doubleClickZoom | boolean | true | 是否允许双击缩放 |
| minScale | number | 0.5 | 最小缩放倍率 |
| maxScale | number | 4 | 最大缩放倍率 |
| initialScale | number | 1 | 初始缩放倍率 |
| initialX | number | 0 | 初始 X 位移(px) |
| initialY | number | 0 | 初始 Y 位移(px) |
| wheelZoomSpeed | number | 0.0025 | 滚轮缩放灵敏度 |
| doubleClickStep | number | 1.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')