js实现课程表拖拽功能

最近发现了一个用js实现拖拽的功能, 记录一下
之前工作中再有的系统上用到过类似的功能,但只会使用, 一直不知道怎么实现的

功能要求: 点击左侧各学科可随意拖动至右边放方格内, 可覆盖,可移除
js实现课程表拖拽功能_第1张图片
html部分, 给元素添加draggable = 'true’属性使其可拖拽, 其中data-drop, data-effect, data-drop为自定义属性, 可通过e.target.dataset获取值

<div>
     <h1 style="text-align: center">课程表</h1>
     <div class="container">
         <div class="left" data-drop="move">
             <div data-effect="copy" draggable="true" class="item">语文</div>
             <div data-effect="copy" draggable="true" class="item">数学</div>
             <div data-effect="copy" draggable="true" class="item">英语</div>
             <div data-effect="copy" draggable="true" class="item">政治</div>
             <div data-effect="copy" draggable="true" class="item">历史</div>
             <div data-effect="copy" draggable="true" class="item">地理</div>
             <div data-effect="copy" draggable="true" class="item">物理</div>
             <div data-effect="copy" draggable="true" class="item">化学</div>
             <div data-effect="copy" draggable="true" class="item">生物</div>
         </div>
         <div class="right">
             <table>
                 <tr>
                     <th>周一</th>
                     <th>周二</th>
                     <th>周三</th>
                     <th>周四</th>
                     <th>周五</th>
                     <th>周六</th>
                     <th>周日</th>
                 </tr>
                 <tr>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                 </tr>
                 <tr>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                 </tr>
                 <tr>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                 </tr>
                 <tr>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                 </tr>
                 <tr>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                 </tr>
                 <tr>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                     <td data-drop="copy"></td>
                 </tr>
             </table>
         </div>
     </div>
 </div>

css样式, 纯手写代码, 有公共部分的样式可以用css变量提出来, 懒得改了, 哈哈…
drop-over是动态添加的元素移入方格内的样式

    <style>
    .container {
      display: flex;
      margin: 50px;
    }

    .left {
      background-color: rgba(192, 192, 186, 0.867);
      padding: 30px 5px;
    }

    .item {
      width: 60px;
      height: 40px;
      text-align: center;
      line-height: 40px;
      border: 1px solid #000;
      background-color: #fff;
    }

    .right {
      margin-left: 50px;
      box-sizing: border-box;
      background-color: rgba(192, 192, 186, 0.867);
    }

    table {
      border: 1px solid black;
    }

    th {
      width: 60px;
      height: 40px;
      padding: 10px;
      margin: 2px;
      line-height: 40px;
      border-radius: 2px;
    }

    td {
      width: 60px;
      height: 40px;
      padding: 10px;
      margin: 2px;
      border-radius: 2px;
      background-color: #fff;
    }

    .drop-over {
      background-color: rgba(248, 248, 244, 0.867);
    }
  </style>

js部分是拖拽事件, 具体分为 点击开始时的状态ondragstart ()–>拖动时经过的位置ondragover ()–> 放下停留的位置ondrop ()


const container = document.querySelector('.container')

let source;
container.ondragstart = e => {
    // html中自定义属性 data-effect="copy" 值copy
    e.dataTransfer.effectAllowed = e.target.dataset.effect  // 获取元素自定义属性值
    source = e.target
    // console.log(e.target)
}

// 拖拽到哪个元素上方
container.ondragover = e => {
    e.preventDefault();  // 阻止浏览器默认行为
    // console.log(e.target)
}

function getDropNode(node) {
    while(node) {
        if(node.dataset && node.dataset.drop){
            return node
        }
        node = node.parentNode
    }
}

function clearDropStyle(){
    // 进入节点前先清除之前的drop-over样式
    document.querySelectorAll('.drop-over').forEach(node => {
        node.classList.remove('drop-over')
    })
}
container.ondragenter = e => {
    console.log(e.target.dataset)
    clearDropStyle()
    const dropNode = getDropNode(e.target)
    if(dropNode && dropNode.dataset.drop == e.dataTransfer.effectAllowed) {
        // 判断当前节点能接受目前拖拽的节点
        e.target.classList.add('drop-over')
    }
}

container.ondrop = e => {
    console.log(e.target)
    clearDropStyle()
    // 判断当前节点能接受目前拖拽的节点
    const dropNode = getDropNode(e.target)
    // debugger
    if(dropNode && dropNode.dataset.drop == e.dataTransfer.effectAllowed){
        // 根据自定义属性判断新增与移除
        if(dropNode.dataset.drop === 'copy'){
            dropNode.innerHTML = ''
            const cloned = source.cloneNode(true)
            cloned.dataset.effect = 'move'
            dropNode.appendChild(cloned)
        }else {
            // dropNode.dataset.drop === 'move' 
            source.remove()
        }
    }
}

js实现课程表拖拽功能_第2张图片

好好学习天天向上, 阿弥陀佛~

你可能感兴趣的:(javascript,css,html5)