简体   繁体   English

通过 JavaScript 为 CSS 网格生成单元格

[英]Generate cells for CSS grid via JavaScript

I'm trying to generate grid cells dynamically, but in a specific pattern.我正在尝试以特定模式动态生成网格单元。 I copied a lot of <div> s, made the necessary adjustments by hand, and got the results I needed, but I'm wondering if someone can help me in developing an algorithm for producing it automatically.我复制了很多<div> ,手动进行了必要的调整,得到了我需要的结果,但我想知道是否有人可以帮助我开发一种自动生成它的算法。 If you look at the example below, the left box is what I want to dynamically calculate.如果你看下面的例子,左边的框就是我要动态计算的。

 function calcCells(){ let cells = ''; for(let a = 1; a <= 10; a++){ for(let b = 1; b <= a; b++){ cells += `<div style="background:#fd8362; grid-area: ${a % b} / ${a % b} / ${a % b} / ${a % b}"> ${b} </div>` } } return cells; } document.getElementById("grid-body-algorithm").innerHTML = calcCells();
 #grid-body, #grid-body-algorithm { float:left; margin-right:30px; box-shadow: 0 0 10px rgba(0, 0, 0, .2); text-align: center; display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(5, 1fr); justify-content: center; align-content: end; border-radius: 5px; width:150px; height:150px; color:#444444; padding:1px; } #grid-body > *, #grid-body-algorithm > *{ border:1px solid white; }
 <div id="grid-body"> <div style="background:#fd8362; grid-area: 1 / 1 / 1 / 1">1</div> <div style="background:#ffad97; grid-area: 2 / 1 / 2 / 1">1</div> <div style="background:#ffad97; grid-area: 1 / 2 / 1 / 2">2</div> <div style="background:#ffded6; grid-area: 3 / 1 / 3 / 1">1</div> <div style="background:#ffded6; grid-area: 2 / 2 / 2 / 2">2</div> <div style="background:#ffded6; grid-area: 1 / 3 / 1 / 3">3</div> <div style="background:#fff0ec; grid-area: 4 / 1 / 4 / 1">1</div> <div style="background:#fff0ec; grid-area: 3 / 2 / 3 / 2">2</div> <div style="background:#fff0ec; grid-area: 2 / 3 / 2 / 3">3</div> <div style="background:#fff0ec; grid-area: 1 / 4 / 2 / 4">4</div> </div> <div id="grid-body-algorithm"> </div>

From the desired output, we can see that the taxicab distance from the top-left corner determines the desired color, and the column number determines the cell text.从所需的output可以看出,出租车距离左上角的距离决定了所需的颜色,列号决定了单元格文字。

The inner loop should be constrained to stay within a maximum taxicab distance.内环应限制在最大出租车距离内。 This maximum could be a parameter to your function.此最大值可能是您的 function 的参数。 In your example that maximum is 3 (as the furthest cells that are concerned are 3 taxicab steps away from the top-left cell).在您的示例中,最大值为 3(因为最远的单元格距离左上角单元格 3 步)。

Furthermore, the desired color seems to get lighter the greater that taxicab distance is.此外,出租车距离越远,所需的颜色似乎越浅。 For that we could vary the alpha part of the same, fixed background color.为此,我们可以改变相同、固定背景颜色的alpha部分。 In RGBA notation, this alpha component which can have a value between 0 and 1.在 RGBA 表示法中,此 alpha 分量的值可以介于 0 和 1 之间。

I opted for creating a document fragment instead of HTML.我选择创建文档片段而不是 HTML。 That way the setting of cell attributes is more JS-syntax controlled and more object oriented.这样,单元格属性的设置更受 JS 语法控制,更面向 object。

I didn't touch your CSS.我没有碰你的 CSS。

In this implementation I added an input box with which you can control the maximum taxicab distance that will be used:在这个实现中,我添加了一个输入框,您可以使用它来控制将使用的最大出租车距离:

 function calcCells(maxDistance) { const fragment = document.createDocumentFragment(); for (let row = 1; row <= 5; row++) { // row + col - 2 is taxicab distance from top-left corner for (let col = 1, distance = row - 1; distance <= maxDistance && col <= 5; col++, distance++) { const cell = document.createElement("div"); // Set background transparency with the alpha part of the background color cell.style.background = `rgba(240,120,80,${1 - (distance + 0.5) / (maxDistance + 1)})`; cell.style.gridArea = [row, col, row, col].join(" / "); cell.textContent = col; fragment.appendChild(cell); } } return fragment; } const inputDistance = document.querySelector("input"); const outputGrid = document.getElementById("grid-body-algorithm"); function refresh() { const maxDistance = +inputDistance.value; outputGrid.innerHTML = ""; // clear previous content outputGrid.appendChild(calcCells(maxDistance)); } inputDistance.addEventListener("click", refresh); refresh();
 #grid-body, #grid-body-algorithm { float:left; margin-right:30px; box-shadow: 0 0 10px rgba(0, 0, 0, .2); text-align: center; display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(5, 1fr); justify-content: center; align-content: end; border-radius: 5px; width:150px; height:150px; color:#444444; padding:1px; } #grid-body > *, #grid-body-algorithm > *{ border:1px solid white; }
 <div id="grid-body-algorithm"></div> distance: <input type="number" value="3" min="0" max="8">

First of all, you should use an eventListener or the defer -attribute to wait until the DOM structure is loaded and the element exists.首先,您应该使用eventListenerdefer属性来等待 DOM 结构被加载并且元素存在。

Then you should not use innerHTML to create elements.那么你不应该使用innerHTML来创建元素。 It is slow as the DOM needs to be reparsed and is an XSS-Injection vulnerability.它很慢,因为 DOM 需要重新解析并且是 XSS 注入漏洞。

To create Elements use either the appendChild or the insertAdjacentHTML method.要创建元素,请使用appendChildinsertAdjacentHTML方法。

Instead of adding everything as inline-style I would work with CSS which is cleaner and with the use of SASS even shorter.我不会将所有内容添加为inline-style ,而是使用更干净的 CSS 并且使用 SASS 更短。

As you already figured out, you need 2 variables.正如您已经知道的那样,您需要 2 个变量。 One for the row and one for the column.一个用于行,一个用于列。 The first for -loop needs the one for the rows and the 2nd for the columns:第一个for循环需要一个用于行,第二个用于列:

 window.addEventListener('DOMContentLoaded', function() { for (let i = 1, n = 5; i < 5; i++) { for (let j = 1; j < n; j++) { document.querySelector('#grid-body-algorithm').insertAdjacentHTML('beforeend', ` <div data-row="${i}" data-col="${j}">${j}</div>` ); } n--; } })
 #grid-body-algorithm { width: 150px; height: 150px; display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(5, 1fr); padding: 2px; gap: 2px; border: 1px solid black; } [data-row="1"] { grid-row: 1 / 2; } [data-row="2"] { grid-row: 2 / 3; } [data-row="3"] { grid-row: 3 / 4; } [data-row="4"] { grid-row: 4 / 5; } [data-row="5"] { grid-row: 5 / 6; } [data-row="1"][data-col="1"] { background: #fd8362; } [data-row="1"][data-col="2"], [data-row="2"][data-col="1"] { background: #ffad97; } [data-row="1"][data-col="3"], [data-row="2"][data-col="2"], [data-row="3"][data-col="1"] { background: #ffded6; } [data-row="1"][data-col="4"], [data-row="2"][data-col="3"], [data-row="3"][data-col="2"], [data-row="4"][data-col="1"] { background: #fff0ec; }
 <div id="grid-body-algorithm"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM