Автор оригинала: Bryony Miles.
Только что написал статью о строительстве 3 Основные диаграммы Я думал, что буду следить за сложным – Пакет сетевого круга Отказ
Это сочетание двух намного любимых диаграмм D3 – Круг пакет и Сила симуляции Отказ
В коде много происходит, и вы можете играть с настраиванием его в наблюдаемых штаб-квартире. Я концентрируюсь здесь, разговаривая по ключевым элементам.
Основные данные
Основная структура – узлы :
{id: 'c1', name:'Crisps', category:'Snacks',children:[
{id: 1, name: "Salt & Vinegar",value:431},
{id: 2, name: "Prawn Cocktail",value:363},
{id: 3, name: "Cheese & Onion",value:173},
{id: 4, name: "Roast Beef",value:83},
{id: 5, name: "Ready Salted",value:410}]
}
где каждый Узел есть ID , Имя , категория и массив детей.
и Ссылки :
{"id": 1,"source": 39,"target": 20,"rating": 1}
Разница в традиционном Сила симуляции Структура данных в том, что ссылка Источник и цель относится к ID из дети не Родители Отказ
Манипуляция данными
Итак, вы начинаете то же самое, что и стандарт Круг пакет :
let pack_data = d3.pack()
.size([width*0.6, width*0.6])
.radius(d => radius_scale(d.data.value))
.padding(10)
(d3.hierarchy({name: 'root',children: nodes})
.sum(d => d.value)
.sort((a, b) => b.value - a.value));
Но тогда вам нужно петить через пакет и установить pack_x и Pack_y Переменные.
- Родители – Их позиция будет определена симуляцией силы, поэтому мы хотим потерять позиционирование D3.pack (). Все, что нам нужно, это радиус круга.
- дети – Мы хотим сохранить позиционирование D3.pack (), но вычтите d3.pack () позиционирование родителя и добавьте радиус круг родительского круга.
pack_data.children.forEach(function(d){
const my_x = d.x;
const my_y = d.y;
d.pack_x = d.r;
d.pack_y = d.r;
d.category = d.data.category;
for(let c in d.children){
d.children[c].pack_x = d.children[c].x - my_x + d.r;
d.children[c].pack_y = d.children[c].y - my_y + d.r;
d.children[c].category = d.data.category;
}
})
Ссылки Sub Country.
Нам не нужно ничего делать с текущими ссылками, поскольку они будут расположены симуляцией силы, но я хотел добавить дополнительные ссылки для узлов.
Вы найдете код в Демо Я уверен, что это может быть улучшено.
Позиционирование круга
Вы увидите, что каждый круг, а другие элементы в группе узлов впервые расположены с pack_x и Pack_y Отказ
my_group.select(".pack_circle")
.attr("id",d => "node_" + d.data.id)
.attr("cx", d => d.pack_x)
.attr("cy",d => d.pack_y)
.attr("r",d => d.r)
Если вы оставили его здесь, они все будут на вершине друг друга в верхнем левом углу SVG.
Симуляция силой
Затем я создал симуляцию силы. Я использовал Forcyinabox На этот раз вы можете настроить ваши потребности. Важным битом является функция галочки, где ссылки и элементы узла помещаются с использованием этих двух функций.
function get_node_translate(d){
if( d.depth === 1){
return "translate(" + (d.x + margin) + "," + (d.y + (margin/2)) + ")";
} else {
return "translate(" + (d.parent.x + margin) + "," + (d.parent.y + (margin/2)) + ")";
}
}
function get_link_extra(d, type,coord){
return d.parent === undefined ? d[type].parent[coord] : d[type][coord]
}
Важно вернуть правильные координаты X и Y, определяемые симуляцией силы.
- Родители (d.depth) Это просто d.x и d.y
- дети (Глубина) Вам нужно ссылаться на родитель – d.cparent.x и d.cparent.y.
Я очень доволен этим. Потребовалось много мысли, чтобы адаптировать его должным образом, а также думать через дизайн и взаимодействие на мыши.
Клиент I разработал его для имел большие объемы данных, поэтому я добавил дополнительный уровень увеличения и панорамирования, а также панель для получения информации, поскольку текстовые элементы стали слишком маленькими для чтения.
Надеюсь, вам это нравится.