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

发布于:2024-12-06 ⋅ 阅读:(34) ⋅ 点赞:(0)

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

效果图如下:
在这里插入图片描述
将【item10】拖动到【item1】前面
在这里插入图片描述
直接上代码:

html部分

<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部分

 <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>
      * {
        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>

完整版代码如下:

<!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>

网站公告

今日签到

点亮在社区的每一天
去签到