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