Порядок управления при добавлении нескольких элементов в соединение d3

Продолжение раздела Добавление строк в макет сетки с помощью 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>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
51
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Используйте класс, чтобы установить столбец в сетке.

И установите автоматический поток на плотный

#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>

Красиво +1. Просто из любопытства, думаю, мне не удалось изменить порядок в самом d3?

thothal 17.05.2024 12:14

Извините, насчет d3 не знаю, не могу сказать.

vals 17.05.2024 12:50
Ответ принят как подходящий

Помимо прекрасного ответа от @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>

Хороший ответ. Имейте в виду, что современный способ сделать это — использовать подсетку для строки вместо отображения: содержимого. (с немного меньшим количеством кобертуры)

vals 21.05.2024 10:40

Ах, интересно, как вы, наверное, заметили, я занимался всем, кроме веб-разработчика, так что спасибо за стимул. адаптируюсь (+1)

thothal 21.05.2024 11:41

Как я могу гарантировать, что столбцы имеют одинаковый размер без указания фиксированной ширины? С подсеточным подходом?

thothal 21.05.2024 13:34

используйте, например, 1fr:grid-template-columns:repeat(3,minmax(0px,1fr))

vals 22.05.2024 12:10

Это очень интересный вопрос, и ваш ответ на него намекает на вашу основную проблему. Проблема в том, что у вас есть иерархические данные, но вы просите 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 можно создавать массивы смешанных типов, и даже объекты могут быть элементами массива (я считал Массив как однотипная коллекция).

thothal 21.05.2024 09:33

Другие вопросы по теме