一、npm上介绍 

网址:vue3-draggable-resizable - npm

 1、安装、下载

npm下载插件

$ npm install vue3-draggable-resizable

文件中引入:全局注册

// >main.js
import { createApp } from 'vue'
import App from './App.vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
//default styles
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
 
// You will have a global component named "Vue3DraggableResizable"
createApp(App)
  .use(Vue3DraggableResizable)
  .mount('#app')

 在组件中使用

// >component.js
import { defineComponent } from 'vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
//default styles
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
 
export default defineComponent({
  components: { Vue3DraggableResizable }
  // ...other
})

 示范案例:

<template>
  <div id="app">
    <div class="parent">
      <Vue3DraggableResizable
        :initW="110"
        :initH="120"
        v-model:x="x"
        v-model:y="y"
        v-model:w="w"
        v-model:h="h"
        v-model:active="active"
        :draggable="true"
        :resizable="true"
        @activated="print('activated')"
        @deactivated="print('deactivated')"
        @drag-start="print('drag-start')"
        @resize-start="print('resize-start')"
        @dragging="print('dragging')"
        @resizing="print('resizing')"
        @drag-end="print('drag-end')"
        @resize-end="print('resize-end')"
      >
        This is a test example
      </Vue3DraggableResizable>
    </div>
  </div>
</template>
 
<script>
import { defineComponent } from 'vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
//default styles
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
export default defineComponent({
  components: { Vue3DraggableResizable },
  data() {
    return {
      x: 100,
      y: 100,
      h: 100,
      w: 100,
      active: false
    }
  },
  methods: {
    print(val) {
      console.log(val)
    }
  }
})
</script>
<style>
.parent {
  width: 200px;
  height: 200px;
  position: absolute;
  top: 100px;
  left: 100px;
  border: 1px solid #000;
  user-select: none;
}
</style>

2、参数Props

1.设置长宽高等

initW:设置宽度;

<Vue3DraggableResizable :initW="100" />

initH:设置高度;

<Vue3DraggableResizable :initH="100" />

w:容器的当前宽度(px),您可以使用“v-model:w”使其保持最新状态;

<Vue3DraggableResizable v-model:w="100" />

h:容器的当前高度(px),您可以使用“v-model:h”使其保持最新状态;

x:容器的当前距离左边的距离(px),您可以使用“v-model:x”使其保持最新状态;

y:容器的当前距离顶部的距离(px),您可以使用“v-model:y”使其保持最新状态;

minW:设置最小宽度;

<Vue3DraggableResizable :minW="100" />

minH:设置最小高度;

2.设置状态

active:显示该组件是否被选中,您可以使用“v-model:active”使其保持最新状态;

<Vue3DraggableResizable v-model:active="100" />

draggable:定义组件是否可拖动;

<Vue3DraggableResizable :draggable="true" />

resizable:定义组件是否可调整大小;

lockAspectRatio:lockAspectRatio属性用于锁定长宽比;

disabledX:定义组件是否可以在x轴上移动;

disabledY:定义组件是否可以在y轴上移动;

disabledW:定义组件的宽度是否可以修改;

disabledH:定义组件的高度是否可以修改;

parent:限制父节点内的移动和大小;

<Vue3DraggableResizable :parent="true" />

handles:定义枚举的大小数组来限制元素的大小调整

default: ['tl', 'tm', 'tr', 'ml', 'mr', 'bl', 'bm', 'br']

  • tl : Top left
  • tm : Top middle
  • tr : Top right
  • mr : Middle right
  • ml : Middle left
  • bl : Bottom left
  • bm : Bottom middle
  • br : Bottom right
<Vue3DraggableResizable :handles="['tl','tr','bl','br']" />

3.是否开启某设置

classNameDraggable:用于在启用可拖动组件时设置可拖动可调整大小的组件的自定义类;

<Vue3DraggableResizable classNameResizable="resizable" />

classNameResizable:用于在拖动时设置可拖动可调整大小的组件的自定义类;

classNameDragging:用于在拖动时设置可拖动可调整大小的组件的自定义类;

classNameResizing:用于在调整大小时设置可拖动可调整大小的组件的自定义类;

classNameActive:用于在活动时设置可拖动可调整大小的组件的自定义类;

classNameHandle:用于设置每个句柄元素的自定义公共类。

二、Vue3DraggableResizable

[Vue3 组件] 用于拖拽调整位置和大小的的组件,同时支持冲突检测,元素吸附对齐,实时参考线。

文档目录

特性

  • 支持拖拽和缩放,可分别定义开启或关闭
  • 自定义缩放句柄(缩放时共有八个方位可操作,可分别定义开启或关闭)
  • 限制组件的拖动和缩放在其父节点内
  • 自定义组件内各种类名
  • 缩放句柄的类名也可自定义
  • 元素吸附对齐
  • 实时参考线
  • 自定义参考线
  • 使用 Vue3 和 ts

1、使用

$ npm install vue3-draggable-resizable

使用 use 方法注册组件

// >main.js
import { createApp } from 'vue'
import App from './App.vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
//需引入默认样式
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'

// 你将会获得一个名为Vue3DraggableResizable的全局组件
createApp(App)
  .use(Vue3DraggableResizable)
  .mount('#app')

也可以单独在你的组件内部使用

// >component.js
import { defineComponent } from 'vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
//需引入默认样式
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'

export default defineComponent({
  components: { Vue3DraggableResizable }
  // ...other
})

下面是一个使用 vue-template 语法写的例子

<template>
  <div id="app">
    <div class="parent">
      <Vue3DraggableResizable
        :initW="110"
        :initH="120"
        v-model:x="x"
        v-model:y="y"
        v-model:w="w"
        v-model:h="h"
        v-model:active="active"
        :draggable="true"
        :resizable="true"
        @activated="print('activated')"
        @deactivated="print('deactivated')"
        @drag-start="print('drag-start')"
        @resize-start="print('resize-start')"
        @dragging="print('dragging')"
        @resizing="print('resizing')"
        @drag-end="print('drag-end')"
        @resize-end="print('resize-end')"
      >
        This is a test example
      </Vue3DraggableResizable>
    </div>
  </div>
</template>

<script>
import { defineComponent } from 'vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
//default styles
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
export default defineComponent({
  components: { Vue3DraggableResizable },
  data() {
    return {
      x: 100,
      y: 100,
      h: 100,
      w: 100,
      active: false
    }
  },
  methods: {
    print(val) {
      console.log(val)
    }
  }
})
</script>
<style>
.parent {
  width: 200px;
  height: 200px;
  position: absolute;
  top: 100px;
  left: 100px;
  border: 1px solid #000;
  user-select: none;
}
</style>

2、Props

initW

type: Number
default: null

设置初始宽度(px)

<Vue3DraggableResizable :initW="100" />
initH

type: Number
default: null

设置初始高度(px)

<Vue3DraggableResizable :initH="100" />
w

type: Number
default: 0

组件的当前宽度(px)
你可以使用“v-model:w”语法使它和父组件保持一致

<Vue3DraggableResizable v-model:w="100" />
h

type: Number
default: 0

组件的当前高度(px)
你可以使用“v-model:h”语法使它和父组件保持一致

<Vue3DraggableResizable v-model:h="100" />
x

type: Number
default: 0

组件距离父容器的左侧的距离(px)
你可以使用“v-model:x”语法使它和父组件保持一致

<Vue3DraggableResizable v-model:x="100" />
y

type: Number
default: 0

组件距离父容器顶部的距离(px)
你可以使用“v-model:y”语法使它和父组件保持一致

<Vue3DraggableResizable v-model:y="100" />
minW

type: Number
default: 20

组件的最小宽度(px)

<Vue3DraggableResizable :minW="100" />
minH

type: Number
default: 20

组件的最小高度(px)

<Vue3DraggableResizable :minH="100" />
active

type: Boolean
default: false

组件当前是否处于活跃状态
你可以使用“v-model:active”语法使它和父组件保持一致

<Vue3DraggableResizable v-model:active="100" />
draggable

type: Boolean
default: true

组件是否可拖动

<Vue3DraggableResizable :draggable="true" />
resizable

type: Boolean
default: true

组件是否可调整大小

<Vue3DraggableResizable :draggable="true" />
lockAspectRatio

type: Boolean
default: false

该属性用来设置是否锁定比例

<Vue3DraggableResizable :lockAspectRatio="true" />
disabledX

type: Boolean
default: false

是否禁止组件在 X 轴上移动

<Vue3DraggableResizable :disabledX="true" />
disabledY

type: Boolean
default: false

是否禁止组件在 Y 轴上移动

<Vue3DraggableResizable :disabledY="true" />
disabledW

type: Boolean
default: false

是否禁止组件修改宽度

<Vue3DraggableResizable :disabledW="true" />
disabledH

type: Boolean
default: false

是否禁止组件修改高度

<Vue3DraggableResizable :disabledH="true" />
parent

type: Boolean
default: false

是否将组件的拖动和缩放限制在其父节点内,即组件不会超出父节点,默认关闭

<Vue3DraggableResizable :parent="true" />
handles

type: Array
default: ['tl', 'tm', 'tr', 'ml', 'mr', 'bl', 'bm', 'br']

定义缩放的句柄(共八个方向)

  • tl : 上左
  • tm : 上中
  • tr : 上右
  • mr : 中左
  • ml : 中右
  • bl : 下左
  • bm : 下中
  • br : 下右
<Vue3DraggableResizable :handles="['tl','tr','bl','br']" />
classNameDraggable

type: String
default: draggable

自定义组件的类名,该类名在组件是“可拖动”时显示

<Vue3DraggableResizable classNameDraggable="draggable" />
classNameResizable

type: String
default: resizable

自定义组件类名,该类名在组件是“可缩放”时显示

<Vue3DraggableResizable classNameResizable="resizable" />
classNameDragging

type: String
default: dragging

定义组件在拖动时显示的类名

<Vue3DraggableResizable classNameDragging="dragging" />
classNameResizing

type: String
default: resizing

定义组件在缩放时显示的类名

<Vue3DraggableResizable classNameResizing="resizing" />
classNameActive

type: String
default: active

定义组件在活跃状态下的类名

<Vue3DraggableResizable classNameActive="active"></Vue3DraggableResizable>
classNameHandle

type: String
default: handle

定义缩放句柄的类名

<Vue3DraggableResizable classNameHandle="my-handle" />

以上设置将会渲染出下面的缩放句柄节点(my-handle-*)

...
<div class="vdr-handle vdr-handle-tl my-handle my-handle-tl"></div>
<div class="vdr-handle vdr-handle-tm my-handle my-handle-tm"></div>
<div class="vdr-handle vdr-handle-tr my-handle my-handle-tr"></div>
<div class="vdr-handle vdr-handle-ml my-handle my-handle-mr"></div>
...

3、Events

activated

payload: -

组件从非活跃状态到活跃状态时触发

<Vue3DraggableResizable @activated="activatedHandle" />
deactivated

payload: -

组件从活跃状态到非活跃状态时触发

<Vue3DraggableResizable @deactivated="deactivatedHandle" />
drag-start

payload: { x: number, y: number }

组件开始拖动时触发

<Vue3DraggableResizable @drag-start="dragStartHandle" />
dragging

payload: { x: number, y: number }v

组件在拖动过程中持续触发

<Vue3DraggableResizable @dragging="dragStartHandle" />
drag-end

payload: { x: number, y: number }

组件拖动结束时触发

<Vue3DraggableResizable @drag-end="dragEndHandle" />
resize-start

payload: { x: number, y: number, w: number, h: number }

组件开始缩放时触发

<Vue3DraggableResizable @resize-start="resizeStartHandle" />
resizing

payload: { x: number, y: number, w: number, h: number }

组件在缩放过程中持续触发

<Vue3DraggableResizable @resizing="resizingHandle" />
resize-end

payload: { x: number, y: number, w: number, h: number }

组件缩放结束时触发

<Vue3DraggableResizable @resize-end="resizeEndHandle" />

使用吸附对齐功能

吸附对齐功能可以在拖动过程中和其他元素自动吸附,你也可以自定义吸附对齐的校准线

你需要引入另外一个组件来使用该特性

像下面这样,将 Vue3DraggableResizable 放在 DraggableContainer 内:

<template>
  <div id="app">
    <div class="parent">
      <DraggableContainer>
        <Vue3DraggableResizable>
          Test
        </Vue3DraggableResizable>
        <Vue3DraggableResizable>
          Another test
        </Vue3DraggableResizable>
      </DraggableContainer>
    </div>
  </div>
</template>

<script>
import { defineComponent } from 'vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
// 这个组件不是默认导出的,
// 如果你之前是通过“app.use(Vue3DraggableResizable)”注册的,
// 那么你这里就不需要再引入了,因为DraggableContainer这个已经被全局注册了,你可以直接使用
import { DraggableContainer } from 'vue3-draggable-resizable'
//default styles
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
export default defineComponent({
  components: { Vue3DraggableResizable, DraggableContainer }
})
</script>
<style>
.parent {
  width: 200px;
  height: 200px;
  position: absolute;
  top: 100px;
  left: 100px;
  border: 1px solid #000;
  user-select: none;
}
</style>

4、DraggableContainer Props

这些 props 适用于 DraggableContainer 组件

disabled

type: Boolean
default: false

关闭吸附对齐功能

<DraggableContainer :disabled="true">
  <Vue3DraggableResizable>
    Test
  </Vue3DraggableResizable>
  <Vue3DraggableResizable>
    Another test
  </Vue3DraggableResizable>
</DraggableContainer>
adsorbParent

type: Boolean
default: true

是否和父组件对齐,如果开启,则元素拖拽到父容器边缘(父容器的上中下左中右边)时会发生吸附,否则不会

<DraggableContainer :adsorbParent="false">
  <Vue3DraggableResizable>
    Test
  </Vue3DraggableResizable>
  <Vue3DraggableResizable>
    Another test
  </Vue3DraggableResizable>
</DraggableContainer>
adsorbCols

type: Array<Number>
default: null

自定义列的校准线,元素在x轴上拖动到这些线附近时,会产生吸附

<DraggableContainer :adsorbCols="[10,20,30]">
  <Vue3DraggableResizable>
    Test
  </Vue3DraggableResizable>
  <Vue3DraggableResizable>
    Another test
  </Vue3DraggableResizable>
</DraggableContainer>
adsorbRows

type: Array<Number>
default: null

自定义行的校准线,元素在y轴上拖动到这些线附近时,会产生吸附

<DraggableContainer :adsorbRows="[10,20,30]">
  <Vue3DraggableResizable>
    Test
  </Vue3DraggableResizable>
  <Vue3DraggableResizable>
    Another test
  </Vue3DraggableResizable>
</DraggableContainer>
referenceLineVisible

type: Boolean
default: true

是否显示实时参考线,元素在产生自动吸附后,会有一条参考线线出现,如果不需要,可通过该选项关闭。

<DraggableContainer :referenceLineVisible="false">
  <Vue3DraggableResizable>
    Test
  </Vue3DraggableResizable>
  <Vue3DraggableResizable>
    Another test
  </Vue3DraggableResizable>
</DraggableContainer>
referenceLineColor

type: String
default: #f00

实时参考线的颜色,默认红色

<DraggableContainer :referenceLineColor="#0f0">
  <Vue3DraggableResizable>
    Test
  </Vue3DraggableResizable>
  <Vue3DraggableResizable>
    Another test
  </Vue3DraggableResizable>
</DraggableContainer>

3、事件

1.activated

<Vue3DraggableResizable @activated="activatedHandle" />

2.deactivated

3.drag-start

<Vue3DraggableResizable @drag-start="dragStartHandle" />

4.dragging

5.drag-end

6.resize-start

7.resizing

8.resize-end

三、vue3基础组件使用

网址:Vue3DragResizeRotate

  • 基本组件
  • 自适应大小
  • 最小宽高限制
  • 最大宽高限制
  • 组件插槽
  • 控制是否处于活动状态
  • 阻止失活
  • 是否允许拖动位置
  • 是否允许调整大小
  • 是否允许旋转角度 (新增)
  • 是否允许内部元素拖拽
  • 限制允许拖动的范围
  • 限制禁止拖动的范围
  • 控制组件的z-index
  • 控制拉伸手柄的数量
  • 限制运动轴
  • 限制用户选择
  • 放缩 (新增)

1、基本

1.基本组件

最基本的组件,没有任何道具,甚至可以在父元素之外自由移动。

<template>
  <div class="view-box">
    <div id="toolbar">基本组件</div>
    <div class="container">
      <VueDragResizeRotate :x="0" :y="0" :w="200" :h="200">
        <p>你可以拖着我,按照自己的意愿调整大小。1</p>
      </VueDragResizeRotate>
      <VueDragResizeRotate :x="200" :y="200" :w="200" :h="200">
        <p>你可以拖着我,按照自己的意愿调整大小。2</p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

2.自适应大小

<template>
  <div class="view-box">
    <div id="toolbar">自适应大小</div>
    <div class="container">
      <VueDragResizeRotate w="auto" h="auto">随便填一点内容,我会自动适应大小</VueDragResizeRotate>
    </div>
  </div>
</template>

3.最小宽高限制

具有Min Height和Min Width基本组件的基本组件,最小高度和最小宽度分别由:minw 和:minh 属性控制。

<template>
  <div class="view-box">
    <div id="toolbar">
      min Width:
      <input type="number" v-model.number="minWidth" />
      min Height:
      <input type="number" v-model.number="minHeight" />
    </div>
    <div class="container">
      <VueDragResizeRotate
        :min-width="minWidth"
        :min-height="minHeight"
        :w="200"
        :h="200"
        @resizing="onResize"
        @resizestop="onResize"
      >
        <div>
          <p>基本组件,可以配置</p>
          <b>minWidth</b>
          和
          <b>minHeight</b>
          属性
          <p>w:{{ w }},h:{{ h }}</p>
        </div>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      minWidth: 200,
      minHeight: 200,
      w: 200,
      h: 200
    };
  },
  methods: {
    onResize: function (x, y, width, height) {
      this.w = width;
      this.h = height;
    }
  }
};
</script>

4.最大宽高限制

具有Max Height和Max Width基本组件的基本组件,最大高度和最大宽度分别由 :max-height 和:max-width 属性控制。

5.组件插槽

一个基本组件,内部有一个表单。 输入应该是可聚焦的,按钮应该是可点击的。

<template>
  <div class="view-box">
    <div id="toolbar">组件插槽</div>
    <div class="container">
      <VueDragResizeRotate>
        <p>基本组件内插入表单</p>
        <form @submit.stop.prevent="onSubmit">
          <input type="text" name="input" value="Hello" />
          <button type="submit">Submit</button>
        </form>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  methods: {
    onSubmit(e) {
      console.log(e);
      alert("You just submitted the form!");
    }
  }
};
</script>

6.控制是否处于活动状态

一个基本组件,带有active prop,用于控制组件外部的活动状态。

<template>
  <div class="view-box">
    <div id="toolbar">
      <input type="checkbox" v-model="active1" />
      Toggle Active1
      <input type="checkbox" v-model="active2" />
      Toggle Active2
    </div>
    <div class="container">
      <VueDragResizeRotate :active="active1">
        <p>
          外部组件通过控制
          <b>:active</b>
          prop来控制组件的激活状态
        </p>
      </VueDragResizeRotate>
      <VueDragResizeRotate :active="active2">
        <p>
          外部组件通过控制
          <b>:active</b>
          prop来控制组件的激活状态
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      active1: false,
      active2: false
    };
  },
  methods: {}
};
</script>

7.阻止失活

一个基本组件,带有prevent-deactivation prop,以避免在外部点击时解除活动状态。

<template>
  <div class="view-box">
    <div id="toolbar">外部点击不会失活</div>
    <div class="container">
      <VueDragResizeRotate :prevent-deactivation="true">
        <p>
          设置
          <b>:prevent-deactivation</b>
          属性,让组件不能取消激活状态
        </p>
      </VueDragResizeRotate>
      <VueDragResizeRotate :prevent-deactivation="true">
        <p>
          设置
          <b>:prevent-deactivation</b>
          属性,让组件不能取消激活状态
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

8.是否允许拖动位置

一个基本组件,draggable prop设置为false,因此它不可拖动。

9.是否允许调整大小

一个基本组件,resizable prop设置为false,因此它不可调整大小。

10.是否允许旋转角度

一个基本组件,rotatable prop设置为true,因此它可以旋转角度。

11.是否允许内部元素拖拽

一个基本组件,enable-native-drag prop设置为true,以允许组件内部元素的拖动行为。 您可以通过使用球拖动每个组件来查看差异。 默认值为false

<template>
  <div class="view-box">
    <div id="toolbar">允许内部元素拖拽</div>
    <div class="container">
      <VueDragResizeRotate :enable-native-drag="false" :x="0" :y="0" :w="200" :h="200">
        <p>不允许浏览器原生JavaScript拖拽</p>
        <p>Native drag disabled. Try to drag the component from the ball.</p>
        <img :src="require('@/assets/ball.svg')" />
      </VueDragResizeRotate>
      <VueDragResizeRotate :enable-native-drag="true" :x="0" :y="200" :w="200" :h="200">
        <p>允许浏览器原生JavaScript拖拽</p>
        <p>Native drag enabled. Try to drag the component from the ball.</p>
        <img :src="require('@/assets/ball.svg')" />
      </VueDragResizeRotate>
    </div>
  </div>
</template>

12.限制允许拖动的范围

一个基本组件,只能通过一个句柄拖动,由prop drag-handle 和一个有效的CSS选择器来指定,只能通过该DOM元素来拖动组件。

<template>
  <div class="view-box">
    <div id="toolbar">限制允许拖动的范围</div>
    <div class="container">
      <VueDragResizeRotate v-for="(item, index) in list" :z="item.zIndex" :x="item.x" :y="item.y" :key="index" @activated="onActivated(index)"
        style="border: 1px solid black" :drag-handle="'.drag-handle'">
        <div class="full-box" :style="{ 'background-color': item.color }">
          <div class="drag-handle">Drag Only Here</div>
        </div>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [
        { zIndex: 1, x: 100, y: 100, color: 'red', },
        { zIndex: 2, x: 250, y: 200, color: 'green' },
        { zIndex: 3, x: 400, y: 100, color: 'blue', }
      ]
    }
  },
  methods: {
    onActivated(index) {
      console.log('onActivated', index)
      const indexs  = this.list.map(item => item.zIndex);
      const maxIndex = Math.max(...indexs);
      this.list[index].zIndex = maxIndex + 1;
    }
  }
};
</script>

<style scoped>
.full-box {
  width: 100%;
  height: 100%;
}
</style>

13.限制禁止拖动的范围

一个基本组件,无法通过句柄拖动,由prop drag-cancel 和有效的CSS选择器来指定,该范围无法将无法拖动组件。

<template>
  <div class="view-box">
    <div id="toolbar">限制禁止拖动的范围</div>
    <div class="container">
      <VueDragResizeRotate style="border: 1px solid black" :drag-cancel="'.drag-cancel'">
        <div class="drag-cancel">Cannot Drag Here</div>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

14.控制组件的z-index

一个基本组件,使用z-index prop来控制组件外部的z-index。 如果没有提供,它将采用值auto

<template>
  <div class="view-box">
    <div id="toolbar">
      Change z-index:
      <input type="number" v-model="z" />
    </div>
    <div class="container">
      <VueDragResizeRotate :z="z" :x="150" :y="150" style="background-color: #ccc">
        <div>
          通过
          <b>:z属性</b>
          <p>控制组件的z-index:{{ z }}层级</p>
        </div>
      </VueDragResizeRotate>
      <div
        style="
          width: 200px;
          height: 200px;
          background-color: red;
          position: absolute;
          top: 100px;
          left: 100px;
          z-index: 1;
          text-align: center;
          font-size: 24px;
        "
      >
        1
      </div>
      <div
        style="
          width: 300px;
          height: 300px;
          background-color: green;
          position: absolute;
          top: 200px;
          left: 200px;
          z-index: 9;
          text-align: center;
          font-size: 24px;
        "
      >
        9
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      z: 0
    };
  }
};
</script>

15.控制拉伸手柄的数量

您可以使用handles prop选择要为组件提供的句柄,它接受句柄数组。 例如,如果你想仅在横轴上进行成本调整,你只能提供左右句柄:handles =“['ml','mr']”

<template>
  <div class="view-box">
    <div id="toolbar">
      <label v-for="handle in Object.keys(handles)" :key="handle">
        <input type="checkbox" v-model="handles[handle]" />
        {{ handle }}
      </label>
    </div>
    <div class="container">
      <VueDragResizeRotate :handles="enabledHandles" :prevent-deactivation="true" :w="250" :h="250">
        <p>Enable/disable handles.</p>
        <ul>
          <li v-for="handle in Object.keys(handles)" :key="handle">
            {{ handle }} - {{ handles[handle] ? "&check;" : "&cross;" }}
          </li>
        </ul>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      handles: {
        tl: true,
        tm: true,
        tr: true,
        mr: true,
        br: true,
        bm: true,
        bl: true,
        ml: true
      }
    };
  },
  computed: {
    enabledHandles() {
      return Object.keys(this.handles).filter(handle => this.handles[handle] === true);
    }
  }
};
</script>

<style scoped>
.vdr ul,
.VueDragResizeRotate ul {
  margin: 0 0 0 25px;
}
</style>

16.限制运动轴

一个基本组件,使用axis来控制可拖动的轴。 合适的值是xyboth

<template>
  <div class="view-box">
    <div id="toolbar">
      <label>
        <input type="checkbox" v-model="x" />
        X
      </label>
      <label>
        <input type="checkbox" v-model="y" />
        Y
      </label>
    </div>
    <div class="container">
      <VueDragResizeRotate :axis="axis">
        <p>Draggable on {{ axis }} axis.</p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      x: true,
      y: true
    };
  },
  computed: {
    axis() {
      if (this.x && this.y) return "both";
      if (this.x) return "x";
      if (this.y) return "y";
      return false;
    }
  }
};
</script>

17.限制用户选择

阻止用户选中组件内文本

<template>
  <div class="view-box">
    <div id="toolbar">
      <input type="checkbox" v-model="disableUserSelect1" />
      Toggle disableUserSelect1
      <input type="checkbox" v-model="disableUserSelect2" />
      Toggle disableUserSelect2
    </div>
    <div class="container">
      <VueDragResizeRotate :parent="true" :disableUserSelect="disableUserSelect1">
        <p>
          你
          {{ disableUserSelect1 ? "不可以" : "可以" }}
          选择组件内部的的文字,不妨双击试试!!!
          <br />
          <b>:disableUserSelect</b>
          prop equal to {{ disableUserSelect1 }}.
        </p>
      </VueDragResizeRotate>
      <VueDragResizeRotate :parent="true" :disableUserSelect="disableUserSelect2">
        <p>
          你
          {{ disableUserSelect2 ? "不可以" : "可以" }}
          选择组件内部的的文字,不妨双击试试!!!
          <br />
          <b>:disableUserSelect</b>
          prop equal to {{ disableUserSelect2 }}.
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      disableUserSelect1: false,
      disableUserSelect2: false
    };
  }
};
</script>

18.放缩 

放缩时,建议保持父元素盒子和vue-drag-resize-rotate放缩值保持一致

<template>
  <div class="view-box">
    <div id="toolbar">
      <el-input-number size="mini" v-model="scaleRatio" :step="0.1" :min="0.1" :max="10" />
      <span class="ml_10">scaleRatio</span>
    </div>
    <div class="container" :style="containerStyle()">
      <VueDragResizeRotate
        :rotatable="rotatable"
        :x="position.x"
        :y="position.y"
        :w="position.w"
        :h="position.h"
        :r="angle"
        @rotating="rotating"
        :resizable="true"
        @resizing="resizing"
        :parent="true"
        :scaleRatio="scaleRatio"
      >
        <p>位置为({{ position.x }},{{ position.y }})</p>
        <p>大小为({{ position.w }},{{ position.h }})</p>
        <p>角度为{{ angle }}</p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      rotatable: true,
      position: {
        x: 0,
        y: 0,
        w: 200,
        h: 200
      },
      angle: 0,
      scaleRatio: 1
    };
  },
  methods: {
    rotating(val) {
      this.angle = val;
    },
    resizing(x, y, w, h) {
      this.position = { x, y, w, h };
    },
    containerStyle() {
      return {
        transform: `scale(${this.scaleRatio})`
      };
    }
  }
};
</script>

<style scoped>
#toolbar {
  display: flex;
  align-items: center;
}
.container {
  transform-origin: left top;
}
</style>

2、网格对齐

1.网格20x20

一个基本组件,用grid = [20,20] prop来设置网格单元的尺寸(高度和宽度,以像素为单位)。

<template>
  <div class="view-box">
    <div id="toolbar">Size: {{ width }} x {{ height }}</div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate :grid="[20, 20]" :x="0" :y="0" @resizing="onResizing">
          <p>Grid 20x20 starting from the top-left corner</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: 200,
      height: 200,
      style: {
        position: "relative",
        height: "100%",
        width: "100%",
        backgroundColor: "#808080",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 20px, 20px 20px"
      }
    };
  },
  methods: {
    onResizing(x, y, width, height) {
      this.width = width;
      this.height = height;
    }
  }
};
</script>

2.网格20x40

3.网格20x20+偏移10x10

始终从组件的左上角计算网格。 在此示例中,您可以看到它相对于父元素具有偏移量。 这对于父元素中的成本要求很重要。

<template>
  <div class="view-box">
    <div id="toolbar">Size: {{ width }} x {{ height }}</div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate :grid="[20, 20]" :x="10" :y="10" @resizing="onResizing">
          <p>Grid 20x20 starting with a 10x10 offset</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: 200,
      height: 200,
      style: {
        position: "relative",
        height: "100%",
        width: "100%",
        backgroundColor: "#808080",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 20px, 20px 20px",
        backgroundPosition: "10px 10px"
      }
    };
  },
  methods: {
    onResizing(x, y, width, height) {
      this.width = width;
      this.height = height;
    }
  }
};
</script>

4.网格20x40+偏移10x20+最小限制

如果您提供的minHeightminWidth值低于相应的网格值,您可以注意到调整大小会停止到最低的合适值。 例如,在x轴上,尊重minWidthgrid [x]约束的最低有效值是40.同样适用于y轴。

<template>
  <div class="view-box">
    <div id="toolbar">Size: {{ width }} x {{ height }}</div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate :grid="[20, 40]" :x="10" :y="20" :minHeight="30" :minWidth="30">
          <p>Grid 20x40 starting with a 10x20 offset and min height, min width values equal to 30.</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: 200,
      height: 200,
      style: {
        position: "relative",
        backgroundColor: "#808080",
        height: "100%",
        width: "100%",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 40px, 20px 40px",
        backgroundPosition: "10px 20px"
      }
    };
  },
  methods: {
    onResizing(x, y, width, height) {
      this.width = width;
      this.height = height;
    }
  }
};
</script>

5.网格20x40+偏移10x20+最大限制

如果提供的maxHeightmaxWidth值高于相应的网格值,则可以注意到调整大小会停止到较低的合适值。 例如,在x轴上,尊重maxWidthgrid [x]约束的最低有效值是80.这同样适用于y轴。

3、父级限制

1.父级容器基本案例

无法在其父元素之外拖动或调整大小的组件,使用prop :parent =“true”定义。

<template>
  <div class="view-box">
    <div id="toolbar">父级容器基本案例</div>
    <div class="container">
      <VueDragResizeRotate :parent="true">
        <p>你不能将当前组件拖动或调整大小超过父元素容器</p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

2.父级+自适应

<template>
  <div class="view-box">
    <div id="toolbar">父级+自适应</div>
    <div class="container">
      <VueDragResizeRotate :parent="true" w="auto" h="auto">随便填一点东西</VueDragResizeRotate>
    </div>
  </div>
</template>

3.父级+最大限制

无法在其父元素之外拖动或调整大小的组件,使用 maxWidth  maxHeight 来限制其大小。

<template>
  <div class="view-box">
    <div id="toolbar">Size: {{ width }} x {{ height }}</div>
    <div class="container">
      <VueDragResizeRotate :parent="true" :max-width="300" :max-height="300" @resizing="onResizing">
        <p>
          Component costrained in parent with
          <b>maxWidth</b>
          and
          <b>maxHeight</b>
          equal to 300.
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: 200,
      height: 200
    };
  },
  methods: {
    onResizing(x, y, width, height) {
      this.width = width;
      this.height = height;
    }
  }
};
</script>

4.父级+网格

附加到网格的组件,不能在其父元素之外拖动或调整大小,使用prop :parent =“true”定义。 在这种情况下,父级的大小完全匹配网格。

<template>
  <div class="view-box">
    <div id="toolbar">父级+网格</div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate :parent="true" :grid="[20, 20]">
          <p>You cannot move me or resize me outside my parent.</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      style: {
        position: "relative",
        backgroundColor: "#808080",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 20px, 20px 20px",
        height: "100%",
        width: "100%"
      }
    };
  }
};
</script>

5.父级+网格+偏移

组件附加到具有小偏移的网格。 它的起始位置与父级的左上角不完全对齐。

<template>
  <div class="view-box">
    <div id="toolbar">父级限制+网格+偏移</div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate :parent="true" :grid="[20, 20]" :x="10" :y="10" :h="400" :w="400">
          <p>You cannot move me or resize me outside my parent. And my edges cannot touch the parent element.</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      style: {
        position: "relative",
        backgroundColor: "#808080",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 20px, 20px 20px",
        backgroundPosition: "10px 10px",
        width: "100%",
        height: "100%",
        boxSizing: "border-box"
      }
    };
  }
};
</script>

6.父级+网格+最大限制

附加到网格的组件,无法在其父元素之外拖动或调整大小,使用 maxWidth  maxHeight 来限制其大小。 __Notice__使用20作为grid prop为 y轴,元素的maxHeight280而不是290

<template>
  <div class="view-box">
    <div id="toolbar">Size: {{ width }} x {{ height }}</div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate
          :parent="true"
          :max-width="290"
          :max-height="290"
          @resizing="onResizing"
          :grid="[10, 20]"
        >
          <p>
            Component costrained in parent with
            <b>maxWidth</b>
            and
            <b>maxHeight</b>
            equal to 290.
          </p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: 200,
      height: 200,
      style: {
        position: "relative",
        backgroundColor: "#808080",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "10px 20px, 10px 20px",
        width: "100%",
        height: "100%",
        boxSizing: "border-box"
      }
    };
  },
  methods: {
    onResizing(x, y, width, height) {
      this.width = width;
      this.height = height;
    }
  }
};
</script>

7.父级+控制组件

一个基本的父控制组件,x y w h 用于控制组件位置和大小的道具。 __Notice__使用grid prop,组件只会对网格值的有效倍数作出反应。

<template>
  <div class="view-box">
    <div id="toolbar">
      X:
      <input type="number" v-model.number="x" />
      Y:
      <input type="number" v-model.number="y" />
      Width:
      <input type="number" v-model.number="w" />
      Height:
      <input type="number" v-model.number="h" />
    </div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate
          :parent="true"
          :grid="[20, 20]"
          :x="x"
          :y="y"
          :h="h"
          :w="w"
          @dragging="onDrag"
          @resizing="onResize"
        >
          <p>You cannot move me or resize me outside my parent.</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      x: 10,
      y: 10,
      w: 100,
      h: 100,
      style: {
        position: "relative",
        backgroundColor: "#808080",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 20px, 20px 20px",
        backgroundPosition: "10px 10px",
        width: "100%",
        height: "100%",
        boxSizing: "border-box"
      }
    };
  },
  methods: {
    onDrag(left, top) {
      this.x = left;
      this.y = top;
    },
    onResize(left, top, width, height) {
      this.x = left;
      this.y = top;
      this.w = width;
      this.h = height;
    }
  }
};
</script>

4、纵横比 

1.锁定纵横比

具有lock-aspect-ratio prop的组件,用于在调整大小期间保持组件的宽高比。

<template>
  <div class="view-box">
    <div id="toolbar">
      <input type="checkbox" v-model="ratio" />
      Toggle Lock Aspect Ratio
    </div>
    <div class="container">
      <VueDragResizeRotate :lock-aspect-ratio="ratio">
        <p>
          Keep aspect ratio using
          <b>:lock-aspect-ratio</b>
          prop.
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      ratio: true
    };
  }
};
</script>

2.纵横比+最小限制

一个组件,lock-aspect-ratio prop和最小高度设置为100,最小宽度设置为50.请注意,锁定纵横比也会强制最小宽度为100(条件:1 / 1)。

<template>
  <div class="view-box">
    <div id="toolbar">Size: {{ width }} x {{ height }}</div>
    <div class="container">
      <VueDragResizeRotate :lock-aspect-ratio="true" :minHeight="100" :minWidth="50" @resizing="onResizing">
        <p>
          Keep aspect ratio and set
          <b>minHeight</b>
          to 100 and
          <b>minWidth</b>
          to 50.
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: 200,
      height: 200
    };
  },
  methods: {
    onResizing(x, y, width, height) {
      this.width = width;
      this.height = height;
    }
  }
};
</script>

3.纵横比+最大限制

一个组件,lock-aspect-ratio prop和 maxWidth 设置为300 maxHeight 设置为250。 请注意,锁定纵横比也会强制最大宽度为250

4.纵横比+父级容器限制

在父级中使用的组件,lock-aspect-ratio prop用于在调整大小期间保持组件的宽高比。

<template>
  <div class="view-box">
    <div id="toolbar"></div>
    <div class="container">
      <VueDragResizeRotate :lock-aspect-ratio="true" :parent="true">
        <p>Combine aspect ratio and costrain in parent.</p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

5.纵横比+对齐网格

具有宽高比的组件在20x20网格上进行了受限

使用lock-aspect-ratio时,在网格上使用组件的成本并不是很好。 您可以通过拖动(例如右手柄或底部手柄)来注意到您有不同的结果。

<template>
  <div class="view-box">
    <div id="toolbar"></div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate :w="400" :h="200" :lock-aspect-ratio="true" :grid="[20, 20]">
          <p>Keep aspect ratio in component costrained on grid.</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      style: {
        position: "relative",
        backgroundColor: "#808080",
        height: "100%",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 20px, 20px 20px"
      }
    };
  }
};
</script>

6.在偏移的网格上对齐

<template>
  <div class="view-box">
    <div id="toolbar"></div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate :grid="[20, 40]" :x="10" :y="20" :minh="30" :minw="30" :lock-aspect-ratio="true">
          <p>Aspect ratio in Grid 20x40 starting with a 10x20 offset</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      style: {
        position: "relative",
        backgroundColor: "#808080",
        height: "100%",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 40px, 20px 40px",
        backgroundPosition: "10px 20px"
      }
    };
  }
};
</script>

7.在父级中对齐网格

<template>
  <div class="view-box">
    <div id="toolbar"></div>
    <div class="container">
      <div :style="style">
        <VueDragResizeRotate :grid="[20, 20]" :parent="true" :lock-aspect-ratio="true">
          <p>Keep aspect ratio, grid and parent costrained.</p>
        </VueDragResizeRotate>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      style: {
        position: "relative",
        backgroundColor: "#808080",
        background:
          "linear-gradient(-90deg, rgba(0, 0, 0, .1) 1px, transparent 1px), linear-gradient(rgba(0, 0, 0, .1) 1px, transparent 1px)",
        backgroundSize: "20px 20px, 20px 20px",
        height: "100%",
        width: "100%",
        boxSizing: "border-box"
      }
    };
  }
};
</script>

8.外部传入纵横比参数 (新增)

