v3-drag-zoom
一个轻量、高效的缩放拖拽逐渐,帮助开发人员快速实现类似地图缩放拖拽等功能
4,424
| Install | |
|---|---|
npm install v3-drag-zoom |
|
| Latest Version: | 1.3.1 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | May 20, 2026 |
| Links: | Gitee · npm |
Maintainer: fangjc1986
V3DragZoom
一个基于 vue3 开发的轻量、高效缩放拖拽组件,方便开发者快速实现缩放拖拽功能。
📖 中文文档 | 📖 English Documentation
需要 Vue 2 版本?查看 v2-drag-zoom
在线演示和使用手册(DEMO)
GIT地址
https://gitee.com/ericfang/v3-drag-zoom
🚀 特性
- ✅ 支持拖拽和缩放功能
- ✅ 支持多种对齐模式(cover、contain、auto)
- ✅ 支持跟随鼠标缩放
- ✅ 支持固定大小的子元素
- ✅ 支持自定义标记点
- ✅ TypeScript 原生支持
- ✅ 响应式设计,自动适应容器大小变化
- ✅ 平滑动画过渡效果
- ✅ 支持加载状态显示
- ✅ Composition API 设计
📦 安装
使用以下命令安装 v3-drag-zoom:
npm install v3-drag-zoom
# 或
yarn add v3-drag-zoom
🎯 用途介绍
V3 Drag Zoom 是一个专为 Vue 3 设计的交互式缩放拖拽组件,适用于需要实现以下功能的场景:
- 地图应用:实现地图的缩放和平移功能
- 图片查看器:支持图片的放大缩小和拖拽浏览
- 图表交互:允许用户缩放和移动复杂的数据可视化图表
- 设计工具:提供画布的缩放和拖拽能力
- 文档预览:支持大型文档或图纸的局部查看
- 虚拟现实界面:创建可交互的 3D 或 2.5D 界面元素
🏗️ 架构介绍
该组件采用模块化设计,主要包含两个核心组件:
V3DragZoomContainer
主容器组件,负责管理整体的缩放和拖拽逻辑,包括:
- 容器尺寸检测和自适应
- 缩放计算和动画控制
- 鼠标事件处理
- 子组件协调
- 使用 Composition API 实现
V3DragZoomItem
子项组件,用于在可缩放容器内放置可交互的元素,如:
- 标记点
- 注释
- 图标
- 其他自定义内容
组件间通过 Vue 的 provide/inject 机制进行通信,确保良好的解耦和可扩展性。
💻 导入组件
全局导入
在 main.js 中全局引入 v3-drag-zoom:
import {createApp} from "vue";
import App from "./App.vue";
// v3-drag-zoom 组件
import V3DragZoom from "v3-drag-zoom";
// v3-drag-zoom 全局样式(必须导入,否则无法正常使用)
import "v3-drag-zoom/dist/style.css";
createApp(App).use(V3DragZoom).mount("#app");
按需导入
在需要的组件中导入 v3-drag-zoom:
<script setup lang="ts">
import {V3DragZoomContainer, V3DragZoomItem} from "v3-drag-zoom";
</script>
<template>
<v3-drag-zoom-container>
<div>需要缩放与拖拽的元素</div>
<v3-drag-zoom-item :position="{ x: 50, y: 50 }" :draggable="true">
<span>标记点</span>
</v3-drag-zoom-item>
</v3-drag-zoom-container>
</template>
📖 使用示例
基础用法
<template>
<div style="width: 800px; height: 600px;">
<v3-drag-zoom-container
ref="containerRef"
align="contain"
:follow-pointer="true"
@onMove="handleMove"
@onZoom="handleZoom"
>
<!-- 主要内容 -->
<!-- 标记点 -->
<v3-drag-zoom-item
:position="{ x: 50, y: 50 }"
:draggable="true"
:fixed-size="false"
@onMove="handleItemMove"
>
<span>标记点</span>
</v3-drag-zoom-item>
</v3-drag-zoom-container>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { V3DragZoomContainer, V3DragZoomItem } from 'v3-drag-zoom';
const containerRef = ref();
const handleMove = (event) => {
console.log('容器移动:', event);
};
const handleZoom = (event) => {
console.log('容器缩放:', event);
};
const handleItemMove = (position) => {
console.log('项目移动:', position);
};
</script>
完整示例
<template>
<div class="app">
<h1>V3 Drag Zoom 演示</h1>
<div class="controls">
<button @click="resetView">重置视图</button>
<button @click="zoomIn">放大</button>
<button @click="zoomOut">缩小</button>
</div>
<v3-drag-zoom-container
ref="container"
align="contain"
:max-zoom="5"
:min-zoom="0.1"
:follow-pointer="true"
:animate-duration="300"
style="width: 100%; height: 600px; border: 1px solid #ccc;"
>
<!-- 多个标记点 -->
<v3-drag-zoom-item
v-for="(marker, index) in markers"
:key="index"
:position="marker.position"
:draggable="true"
:fixed-size="false"
@onMove="updateMarkerPosition(index, $event)"
>
<div class="marker">
{{ marker.label }}
</div>
</v3-drag-zoom-item>
</v3-drag-zoom-container>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { V3DragZoomContainer, V3DragZoomItem } from 'v3-drag-zoom';
interface Marker {
position: { x: number; y: number };
label: string;
}
const container = ref();
const markers = ref<Marker[]>([
{ position: { x: 20, y: 30 }, label: '地点A' },
{ position: { x: 60, y: 40 }, label: '地点B' },
{ position: { x: 40, y: 70 }, label: '地点C' }
]);
const resetView = () => {
container.value?.reset();
};
const zoomIn = () => {
container.value?.zoom(0.2); // 放大20%
};
const zoomOut = () => {
container.value?.zoom(-0.2); // 缩小20%
};
const updateMarkerPosition = (index: number, newPosition: any) => {
markers.value[index].position = newPosition;
};
</script>
<style scoped>
.marker {
background: red;
color: white;
padding: 5px 10px;
border-radius: 15px;
font-size: 12px;
cursor: pointer;
}
.controls {
margin-bottom: 10px;
}
.controls button {
margin-right: 10px;
padding: 5px 15px;
}
</style>
📚 API参数
v3-drag-zoom-container
Props
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| align | String | contain | 内容对齐方式,可选值有 auto、 contain、cover |
| autoResize | Boolean | true | 是否自动重置尺寸,当容器尺寸为百分比的时候,会根据父容器变化而自动变化 |
| followPointer | Boolean | true | 缩放时是否跟随鼠标 |
| maxZoom | Float | 100 | 最大缩放倍数 |
| minZoom | Float | 0.01 | 最小缩放倍数 |
| zoomFactor | Float | 0.1 | 鼠标滚轮一次的缩放比例 |
| loading | Boolean | false | 是否加载中 |
| animateDuration | Number | 200 | 缩放时候的过度动画时长,单位 ms |
| draggable | Boolean | true | 是否可拖拽 |
| zoomable | Boolean | true | 是否可缩放 |
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| onMove | ( event :ContainerEvent)=> void | 每移动一点距离触发,返回当前位置 |
| onMoveFinished | ( event :ContainerEvent)=> void | 移动结束(鼠标抬起或超出范围)触发, 返回当前位置 |
| onZoom | ( event :ContainerEvent)=> void | 缩放触发,返回当前缩放倍数 |
Slots
| Slot | 说明 |
|---|---|
| default | 直接填写需要放置的内容 |
| loading | 自定义加载状态显示内容 |
Exposed
| 参数名 | 类型 | 说明 |
|---|---|---|
| zoom | (zoom:Float) => void | 手动缩放 zoom: 为缩放因子 |
| reset | () => void | 重置缩放 |
v3-drag-zoom-item
Props
| 参数名 | 类型 | 默认值 | 是否必须 | 说明 |
|---|---|---|---|---|
| offset | Array<Integer> | [-50,-50] | 否 | 偏移量,默认值代表横向和纵向均偏移 -50%,也就是对齐中心点位置,偏移量单位为 %, 不支持 px |
| fixedSize | Boolean | false | 否 | 是否固定大小, true代表在缩放过程中该item内容尺寸不变 |
| rotate | Float | 0 | 否 | 旋转角度单位 deg (360度) |
| draggable | Boolean | false | 否 | 是否可以拖拽移动 |
| position(v-model) | CurPosition | 无 | 是 | 该 item 在内容中的位置(百分比位置) |
Slots
| Slot | 说明 |
|---|---|
| default | 直接填写需要放置的内容 |
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| onMove | ( pos :Position)=> void | 每移动一点距离触发,返回当前位置 |
| onMoveFinished | ( pos :Position)=> void | 移动结束(鼠标抬起或超出范围)触发, 返回当前位置 |
| update:position | ( pos :Position)=> void | 位置更新时触发(支持 v-model) |
类型定义
CurPosition
| 参数名 | 类型 | 默认值 | 是否必须 | 说明 |
|---|---|---|---|---|
| x | Float | 无 | 是 | 横向位置 % |
| y | Float | 无 | 是 | 纵向位置 % |
Position extend CurPosition
| 参数名 | 类型 | 默认值 | 是否必须 | 说明 |
|---|---|---|---|---|
| x | Float | 无 | 是 | 横向位置 % |
| y | Float | 无 | 是 | 纵向位置 % |
| sub | (pos:Position)=>Position | 无 | 否 | 计算当前 Position 与 pos 之间的差值 new Position(this.x - pos.x, this.y - pos.y); |
| add | (pos:Position)=>Position | 无 | 否 | 计算当前 Position 与 pos 之间的和值 new Position(this.x + pos.x, this.y + pos.y); |
Size
| 参数名 | 类型 | 默认值 | 是否必须 | 说明 |
|---|---|---|---|---|
| width | Integer | 无 | 是 | 宽度 像素 |
| height | Integer | 无 | 是 | 高度 像素 |
ContainerEvent
| 参数名 | 类型 | 默认值 | 是否必须 | 说明 |
|---|---|---|---|---|
| center | CurPosition | 无 | 是 | 容器中心位置(相对于容器左上角的绝对像素坐标) |
| containerSize | Size | 无 | 是 | 容器大小(像素) |
| contentSize | Size | 无 | 是 | 内容大小(像素) |
| zoom | Float | 无 | 是 | 缩放倍数 |
🔧 开发
# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 构建
npm run build
🤝 贡献指南
欢迎提交 Issue 和 Pull Request 来改进这个项目。
📄 License
MIT
Related Packages
@minogin/vue-drag-resize-rotate
Vue component which acts as a draggable, resizable and rotateable container for...
7,341
78
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.3.1 | ^3.3.4 | MIT | |
| 1.3.0 | ^3.3.4 | MIT | |
| 1.2.1 | ^3.3.4 | MIT | |
| 1.2.0 | ^3.3.4 | MIT | |
| 1.1.20 | ^3.3.4 | MIT | |
| 1.1.19 | ^3.3.4 | MIT | |
| 1.1.18 | ^3.3.4 | MIT | |
| 1.1.17 | ^3.3.4 | MIT | |
| 1.1.16 | ^3.3.4 | MIT | |
| 1.1.15 | ^3.3.4 | MIT | |
| 1.1.14 | ^3.3.4 | MIT | |
| 1.1.13 | ^3.3.4 | MIT | |
| 1.1.12 | ^3.3.4 | MIT | |
| 1.1.11 | ^3.3.4 | MIT | |
| 1.1.10 | ^3.3.4 | MIT | |
| 1.1.9 | ^3.3.4 | MIT | |
| 1.1.8 | ^3.3.4 | MIT | |
| 1.1.7 | ^3.3.4 | MIT | |
| 1.1.6 | ^3.3.4 | MIT | |
| 1.1.5 | ^3.3.4 | MIT | |
| 1.1.4 | ^3.3.4 | MIT | |
| 1.1.3 | ^3.3.4 | MIT | |
| 1.1.2 | ^3.3.4 | MIT | |
| 1.1.1 | ^3.3.4 | MIT | |
| 1.1.0 | ^3.3.4 | MIT | |
| 1.0.2 | ^3 | MIT | |
| 1.0.1 | ^3 | MIT | |
| 1.0.0 | ^3 | MIT |