代码之家  ›  专栏  ›  技术社区  ›  Cute dog

如何将文本与重新排序的图像相匹配?

  •  0
  • Cute dog  · 技术社区  · 1 年前

    我正在做一个项目,通过拖放重新排列33网格中的图像。
    当一个图像被拖放到另一个图像上时,它们 掉期头寸 我已经完成了这一部分,但我还需要在底部写一行文字,显示图像是如何重新排序的。因此,如果我交换项目1和5,文本将不再是:1,2,3,4,5,6,7,8,9,而是应该看起来像:5,2,3,4,1,6,7,8,8,9。

    我真的很难在物品交换后打印新的数字订单。以下是它的外观(盒子的颜色是随机选择的,没有重要性):

    Image re-ordering

    这是我的代码:

    //IMAGE ORDER
    
    let order = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    function showOrder(order) {
      document.getElementById('order').textContent = "Order: " + order.toString();
    }
    
    showOrder(order);
    
    //DRAG AND DROP SWAP
    
    var draggedImage = null;
    var items;
    
    function dragStart(e) {
      draggedImage = this;
      e.dataTransfer.effectAllowed = "move";
      e.dataTransfer.setData("item", this.innerHTML);
    }
    
    function dragOver(e) {
      e.preventDefault();
    
      e.dataTransfer.dropEffect = "move";
      return false;
    }
    
    function dragEnter(e) {
      this.classList.add("dragover");
    }
    
    function dragLeave(e) {
      this.classList.remove("dragover");
    }
    
    function drop(e) {
      e.stopPropagation();
    
      if (draggedImage != this) {
        draggedImage.innerHTML = this.innerHTML;
        draggedImage.setAttribute("data-item", this.innerHTML);
    
        let replacedImage = e.dataTransfer.getData("item");
        this.innerHTML = replacedImage;
        this.setAttribute("data-item", replacedImage);
      }
      return false;
    }
    
    function dragEnd(e) {
      items.forEach(function(item) {
        item.classList.remove("dragover");
      });
    }
    
    document.addEventListener("DOMContentLoaded", event => {
      items = document.querySelectorAll(".container .image");
    
      items.forEach(function(item) {
        item.addEventListener("dragstart", dragStart);
        item.addEventListener("dragenter", dragEnter);
        item.addEventListener("dragover", dragOver);
        item.addEventListener("dragleave", dragLeave);
        item.addEventListener("drop", drop);
        item.addEventListener("dragend", dragEnd);
      });
    
    });
    .container {
      width: 330px;
      height: 330px;
      background-color: lightgrey;
      display: flex;
      flex-wrap: wrap;
    }
    
    .image {
      width: 100px;
      height: 100px;
      background-color: #fff5d7;
      text-align: center;
      line-height: 100px;
      margin: 5px;
      cursor: move;
    }
    
    .order {
      width: 330px;
      height: 50px;
      background-color: lightgrey;
      margin-top: 10px;
      text-align: center;
      line-height: 50px;
      font-size: x-large;
      font-family: Helvetica;
    }
    <div class="container">
      <div draggable="true" class="image" id="1"><img src="Dummy billeder/nummer 1.png" width="100px"></div>
      <div draggable="true" class="image" id="2"><img src="Dummy billeder/nummer 2.png" width="100px"></div>
      <div draggable="true" class="image" id="3"><img src="Dummy billeder/nummer 3.png" width="100px"></div>
      <div draggable="true" class="image" id="4"><img src="Dummy billeder/nummer 4.png" width="100px"></div>
      <div draggable="true" class="image" id="5"><img src="Dummy billeder/nummer 5.png" width="100px"></div>
      <div draggable="true" class="image" id="6"><img src="Dummy billeder/nummer 6.png" width="100px"></div>
      <div draggable="true" class="image" id="7"><img src="Dummy billeder/nummer 7.png" width="100px"></div>
      <div draggable="true" class="image" id="8"><img src="Dummy billeder/nummer 8.png" width="100px"></div>
      <div draggable="true" class="image" id="9"><img src="Dummy billeder/nummer 9.png" width="100px"></div>
    </div>
    
    <div id="order"></div>

    我试着找到一种方法来识别网格中两个图像的位置,然后在一个数组中交换这些数字,当一个图像被丢弃但我无法使其工作时。

    1 回复  |  直到 1 年前
        1
  •  2
  •   Alexander Nenashev    1 年前

    将ID复制到您的可拖动内容中(),并在放置时更新订单框。

    document.querySelectorAll('.container .image').forEach(div => {
      div.querySelector('img').dataset.id = div.id;
    });
    
    const updateOrder = () => {
      document.getElementById('order').textContent = 'Order: ' + 
        [...document.querySelectorAll('.container .image img')].map(img => img.dataset.id).join(', ');
    };
    
    updateOrder();
    
    //DRAG AND DROP SWAP
    
    var draggedImage = null;
    var items;
    
    function dragStart(e) {
        draggedImage = this;
        e.dataTransfer.effectAllowed="move";
        e.dataTransfer.setData("item", this.innerHTML); 
    }
    
    function dragOver(e) {
        e.preventDefault();
    
        e.dataTransfer.dropEffect = "move";
        return false;
    }
    
    function dragEnter(e) {
        this.classList.add("dragover"); 
    }
    
    function dragLeave(e) {
        this.classList.remove("dragover"); 
    }
    
    function drop(e) {
        e.stopPropagation();
    
        if (draggedImage != this) {
            draggedImage.innerHTML = this.innerHTML; 
            draggedImage.setAttribute("data-item", this.innerHTML);
    
            let replacedImage = e.dataTransfer.getData("item"); 
            this.innerHTML = replacedImage;
            this.setAttribute("data-item", replacedImage);
            updateOrder();
            }
            return false;
    }
    
    function dragEnd(e) {
        items.forEach(function(item) {
            item.classList.remove("dragover"); 
        });
    }
    
    document.addEventListener("DOMContentLoaded", event => {
        items = document.querySelectorAll(".container .image");
    
        items.forEach(function(item) {
            item.addEventListener("dragstart", dragStart);
            item.addEventListener("dragenter", dragEnter);
            item.addEventListener("dragover", dragOver);
            item.addEventListener("dragleave", dragLeave);
            item.addEventListener("drop", drop);
            item.addEventListener("dragend", dragEnd);
        });
    });
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>My Website</title>
        <link rel="stylesheet" href="./style.css">
        <link rel="icon" href="./favicon.ico" type="image/x-icon">
        <style>
          .container {
              width: 330px;
              height: 330px;
              background-color: lightgrey;
              display: flex;
              flex-wrap: wrap;
          }
          .image {
            width: 100px;
            height: 100px;
            background-color: #fff5d7;
            text-align: center;
            line-height: 100px;
            margin: 5px;
            cursor: move;
          }
          .order {
            width: 330px;
            height: 50px;
            background-color: lightgrey;
            margin-top: 10px;
            text-align: center;
            line-height: 50px;
            font-size:x-large;
            font-family: Helvetica;
          }
      </style>
      </head>
      <body>
            <h1>Image re-ordering</h1>  
            <h2>Drag and drop to swap images</h2>
            <div class="container">
              <div draggable="true" class="image" id="1"><img src="Dummy billeder/nummer 1.png" width="100px"></div>
              <div draggable="true" class="image" id="2"><img src="Dummy billeder/nummer 2.png" width="100px"></div>
              <div draggable="true" class="image" id="3"><img src="Dummy billeder/nummer 3.png" width="100px"></div>
              <div draggable="true" class="image" id="4"><img src="Dummy billeder/nummer 4.png" width="100px"></div>
              <div draggable="true" class="image" id="5"><img src="Dummy billeder/nummer 5.png" width="100px"></div>
              <div draggable="true" class="image" id="6"><img src="Dummy billeder/nummer 6.png" width="100px"></div>
              <div draggable="true" class="image" id="7"><img src="Dummy billeder/nummer 7.png" width="100px"></div>
              <div draggable="true" class="image" id="8"><img src="Dummy billeder/nummer 8.png" width="100px"></div>
              <div draggable="true" class="image" id="9"><img src="Dummy billeder/nummer 9.png" width="100px"></div>
            </div>
            <div class="order" id="order"></div>
        <script src="gasflasker test.js"></script>
      </body>
    </html>

    但更好的方法是移动整个盒子:

    const $container = document.querySelector('.container');
    
    const updateOrder = () => {
      document.getElementById('order').textContent = 'Order: ' + 
        [...document.querySelectorAll('.container .image')].map(img => img.id).join(', ');
    };
    
    updateOrder();
    
    //DRAG AND DROP SWAP
    
    var draggedImage = null;
    var items;
    
    function dragStart(e) {
        draggedImage = this;
        e.dataTransfer.effectAllowed="move";
    }
    
    function dragOver(e) {
        e.preventDefault();
        e.dataTransfer.dropEffect = "move";
        return false;
    }
    
    function dragEnter(e) {
        this.classList.add("dragover"); 
    }
    
    function dragLeave(e) {
        this.classList.remove("dragover"); 
    }
    
    function drop(e) {
        e.stopPropagation();
    
        if (draggedImage != this) {
            const span = document.createElement('span');
            $container.insertBefore(span, draggedImage);
            $container.insertBefore(draggedImage, this.nextSibling);
            $container.insertBefore(this, span);
            span.remove();
            updateOrder();
        }
    }
    
    function dragEnd(e) {
        items.forEach(function(item) {
            item.classList.remove("dragover"); 
        });
    }
    
    document.addEventListener("DOMContentLoaded", event => {
        items = document.querySelectorAll(".container .image");
    
        items.forEach(function(item) {
            item.addEventListener("dragstart", dragStart);
            item.addEventListener("dragenter", dragEnter);
            item.addEventListener("dragover", dragOver);
            item.addEventListener("dragleave", dragLeave);
            item.addEventListener("drop", drop);
            item.addEventListener("dragend", dragEnd);
        });
    });
    <!文档类型html>
    <html lang=“en”>
    <头部>
    <meta字符集=“UTF-8”>
    <meta name=“viewport”content=“width=设备宽度,初始比例=1.0”>
    <meta-http-equiv=“X-UA-Compatible”content=“ie=edge”>
    <标题>我的网站</标题>
    <链接rel=“stylesheet”href=“./style.css”>
    <link rel=“icon”href=“./favicon.ico”type=“images/x-icon”>
    <样式>
    .容器{
    宽度:330px;
    高度:330px;
    背景颜色:浅灰色;
    显示:flex;
    柔性包裹:包裹;
    }
    .图像{
    宽度:100px;
    高度:100px;
    背景颜色:#fff5d7;
    文本对齐:居中;
    线条高度:100px;
    保证金:5倍;
    光标:移动;
    }
    .订单{
    宽度:330px;
    高度:50px;
    背景颜色:浅灰色;
    页边空白:10px;
    文本对齐:居中;
    线条高度:50px;
    字体大小:x-large;
    字体家族:Helvetica;
    }
    </样式>
    </头部>
    <身体>
    <h1>图像重新排序</h1>
    <h2>拖放可交换图像</h2>
    <div class=“container”>
    <div draggable=“true”class=“image”id=“1”><img src=“Dummy billeder/nummer 1.png”width=“100px”></div>
    <div draggable=“true”class=“image”id=“2”><img src=“Dummy billeder/nummer 2.png”width=“100px”></div>
    <div draggable=“true”class=“image”id=“3”><img src=“Dummy billeder/nummer 3.png”width=“100px”></div>
    <div draggable=“true”class=“image”id=“4”><img src=“Dummy billeder/nummer 4.png”width=“100px”></div>
    <div draggable=“true”class=“image”id=“5”><img src=“Dummy billeder/nummer 5.png”width=“100px”></div>
    <div draggable=“true”class=“image”id=“6”><img src=“Dummy billeder/nummer 6.png”width=“100px”></div>
    <div draggable=“true”class=“image”id=“7”><img src=“Dummy billeder/nummer 7.png”width=“100px”></div>
    <div draggable=“true”class=“image”id=“8”><img src=“Dummy billeder/nummer 8.png”width=“100px”></div>
    <div draggable=“true”class=“image”id=“9”><img src=“Dummy billeder/nummer 9.png”width=“100px”></div>
    </div>
    <div class=“order”id=“order”></div>
    <script src=“gasflasker test.js”></脚本>
    </身体>
    </html>

    如果你想变得非常酷,这里有一种无需手动操作DOM的反应式方法:

    const $container = document.querySelector('.container');
    
    let updatePromise;
    
    const ids = new Proxy([], {
      set(target, prop, val){
        // postpone the update with a microtask
        updatePromise ??= Promise.resolve().then(() => {
          updatePromise = null;
          document.getElementById('order').textContent = 'Order: ' + 
        target.join(', ');
          target.forEach(id => {
            $container.appendChild(document.getElementById(id));
          });
        });
        return Reflect.set(target, prop, val);
      }
    });
    
    ids.push(...[...document.querySelectorAll('.container .image')].map(img => img.id));
    
    let draggedImageId;
    
    const events = {
      dragstart: e => {
        draggedImageId = e.target.id;
        e.dataTransfer.effectAllowed = "move";
      },
      dragover: e => {
        e.preventDefault();
        e.dataTransfer.dropEffect = "move";  
      },
      dragenter: e => {
        const $image = e.target.closest('.image');
        $image?.id === draggedImageId || $image?.classList.add("dragover");
      },
      dragleave: e => e.target.classList.remove("dragover"),
      dragend: e => e.target.classList.remove("dragover"),
      drop: e => {
        if (draggedImageId !== e.target.id) {
            $container.querySelector('.dragover')?.classList.remove('dragover');
            const [from, to] = [ids.indexOf(draggedImageId), ids.indexOf(e.target.id)];
            [ids[from], ids[to]] = [ids[to], ids[from]];
        }
      }
    };
    
    for(const name in events){
      $container.addEventListener(name, events[name]);
    }
    .container {
      width: 330px;
      height: 330px;
      background-color: lightgrey;
      display: flex;
      flex-wrap: wrap;
    }
    .image.dragover{
      background-color: yellow;
    }
    .image {
      width: 100px;
      height: 100px;
      background-color: #fff5d7;
      text-align: center;
      line-height: 100px;
      margin: 5px;
      cursor: move;
    }
    .order {
      width: 330px;
      height: 50px;
      background-color: lightgrey;
      margin-top: 10px;
      text-align: center;
      line-height: 50px;
      font-size:x-large;
      font-family: Helvetica;
    }
    <div class="container">
      <div draggable="true" class="image" id="1">1</div>
      <div draggable="true" class="image" id="2">2</div>
      <div draggable="true" class="image" id="3">3</div>
      <div draggable="true" class="image" id="4">4</div>
      <div draggable="true" class="image" id="5">5</div>
      <div draggable="true" class="image" id="6">6</div>
      <div draggable="true" class="image" id="7">7</div>
      <div draggable="true" class="image" id="8">8</div>
      <div draggable="true" class="image" id="9">9</div>
    </div>
    <div class="order" id="order"></div>
        2
  •  2
  •   Roko C. Buljan    1 年前

    以下是一个更简单、更清晰的示例/建议,其中:

    • 在中存储索引 data atrribute的
    • 检索拖动元素和目标放置元素的索引
    • 交换DOM中的元素
    • 在给定这两个索引的情况下更新数组
    • 打印 顺序 大堆
    • 使用委派的事件(在包装上分配 .grid 元素)

    const elGrid = document.querySelector(".grid");
    const elOrder = document.querySelector("#order");
    const order = [...elGrid.children].map(el => el.dataset.index);
    let elDrag;
    
    const showOrder = () => elOrder.textContent = `Order: ${order}`;
    
    const events = {
      dragstart() { elDrag = this; },
      dragover(ev) { ev.preventDefault(); },
      drop() {
        if (elDrag === this) return;
        const ia = [...elGrid.children].indexOf(elDrag);
        const ib = [...elGrid.children].indexOf(this);
        elDrag.replaceWith(this.cloneNode(true));
        this.replaceWith(elDrag);
        [order[ia], order[ib]] = [order[ib], order[ia]];
        showOrder();
      }
    };
    
    [...elGrid.children].forEach((el, i) => el.draggable = true);
    ["dragstart", "dragover", "drop"].forEach(evName => {
      elGrid.addEventListener(evName, (ev) => {
        const elItem = ev.target.closest(".item");
        if (!elItem) return; 
        events[evName].call(elItem, ev);
      });
    });
    showOrder();
    .grid {
      display: inline-grid;
      grid-template-columns: repeat(3, 1fr);
      background-color: #d3d3d3;
      gap: 0.3rem;
      padding: 0.3rem;
    }
    
    .item {
      display: inline-flex;
      background-color: #fffac2;
      padding: 0.3rem;
    }
    <div class="grid">
      <div class="item" data-index="1"><img src="https://placehold.co/40x40/0bf/fff?text=1" alt="1"></div>
      <div class="item" data-index="2"><img src="https://placehold.co/40x40/0fb/fff?text=2" alt="2"></div>
      <div class="item" data-index="3"><img src="https://placehold.co/40x40/bf0/fff?text=3" alt="3"></div>
      <div class="item" data-index="4"><img src="https://placehold.co/40x40/b0f/fff?text=4" alt="4"></div>
      <div class="item" data-index="5"><img src="https://placehold.co/40x40/fb0/fff?text=5" alt="5"></div>
      <div class="item" data-index="6"><img src="https://placehold.co/40x40/f0b/fff?text=6" alt="6"></div>
      <div class="item" data-index="7"><img src="https://placehold.co/40x40/8f0/fff?text=7" alt="7"></div>
      <div class="item" data-index="8"><img src="https://placehold.co/40x40/f80/fff?text=8" alt="8"></div>
      <div class="item" data-index="9"><img src="https://placehold.co/40x40/08f/fff?text=9" alt="9"></div>
    </div>
    
    <div id="order"></div>