Я хотел бы нарисовать простой график с d3.js, как этот
Мне не удалось найти схему графа ни в документации по v5 API, ни в Интернете.
Во всех примерах используется макет d3.force из d3-сила. Хотя это выглядит впечатляюще, я не ищу компоновку графика с физическим моделированием.
Есть ли более простая раскладка или лучше всего использовать раскладку d3.force с отключенной физикой?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Нет необходимости использовать d3.forceSimulation, это, в конечном счете, лишь один из множества предлагаемых макетов D3. Если вы посмотрите на пример Майка Бостока График, направленный по силе, то вам понадобятся следующие модификации:
nodes - в основном набор вещей для представления круговsvg:circle в DOM с помощью .data(nodes)linkssvg:line в DOM с помощью .data(links)По сути, здесь используется D3 для привязки данных чистой DOM, а не предварительно созданный макет.
Вы действительно можете скопировать любой из примеров силы - все, что он делает внизу, это установка x и позиции y внизу. Если они у вас уже есть, просто разместите свои круги в этих точках.
Все части, связанные с simulation и событием ticked, вы можете удалить из примера.
Вот пример статического макета:
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory20);
const layout = (graph) => {
return new Promise((resolve) => {
var simulation = d3
.forceSimulation()
.alphaMin(0.3)
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.on("end", resolve(graph));
simulation.nodes(graph.nodes);
simulation.force("link").links(graph.links);
});
};
const render = (graph) => {
var link = d3.select("#target").append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); })
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
var node = d3.select("#target").append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("fill", function(d) { return color(d.group); });
}
d3.json("https://gist.githubusercontent.com/mbostock/4062045/raw/5916d145c8c048a6e3086915a6be464467391c62/miserables.json", function(error, graph) {
if (error) throw error;
layout(graph)
.then((graph) => render(graph));
});.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}<script src = "https://d3js.org/d3.v4.min.js"></script>
<svg width = "960" height = "600">
<g id = "target" transform = "translate(480, 300)">
</g>
</svg>РЕДАКТИРОВАТЬ
Чтобы изменить расстояние между узлами, вам нужно изменить некоторые действующие силы. Документы действительно хороши - в частности, вы хотите изменить https://github.com/d3/d3-force#many-body
Итак, измените силу charge, чтобы она читалась:
.force("charge", d3.forceManyBody().strength(-charge))
Вам нужно будет определить заряд и немного подправить его, пока сила не даст вам хороший макет.
Причина, по которой мне нужен макет, заключается в том, что я хочу, чтобы x и y были рассчитаны для меня для узлов и ссылок, например, в макете дерева.
@Zak похоже, что bl.ocks.org сейчас не работает. Это будет временно, поэтому я пока оставлю ссылку. Источник можно увидеть на gist.github.com/mbostock/4062045
@ dev-null вы можете использовать любой макет для расчета позиций. Вы даже можете использовать силу - дать ему поработать несколько сотен миллисекунд, остановить его и занять те позиции, которые он создал. Нет необходимости держать его в рабочем состоянии / перезапускать, давая эффекты движения.
@ dev-null Я добавил пример использования силы только для расчета макета, а затем разделил рендеринг. Если вы хотите, вы можете изменить эту функцию layout для запуска макета tree, макета circle pack или любого другого пользовательского макета, который вы хотите.
ОК. Я вижу результаты. Но они довольно плотно упакованы. Как мне отрегулировать, как далеко они должны быть? Кроме того, правильно ли я понимаю, что если мне нужен график и макет, это мой лучший выбор? Мне не нужен макет tree (и, кроме того, разве он не требует древовидной иерархии с корнями?), И подумал, что circle pack предназначен для группировки, что не подходит для моего случая.
@ dev-null да, похоже, forceSimulation - лучший макет для вас. Настоятельно рекомендую посмотреть документацию по API (она не такая уж и длинная) github.com/d3/d3-force#forceSimulation. Но я обновлю свой ответ
ПРИМЕЧАНИЕ. Когда я перехожу по указанной вами ссылке, я получаю Ошибка приложения