为什么元素最终会出现在网格之外而不是交换?

问题描述 投票:0回答:0

有一个网格,其中有一个谜题,可以通过拖放来交换方块,以便重新创建显示在网格旁边/下方的图像。但是,当用户快速拖放一个方块时,网格会被打乱,并且某些方块最终会出现在网格之外。然而游戏仍然有效,用户仍然可以将网格中的方块与网格外的方块交换。网格外的正方形原本应该在的地方只有空白。

我尝试过使用不同的拖放方法,但尽管如此,这个错误仍然出现,所以问题不在于拖放方法。

我该如何解决这个问题?

JS 小提琴:https://jsfiddle.net/c5ayk3re/

let images = [{
    src: "https://picsum.photos/200",
    title: "the first image"
  },
  {
    src: "https://picsum.photos/200",
    title: "the second image"
  },
  {
    src: "https://picsum.photos/200",
    title: "the woffle image"
  },
  {
    src: "https://picsum.photos/200",
    title: "the puzzel image"
  },
  {
    src: "https://picsum.photos/200",
    title: "the lone image"
  },
  {
    src: "https://picsum.photos/200",
    title: "the noone image"
  },
  {
    src: "https://picsum.photos/200",
    title: "the ,mdp image"
  },
  {
    src: "https://picsum.photos/200",
    title: "the dfkg image"
  },
  {
    src: "https://picsum.photos/200",
    title: "the title image"
  },
];
let dragindex = 0;
let steps = 0;
let draged = null;
let sortUl = document.querySelector(".sort");
let sortLi;
let actImg = document.querySelector(".act-img img");
let levels = Array.from(document.querySelectorAll(".show span"));
let start = document.querySelector(".show button");
// on start game

// handle active function
let handleActive = function(span) {
  span.currentTarget.parentElement
    .querySelectorAll(".active")
    .forEach(ele => {
      ele.classList.remove("active");
    });
  span.currentTarget.classList.add("active");
};
levels.forEach(level => {
  level.addEventListener("click", e => {
    handleActive(e);
    window.sessionStorage.setItem("level", e.currentTarget.dataset.mode);
    window.sessionStorage.setItem("level1", e.currentTarget.textContent);
  });
});
let unshuffled = [];
let shuffled = [];
let arr = [];
let sizeUi = 400;
let actLevel = document.querySelector(".act-level span");
start.addEventListener("click", () => {
  document.querySelector(".show").style.left = "-100%";
  actLevel.textContent = window.sessionStorage.getItem("level1");
  const randomImg = images[Math.floor(Math.random() * images.length)].src;
  actImg.src = randomImg;
  let level = window.sessionStorage.getItem("level");
  if (!level) level = 3;
  let size = level * 100;
  let percent = 100 / (level - 1);
  unshuffled = [];
  arr = [];
  for (i = 0; i < level * level; i++) {
    let x = percent * (i % level);
    let y = percent * Math.floor(i / level);
    const li = document.createElement("li");
    li.style.cssText = "background-image: url(" + randomImg + ");";

    li.setAttribute("data-num", i);
    li.setAttribute("draggable", "true");
    li.setAttribute("id", `id-${i}`);

    li.style.backgroundSize = size + "%";
    li.style.backgroundPosition = x + "%" + y + "%";

    if (window.innerWidth < 315) {
      li.style.width = 225 / level + "px";
      li.style.height = 225 / level + "px";
    } else if (window.innerWidth < 375) {
      li.style.width = 250 / level + "px";
      li.style.height = 250 / level + "px";
    } else if (window.innerWidth < 450) {
      li.style.width = 300 / level + "px";
      li.style.height = 300 / level + "px";
    } else if (window.innerWidth < 550) {
      li.style.width = 350 / level + "px";
      li.style.height = 350 / level + "px";
    } else {
      li.style.width = 400 / level + "px";
      li.style.height = 400 / level + "px";
    }

    unshuffled.push(li);
    arr.push(li);
  }
  for (let i = unshuffled.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    const temp = unshuffled[i];
    unshuffled[i] = unshuffled[j];
    unshuffled[j] = temp;
  }
  unshuffled.forEach(e => {
    sortUl.appendChild(e);
  });
});
// let act_arr = Array.from(document.querySelectorAll(".sort li"));

