js实现一个高效无延迟拖动元素的方案

1,498 阅读1分钟

如题,分析,涉及到两个角色,一个是可拖动的元素,取名为节点。另一个是什么呢?如果一个元素可拖动,当它停止的时候,总要依附于什么,这个角色取名为画布。

通过场景,分析出了两个角色,进而可以得出两个角色具备的功能。

节点:

  • 可被拖动。
  • 拖动开始事件。
  • 拖动结束事件。

画布:

  • 元素在其中可被放置。

如上,核心功能已经确定,且看代码如何简单。

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Document</title>
  <style> 
    #canvas {
      width: 500px;
      height: 500px;
      border: 1px solid red;
      position: relative;
    }
    .node {
      width: 100px;
      height: 100px;
      border: 1px solid green;
      position: absolute;
    }
  </style>
</head>
<body>
  <div id="canvas">
    <div class="node">我可以被拖动</div>
  </div>

  <script>
    const canvas = document.querySelector('#canvas') // 画布
    const node = document.querySelector('.node') // 节点

    class Drag {
      constructor (canvas, node) {
        this.canvas = canvas
        this.canvas.ondragover = event => event.preventDefault() // 设置画布可被拖入元素

        this.node = node
        node.setAttribute('draggable', true) // 设置元素可被拖动
    
        node.addEventListener('dragstart', this.dragstart.bind(this))
        node.addEventListener('dragend', event => this.dragend(event))
      }
    
      dragstart (event) {
        this.ondragstartX = event.x
        this.ondragstartY = event.y
        this.node.style.opacity = 0.382
      }
    
      dragend (event) {
        const offsetX = event.x - this.ondragstartX
        const offsetY = event.y - this.ondragstartY
    
        const node = this.node

        const left = node.offsetLeft + offsetX
        const top = node.offsetTop + offsetY
    
        node.style.left = left + 'px'
        node.style.top = top + 'px'
    
        node.style.opacity = 1
      }
    }

    // 设置可拖动的元素及画布
    new Drag(canvas, node)
  </script>
</body>
</html>

以上,是全部实现,全部拷贝代码,可以轻松验证。如果有疑问,留言讨论。