d3.pie() формирует вспомогательную структуру данных для
построения круговых диаграмм, преобразуя линейный массив значений в
набор объектов с угловыми параметрами. Важная особенность заключается в
том, что функция не занимается отрисовкой — она только вычисляет
геометрию секторов, оставляя визуализацию на d3.arc().
Круговая диаграмма в D3 строится в два этапа:
d3.pie()d3.arc()Функция принимает массив данных и возвращает массив объектов, содержащих:
value — исходное значениеstartAngle — начальный угол сектораendAngle — конечный угол сектораindex — индекс элементаКаждый угол измеряется в радианах, где полный круг равен
2π.
const data = [10, 20, 30];
const pie = d3.pie();
const arcs = pie(data);
console.log(arcs);
Результатом будет структура, где каждый элемент содержит диапазон углов, пропорциональный значению.
d3.pie() суммирует все элементы массива и вычисляет долю
каждого значения:
[ = ]
Затем эта доля умножается на полный угол окружности:
[ = ]
Таким образом обеспечивается пропорциональность секторов.
Если данные представлены объектами, используется функция доступа
value():
const data = [
{ name: "A", count: 10 },
{ name: "B", count: 20 },
{ name: "C", count: 30 }
];
const pie = d3.pie()
.value(d => d.count);
const arcs = pie(data);
Value accessor позволяет отделить визуализацию от структуры данных и использовать произвольные поля.
По умолчанию d3.pie() сортирует данные по убыванию
значения. Это поведение можно изменить.
d3.pie().sort(null);
Возможные варианты:
sort(null) — сохраняет исходный порядок массиваsort((a, b) => a.count - b.count) — пользовательская
сортировкаСортировка влияет на расположение секторов по окружности, но не на их размер.
Диапазон построения можно контролировать через:
startAngleendAngleconst pie = d3.pie()
.startAngle(0)
.endAngle(Math.PI);
Это позволяет создавать полу-круговые диаграммы и нестандартные сегментированные дуги.
Результат d3.pie() напрямую используется в
d3.arc():
const arc = d3.arc()
.innerRadius(0)
.outerRadius(100);
svg.selectAll("path")
.data(pie(data))
.enter()
.append("path")
.attr("d", arc);
Каждый элемент массива уже содержит startAngle и
endAngle, которые интерпретируются генератором дуг.
Добавление внутреннего радиуса превращает круговую диаграмму в кольцевую:
const arc = d3.arc()
.innerRadius(50)
.outerRadius(100);
Разница между внешним и внутренним радиусом формирует толщину кольца.
Для визуального отделения сегментов используется
padAngle:
const pie = d3.pie()
.padAngle(0.02);
Эта настройка добавляет промежутки между секторами, улучшая читаемость диаграммы при большом количестве элементов.
Каждый сектор имеет геометрический центр, вычисляемый через
d3.arc().centroid():
const arc = d3.arc()
.innerRadius(0)
.outerRadius(100);
const labelArc = d3.arc()
.innerRadius(60)
.outerRadius(60);
svg.selectAll("text")
.data(pie(data))
.enter()
.append("text")
.attr("transform", d => `translate(${labelArc.centroid(d)})`)
.text(d => d.data.name);
Centroid позволяет точно позиционировать подписи внутри секторов.
При передаче объектов d3.pie() сохраняет исходные данные
в поле data:
{
data: { name: "A", count: 10 },
value: 10,
startAngle: 0,
endAngle: 1.2
}
Это позволяет легко получать дополнительные свойства:
.text(d => d.data.name)
При изменении данных генератор пересчитывает углы заново:
function update(data) {
const arcs = pie(data);
svg.selectAll("path")
.data(arcs)
.transition()
.attr("d", arc);
}
Изменение набора данных автоматически приводит к перестройке всех сегментов.
d3.pie() всегда начинает с 12 часов (−π/2 радиан по
умолчанию в arc-логике отображения), если не задан
startAngle. Это влияет на визуальную ориентацию
диаграммы.
При необходимости диаграмму можно повернуть:
d3.pie().startAngle(Math.PI / 2);
const filtered = data.filter(d => d.count > 0);
const arcs = pie(filtered);
Корректная подготовка данных критична для стабильной геометрии.
d3.pie() часто используется как основа для:
В таких случаях важна синхронизация нескольких генераторов секторов и общих радиусов.
Плавные переходы достигаются через интерполяцию углов:
path.transition()
.duration(750)
.attrTween("d", function(d) {
const interpolate = d3.interpolate(this._current, d);
this._current = interpolate(1);
return t => arc(interpolate(t));
});
Сохранение предыдущего состояния позволяет корректно анимировать изменение формы секторов.
Алгоритм работы включает несколько этапов:
Такая модель обеспечивает стабильную геометрию независимо от размера входных данных.
Хотя d3.pie() не управляет стилем, типичная связка
включает:
d3.scaleOrdinal() для цветовconst color = d3.scaleOrdinal(d3.schemeCategory10);
svg.selectAll("path")
.data(pie(data))
.enter()
.append("path")
.attr("fill", d => color(d.index));
Цветовое кодирование усиливает читаемость сегментированной структуры.
В объекты можно включать дополнительные метаданные, которые
сохраняются в d.data:
const data = [
{ label: "Chrome", value: 60, region: "global" },
{ label: "Firefox", value: 25, region: "global" }
];
Эти поля могут использоваться для фильтрации, подсказок и интерактивности без изменения логики генератора.