我正在尝试动态生成网格单元,但使用特定的模式。我复制了很多<div>
,手工进行了必要的调整,得到了我需要的结果,但我想知道是否有人能帮助我开发一种自动生成它的算法。如果你看下面的例子,左边的框是我想要动态计算的。
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>
从所需的输出中,我们可以看到从左上角到出租车的距离决定了所需的颜色,列号决定了单元格文本。
内环应限制在出租车的最大距离内。这个最大值可能是函数的一个参数。在您的示例中,最大值为3(因为最远的单元格距离左上角的单元格有3步出租车距离(。
此外,出租车距离越远,所需的颜色似乎越浅。为此,我们可以改变相同固定背景颜色的alpha部分。在RGBA表示法中,这个阿尔法分量的值可以在0和1之间。
我选择创建一个文档片段而不是HTML。这样,单元格属性的设置更受JS语法控制,更面向对象。
我没有碰你的CSS。
在这个实现中,我添加了一个输入框,用它可以控制将要使用的最大出租车距离:
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">
首先,您应该使用eventListener
或defer
-属性来等待DOM结构加载并且元素存在。
那么就不应该使用innerHTML
来创建元素。它很慢,因为DOM需要重新分析,并且是XSS注入漏洞。
要创建元素,请使用appendChild
或insertAdjacentHTML
方法。
与其将所有内容添加为inline-style
,我将使用CSS,它更干净,SASS的使用时间更短。
正如您已经发现的,您需要2个变量。一个用于行,一个用于列。第一个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>