拖拽并复制到指定区域

拖拽并复制到指定区域

代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style>
      .test {
        width: 100px;
        height: 50px;
        background-color: red;
        border-radius: 50%;
        user-select: none;
      }
      
      .test2 {
        width: 300px;
        height: 300px;
        background-color: skyblue;
      }
    </style>
  </head>
  <body>
    <div class="test" id="testDiv">
      test
    </div>
    
    <div class="test2" id="canvasDom"></div>
  </body>
  
  <script>
    const bodyDom = document.querySelector('body')
    const canvasDom = document.getElementById('canvasDom')
    const tdd = document.getElementById('testDiv')
    let dragingDom = null
    let dragWrap = null
    tdd.addEventListener('mousedown', itemMouseDown)
    
    // 拖动
    function itemDrag(e) {
      const { clientX, clientY } = e
      if (dragingDom) {
        const { clientWidth, clientHeight } = dragingDom
        // 保证鼠标在拖动元素的中心点
        dragWrap.style.top = `${clientY - clientHeight / 2 }px`
        dragWrap.style.left = `${clientX - clientWidth / 2 }px`
      }
    }
    
    // 鼠标抬起事件
    function itemMouseUp(e) {
      // 删除临时复制dom
      bodyDom.removeChild(dragWrap)
      dragWrap = null
      // 回收
      document.addEventListener('mouseover', isInCanvas)
      document.removeEventListener('mousemove', itemDrag)
      document.removeEventListener('mouseup', itemMouseUp)
    }

    // 判断是否拖到指定dom区域
    function isInCanvas(e) {
      const { clientX, clientY } = e
      const { offsetLeft, offsetTop, offsetHeight, offsetWidth } = canvasDom

      // 判断是否超出范围
      let flag = (
        clientX > offsetLeft
        && clientX < offsetLeft + offsetWidth
        && clientY > offsetTop
        && clientY < offsetHeight + offsetTop
      )
      
      // 将dom元素置入指定区域
      if (dragingDom && flag) {
        e.target.appendChild(dragingDom)
      }
      // 回收
      dragingDom = null
      document.removeEventListener('mouseover', isInCanvas)
    }

    // 事件触发器
    function itemMouseDown(e) {
      const { clientX, clientY, target } = e
      const { clientWidth, clientHeight } = target
    
      // 点击待拖动元素时克隆一个新的dom元素,作为虚化显示效果
      const cloneT = e.target.cloneNode(true)
      dragWrap = document.createElement('div')
      dragWrap.style.opacity = 0.3
      dragWrap.style.position = 'absolute'
      dragWrap.style.cursor = 'pointer'
      dragWrap.style.top = `${clientY - clientHeight / 2 }px`
      dragWrap.style.left = `${clientX - clientWidth / 2 }px`
      dragWrap.appendChild(cloneT)
      dragingDom = cloneT
      bodyDom.appendChild(dragWrap)
    
      document.addEventListener('mousemove', itemDrag)
      document.addEventListener('mouseup', itemMouseUp)
    }
  </script>
</html>

演示图片

初始状态
拖动效果
松开鼠标

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要禁止vuedraggable拖拽出所在区域,可以使用`group`属性来指定同一区域的元素,然后使用`lockAxis`属性来锁定拖拽方向,再结合一些事件和方法来限制拖拽范围。 例如,假设我们有一个包含多个列表的父级容器,每个列表都可以通过vuedraggable进行拖拽排序,我们可以在每个列表上添加以下属性: ```html <draggable v-model="list" :group="{name:'items', pull:'clone', put:false}" :lock-axis="true" @start="dragStart" @end="dragEnd" :move="checkMove"> <!-- 列表内容 --> </draggable> ``` 其中,`group`属性中的`name`值要相同,表示同一区域;`pull`值为`clone`表示可以拖拽复制,`put`值为`false`表示不能将元素拖到其他列表中。 然后,我们可以使用`lockAxis`属性来锁定拖拽方向,例如: ```html <draggable v-model="list" :group="{name:'items', pull:'clone', put:false}" :lock-axis="true" @start="dragStart" @end="dragEnd" :move="checkMove"> <!-- 列表内容 --> </draggable> ``` 在`dragStart`事件中,我们可以记录当前列表的位置和大小,例如: ```js dragStart(event) { this.containerRect = event.target.getBoundingClientRect() } ``` 在`dragEnd`事件中,我们可以清空位置和大小记录,例如: ```js dragEnd() { this.containerRect = null } ``` 最后,在`move`方法中,我们可以判断拖拽元素是否超出当前列表的范围,然后返回`false`来禁止拖拽,例如: ```js checkMove(event) { if (!this.containerRect) return true const dragRect = event.draggedContext.element.getBoundingClientRect() return ( dragRect.left >= this.containerRect.left && dragRect.top >= this.containerRect.top && dragRect.right <= this.containerRect.right && dragRect.bottom <= this.containerRect.bottom ) } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值