Boaz

想要绝对定位下的dom节点任意拖拽?1个指令搞定
v-dom-drag="{dom: '.dm-icon-task', stop: true}"...
扫描右侧二维码阅读全文
07
2022/05

想要绝对定位下的dom节点任意拖拽?1个指令搞定

 v-dom-drag="{dom: '.dm-icon-task', stop: true}"
 @params {dom: '节点选择器', stop: '是否阻止点击附带的默认事件'}
import Vue from 'vue';

Vue.directive('domDrag', {
bind(el, binding) {
    const dialogHeaderEl = ((binding||{}).value||{}).dom?el.querySelector(binding.value.dom):el
    const dragDom = ((binding||{}).value||{}).box?el.querySelector(binding.value.box):el
    dialogHeaderEl.style.cssText += ';cursor:move;'
    // dragDom.style.cssText += ';top:0px;'
    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const getStyle = (function() {
        if (window.document.currentStyle) {
            return (dom, attr) => dom.currentStyle[attr]
        } else {
            return (dom, attr) => getComputedStyle(dom, false)[attr]
        }
    })()
    dragDom.onselectstart = function () {
        return false;
    };
    if (((binding||{}).value||{}).stop)
        dialogHeaderEl.onclick = (e) => {
            e.stopPropagation()
            e.preventDefault()
        }
    dialogHeaderEl.onmousedown = (e) => {
        // 解决快速拖动滞后问题
        // 鼠标按下,计算当前元素距离可视区的距离
        const disX = e.clientX - dialogHeaderEl.offsetLeft
        const disY = e.clientY - dialogHeaderEl.offsetTop

        const dragDomWidth = dragDom.offsetWidth
        const dragDomheight = dragDom.offsetHeight

        const screenWidth = document.body.clientWidth
        const screenHeight = document.body.clientHeight

        const minDragDomLeft = dragDom.offsetLeft
        const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth

        const minDragDomTop = dragDom.offsetTop
        const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight
        // // 获取到的值带px 正则匹配替换
        let styL = getStyle(dragDom, 'left')
        let styT = getStyle(dragDom, 'top')

        if (styL.includes('%')) {
            styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100)
            styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100)
        } else {
            styL = +styL.replace(/px/g, '')
            styT = +styT.replace(/px/g, '')
        }

        document.onmousemove = function(e) {
            // 通过事件委托,计算移动的距离
            let left = e.clientX - disX
            let top = e.clientY - disY
            // 边界处理
            if (-(left) > minDragDomLeft)
                left = -minDragDomLeft
            else if (left > maxDragDomLeft)
                left = maxDragDomLeft

            if (-(top) > minDragDomTop)
                top = -minDragDomTop
            else if (top > maxDragDomTop)
              top = maxDragDomTop
            // 移动当前元素
            dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
        }
        document.onmouseup = function(e) {
            e.stopPropagation()
            e.preventDefault()
            document.onmousemove = null
            document.onmouseup = null
        }
    }
}
})
Last modification:May 7th, 2022 at 03:10 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment