用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>
相关推荐
AOwhisky12 分钟前
Python 学习笔记(第五期)——组合数据类型:列表、元组、集合与字典精讲——核心知识点自测与详解
开发语言·笔记·python·学习·云计算
To_OC8 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
触底反弹9 小时前
一文搞懂 Tailwind CSS 弹性布局:从原理到实战
前端·css·html
灯澜忆梦9 小时前
GO_并发编程---定时器
开发语言·后端·golang
-银雾鸢尾-10 小时前
C#中的StringBuilder相关方法
开发语言·c#
To_OC10 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
小林ixn10 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
-银雾鸢尾-10 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
এ慕ོ冬℘゜11 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
大模型码小白11 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程