/////////////////////////////////////
sortUl.addEventListener("dragstart", dragstart);
sortUl.addEventListener("dragover", dragover);
sortUl.addEventListener("drop", drop);

function dragstart(e) {
  e.dataTransfer.setData("text/plain", e.target.id);
}

function dragover(e) {
  e.preventDefault();
}

function drop(e) {
  e.preventDefault();
  const clone = e.target.cloneNode(true);
  let data = e.dataTransfer.getData("text/plain");
  if (document.getElementById(data)) {
    if (clone.id !== data) {
      let nodelist = document.querySelector(".sort").childNodes;
      for (let i = 0; i < nodelist.length; i++) {
        if (nodelist[i].id === data) {
          dragindex = i;
        }
      }
      const targetElement = document.getElementById(data);
      if (targetElement) {
        document
          .querySelector(".sort")
          .replaceChild(document.getElementById(data), e.target);
        document
          .querySelector(".sort")
          .insertBefore(
            clone,
            document.querySelector(".sort").childNodes[dragindex],
          );
      }
    }
  }
}
/////////////////////////////////
let count = document.querySelector(".count");

let win = document.querySelector(".body .win");
const playMore = document.querySelector(".win span");
sortUl.addEventListener("dragend", e => {
  const actElements = Array.from(document.querySelectorAll(".sort li"));
  const correctOrder = Array.from(arr).map(piece => piece.id);
  if (actElements.every((piece, index) => piece.id === correctOrder[index])) {
    win.style.left = "15%";
    win.style.transform = "translate(-50%)";
    document.querySelector(".win .count").textContent = steps;
  } else {
    steps++;
    count.textContent = steps;
  }
});
playMore.addEventListener("click", () => {
  document.querySelector(".show").style.left = "0";
  win.style.left = "-100%";
  document.querySelectorAll(".sort li").forEach(e => {
    e.remove();
  });
});
document.getElementById("exit").onclick = () => {
  document.querySelectorAll(".sort li").forEach(e => {
    e.remove();
  });
  document.querySelector(".show").style.left = "0";
  steps = 0;
  count.textContent = "0";
};
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@600&family=Oswald&family=PT+Sans+Narrow&family=Roboto+Slab&display=swap");
@font-face {
  font-family: LapsusPro;
  src: url('LapsusPro-Bold.otf');
}

* {
  font-family: LapsusPro, sans-serif;
}

body {
  margin: 0;
  padding: 0;
}

.container {
  width: 90%;
  padding: 2rem 1rem;
  height: 100%;
  margin: auto;
}

.head {
  text-align: center;
}

.head h1 {
  background-color: #2196f3;
  padding: 10px;
}

.head p {
  font-size: 20px;
  margin-top: -6px;
}

.body {
  display: flex;
  gap: 3rem;
  background: #03a9f4;
  padding: 10px;
  border-radius: 10px;
  justify-content: center;
  overflow: hidden;
  transition: 0.5s;
  z-index: 1;
  text-align: center;
}

@media only screen and (max-width: 900px) {
  .body {
    display: grid;
    grid-template-columns: 1fr;
    align-items: center;
    gap: 1rem;
  }
}

.body .show {
  text-align: center;
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: #607d8b;
  border-radius: 8px;
  transition: all 0.5s;
  left: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 2rem;
}

.body .show h2 {
  color: #fff;
  font-style: italic;
  font-size: 30px;
  border-bottom: 2px solid #3333;
  margin: 0;
}

