用html+jq实现元素的拖动效果——js基础积累

html+jq实现元素的拖动效果

效果图如下:

将【item10】拖动到【item1】前面

直接上代码:

html部分

js 复制代码
<ul id="sortableList">
  <li id="item1" class="w1" draggable="true">Item 1</li>
  <li id="item2" class="w2" draggable="true">Item 2</li>
  <li id="item3" class="w3" draggable="true">Item 3</li>
  <li id="item4" class="w1" draggable="true">Item 4</li>
  <li id="item5" class="w1" draggable="true">Item 5</li>
  <li id="item6" class="w2" draggable="true">Item 6</li>
  <li id="item7" class="w3" draggable="true">Item 7</li>
  <li id="item8" class="w1" draggable="true">Item 8</li>
  <li id="item9" class="w2" draggable="true">Item 9</li>
  <li id="item10" class="w3" draggable="true">Item 10</li>
</ul>

js部分

js 复制代码
 <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
      document.addEventListener('DOMContentLoaded', function () {
        const sortableList = document.getElementById('sortableList');
        const items = sortableList.querySelectorAll('li');

        items.forEach((item) => {
          item.addEventListener('dragstart', dragStart);
          item.addEventListener('dragover', dragOver);
          item.addEventListener('drop', drop);
          item.addEventListener('dragenter', dragEnter);
          item.addEventListener('dragleave', dragLeave);
        });

        function dragStart(e) {
          e.dataTransfer.setData('text/plain', e.target.id);
          // setTimeout(() => {
          //     e.target.classList.add('hide');
          // }, 0);
          console.log('Drag started:', e.target.id);
        }

        function dragOver(e) {
          e.preventDefault();
          e.target.classList.add('over');
          console.log('Drag over:', e.target.id);
        }

        function dragEnter(e) {
          e.preventDefault();
          console.log('Drag enter:', e.target.id);
        }

        function dragLeave(e) {
          e.target.classList.remove('over');
          console.log('Drag leave:', e.target.id);
        }

        function drop(e) {
          e.preventDefault();
          const draggedItemId = e.dataTransfer.getData('text/plain');
          const draggedItem = document.getElementById(draggedItemId);
          const targetItem = e.target;

          if (targetItem !== draggedItem) {
            const targetIndex = Array.from(items).indexOf(targetItem);
            const draggedIndex = Array.from(items).indexOf(draggedItem);

            if (targetIndex > draggedIndex) {
              targetItem.parentNode.insertBefore(
                draggedItem,
                targetItem.nextSibling
              );
            } else {
              targetItem.parentNode.insertBefore(draggedItem, targetItem);
            }
          }

          e.target.classList.remove('over');
          draggedItem.classList.remove('hide');
          console.log('Drop:', e.target.id);
          console.log('在这里加检查宽度方法');
          checkWidth();
        }
      });

      // 检查宽度
      function checkWidth(first = true) {
        //清空空白块
        if (first) $('#sortableList li.box').remove();
        //盒子宽度
        let boxWidth = document.getElementById('sortableList').offsetWidth;
        //当前li行的宽度
        let rowLiWidth = 0;
        //循环li
        for (let i = 0; i < $('#sortableList li').length; i++) {
          var outerWidthWithMargin = $('#sortableList li')
            .eq(i)
            .outerWidth(true);
          var itemWidth = parseFloat(outerWidthWithMargin.toFixed(2));
          console.log(i, rowLiWidth, itemWidth);
          //当前li行的宽度+当前项宽度
          let RAW = rowLiWidth + itemWidth;
          //如果当前li行的宽度+当前项宽度大于盒子宽度,则添加空白块,并重新计算。
          //3是容错宽度。
          if (
            RAW >= boxWidth ||
            (RAW - boxWidth >= -3 && RAW - boxWidth <= 3)
          ) {
            //宽度大于盒子宽度,则添加空白块,并重新计算。
            if (RAW > boxWidth) {
              let thisWidth = boxWidth - rowLiWidth;
              if (thisWidth > 3) {
                $('#sortableList li')
                  .eq(i)
                  .before(`<li class="box" style="width:${thisWidth}px"></li>`);
                rowLiWidth = 0; //重新计算。
                checkWidth(false);
                break;
              }
            }
            rowLiWidth = 0; //重新计算。
          } else {
            rowLiWidth += itemWidth;
          }
          if (i == $('#sortableList li').length - 1) {
            let thisWidth = boxWidth - rowLiWidth;
            $('#sortableList li')
              .eq(i)
              .after(`<li class="box" style="width:${thisWidth}px"></li>`);
            break;
          }
        }
      }
    </script>

css部分

style 复制代码
 <style>
      * {
        box-sizing: border-box;
      }
      #sortableList {
        list-style-type: none;
        padding: 0;
        display: flex;
        flex-wrap: wrap;
        position: relative;
      }
      #sortableList:after {
        border-top: none;
        border-left: none;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 0;
        pointer-events: none;
      }
      #sortableList:after,
      #sortableList li:after {
        content: '';
        border: 1px solid #eee;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 0;
        pointer-events: none;
      }
      #sortableList li:after {
        border-right: none;
        border-bottom: none;
      }
      #sortableList li {
        padding: 8px;
        background-color: #fff;
        cursor: move;
        position: relative;
      }
      #sortableList li.box {
        background-color: #fff;
      }
      #sortableList li.over {
        border: 2px dashed #000;
      }
      #sortableList li.w1 {
        width: 20%;
      }
      #sortableList li.w2 {
        width: 30%;
      }
      #sortableList li.w3 {
        width: 50%;
      }
      #sortableList li.hide {
        display: none;
      }
    </style>

完整版代码如下:

js 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <style>
      * {
        box-sizing: border-box;
      }
      #sortableList {
        list-style-type: none;
        padding: 0;
        display: flex;
        flex-wrap: wrap;
        position: relative;
      }
      #sortableList:after {
        border-top: none;
        border-left: none;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 0;
        pointer-events: none;
      }
      #sortableList:after,
      #sortableList li:after {
        content: '';
        border: 1px solid #eee;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 0;
        pointer-events: none;
      }
      #sortableList li:after {
        border-right: none;
        border-bottom: none;
      }
      #sortableList li {
        padding: 8px;
        background-color: #fff;
        cursor: move;
        position: relative;
      }
      #sortableList li.box {
        background-color: #fff;
      }
      #sortableList li.over {
        border: 2px dashed #000;
      }
      #sortableList li.w1 {
        width: 20%;
      }
      #sortableList li.w2 {
        width: 30%;
      }
      #sortableList li.w3 {
        width: 50%;
      }
      #sortableList li.hide {
        display: none;
      }
    </style>
  </head>
  <body>
    <ul id="sortableList">
      <li id="item1" class="w1" draggable="true">Item 1</li>
      <li id="item2" class="w2" draggable="true">Item 2</li>
      <li id="item3" class="w3" draggable="true">Item 3</li>
      <li id="item4" class="w1" draggable="true">Item 4</li>
      <li id="item5" class="w1" draggable="true">Item 5</li>
      <li id="item6" class="w2" draggable="true">Item 6</li>
      <li id="item7" class="w3" draggable="true">Item 7</li>
      <li id="item8" class="w1" draggable="true">Item 8</li>
      <li id="item9" class="w2" draggable="true">Item 9</li>
      <li id="item10" class="w3" draggable="true">Item 10</li>
    </ul>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
      document.addEventListener('DOMContentLoaded', function () {
        const sortableList = document.getElementById('sortableList');
        const items = sortableList.querySelectorAll('li');

        items.forEach((item) => {
          item.addEventListener('dragstart', dragStart);
          item.addEventListener('dragover', dragOver);
          item.addEventListener('drop', drop);
          item.addEventListener('dragenter', dragEnter);
          item.addEventListener('dragleave', dragLeave);
        });

        function dragStart(e) {
          e.dataTransfer.setData('text/plain', e.target.id);
          // setTimeout(() => {
          //     e.target.classList.add('hide');
          // }, 0);
          console.log('Drag started:', e.target.id);
        }

        function dragOver(e) {
          e.preventDefault();
          e.target.classList.add('over');
          console.log('Drag over:', e.target.id);
        }

        function dragEnter(e) {
          e.preventDefault();
          console.log('Drag enter:', e.target.id);
        }

        function dragLeave(e) {
          e.target.classList.remove('over');
          console.log('Drag leave:', e.target.id);
        }

        function drop(e) {
          e.preventDefault();
          const draggedItemId = e.dataTransfer.getData('text/plain');
          const draggedItem = document.getElementById(draggedItemId);
          const targetItem = e.target;

          if (targetItem !== draggedItem) {
            const targetIndex = Array.from(items).indexOf(targetItem);
            const draggedIndex = Array.from(items).indexOf(draggedItem);

            if (targetIndex > draggedIndex) {
              targetItem.parentNode.insertBefore(
                draggedItem,
                targetItem.nextSibling
              );
            } else {
              targetItem.parentNode.insertBefore(draggedItem, targetItem);
            }
          }

          e.target.classList.remove('over');
          draggedItem.classList.remove('hide');
          console.log('Drop:', e.target.id);
          console.log('在这里加检查宽度方法');
          checkWidth();
        }
      });

      // 检查宽度
      function checkWidth(first = true) {
        //清空空白块
        if (first) $('#sortableList li.box').remove();
        //盒子宽度
        let boxWidth = document.getElementById('sortableList').offsetWidth;
        //当前li行的宽度
        let rowLiWidth = 0;
        //循环li
        for (let i = 0; i < $('#sortableList li').length; i++) {
          var outerWidthWithMargin = $('#sortableList li')
            .eq(i)
            .outerWidth(true);
          var itemWidth = parseFloat(outerWidthWithMargin.toFixed(2));
          console.log(i, rowLiWidth, itemWidth);
          //当前li行的宽度+当前项宽度
          let RAW = rowLiWidth + itemWidth;
          //如果当前li行的宽度+当前项宽度大于盒子宽度,则添加空白块,并重新计算。
          //3是容错宽度。
          if (
            RAW >= boxWidth ||
            (RAW - boxWidth >= -3 && RAW - boxWidth <= 3)
          ) {
            //宽度大于盒子宽度,则添加空白块,并重新计算。
            if (RAW > boxWidth) {
              let thisWidth = boxWidth - rowLiWidth;
              if (thisWidth > 3) {
                $('#sortableList li')
                  .eq(i)
                  .before(`<li class="box" style="width:${thisWidth}px"></li>`);
                rowLiWidth = 0; //重新计算。
                checkWidth(false);
                break;
              }
            }
            rowLiWidth = 0; //重新计算。
          } else {
            rowLiWidth += itemWidth;
          }
          if (i == $('#sortableList li').length - 1) {
            let thisWidth = boxWidth - rowLiWidth;
            $('#sortableList li')
              .eq(i)
              .after(`<li class="box" style="width:${thisWidth}px"></li>`);
            break;
          }
        }
      }
    </script>
  </body>
</html>
相关推荐
以卿a25 分钟前
C++ 模板初阶
开发语言·c++
s:10329 分钟前
【框架】参考 Spring Security 安全框架设计出,轻量化高可扩展的身份认证与授权架构
java·开发语言
道不尽世间的沧桑1 小时前
第17篇:网络请求与Axios集成
开发语言·前端·javascript
久绊A1 小时前
Python 基本语法的详细解释
开发语言·windows·python
bin91534 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
软件黑马王子5 小时前
C#初级教程(4)——流程控制:从基础到实践
开发语言·c#
闲猫5 小时前
go orm GORM
开发语言·后端·golang
晴空万里藏片云6 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
曦月合一6 小时前
html中iframe标签 隐藏滚动条
前端·html·iframe
奶球不是球6 小时前
el-button按钮的loading状态设置
前端·javascript