D3JS - Могу ли я сделать форсированный граф с отдельными узлами и как?

1

Вопрос: Возможно ли, чтобы я сделал каждый узел по отдельности, а затем применил силовой макет для их подключения? Если нет, то как я буду делать предварительную установку узлов? И если да, могу ли я получить некоторую помощь в синтаксисе, пожалуйста?

Контекст: я новичок в D3, и я пытаюсь сделать ориентированный на силу граф только для пяти узлов как часть целевой страницы для академического проекта. Я использую этот пример и этот пример, и вроде хочу сделать комбинацию из двух, поместив мои узлы в массивы.

Например, могу ли я сделать что-то вроде:

        var w = 1300;
        var h = 10000;
        //An area for svg elements
        var svgArea = d3.select("body").append("svg")
            .attr("width", w)
            .attr("height", h);

        //All the node definitions
        var nodeMain = svgArea.append("a")
            .attr("height", 300)
            .attr("width", 300)
            .append("circle")
            .attr("r", 300)
            .attr("cx", 650)
            .attr("cy", 700)
            .attr("fill", "orange");

        var nodeMedia = svgArea.append("a")
            .attr("height", 200)
            .attr("width", 200)
            .append("circle")
            .attr("r", 200)
            .attr("cx", 250)
            .attr("cy", 1150)
            .attr("fill", "orange");

        var nodeRef = svgArea.append("a")
            .attr("height", 200)
            .attr("width", 200)
            .append("circle")
            .attr("r", 200)
            .attr("cx", 1050)
            .attr("cy", 1150)
            .attr("fill", "orange");

        //Nodes for the visualization
        var nodes = [nodeMain, nodeMedia, nodeRef];

        //Connected using indices of the array
        var edges = [{source: 1, target: 0}, {source: 2, target: 0}];

        //Force-directed
        var connect = d3.layout.force()
            .size([w, h])
            .gravity(1)             
            .distance(100)
            .charge(-50);

        connect.nodes(nodes).links(edges);

        var orb = svgArea.selectAll(".node").data(nodes)
            .enter().append("g")    
            .call(force.drag);


        var link = svgArea.selectAll(".link").data(edges)
            .enter()
            .append("line")
            .attr("class", "link");

        connect.on("tick", function(){
            link.attr("x1", function(d) {return d.source.x})
                .attr("y1", function(d) {return d.source.y})
                .attr("x2", function(d) {return d.source.x})
                .attr("y2", function(d) {return d.source.y});

            orb.attr("transform", function(d){ return "translate(" + d.x + "," + d.y + ")";});
        });

        connect.start();

(И в случае, если я задал действительно глупый вопрос, кто-нибудь возражал бы, направляя меня к некоторым ресурсам D3, где я могу узнать больше о концепциях/синтаксисе, не подражая/полагаясь исключительно на примеры?)

Спасибо заранее, всем!

Теги:
d3.js

2 ответа

0
Лучший ответ

Я внес небольшие изменения в фрагмент кода и добавил необходимые комментарии. Поделитесь своими запросами, если они есть.

var w = 500;
var h = 500;

//An area for svg elements
var svgArea = d3.select("body").append("svg")
  .attr("width", w)
  .attr("height", h);

//Nodes for the visualization
var nodes = [{
  name: "Main",
  x: 80,
  y: 10
}, {
  name: "Media",
  x: 15,
  y: 40
}, {
  name: "Reference",
  x: 60,
  y: 60
}];

//Connected using indices of the array
var edges = [{
  source: 1,
  target: 0
}, {
  source: 2,
  target: 0
}];

//Force-directed
var connect = d3.layout.force()
  .size([w, h])
  .gravity(1)
  .distance(150)
  .charge(-200);

connect
  .nodes(nodes)
  .links(edges);

//Creating links
var link = svgArea.selectAll(".link")
  .data(edges)
  .enter()
  .append("line")
  .attr("class", "link")
  .style("stroke", "black");

//Creating nodes
var orb = svgArea.selectAll(".node")
  .data(nodes)
  .enter()
  .append("g")
  .attr("class", "node");  

orb.append("circle")
  .attr("r", 10)
  .style("fill", "orange");

//Adding Labels
orb.append("text")
  .attr("dx", 12)
  .attr("dy", ".35em")
  .text(function(d) {
    return d.name
  });
  
//Adding images
orb.append("image")
  .attr("xlink:href", "https://github.com/favicon.ico")
  .attr("x", -10)
  .attr("y", -10)
  .attr("width", 20)
  .attr("height", 20);
  
orb.on("click",function(d){
  alert("clicked "+d.name);
});

connect.on("tick", function() {

  //Updating the link positions during force simulation.
  link.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
    });

  //Updating the node position during force simulation  
  orb.attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
  });
});

connect.start();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

D3 имеет богатую документацию, которая доступна здесь: GitHub

Сценарий: https://jsfiddle.net/gilsha/kv05y1hq/

  • 0
    Спасибо вам большое! Могу ли я установить их местоположение заранее? Или у меня нет выбора, где будет отображаться каждый узел, когда я использую макет с принудительной ориентацией? Возможно ли настроить каждый узел?
  • 0
    Вы можете установить статические позиции x, y для каждого узла. Попробуйте запустить фрагмент кода несколько раз. Вы можете видеть, что узлы приходят в те же позиции каждый раз, когда вы выполняете.
Показать ещё 2 комментария
0

Если это поможет, у меня есть следующие Plunkers...

http://plnkr.co/edit/TiKKmvydqXNipe103juL?p=preview

http://plnkr.co/edit/ZSmvH05nnAD6cYZb0EM4?p=preview

Первый - показать/скрыть группы элементов при нажатии.

Во-вторых, это продемонстрировать drag/zoom.

Кроме того, данные экрнализируются в json файл и читаются с использованием...

d3.json("data.json", function(error, graph) {

Это должно позволить вам снизить количество определений узлов до одной функции.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню