一、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 lefttm
: Top middletr
: Top rightmr
: Middle rightml
: Middle leftbl
: Bottom leftbm
: Bottom middlebr
: 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基础组件使用
- 基本组件
- 自适应大小
- 最小宽高限制
- 最大宽高限制
- 组件插槽
- 控制是否处于活动状态
- 阻止失活
- 是否允许拖动位置
- 是否允许调整大小
- 是否允许旋转角度 (新增)
- 是否允许内部元素拖拽
- 限制允许拖动的范围
- 限制禁止拖动的范围
- 控制组件的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] ? "✓" : "✗" }} </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
来控制可拖动的轴。 合适的值是x
,y
或both
。
<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+最小限制
如果您提供的minHeight
和minWidth
值低于相应的网格值,您可以注意到调整大小会停止到最低的合适值。 例如,在x
轴上,尊重minWidth
和grid [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+最大限制
如果提供的maxHeight
和maxWidth
值高于相应的网格值,则可以注意到调整大小会停止到较低的合适值。 例如,在x
轴上,尊重maxWidth
和grid [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轴,元素的maxHeight
是280
而不是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”
)。
<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,里面包含vLine
与hLine
,具体使用参考下面代码。
<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>