具有lock-aspect-ratio prop的组件,用于在调整大小期间保持组件的宽高比。
设置outsideAspectRatio来控制组件的纵横比

<template>
  <div class="view-box">
    <div id="toolbar">
      <input type="checkbox" v-model="ratio" />
      Toggle Lock Aspect Ratio
      <input type="number" v-model="outsideAspectRatio" />
    </div>
    <div class="container">
      <VueDragResizeRotate :lock-aspect-ratio="ratio" :outsideAspectRatio="outsideAspectRatio">
        <p>
          Keep aspect ratio using
          <b>:lock-aspect-ratio</b>
          prop.
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      ratio: true,
      outsideAspectRatio: 1.7777
    };
  }
};
</script>

5、样式

1.Style 组件

具有自定义类名的组件,由prop class-name 提供。

<template>
  <div class="view-box">
    <div id="toolbar">具有自定义类名的组件</div>
    <div class="container">
      <VueDragResizeRotate class-name="my-class">
        <p>
          你可以给组件设置一个类名,覆盖其默认类名
          <b>class-name</b>
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<style scoped>
.my-class {
  border: 1px solid red;
  -webkit-transition: background-color 200ms linear;
  -ms-transition: background-color 200ms linear;
  transition: background-color 200ms linear;
}
</style>

2.Style 拖动

在拖动时具有自定义类名的组件,由prop class-name-dragging 提供。

<template>
  <div class="view-box">
    <div id="toolbar">拖动时具有自定义类名的组件</div>
    <div class="container">
      <VueDragResizeRotate class-name-dragging="my-dragging-class" class-name="my-class">
        <p>
          你也可以设置组件处于拖拽式的类名
          <b>class-name-dragging</b>
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<style scoped>
.my-class {
  border: 1px solid red;
  -webkit-transition: background-color 200ms linear;
  -ms-transition: background-color 200ms linear;
  transition: background-color 200ms linear;
}
.my-dragging-class {
  background-color: red;
  border: 1px solid black;
}
</style>

3.Style 拉伸

调整大小时具有自定义类名的组件,由prop class-name-resizing 提供。

4.Style 活跃

在活动状态下具有自定义类名的组件,由prop class-name-active 提供。

5.Style 句柄

具有handle的自定义类的组件,随prop class-name-handle 提供。 这样,您可以单独设置每个手柄的样式。

记得为句柄类设置position:absolute

6.Style 手柄插槽

具有句柄自定义标记的组件,由VueJS named slots提供(例如slot =“tl”)。

Slots | Vue.js

<template>
  <div class="view-box">
    <div id="toolbar">具有句柄自定义标记的组件</div>
    <div class="container">
      <VueDragResizeRotate class-name-handle="my-handle-class">
        <p>The first child will populate the default slot.</p>
        <template v-slot:tl>😀</template>
        <template v-slot:tm>😂</template>
        <template v-slot:tr>😆</template>
        <template v-slot:mr>😉</template>
        <template v-slot:br>😎</template>
        <template v-slot:bm>😍</template>
        <template v-slot:bl>😣</template>
        <template v-slot:ml>😕</template>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<style scoped></style>

6、事件

1.激活组件事件

当组件被激活时,会发出activated()事件。 当组件被停用时,会发出deactivated()事件。

<template>
  <div class="view-box">
    <div id="toolbar">点击激活组件activated和取消激活deactivated</div>
    <div class="container">
      <VueDragResizeRotate :w="200" :h="200" @activated="onActivated" @deactivated="onDeactivated">
        <p v-if="active">这个组件正处于激活状态</p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      active: false
    };
  },
  methods: {
    onActivated() {
      this.active = true;
    },
    onDeactivated() {
      this.active = false;
    }
  }
};
</script>

2.拖动位置事件

拖动组件时会发出dragging(x,y)事件。 拖动停止时会发生dragstop(x,y)事件。

<template>
  <div class="view-box">
    <div id="toolbar">拖动组件触发事件dragging和停止拖拽dragstop</div>
    <div class="container">
      <VueDragResizeRotate :w="200" :h="200" :r="0" @dragging="onDrag" @dragstop="onDragStop">
        <p>
          {{ dragging ? "你正在拖动" : "我就待在这里" }}
          <br />
          X: {{ x }} / Y: {{ y }}
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dragging: false,
      x: 0,
      y: 0
    };
  },
  beforeUnmount: function () {
    clearTimeout(this.timer);
  },
  methods: {
    onDrag: function (x, y) {
      this.dragging = true;
      this.x = x;
      this.y = y;
    },
    onDragStop: function (x, y) {
      console.log(x,y)
      this.dragging = false;
    }
  }
};
</script>

3.调整大小事件

调整组件大小时会发出resizing(x,y,width,height)事件。 调整大小停止时会发出resizestop(x,y,width,height)事件。

<template>
  <div class="view-box">
    <div id="toolbar">调整大小触发事件resizing和停止调整resizestop</div>
    <div class="container">
      <VueDragResizeRotate :w="200" :h="200" :x="0" :y="0" :r="0" @resizing="onResize" @resizestop="onResizeStop">
        <p>
          {{ resizing ? "你正在调整大小" : "这个大小还行" }}
          <br />
          X: {{ x }} / Y: {{ y }} - Width: {{ width }} / Height: {{ height }}
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      resizing: false,
      x: 0,
      y: 0,
      width: 200,
      height: 200
    };
  },
  methods: {
    onResize: function (x, y, width, height) {
      this.resizing = true;
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
    },
    onResizeStop: function () {
      this.resizing = false;
      console.log(arguments);
    }
  }
};
</script>

4.旋转角度事件 

<template>
  <div class="view-box">
    <div id="toolbar">调整旋转角度触发事件rotating和rotatestop</div>
    <div class="container">
      <VueDragResizeRotate
        :w="200"
        :h="200"
        :x="0"
        :y="0"
        :rotatable="true"
        @rotating="onRotating"
        @rotatestop="onRotateStop"
      >
        <p>
          {{ rotating ? "你正在旋转" : "这个角度刚刚好" }}
          <br />
          Rotate: {{ rotate }}
        </p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      rotating: false,
      x: 0,
      y: 0,
      width: 200,
      height: 200,
      rotate: 0
    };
  },
  methods: {
    onRotating: function (degree) {
      this.resizing = true;
      this.rotate = degree;
    },
    onRotateStop: function (degree) {
      this.resizing = false;
      this.rotate = degree;
    }
  }
};
</script>

7、高级

1.位置冲突检测

开启冲突检测时,各个可拖拽组件之间不可重叠,冲突后当前元素回到原来的位置

