Skip to content

缩放拖拽组件使用手册(v3-drag-zoom)

v3-drag-zoom 是基于 vue3 开发的一个缩放拖拽组件,方便开发者快速实现缩放拖拽功能。

效果类似地图的缩放与拖拽,但是不同的是,v3-drag-zoom 可以缩放任意元素,而不仅仅是地图。

使用场景:

  • 地图缩放与拖拽
  • 图片缩放与拖拽
  • 任意元素缩放与拖拽
  • 其他任意需要缩放与拖拽的场景

安装

使用以下命令安装 v3-drag-zoom

bash
npm install v3-drag-zoom
# 或
yarn add v3-drag-zoom

导入组件

全局导入

main.js 中全局引入 v3-drag-zoom

ts
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

vue

<script setup lang="ts">
  import {V3DragZoomContainer} from "v3-drag-zoom";
</script>

<template>
  <v3-drag-zoom-container>
    <div>需要缩放与拖拽的元素</div>
  </v3-drag-zoom-container>
</template>

TIP

由于v3-drag-zoom 全局导入也就只有 2 个组件,因此建议全局导入。

基本使用

使用 v3-drag-zoom 组件包裹需要缩放与拖拽的元素即可。

TIP

如果 v3-drag-zoom 内部存在 img 元素,则会自动等待所有元素加载完毕后初始化,因此不需要手动等待图片加载完毕后再初始化。

vue
<script setup lang="ts"></script>

<template>
  <v3-drag-zoom-container style="width: 600px; height: 400px; background-color: #ccc">
    <div
      class="flex-column flex-same"
      style="background-color: darkred; height: 500px; width: 900px"
    >
      <div class="flex-grow flex-horiz flex-same" v-for="i in 10">
        <div class="border-box bca-border" v-for="i in 10"></div>
      </div>
    </div>
  </v3-drag-zoom-container>
</template>

容器中内容对齐方式

对齐方式可以通过 align 属性设置,可选值有 autocontaincover

  • auto:不做任何处理,实际多大就显示多大
  • contain:默认值,内容居中,且不超出容器
  • cover:内容居中,且对齐短边撑满容器

可以通过下方 demo 查看实际效果;

点击展开源码
vue
<script setup lang="ts">
import { ref } from "vue";

const dragRef = ref();
const alignMode = ref("contain");

const sizeOptions = [
  { label: "400x200", value: 0, size: { width: "400px", height: "200px" } },
  { label: "200x400", value: 1, size: { width: "200px", height: "400px" } },
  { label: "100x100", value: 2, size: { width: "100px", height: "100px" } },
  { label: "10000x10000", value: 3, size: { width: "10000px", height: "10000px" } },
];
const size = ref(0);

const onChange = () => {
  setTimeout(() => {
    dragRef.value.reset();
  });
};
</script>
<template>
  <a-space class="">
    <a-space direction="vertical">
      <a-space class="flex-horiz flex-center">
        <div class="no">对齐方式:</div>
        <a-select
          style="width: 120px"
          v-model="alignMode"
          @change="onChange"
          :options="[
            { label: 'cover', value: 'cover' },
            { label: 'contain', value: 'contain' },
            { label: 'auto', value: 'auto' },
          ]"
        />
        <div class="ml-md">内容尺寸</div>
        <a-select :options="sizeOptions" v-model="size" @change="onChange" style="width: 200px" />
      </a-space>
      <v3-drag-zoom-container
        ref="dragRef"
        :align="alignMode"
        style="width: 600px; height: 400px; background-color: #ccc"
      >
        <div
          class="flex-column flex-same"
          style="background-color: darkred"
          :style="sizeOptions[size].size"
        >
          <div class="flex-grow flex-horiz flex-same" v-for="i in 10">
            <div class="border-box bca-border" v-for="i in 10"></div>
          </div>
        </div>
      </v3-drag-zoom-container>
    </a-space>
  </a-space>
</template>

地图标点

v3-drag-zoom 也可以用于地图标点,只需要将 v3-drag-zoom-item 组件放置在 v3-drag-zoom-container 组件中即可。

任意截图一张地图图片作为容器内容,添加若干点标记(v3-drag-zoom-item);

在下面demo中尝试拖拽标记点,以及缩放地图;

TIP

v3-drag-zoom-item 中,也可以添加其他内容,比如文字、图片等。

点击展开源码
vue
<script setup lang="ts">
import { ref } from "vue";

const dragRef = ref();

const alignMode = ref("contain");

const size = ref(0);

const onChange = () => {
  setTimeout(() => {
    dragRef.value.reset();
  });
};

const points = ref([
  { label: 1, position: { x: 20, y: 20 }, color: "darkred" },
  { label: 1, position: { x: 50, y: 20 }, color: "darkblue" },
  { label: 1, position: { x: 80, y: 20 }, color: "darkgreen" },
]);

const textPoints = ref([
  { label: 1, position: { x: 20, y: 50 }, text: "哈哈" },
  { label: 1, position: { x: 50, y: 50 }, text: "吼吼" },
  { label: 1, position: { x: 80, y: 50 }, text: "嘿嘿" },
]);

const draggable = ref(true);

const fixedSize = ref(true);
</script>

<template>
  <a-space class="">
    <a-space direction="vertical">
      <a-space class="flex-horiz flex-center">
        <div class="no">对齐方式:</div>
        <a-select
          style="width: 120px"
          v-model="alignMode"
          @change="onChange"
          :options="[
            { label: 'cover', value: 'cover' },
            { label: 'contain', value: 'contain' },
            { label: 'auto', value: 'auto' },
          ]"
        />
        <div class="ml-md">是否允许拖拽:</div>
        <a-switch v-model="draggable"></a-switch>
        <div class="ml-md">是否固定大小:</div>
        <a-switch v-model="fixedSize"></a-switch>
      </a-space>
      <v3-drag-zoom-container
        ref="dragRef"
        :align="alignMode"
        style="width: 600px; height: 400px; background-color: #ccc"
      >
        <img src="/v3-drag-zoom/map.png" alt="" />
        <v3-drag-zoom-item
          v-for="point in points"
          :position="point.position"
          style="width: 40px; height: 40px"
          :style="{ 'background-color': point.color }"
          :draggable="draggable"
          :fixed-size="fixedSize"
        />

        <v3-drag-zoom-item
          v-for="point in textPoints"
          :position="point.position"
          :draggable="draggable"
          :fixed-size="fixedSize"
        >
          <span style="font-size: 20px; color: black">{{ point.text }} </span>
        </v3-drag-zoom-item>
      </v3-drag-zoom-container>
    </a-space>
  </a-space>
</template>

API参数

v3-drag-zoom-container

Props

参数名类型默认值说明
alignStringcontain内容对齐方式,可选值有 autocontaincover
autoResizeBooleantrue是否自动重置尺寸,当容器尺寸为百分比的时候,会根据父容器变化而自动变化
followPointerBooleantrue缩放时是否跟随鼠标
maxZoomFloat100最大缩放倍数
minZoomFloat0.01最小缩放倍数
zoomFactorFloat0.1鼠标滚轮一次的缩放比例
loadingBooleanfalse是否加载中
animateDurationNumber200缩放时候的过度动画时长,单位 ms

Slots

Slot说明
default直接填写需要放置的内容

Exposed

参数名类型说明
zoom(zoom:Float) => void手动缩放 zoom: 为缩放倍数
reset() => void重置缩放

v3-drag-zoom-item

Props

参数名类型默认值是否必须说明
offsetArray<Integer>[-50,-50]偏移量,默认值代表横向和纵向均偏移 -50%,也就是对齐中心点位置,偏移量单位为 %, 不支持 px
fixedSizeBooleanfalse是否固定大小, true代表在缩放过程中该item内容尺寸不变
rotateFloat0旋转角度单位 deg (360度)
draggableBooleanfalse是否可以拖拽移动
position(v-model)CurPosition该 item 在内容中的位置(百分比位置)

Slots

Slot说明
default直接填写需要放置的内容

Events

事件名参数说明
onMove( pos :Position)=> void每移动一点距离触发,返回当前位置
onMoveFinished( pos :Position)=> void移动结束(鼠标抬起或超出范围)触发, 返回当前位置

CurPosition

参数名类型默认值是否必须说明
xFloat横向位置 %
yFloat纵向位置 %

Position extend CurPosition

参数名类型默认值是否必须说明
xFloat横向位置 %
yFloat纵向位置 %
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);

MIT Licensed | fangjc1986@qq.com