我使用 JavaScript 构建的砖石布局中的错误

问题描述

我正在尝试使用尽可能少的其他人的代码来构建网站。我使用 JavaScript 构建了一个砖石风格的布局,除了我在 chrome 的开发人员工具功能“切换设备工具栏”中切换屏幕大小时发现的一个错误外,它在大多数情况下都可以正常工作。如果我手动调整窗口大小,我的布局会按预期工作。只有当我在顶部使用给定名称(例如“mobile s - 320px”)的不同大小进行切换时才会触发此错误

砌体函数有点长,但我会尽力解释它。我在我的函数添加了内嵌注释,以尽可能彻底地解释事物。

我首先使用它们的宽度、视口的宽度、我想要的卡片之间的边距以及卡片与视口最左侧和最右侧的边距来计算在视口中适合多少张卡片。我希望我的卡片之间有 1em 的边距,并且我的卡片和视口的左侧和右侧之间至少有 0.5 rem 的边距。我计算为“cardsspace”。然后我从视口中减去它以计算剩余的“空白”将是什么。然后我将它均匀地分布在页面的左侧和右侧,以便我的卡片始终居中。将卡片放在页面的第一个“行”后,然后我通过计算哪一个“列”是最短的来确定我应该在页面的哪个“列”中放置我的下一张卡片。然后我将我的卡片放在各自的位置,然后更新存储页面“列”高度的数组以反映其新值。然后我对剩余的卡片重复这个过程,直到没有剩下的卡片为止。

最后,我在窗口调整大小时向窗口添加一个事件侦听器,每当窗口调整大小时运行我的砌体布局函数

const controller = new AbortController();
const heights = [];
const blocks = document.querySelectorAll('.card'); //getting all of the cards from the page
let margin = 0;
let windowWidth = 0;
let colWidth = 0;
let cardsspace = 0;
let colCount = 0;
let whiteSpace = 0;
let min = 0;
let index = 0;

// function that places cards where they should be to get a pinterest like layout
function setupBlocks() {
  // getting window width,width of a card,and setting the margin to be equal to one rem
  windowWidth = window.innerWidth;
  colWidth = blocks[0].clientWidth;
  margin = parseInt(window.getComputedStyle(document.body).getPropertyValue('font-size'));
  // calculating how many cards fit in a "row" of the viewport
  colCount = Math.floor(windowWidth / (colWidth + margin));
  // calculating the space the cards will take (including the margin I want between them as well as the 
  // minimum margin between the cards and the left and right side of the page)
  cardsspace = colCount * (colWidth + margin);
  // calculating the whitespace that will remain
  whiteSpace = windowWidth - cardsspace;
  // only placing the cards that fit in the first row in their appropriate places
  for (let i = 0; i < colCount; i++) {
    // I want the white space to be divided evenly on the left and right side of the page
    blocks[i].style.left = `${(whiteSpace + margin)/ 2 + (colWidth + margin) * i}px`;
    // placing the cards at the top of their container and letting top margin take care of the rest 
    blocks[i].style.top = '0px';
    // storing height of each of these cards in an array called "heights" 
    heights.push(blocks[i].offsetHeight + margin);
  }
  // placing the remainder of the cards
  for (let i = colCount; i < blocks.length; i++) {
    // calculating the smallest value in the array of heights
    min = Math.min(...heights);
    // calculating the index of this of this smallest value
    index = heights.findindex(n => n === min);
    // placing a card below the shortest card column
    blocks[i].style.left = `${blocks[index].offsetLeft}px`;
    blocks[i].style.top = `${heights[index]}px`;
    // updating the heights array to reflect the new height of the column
    heights[index] += (blocks[i].offsetHeight + margin);
  }
  // resetting the heights array to reuse this function if needed
  heights.length = [];
};

// waiting until everything has loaded to run the function that places cards where they 
// should be 
document.addEventListener('readystatechange',(event) => {
    if (document.readyState === "complete") {
        setupBlocks();
    }
});

window.addEventListener('resize',setupBlocks,{signal: controller.signal});
/* GENERAL STYLES */

:root {
  Box-sizing: border-Box;
  font-size: calc(1vw + 0.6em);
  font-family: 'Montserrat',sans-serif;
  --main-color: #557d79ff;
  --secondary-color: #dae0e6;
  --light-gray: #999;
  --accent: #2d2e2f;
  --dark-text: black;
  font-weight: 300;
}

*,::before,::after {
  Box-sizing: inherit;
}

html,body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  line-height: 1.6;
  background-color: var(--main-color);
}

body,h1,h2,h3,h4,p,ul {
  margin: 0;
}

h3 {
  font-size: 1.25em;
}

img {
  max-width: 100%;
}


/* Container module */

.container {
  margin-inline: auto;
  width: min(90%,60em);
}

.container--shops {
  margin: 0;
  width: 100%;
  position: relative;
  padding: 0;
}


/* Default card used for masonry layout */

.card {
  position: absolute;
  border-radius: 4em 4em 4em 4em;
  max-width: 16em;
  background-color: var(--secondary-color);
  margin-top: 1em;
}


/* On mouse-over,add a deeper shadow */

.card:hover {
  Box-shadow: 0 8px 16px 0 rgba(0,0.2);
}

.card__body>*+* {
  margin-top: 0.4em;
}

.card__body {
  padding: .5em 0 2em 1.5em;
}


/* Add rounded corners to the top left and the top right corner of the image */

.card__image>a>img {
  margin-top: 0rem;
  border-radius: 4em 4em 0em 0em;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <Meta charset="UTF-8">
  <Meta http-equiv="X-UA-Compatible" content="IE=edge">
  <Meta name="viewport" content="width=device-width,initial-scale=1.0">
  <!-- Google Fonts! -->
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Sansita+Swashed:wght@300;400;500;600&display=swap" rel="stylesheet">
  <!-- Font Awesome! -->
  <script defer src="all.js"></script>
  <title>Cards & Navbar</title>
  <!-- Custom CSS! -->
  <link rel="stylesheet" href="home.css">
</head>

<body>
  <div class="container container--shops">
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/ItaV89TNkks" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/d5SZqLkpIrY" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/EipOdzc58Xo" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/MiTpGlCw-o0" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/Djtc1T38-GY" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/4YApsoSaNKA" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/2F8LA55VgzE" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/ItaV89TNkks" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/d5SZqLkpIrY" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/EipOdzc58Xo" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/MiTpGlCw-o0" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/Djtc1T38-GY" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/4YApsoSaNKA" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
    <div class="card">
      <div class="card__image">
        <a href="https://www.youtube.com/">
          <img src="https://source.unsplash.com/2F8LA55VgzE" alt="Avatar">
        </a>
      </div>
      <div class="card__body">
        <h3>Best Cafe</h3>
        <h4>Jonathan</h4>
        <p>Cozy cafe with great food and drinks!</p>
      </div>
    </div>
  </div>
  <script src="home.js"></script>
</body>
</html>

如您所见,除了单边缘场景外,它在大多数情况下都可以正常工作。显然,使用 chrome 的调整大小选项调整窗口大小并不是我希望用户做的事情,但让我担心的是,对于从纵向切换到横向的人,或者在我没有预料到的情况下,这种行为可能会意外弹出。可以通过打开 chrome 的开发人员工具并切换设备栏(正如我之前提到的),然后从大窗口(例如 1440 或 4k)切换到小窗口大小(例如 320px)来复制该错误。这是执行此操作时发生的情况的图像。

Picture of layout bug

知道为什么会发生这种情况吗?我现在已经检查了我的代码很多次,在我看来,在更改分辨率后,我的函数应该重新运行,因为我为窗口调整大小添加一个事件侦听器。在此先感谢您的任何帮助或建议,并为长篇幅道歉。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)