<template>
  <div class="view-box">
    <div id="toolbar">位置冲突检测</div>
    <div class="container">
      <VueDragResizeRotate
        :w="200"
        :h="200"
        :parent="true"
        :x="210"
        :debug="false"
        :min-width="200"
        :min-height="200"
        :isConflictCheck="true"
        :rotatable="true"
        style="background-color: rgb(174, 213, 129)"
      ></VueDragResizeRotate>
      <VueDragResizeRotate
        :w="200"
        :h="200"
        :parent="true"
        :x="420"
        :debug="false"
        :min-width="200"
        :min-height="200"
        :isConflictCheck="true"
        :rotatable="true"
        style="background-color: rgb(129, 212, 250)"
      ></VueDragResizeRotate>
    </div>
  </div>
</template>

2.元素位置吸附

设置:snap="true"开启吸附功能和设置:snapTolerance="20"可控制吸附判断距离

<template>
  <div class="view-box">
    <div id="toolbar">位置吸附对齐</div>
    <div class="container">
      <VueDragResizeRotate
        :w="200"
        :h="200"
        :parent="true"
        :x="210"
        :min-width="200"
        :min-height="200"
        :snap="true"
        :snapTolerance="20"
        style="background-color: rgb(174, 213, 129)"
      ></VueDragResizeRotate>
      <VueDragResizeRotate
        :w="200"
        :h="200"
        :parent="true"
        :x="420"
        :min-width="200"
        :min-height="200"
        :snap="true"
        :snapTolerance="20"
        style="background-color: rgb(129, 212, 250)"
      ></VueDragResizeRotate>
    </div>
  </div>
</template>

3.对齐时有辅助线

返回参数是一个Object,里面包含vLinehLine,具体使用参考下面代码。

<template>
  <div class="view-box">
    <div id="toolbar">对齐时出现辅助线</div>
    <div class="container">
      <VueDragResizeRotate
        :w="200"
        :h="200"
        :parent="true"
        :debug="false"
        :min-width="200"
        :min-height="200"
        :isConflictCheck="true"
        :snap="true"
        :snapTolerance="10"
        @refLineParams="getRefLineParams"
        style="background-color: rgb(174, 213, 129)"
      ></VueDragResizeRotate>
      <VueDragResizeRotate
        :w="200"
        :h="200"
        :parent="true"
        :x="210"
        :debug="false"
        :min-width="200"
        :min-height="200"
        :isConflictCheck="true"
        :snap="true"
        :snapTolerance="10"
        @refLineParams="getRefLineParams"
        style="background-color: rgb(129, 212, 250)"
      ></VueDragResizeRotate>
      <VueDragResizeRotate
        :w="200"
        :h="200"
        :parent="true"
        :x="420"
        :debug="false"
        :min-width="200"
        :min-height="200"
        :isConflictCheck="true"
        :snap="true"
        :snapTolerance="10"
        @refLineParams="getRefLineParams"
        style="background-color: rgb(239, 154, 154)"
      ></VueDragResizeRotate>
      <span
        class="ref-line v-line"
        v-for="(item, index) in vLine"
        :key="'v_' + index"
        v-show="item.display"
        :style="{
          left: item.position,
          top: item.origin,
          height: item.lineLength
        }"
      />
      <span
        class="ref-line h-line"
        v-for="(item, index) in hLine"
        :key="'h_' + index"
        :style="{
          top: item.position,
          left: item.origin,
          width: item.lineLength
        }"
      />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      vLine: [],
      hLine: []
    };
  },
  methods: {
    getRefLineParams(params) {
      const { vLine, hLine } = params;
      this.vLine = vLine;
      this.hLine = hLine;
    }
  }
};
</script>

<style scoped>
.ref-line {
  position: absolute;
  background-color: rgb(219, 89, 110);
  z-index: 9999;
}
.v-line {
  width: 1px;
}
.h-line {
  height: 1px;
}
</style>

8、应用

1.同时拖动多个元素(20)

默认情况下,这不是组件提供的功能,但它是如何使用现有功能构建复杂方案的示例。

由于ctrl事件处理程序的注册方式,请确保在开始拖动元素之前单击容器内的任何位置。

<template>
  <div class="view-box">
    <div id="toolbar">
      <label>
        同时拖动多个内部元素(20个)
        <input type="checkbox" name="sync" v-model="sync" />
        Synchronize (Use
        <b>ctrl</b>
        Key)
      </label>
    </div>
    <div class="container">
      <VueDragResizeRotate
        class-name-active="my-active-class"
        ref="vdrr"
        v-for="element in elements"
        :key="element.id"
        :id="element.id"
        :x="element.x"
        :y="element.y"
        :w="200"
        :h="200"
        :resizable="false"
        @dragging="(left, top) => dragging(element.id, left, top)"
        @dragstop="(left, top) => dragstop(element.id, left, top)"
      >
        <p>{{ element.text }}</p>
      </VueDragResizeRotate>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      sync: false,
      draggingId: null,
      prevOffsetX: 0,
      prevOffsetY: 0,
      count: 20,
      batchable: false,
      elements: []
    };
  },
  computed: {
    draggingElement: function () {
      if (!this.draggingId) return;
      return this.elements.find(el => el.id === this.draggingId);
    }
  },
  created() {
    this.fillElements();
  },
  mounted() {
    window.addEventListener("keydown", ev => {
      if (ev.keyCode === 17) {
        this.sync = true;
      }
    });
    window.addEventListener("keyup", ev => {
      if (ev.keyCode === 17) {
        this.sync = false;
      }
    });
  },
  methods: {
    fillElements() {
      for (let i = 1; i < this.count; i++) {
        let template = { id: 1, x: 0, y: 0, text: "Element ", active: false };
        template.id = i;
        template.text += i;
        template.x = Math.floor(Math.random() * 1000);
        template.y = Math.floor(Math.random() * 400);
        this.elements.push(template);
      }
    },
    dragging(id, left, top) {
      if (!this.sync) return;
      this.draggingId = id;
      const offsetX = left - this.draggingElement.x;
      const offsetY = top - this.draggingElement.y;
      const deltaX = this.deltaX(offsetX);
      const deltaY = this.deltaY(offsetY);
      this.elements.forEach((el) => {
        if (el.id !== id) {
          el.x += deltaX;
          el.y += deltaY;
        }
      });
    },
    dragstop(id, left, top) {
      this.elements.map(el => {
        if (el.id === id) {
          el.x = left;
          el.y = top;
        }
        return el;
      });
      this.draggingId = null;
      this.prevOffsetX = 0;
      this.prevOffsetY = 0;
    },
    deltaX(offsetX) {
      const ret = offsetX - this.prevOffsetX;
      this.prevOffsetX = offsetX;
      return ret;
    },
    deltaY(offsetY) {
      const ret = offsetY - this.prevOffsetY;
      this.prevOffsetY = offsetY;
      return ret;
    }
  }
};
</script>
Logo

前往低代码交流专区

更多推荐