Продолжение раздела Добавление строк в макет сетки с помощью d3
С помощью следующего фрагмента я теперь могу добавлять данные в виде строк в сетке. Однако, как вы можете видеть, d3 добавляет сначала все cell1, затем все cell2 и, наконец, все cell3 элементы div, нарушая порядок моей сетки.
Что мне нужно изменить, чтобы элементы отображались в порядке строк, т.е.:
<div id = "grid">
<div class = "cell1">1/1</div>
<div class = "cell2">1/2</div>
<div class = "cell3">1/3</div>
<div class = "cell1">2/1</div>
<div class = "cell2">2/2</div>
<div class = "cell3">2/3</div>
</div>
function update(data) {
d3.select('#grid')
.selectAll('.cell1')
.data(data, (d) => d.id)
.join((enter) => {
enter.append('div')
.classed('cell1', true)
.text((d) => d.cell1);
enter.append('div')
.classed('cell2', true)
.text((d) => d.cell2)
enter.append('div')
.classed('cell3', true)
.text((d) => d.cell3);
})
}
function addRow() {
const n = data.length + 1;
const newRow = {cell1: n + '/1', cell2: n + '/2', cell3: n + '/3', id: n};
data.push(newRow);
update(data);
}
const data = [
{cell1: '1/1', cell2: '1/2', cell3: '1/3', id: 1},
{cell1: '2/1', cell2: '2/2', cell3: '2/3', id: 2}
];
update(data)#grid {
display: inline-grid;
grid-template-columns: repeat(3, 200px);
}
#grid > div:nth-of-type(3n+2) {
background-color: orange;
}
#grid > div:nth-of-type(3n+1) {
background-color: purple;
}
#grid > div:nth-of-type(3n+0) {
background-color: forestgreen;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<div id = "grid">
</div>
<button id = "add" onclick = "addRow()">Add Row</button>


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Используйте класс, чтобы установить столбец в сетке.
И установите автоматический поток на плотный
#grid {
display: inline-grid;
grid-template-columns: repeat(3, 200px);
grid-auto-flow: dense;
}
.cell1 {
background-color: orange;
grid-column: 1;
}
.cell2 {
background-color: purple;
grid-column: 2;
}
.cell3 {
background-color: forestgreen;
grid-column: 3;
}<div id = "grid">
<div class = "cell1">1/1</div>
<div class = "cell1">2/1</div>
<div class = "cell2">1/2</div>
<div class = "cell2">2/2</div>
<div class = "cell3">1/3</div>
<div class = "cell3">2/3</div>
</div>Извините, насчет d3 не знаю, не могу сказать.
Помимо прекрасного ответа от @vals, я нашел еще одно решение, которое предполагает добавление строки <div>, которая устанавливает display:contents.
Это кажется более естественным, поскольку можно сохранить сопоставление 1 строка <-> 1 элемент (div.row), и добавление дополнительных столбцов в будущем не потребует добавления новых правил в CSS.
function update(data) {
const row = d3.select('#grid')
.selectAll('.row')
.data(data, (d) => d.id)
.join((enter) => {
const row = enter.append('div')
.classed('row', true);
row.append('div')
.classed('cell1', true)
.text((d) => d.cell1);
row.append('div')
.classed('cell2', true)
.text((d) => d.cell2)
row.append('div')
.classed('cell3', true)
.text((d) => d.cell3);
});
}
function addRow() {
const n = data.length + 1;
const newRow = {cell1: n + '/1', cell2: n + '/2', cell3: n + '/3', id: n};
data.push(newRow);
update(data);
}
const data = [
{cell1: '1/1', cell2: '1/2', cell3: '1/3', id: 1},
{cell1: '2/1', cell2: '2/2', cell3: '2/3', id: 2}
];
update(data)#grid {
display: inline-grid;
grid-template-columns: repeat(3, 200px);
}
#grid > .row > div:nth-of-type(3n+2) {
background-color: orange;
}
#grid > .row > div:nth-of-type(3n+1) {
background-color: purple;
}
#grid > .row > div:nth-of-type(3n+0) {
background-color: forestgreen;
}
.row {
display: contents;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<div id = "grid">
</div>
<button id = "add" onclick = "addRow()">Add Row</button>Хороший ответ. Имейте в виду, что современный способ сделать это — использовать подсетку для строки вместо отображения: содержимого. (с немного меньшим количеством кобертуры)
Ах, интересно, как вы, наверное, заметили, я занимался всем, кроме веб-разработчика, так что спасибо за стимул. адаптируюсь (+1)
Как я могу гарантировать, что столбцы имеют одинаковый размер без указания фиксированной ширины? С подсеточным подходом?
используйте, например, 1fr:grid-template-columns:repeat(3,minmax(0px,1fr))
Это очень интересный вопрос, и ваш ответ на него намекает на вашу основную проблему. Проблема в том, что у вас есть иерархические данные, но вы просите d3 игнорировать иерархию и создать плоский DOM из одноуровневых <div>. Ваш ответ заставляет DOM иметь структуру, соответствующую данным. Другой способ решения — заставить данные соответствовать желаемому DOM:
<!DOCTYPE html>
<html>
<head>
<style>
#grid {
display: inline-grid;
grid-template-columns: repeat(3, 200px);
}
#grid > div:nth-of-type(3n + 2) {
background-color: orange;
}
#grid > div:nth-of-type(3n + 1) {
background-color: purple;
}
#grid > div:nth-of-type(3n + 0) {
background-color: forestgreen;
}
</style>
<script src = "lib/script.js"></script>
</head>
<body>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<div id = "grid"></div>
<button id = "add" onclick = "addRow()">Add Row</button>
<script>
function update(data) {
let flatData = data.flatMap(d => {
return [d.cell1, d.cell2, d.cell3];
});
d3.select('#grid')
.selectAll('div')
.data(flatData)
.join((enter) => {
enter.append('div')
.text((d) => d);
});
}
function addRow() {
const n = data.length + 1;
const newRow = {
cell1: n + '/1',
cell2: n + '/2',
cell3: n + '/3',
id: n,
};
data.push(newRow);
update(data);
}
const data = [
{ cell1: '1/1', cell2: '1/2', cell3: '1/3', id: 1 },
{ cell1: '2/1', cell2: '2/2', cell3: '2/3', id: 2 },
];
update(data);
</script>
</body>
</html>Ах, очень проницательно, кусочки постепенно встают на свои места. (+1) Думаю, мой предыдущий опыт программирования запрещал даже думать об этом решении, потому что мне было сегодня много лет, когда я узнал, что в JS можно создавать массивы смешанных типов, и даже объекты могут быть элементами массива (я считал Массив как однотипная коллекция).
Красиво +1. Просто из любопытства, думаю, мне не удалось изменить порядок в самом d3?