vue 使用自定义指令实现拖拽
需求背景,工作中需要实现一个自定义打印模板的需求,能够实现单个及多个dom元素的同时拖拽,也能通过外部的input元素修改dom元素的样式。在npm和GitHub上找了各种已有的vue组件,不够灵活,效果都不是自己想要的
Vue.directive('dragx', (el, binding, vnode) => {
// 默认参数
let defaultOpts = {
dragDirection: 'n, e, s, w, ne, se, sw, nw, all',
dragContainerId: '', //
dragBarClass: '', // 类选择器
canDrag: true,
canResize: true,
multiSelect: false
}
let isMove = false
let isResize = false
let constraintDom
let constraintRect
let constraintRectHeight
let constraintRectWidth
binding.value = binding.value || {
}
let cfg = Object.assign({
}, defaultOpts, binding.value)
if (cfg.dragContainerId) {
constraintDom = document.querySelector('#' + cfg.dragContainerId)
constraintRect = constraintDom.getBoundingClientRect()
constraintRectHeight = constraintRect.height
constraintRectWidth = constraintRect.width
}
let getStyleNumValue = (style, key) => parseInt(style.getPropertyValue(key), 10)
// 设置约束范围
function setConstraint (data) {
if (cfg.dragContainerId) {
if (data.left <= 0) data.left = 0
if (data.top <= 0) data.top = 0
if (data.top + data.height + data.borderTop + data.borderBottom >= constraintRectHeight) data.top = constraintRectHeight - data.height - data.borderTop - data.borderBottom
if (data.left + data.width + data.borderLeft + data.borderRight > constraintRectWidth) data.left = constraintRectWidth - data.width - data.borderLeft - data.borderRight
}
}
el.onmousemove = e => {
if (cfg.dragBarClass.length > 0 && e.target.classList.contains(cfg.dragBarClass) && cfg.canDrag) {
el.style.cursor = 'move'
return
}
el.style.cursor = ''
}
el.onmouseleave = e => {
el.style.cursor = ''
}
el.onmousedown = e => {
let clickId = (e.target || e.srcElement).id
let posData = {
x: e.pageX, y: e.pageY
}
el.onmouseup = e => {
// dom元素选中时发送active事件
if (!cfg.active) el.dispatchEvent(new CustomEvent('bindActive',