gpt4 book ai didi

javascript - 不要用网格和纵横比溢出容器

转载 作者:行者123 更新时间:2023-12-04 01:01:51 27 4
gpt4 key购买 nike

我有一个场景,我必须动态地创建一个 MxN 网格,保持网格正方形,这种情况的代码在这里

rerender = (event) => {
const height = document.getElementById("y-input").value;
const width = document.getElementById("x-input").value;
// console.log(`${event.target.id} :: ${event.target.value}`);
console.log(`${height} :: ${width}`);

const cellContainer = document.getElementById("cell-container");

cellContainer.style.gridTemplateRows = `repeat(${height}, 1fr)`;
cellContainer.style.gridTemplateColumns = `repeat(${width}, 1fr)`;

cellContainer.innerHTML = "";
[...Array(height * width).keys()]
.map(() => document.createElement('div'))
.map((e) => {
e.className = "cell";
return e
})
.map((e) => cellContainer.appendChild(e))
}
#grid-container {
width: 500px;
height: 500px;
background-color: aqua;
padding: 8px;
}

#cell-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
}

.cell {
background-color: blue;
min-width: 4px;
min-height: 4px;
margin: 1px;
aspect-ratio: 1/1;
}
<div>
<label for="x-input">width</label>
<input value=2 min=1 max=50 type="number" name="x" id="x-input" style="width: 4ch;" onchange="rerender(event)">
<label for="y-input">height</label>
<input value=2 min=1 max=50 type="number" name="y" id="y-input" style="width: 4ch;" onchange="rerender(event)">
</div>

<div id="grid-container">
<div id="cell-container">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
</div>

我正在使用网格布局,其中的行数和列数正在由此动态更改
cellContainer.style.gridTemplateRows = `repeat(${height}, 1fr)`;
cellContainer.style.gridTemplateColumns = `repeat(${width}, 1fr)`;
并使用 aspect-ratio属性以保持单元格正方形。当我们绘制正方形(高度和宽度相同)以及宽度大于高度的矩形情况下,该代码可以完美运行。
高度大于宽度的矩形情况也可以使用,但在这种情况下存在 y 溢出,如何防止溢出?
https://codesandbox.io/s/wild-violet-kk6h9
enter image description here

最佳答案

TL; 博士
由于一切都是正方形,我们可以使用假行和列来正确调整单元格的大小。解决方案在本文末尾。
解释
问题定义
如果我正确理解你的问题,你想要

  • W × H单元格
  • 适合在 N 内× N像素正方形
  • 其中每个单元格都是一个正方形

  • 起点,什么已经有效
    因此,如果您开始工作,例如, W=3; H=2 ,我们得到如下所示的结果:
    3×2 cells
    为纯 CSS 重构
    我假设我们正在寻找纯 CSS 解决方案,因为 JS 解决方案既不重要又不理想。所以在我们继续之前,让我们修改 JS 给我们 CSS custom properties然后我们只能在 CSS 中推理:
  • 我们正在定义 --per-row ,第 1 行的单元格数,
  • 我们正在定义 --per-col , 1 列中的单元格数。

  • grid.style.setProperty('--per-row', width);
    grid.style.setProperty('--per-col', height);
    #grid {
    --per-row: 2;
    --per-col: 2;
    grid-template-columns: repeat(var(--per-row), 1fr);
    grid-template-rows: repeat(var(--per-col), 1fr);
    }
    PS:在每个代码片段中,我将省略与当前讨论无关的行。
    了解问题
    现在在您的解决方案中不起作用的是 H > W ,所以让我们举个例子,其中 W=2; H=3 .我们希望我们的网格看起来像这样:
    2×3 cells
    但是由于父级(青色蓝色框)也是一个正方形,我们可以看到此示例和前一个示例具有相同的结果单元格尺寸。在 W=3; H=2的情况下我们在底部看到一条空行;在 W=2; H=3 的情况下我们在右边看到一个空列。 在这两种情况下,我们都将单元格放置在 3×3 中。网格! 这只是 max(width, height) :
    3×3 grid
    所以让我们用 CSS max() 创建这个网格:
    #grid {
    --per-row: 2;
    --per-col: 2;
    --max: max(var(--per-row), var(--per-col));
    grid-template-columns: repeat(var(--max), 1fr);
    grid-template-rows: repeat(var(--max), 1fr);
    }
    但是,使用此网格模板,我们将始终在 3×2 中创建 3 列。案例和 2×3案件。它对 W > H 很有用但 H > W看起来会错。我们需要重构列模板的计算方式。
  • 首先,我们实际想要的列数。这是最简单的部分,它是 --per-row :
    grid-template-columns: repeat(var(--per-row), 1fr);
    但是现在我们的2×3网格看起来像这样,因为每一列都是 1fr ,结果是 50%全宽:
    2×3 cells, with columns that are too large
  • 现在,我们需要找到合适的列宽。我们已经看到使用 1fr不起作用,但由于一切都是正方形,我们知道在 3×2 中案例和2×3如果我们需要每列是宽度的 ⅓,或者 100% / 3 , 或 calc(100% / var(--max)) :
    grid-template-columns: repeat(var(--per-row), calc(100% / var(--max)));

  • 🎉 多啊! 🎉
    我们现在有一个适用于任何 W 的布局和 H用两行简单的 CSS:
    #grid {
    grid-template-columns: repeat(var(--per-row), calc(100% / var(--max)));
    grid-template-rows: repeat(var(--max), 1fr);
    }
    打扫干净
  • 由于“垂直”布局的工作原理(技术上,CSS flow layout 中的“块方向”),我们可以简化行的创建方式。 grid-template-rows将创建固定数量的行,但是现在我们对 grid-template-columns 中的列数有了一个强大的定义。 ,我们可以说“根据需要创建尽可能多的行以适合所有 child ”,这正是 grid-auto-rows做:
    grid-auto-rows: calc(100% / var(--max));
    这使用与列宽相同的数学方法,因为这里的所有内容都是正方形。
  • 因为支持 CSS max()仍然不是很好,这是我们可以在 JS 中做的事情而没有任何性能问题:
    grid.style.setProperty('--per-row', width);
    grid.style.setProperty('--per-col', height);
    grid.style.setProperty('--max', Math.max(width, height));
  • 您会注意到,此时我们没有使用 --per-col再感谢 grid-auto-rows ,所以我们可以删除它:
    grid.style.setProperty('--per-row', width);
    grid.style.setProperty('--max', Math.max(width, height));
    #grid {
    --per-row: 2;
    --max: 2;
    }

  • 解决方案
    这是您的初始代码,在我的回答中解释了修改。

    rerender = (event) => {
    const height = document.getElementById("y-input").value;
    const width = document.getElementById("x-input").value;
    const grid = document.getElementById("grid");

    grid.style.setProperty('--per-row', width);
    grid.style.setProperty('--max', Math.max(width, height));

    grid.innerHTML = "";
    [...Array(height * width).keys()]
    .forEach(() => {
    const e = document.createElement('div')
    e.className = "cell";
    grid.appendChild(e)
    })
    }
    #container {
    width: 500px;
    height: 500px;
    background-color: aqua;
    padding: 8px;
    }

    #grid {
    display: grid;
    height: 100%;
    --per-row: 2;
    --max: 2;
    grid-template-columns: repeat(var(--per-row), calc(100% / var(--max)));
    grid-auto-rows: calc(100% / var(--max));
    gap: 2px;
    }

    .cell {
    background-color: blue;
    aspect-ratio: 1/1;
    }
    <div>
    <label for="x-input">width</label>
    <input value=2 min=1 max=50 type="number" name="x" id="x-input" style="width: 4ch;" onchange="rerender(event)">
    <label for="y-input">height</label>
    <input value=2 min=1 max=50 type="number" name="y" id="y-input" style="width: 4ch;" onchange="rerender(event)">
    </div>

    <div id="container">
    <div id="grid">
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    </div>
    </div>

    关于javascript - 不要用网格和纵横比溢出容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68094306/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com