首页 > 解决方案 > 如何拥有可拖放的行列表?

问题描述

我正在开发一个可以在容器之间启用拖放操作的原型。但是,我有一个冲突案例:

我在下面的卡盘中收集了可测试的代码;请让我知道你认为我该如何解决这个问题。

<!DOCTYPE html>
<html>
  <head>
    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        overflow: hidden;
      }

      .lang1Container {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
      }

      .meaningContainer {
        border: 1px solid rgba(15, 15, 15, 0.2);
        box-shadow: 0px 0px 5px 10px rgba(138, 57, 57, 0.2);
      }

      .lang1Item {
        width: 300px;
        height: 20px;
        position: absolute;
        background-color: #f44336;
        color: #ffffff;
        font-family: Oxygen, sans-serif;
        font-size: px;
        padding: 7px;
        box-shadow: inset 1px 1px 10px 0 rgba(138, 57, 57, 0.2);
        border-radius: 3px;
        cursor: pointer;
      }

      .snap {
        width: 301px;
        height: 30px;
        margin-top: 25px;
        margin-bottom: 25px;
      }

      .over {
        background-color: rgb(158, 89, 87, 0.2);
        border: 1px solid #7c5b59;
        border-radius: 3px;
        border-style: dashed;
      }
    </style>
  </head>
  <body>
    <div style="display: flex; flex-direction: column">
      <div
        id="lang1MeaningContainer"
        style="
          background-color: bisque;
          min-width: 300px;
          min-height: 400px;
          border-color: red;
          border-style: dashed;
          margin: 10px;
        "
      >
        <div class="header">lang1MeaningContainer - Meaning Container</div>
        <div class="snap"></div>
        <div class="snap"></div>
        <div class="snap"></div>
        <div class="snap"></div>
        <div class="snap"></div>
        <div class="snap"></div>
      </div>

      <div
        id="lang1Container"
        style="
          background-color: bisque;
          min-width: 300px;
          min-height: 400px;
          border-color: red;
          border-style: dashed;
          margin: 10px;
          display: flex;
          flex-direction: column;
        "
      >
        <div class="header">lang1Container - English Words</div>
        <div id="item1" class="lang1Item">Lang Item 1</div>
        <div id="item2" class="lang1Item">Lang Item 2</div>
        <span id="item3" class="lang1Item">Lang Item 3</span>
        <span id="item4" class="lang1Item">Lang Item 4</span>
      </div>
    </div>
    <script>
      let lang1Container = document.getElementById("lang1Container");
      let meaningContainer = document.getElementById("lang1MeaningContainer");
      let lang1Items = document.getElementsByClassName("lang1Item");

      console.log("length:" + lang1Items.length);
      for (let i = 0; i < lang1Items.length; i++) {
        let item = lang1Items[i];
        item.addEventListener("mousedown", (e) => {
          onMouseDown(e, item);
        });
        document.body.addEventListener("mousemove", (e) => {
          onMouseMove(e, item);
        });
        item.addEventListener("mouseup", (e) => {
          onMouseUp(e, item);
        });
      }

      let mouseOffset = { x: 0, y: 0 };
      let isMouseDown = false;

      // for (let i = 0; i < 6; i++) {
      //   let snap = document.createElement("div");
      //   snap.className = "snap";
      //   meaningContainer.appendChild(snap);
      // }
      let doElsCollide = function (el1, el2) {
        el1.offsetBottom = el1.offsetTop + el1.offsetHeight;
        el1.offsetRight = el1.offsetLeft + el1.offsetWidth;
        el2.offsetBottom = el2.offsetTop + el2.offsetHeight;
        el2.offsetRight = el2.offsetLeft + el2.offsetWidth;

        return !(
          el1.offsetBottom < el2.offsetTop ||
          el1.offsetTop > el2.offsetBottom ||
          el1.offsetRight < el2.offsetLeft ||
          el1.offsetLeft > el2.offsetRight
        );
      };
      function snapMeaning(item, container) {
        let box = container.getBoundingClientRect();
        item.style.left = box.x + "px";
        item.style.top = box.y + "px";
      }
      function onMouseDown(e, item) {
        isMouseDown = true;

        mouseOffset = {
          x: item.offsetLeft - e.clientX,
          y: item.offsetTop - e.clientY,
        };

        item.style.backgroundColor = "red";
      }
      function onMouseMove(e, item) {
        e.preventDefault();
        if (isMouseDown) {
          item.style.left = e.clientX + mouseOffset.x + "px";
          let tmpStyle = getComputedStyle(item);
          let strMarginTop = tmpStyle.marginTop;
          let tmpMarginTop = strMarginTop.replace("px", "");
          item.style.top = e.clientY - tmpMarginTop + mouseOffset.y + "px"; // zero margin is used in CSS definition, otherwise margin amount need to be subtracted from the item.style.top value to have a proper event reaction. UU

          // checking collusions with snaps
          let snaps = document.getElementsByClassName("snap");
          //console.log("Started checking");
          for (let i = 0; i < snaps.length; i++) {
            if (doElsCollide(item, snaps[i])) {
              snaps[i].className = "snap over";
              //console.log("[" + Date.now() + "]", "Collides with " + i);
            } else {
              snaps[i].className = "snap";
            }
          }
          //console.log("Ended checking");
        }
      }
      function onMouseUp(e, item) {
        isMouseDown = false;

        let snaps = document.getElementsByClassName("snap");
        for (let i = 0; i < snaps.length; i++) {
          if (doElsCollide(item, snaps[i])) {
            snapMeaning(item, snaps[i]);
          }
        }
        item.className = "lang1Item";
      }
    </script>
  </body>
</html>

标签: javascriptcssflexbox

解决方案


推荐阅读