.body .show span {
  margin: 0;
  font-size: 32px;
  text-transform: capitalize;
  color: #fff;
  display: block;
  width: fit-content;
  height: fit-content;
  background-color: #03a9f4;
  padding: 5px 16px;
  border-radius: 7px;
  cursor: pointer;
  opacity: 0.3;
  transition: all 0.5s;
}

.body .show span.active,
.body .show span:hover {
  opacity: 1;
}

.body .show button {
  font-size: 30px;
  padding: 5px 12px;
  background-color: #3f51b5;
  color: #fff;
  font-style: oblique;
  border: none;
  border-radius: 26px;
  cursor: pointer;
  margin-top: 0.5rem;
}

.game-page {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column
}

.body ul {
  /* flex: 1;  */
  border: 1px solid #333;
  border-radius: 3px;
  width: 400px;
  height: 400px;
  padding-left: 0;
}

@media only screen and (max-width: 550px) {
  .body ul {
    width: 350px;
    height: 350px;
  }
}

@media only screen and (max-width: 450px) {
  .body ul {
    width: 300px;
    height: 300px;
  }
}

@media only screen and (max-width: 375px) {
  .body ul {
    width: 250px;
    height: 250px;
  }
}

@media only screen and (max-width: 315px) {
  .body ul {
    width: 225px;
    height: 225px;
  }
}

.body ul li {
  list-style-type: none;
  padding: 0;
  margin: 0;
  float: left;
  cursor: pointer;
}


/* .body ul li:hover {
    opacity: 0.5;
} */

.body .act-img {
  width: 250px;
  height: auto;
}

.body .act-img img {
  max-width: 100%;
}

.body .steps {
  display: inline-block;
  font-size: 23px;
  margin: 8px 0;
}

.body .steps+div {
  display: inline-block;
  font-size: 20px;
}

.body .act-level {
  margin: 20px 0;
  font-size: 24px;
  text-transform: capitalize;
  display: flex;
  justify-content: space-between;
  flex-direction: column;
}

.body .act-level button {
  padding: 5px 12px;
  font-size: 20px;
  border-radius: 20px;
  border: none;
  cursor: pointer;
  background-color: #607d8b;
  color: #fff;
  text-transform: capitalize;
  margin: 20px 0 0 0;
}

.body .win {
  position: absolute;
  width: 70%;
  height: 70%;
  background-color: #2196f3;
  border-radius: 10px;
  color: #fff;
  font-size: 20px;
  left: -100%;
  top: 15%;
  transform: none;
  text-align: center;
  padding: 20px;
  transition: 0.5s;
  opacity: 1;
  z-index: 5;
}

.body .win h2 {
  text-transform: capitalize;
}

.body .win .steps {
  text-transform: capitalize;
}

.body .win span {
  display: block;
  background-color: #607d8b;
  width: fit-content;
  padding: 5px 10px;
  border-radius: 6px;
  margin: auto;
  cursor: pointer;
}
<div class="container">
  <div class="head">
    <h1>PUZZLE</h1>
    <p> Drag each piece to match the image below</p>
  </div>
  <div class="body" style="position: relative">
    <div class="show">
      <h2>choose your game mode</h2>
      <span class="active" data-mode="3">easy</span>
      <span data-mode="4">medium</span>
      <span data-mode="5">hard</span>
      <span data-mode="6"> very hard</span>
      <button>start game</button>
    </div>
    <div class="game-page">
      <ul class="sort">
      </ul>
      <div class="option">
        <div class="steps">Moves:</div>
        <div class="count">0</div>
        <div class="act-img">
          <img src="imgs/img-01.jpg" alt="" />
        </div>
        <div class="act-level">
          <span>easy for test</span>
          <button id="exit">exit img</button>
        </div>
      </div>
    </div>
    <div class="win" style="opacity: 1;">
      <h2>congratulation you made it ^_^</h2>
      <div class="steps">you win in:</div>
      <div class="count">0</div>
      <span>Play More</span>
    </div>
  </div>

javascript html css swap
© www.soinside.com 2019 - 2024. All rights reserved.