В этом разделе мы рассмотрим, как соединять массивы данных с D3 Selection
. Мы обсудим, как создавать соединения данных, как обновлять соединения данных и как соединять массивы объектов.
Data Joins
(соединения данных) создают соответствие между массивами данных и выборками HTML или SVG элементов.
Соединение массива с HTML/SVG элементами означает:
circle
:[40, 10, 20, 60, 30]
Установите радиус каждого круга равным соответствующему значению массива. Радиус первого круга равен 40, радиус второго круга равен 10 и так далее:
d3.select('.chart')
.selectAll('circle')
.data(myData)
.join('circle')
.attr('cx', function(d, i) {
return i * 100;
})
.attr('cy', 50)
.attr('r', function(d) {
return d;
})
.style('fill', 'blue');
> Перед версией 5 D3, `Data Joins` (соединения данных) были не такими простыми для понимания (вы должны были знать `enter, exit, append, remove`). К счастью, для версий 5+ `data joining` стало гораздо проще! **[d3 V-1.4 join notebook](https://observablehq.com/@d3/selection-join)**
Общий шаблон для создания соединения данных выглядит так:
d3.select(container) // container css-селектор обычно представляет собой один элемент html/svg-контейнер
.selectAll(element-type) // element-type определяет тип элемента, который будет соединен, например circle / div
.data(array) // array имя массива, который будет соединен
.join(element-type); // выполнить соединение
Обычно используются четыре метода функции в соединении данных:
.select
определяет элемент, который будет служить контейнером (или родителем) для соединения HTML/SVG
элементов..selectAll
определяет тип элемента, который будет соединен с каждым элементом массива..data
определяет массив, который будет соединен..join
выполняет соединение. Можно добавлять и удалять HTML/SVG
элементы.
Пример: дан массив:let myData = [40, 10, 20, 60, 30];
И элемент svg
с элементом g
:
<svg>
<g class="chart">
</g>
</svg>
Вы можете использовать следующий метод для соединения элементов myData
с circle
:
let myData = [40, 10, 20, 60, 30];
d3.select('.chart')
.selectAll('circle')
.data(myData)
.join('circle');
В этом примере:
g
circle
myData
Запуск этого кода создаст 5 кругов:<svg>
<g class="chart">
<circle></circle>
<circle></circle>
<circle></circle>
<circle></circle>
<circle></circle>
</g>
</svg>
```**Однако при открытии интерфейса ничего не будет видно (пустое поле)**, так как радиус каждого круга равен нулю. Однако, если вы раскроете SVG-элемент, вы увидите, что добавлено пять элементов `circle`:

### Обновление связанных элементов
`.join` возвращает выборку, содержащую все связанные элементы, которые можно обновить с помощью методов, таких как `.attr`, `.style`, и т. д.
Например, можно установить центр, радиус и цвет каждого круга следующим образом:
var myData = [40, 10, 20, 60, 30]; d3.select('.chart') .selectAll('circle') .data(myData) .join('circle') .attr('cx', 200) .attr('cy', 50) .attr('r', 40) .style('fill', 'orange');

Вы увидите только один круг, так как все пять кругов имеют одинаковые размеры и положение.
> [Попробуйте редактировать этот пример на Codepen](https://codepen.io/wantnocode/pen/xxWQOEw)
### Данные-ориентированные обновления
Если передать функцию в `.attr`, или можно обновить HTML/SVG-элементы в **данных-ориентированном** стиле с помощью `.style`.
Функция вызывается для каждого элемента в выборке. Она принимает два параметра, обычно называемых `d` и `i`.
Первый параметр (`d`) представляет соответствующий элемент массива (или "соединительное значение"). Второй параметр `i` представляет индекс элемента в выборке.
Значение, возвращенное функцией, используется для установки значения атрибута или стиля.
Давайте передадим функцию в первый `.attr`.attr`:
var myData = [40, 10, 20, 60, 30]; d3.select('.chart') .selectAll('circle') .data(myData) .join('circle') .attr('cx', function(d, i) { return i * 100; }) .attr('cy', 50) .attr('r', 40) .style('fill', 'blue');
D3 установит атрибут `cx` каждого круга в значение `i * 100`. `i` — это индекс в выборке, поэтому первый круг будет расположен в `0`, следующий в `100`, и так далее:

> [Попробуйте редактировать пример выше на Codepen](https://codepen.io/wantnocode/pen/oNqQxrj)
Теперь давайте установим `r` в зависимости от значений соединения:
var myData = [40, 10, 20, 60, 30]; d3.select('.chart') .selectAll('circle') .data(myData) .join('circle') .attr('cx', function(d, i) { return i * 100; }) .attr('cy', 50) .attr('r', function(d) { return d / 2; }) .style('fill', 'blue');

> [Попробуйте редактировать пример выше на Codepen](https://codepen.io/wantnocode/pen/MWVzeKx)
Вы можете вставить сколько угодно логики в функции, переданные в `.attr` и `.style`. Например, если значение соединения больше 30, давайте закрасим круги:
var myData = [40, 10, 20, 60, 30]; d3.select('.chart') .selectAll('circle') .data(myData) .join('circle') .attr('cx', function(d, i) { return i * 100; }) .attr('cy', 50) .attr('r', function(d) { return d / 2; }) .style('fill', function(d) { return d > 30 ? 'orange' : 'blue'; });

> [Попробуйте редактировать пример выше на Codepen](https://codepen.io/wantnocode/pen/LYdXZZN)
### Добавление массива объектов со связями
При построении данных с использованием D3 вы обычно связываете массив объектов (а не массив чисел).Например:
var persons = [ { name: 'A', score: 10}, { name: 'B', score: 20}, { name: 'C', score: 30}, { name: 'D', score: 40}, { name: 'E', score: 50} ];
Вы можете добавить массив объектов так же, как и раньше. Однако, когда вы передаете функцию в `. attr` или `. style`, параметр `d` является объектом. Это означает, что вы обычно обращаетесь к его **свойствам**.
Например:
. attr('r', function(d) { return d. score; })
Полный пример:
var persons = [ { name: 'A', score: 10}, { name: 'B', score: 20}, { name: 'C', score: 30}, { name: 'D', score: 40}, { name: 'E', score: 50} ]; d3. select('. chart') . selectAll('circle') . data(persons) . join('circle') . attr('cx', function(d, i) { return (i+1) * 100; }) . attr('cy', 50) . attr('r', function(d) { return d. score; }) . style('fill', 'blue');
! [image-20220816113925241](. /image/image-20220816113925241. png)
> [Попробуйте редактировать пример выше на Codepen](https://codepen. io/wantnocode/pen/)io/wantnocode/pen/jOzQrMQ)
Создайте простой столбчатый график. Установите `circle` как элемент `rect`, а не добавляйте элемент `text`:
var persons = [ { name: 'A', score: 10}, { name: 'B', score: 20}, { name: 'C', score: 30}, { name: 'D', score: 40}, { name: 'E', score: 50} ]; // Добавьте rect d3. select('. bars') . selectAll('rect') . data(persons) . join('rect') . attr('height', 19) . attr('width', function(d) { return d. score * 10; }) . attr('y', function(d, i) { return i * 20; });
! [](. /image/image-20220816114355759. png)
График также можно дополнить элементом `text` для описания:
d3. select('. labels') . selectAll('text') . data(persons) . join('text') . attr('y', function(d, i) { return i * 20 + 13; }) . text(function(d) { return d. name; });
! [](. /image/image-20220816114504454. png)
Ух ты!Здесь мы можем использовать D3 для создания простого столбчатого графика. Поздравляем!
> [Попробуйте редактировать пример на Codepen](https://codepen.io/wantnocode/pen/JjLeRmZ)
**Пример, предположим, у вас есть двумерный массив, который вы хотите добавить в таблицу `table`:**
[ [1, 2, 3, 5], [11, 22, 33, 55], [111, 222, 333, 555], [1111, 2322, 3333, 5555] ];
Выберите элемент `body`, добавьте элемент `table`, последовательно выберите элементы `data join`, затем снова `data join`:
d3.select("body") .append("table") .selectAll("tr") .data(matrix) .join("tr") .selectAll("td") .data(d => d) .join("td") .text(d => d);

> [Попробуйте редактировать пример на Codepen](https://codepen.io/wantnocode/pen/KKorzoQ)
## Обновление данных, обновление графика
Если массив данных изменится, вам потребуется снова выполнить соединение (data join).
Поэтому мы обычно помещаем код соединения в функцию. Каждый раз, когда данные изменяются, мы вызываем эту функцию.
Обычно функция называется `update`. Например:
var myData = [40, 10, 20, 60, 30]; function update(data) { d3.select('.chart') .selectAll('circle') .data(data) .join('circle') .attr('cx', function(d, i) { return (i + 1) * 100; }) .attr('cy', 50) .attr('r', function(d) { return 0.5 * d; }) .style('fill', function(d) { return d > 30 ? 'orange' : 'blue'; }); } update(myData);

В предыдущем примере данные никогда не изменяются, поэтому добавим кнопку, нажатие на которую получает случайные данные и вызывает `update`:
function getData() { let data = []; for (let i = 0; i < 5; i++) { data.push(Math.random() * 100); } update(data); }
random() * 60);
}
return data;
}
function update(data) {
d3.select('.chart')
.selectAll('circle')
.data(data)
.join('circle')
.attr('cx', function(d, i) {
return i * 100;
})
.attr('cy', 50)
.attr('r', function(d) {
return 0.5 * d;
})
.style('fill', function(d) {
return d > 30 ? 'orange' : 'blue';
});
}
function updateAll() {
let myData = getData();
update(myData);
}
updateAll();
d3.select("button")
.on("click", updateAll);
```

Функция `getData` возвращает массив случайных чисел. Таким образом, каждый раз при нажатии на кнопку данные и круги обновляются.
> [Попробуйте редактировать пример на CodePen](https://codepen.io/wantnocode/pen/RwMqGyd)
### Отладка
Когда D3 выполняет соединение данных, он добавляет свойство `__data__` для каждого элемента DOM в выборке и присваивает ему соединенные данные.
Мы можем щелкнуть элемент в Google Chrome, выбрать "Проверить" и ввести в консоль: (`$0` представляет элемент, который мы проверяем. )
```javascript
$0.__data__
```

Такой способ проверки соединенных данных особенно полезен при отладке, так как он позволяет проверить, работает ли соединение данных так, как мы ожидаем.
```
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )