用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>
相关推荐
Lyyaoo.6 小时前
【JAVA基础面经】JVM的内存模型
java·开发语言·jvm
杨凯凡6 小时前
【017】泛型与通配符:API 设计里怎么用省心
java·开发语言
2401_8734794013 小时前
如何利用IP查询定位识别电商刷单?4个关键指标+工具配置方案
开发语言·tcp/ip·php
我爱cope13 小时前
【从0开始学设计模式-10| 装饰模式】
java·开发语言·设计模式
菜鸟学Python13 小时前
Python生态在悄悄改变:FastAPI全面反超,Django和Flask还行吗?
开发语言·python·django·flask·fastapi
浪浪小洋14 小时前
c++ qt课设定制
开发语言·c++
charlie11451419114 小时前
嵌入式C++工程实践第16篇:第四次重构 —— LED模板,从通用GPIO到专用抽象
c语言·开发语言·c++·驱动开发·嵌入式硬件·重构
故事和你9114 小时前
洛谷-数据结构1-4-图的基本应用1
开发语言·数据结构·算法·深度优先·动态规划·图论
幺风15 小时前
Claude Code 源码分析 — Tool/MCP/Skill 可扩展工具系统
前端·javascript·ai编程
程序猿编码15 小时前
给你的网络流量穿件“隐形衣“:手把手教你用对称加密打造透明安全隧道
linux·开发语言·网络·安全·linux内核