vue 拖拽指令

要输入一些表单时候,但是模态框又会把我们需要的背景重要部分挡住,于是我们就想拖动窗口。观察了一些组件,基本没有我想要的效果。以前写过一段时间的angular,发现angular的官方组件库material design很好用,他们的拖拽也非常的好。下面我实现的也是借鉴了一点他们的想法,再加上结合了网友们的代码写的。主要是通过transform这个属性

实现效果

通过拖动模态框的头部来拖动模态框

实现

指令
// drag.js
const drag = {
    install (Vue) {
        Vue.directive('dragHandle', {
            inserted: (el) => {
                el.addEventListener('mousedown', touch, false)
                document.addEventListener('mouseup', mouseup, false)
            }
        })
        Vue.directive('drag', {
            bind: (el) => {
                el.classList.add('c-drag')
            }
        })
    }

}
var dom = null
var E_SIZER = {}
export function getStyle (el, attr) {
    if (typeof window.getComputedStyle !== 'undefined') {
        return window.getComputedStyle(el, null)[attr]
    } else if (typeof el.currentStyle !== 'undefined') {
        return el.currentStyle[attr]
    }
    return ''
}
export function getParentDom (el) {
    if (el.parentElement.classList.value.indexOf('c-drag') > -1) {
        dom = el.parentElement
        return el.parentElement
    } else {
        return getParentDom(el.parentElement)
    }
}
export function touch (e) {
    let parentDom = getParentDom(e.target)
    e.stopPropagation()
    e.preventDefault()
    let matrix3dReg = /^matrix3d\((?:[-\d.]+,\s*){12}([-\d.]+),\s*([-\d.]+)(?:,\s*[-\d.]+){2}\)/
    let matrixReg = /^matrix\((?:[-\d.]+,\s*){4}([-\d.]+),\s*([-\d.]+)\)$/
    let matrix3dSourceValue = getStyle(parentDom, 'transform')
    let matrix3dArrValue = matrix3dSourceValue.match(matrix3dReg) || matrix3dSourceValue.match(matrixReg)
    E_SIZER['clientX'] = e.clientX
    E_SIZER['clientY'] = e.clientY
    E_SIZER['targetX'] = matrix3dArrValue ? matrix3dArrValue[1] : 0
    E_SIZER['targetY'] = matrix3dArrValue ? matrix3dArrValue[2] : 0

    E_SIZER['distX'] = E_SIZER['clientX'] - E_SIZER['targetX']
    E_SIZER['distY'] = E_SIZER['clientY'] - E_SIZER['targetY']

    document.addEventListener('mousemove', move, false)

}
export function mouseup (e) {
    e.stopPropagation()
    e.preventDefault()

    document.removeEventListener('mousemove', move)
}
export function move (e) {
    e.stopPropagation();
    e.preventDefault();
    let moveY = e.clientY - E_SIZER['distY']
    let moveX = e.clientX - E_SIZER['distX']

    dom.style.transform = `translate3d(${moveX}px,${moveY}px,1px)`

}
export default drag

// main.js
import drag from './directive/drag.js'
Vue.use(drag)

使用方法

<div class="drag-modal" v-drag>
          <div class="modal-title" v-dragHandle>
            <h2>{{ title }}</h2>
            <a-icon type="close" @click="close" class="close" />
          </div>
          <div class="modal-content">
            <slot name="content"></slot>
          </div>
</div>

说明:指令中关于拖拽的代码来源https://zhuanlan.zhihu.com/p/82906845,写的很详细,想更清楚的了解运行机制啥的可以去看他的文章。这个模态框是自定义的,因为一些UI组件的模态框封装性较好,这个指令用上去会有一些问题,如果要处理这些问题,就会导致指令的通用性较差。有需要自定义模态框(使用了vue)的代码可以看我写的另外一篇文章vue 自定义模态框