vue 拖拽移动指令 v-move

/**
 * 拖拽指令
 * 使用方式:
 * v-move="{ moveDomClass: 'el-dialog', moveOrigin: 'el-dialog__header', moveOut: false, moveOpen:true,notMoveOrigin }"
 * moveDomClass:需要拖拽的节点类名,默认为v-move绑定的节点。
 * moveOrigin:节点可拖拽的区域类名,默认为v-move绑定的节点。
 * moveOut:拖拽的节点是否可以托出视口。默认false,不能
 * moveStop: 默认为空,若是把 moveStop 改成 true 那么节点就拖拽不动了
 * notMoveOrigin: 默认为空 ,若设置 那么就会排除 el-dialog__header 内同类名的节点,点击它是不能启动拖拽的
 */
/**节流 */
const rafThrottle = (callBack?) => {
    let locked = false
    return function(...args) {
        if (locked) return
        locked = true
        window.requestAnimationFrame(_ => {
            callBack.apply(this, args)
            locked = false
        })
    }
}
/** 获取偏移距离 */
function getMoveSpace(moveDom, moveOut, space, type) {
    if (!moveOut) {
        const width = moveDom.clientWidth
        const height = moveDom.clientHeight
        const { clientWidth, clientHeight } = document.body
        if (space < 0) return 0
        if (type === 'y' && space + height > clientHeight) return clientHeight - height
        if (type === 'x' && space + width > clientWidth) return clientWidth - width
    }
    return space
}
export default {
    inserted: (el, binding, vnode) => {
        el.bindValue = binding.value
        const { moveDomClass, moveOrigin, moveOut, notMoveOrigin } = binding.value
        let moveDom = el
        let moveOriginDom = el
        let notMoveOriginDom
        let offsetX, offsetY
        if (moveDomClass) moveDom = el.querySelector(`.${moveDomClass}`)
        if (moveOrigin) moveOriginDom = el.querySelector(`.${moveOrigin}`)
        if (notMoveOrigin) notMoveOriginDom = el.querySelector(`.${notMoveOrigin}`)
        moveOriginDom?.style?.setProperty?.('cursor', 'grab')
        const userSelect = document.body.style['user-select']
        // 鼠标按下
        function onmousedown(e) {
            if (!moveOriginDom?.contains?.(e.target) || notMoveOriginDom?.contains(e.target)) return
            const parentRect = moveDom.getBoundingClientRect()
            offsetX = e.pageX - parentRect.left
            offsetY = e.pageY - parentRect.top
            // 绑定鼠标移动
            window.addEventListener('mousemove', onmousemove)
        }
        // 鼠标松开
        function onmouseup(e) {
            // 移除鼠标移动
            window.removeEventListener('mousemove', onmousemove)
            document.body.style.setProperty('user-select', userSelect || 'auto')
        }
        // 鼠标移动
        const onmousemove = rafThrottle(e => {
            if (el.bindValue?.moveStop) {
                window.removeEventListener('mousemove', onmousemove)
                return
            }
            const { pageX, pageY } = e
            const { clientWidth, clientHeight } = document.body
            const moveX = pageX - offsetX
            const moveY = pageY - offsetY
            // 移出屏幕
            if (pageX < 0 || pageY < 0 || pageX > clientWidth || pageY > clientHeight) return
            document.body.style.setProperty('user-select', 'none')
            moveDom.style.setProperty('margin', 0)
            moveDom.style.setProperty('left', `${getMoveSpace(moveDom, moveOut, moveX, 'x')}px`)
            moveDom.style.setProperty('top', `${getMoveSpace(moveDom, moveOut, moveY, 'y')}px`)
            moveDom.style.setProperty('position', 'fixed')
        })
        // 绑定鼠标按下
        moveDom.addEventListener('mousedown', onmousedown)
        // 绑定鼠标松开
        window.addEventListener('mouseup', onmouseup)
    },
    update: (el, binding, vnode) => {
        el.bindValue = binding.value
    },
}

使用方式:
 

<template>
    <el-dialog
        v-move="{ moveDomClass: 'el-dialog', moveOrigin: 'el-dialog__header', notMoveOrigin: 'el-dialog__headerbtn', moveOut: false, moveOpen: moveOpen }"
        class="sg-dialog publicity-original__dialog"
        title="查看原文-处罚结果信息公开内容"
        visible
        :close-on-click-modal="false"
        @close="cancel"
        :modal="false"
    >
        <div>
            {{ publicityContentInitText }}
        </div>
    </el-dialog>
</template>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现小方块拖拽效果,可以自定义一个指令并使用Vue的事件绑定和DOM操作来实现。 以下是实现小方块拖拽效果的代码示例: ```html <template> <div class="drag-box" v-draggable>拖拽我</div> </template> <script> export default { directives: { draggable: { bind(el) { let isDragging = false; let currentX; let currentY; let initialX; let initialY; let xOffset = 0; let yOffset = 0; el.addEventListener("mousedown", dragStart); el.addEventListener("mouseup", dragEnd); el.addEventListener("mousemove", drag); function dragStart(e) { initialX = e.clientX - xOffset; initialY = e.clientY - yOffset; if (e.target === el) { isDragging = true; } } function dragEnd(e) { initialX = currentX; initialY = currentY; isDragging = false; } function drag(e) { if (isDragging) { e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; xOffset = currentX; yOffset = currentY; setTranslate(currentX, currentY, el); } } function setTranslate(xPos, yPos, el) { el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`; } }, }, }, }; </script> <style> .drag-box { width: 100px; height: 100px; background-color: red; color: white; text-align: center; line-height: 100px; cursor: move; } </style> ``` 在上面的代码中,我们定义了一个名为`draggable`的指令,并在绑定时添加了事件监听器以处理拖动过程中的鼠标事件。在`dragStart`函数中,我们记录了初始的鼠标坐标和元素的偏移量,并设置`isDragging`变量为`true`。在`dragEnd`函数中,我们将元素的位置更新为当前位置,并将`isDragging`变量设置为`false`。在`drag`函数中,我们计算当前鼠标的位置,并根据偏移量以及当前位置计算出元素应该被移动到的位置,并更新元素的位置。 最后,我们在模板中使用`v-draggable`指令绑定到小方块元素上,这样就实现了小方块的拖拽效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值