2014-10-28 3 views
0

я пытался склеить идеи из различных d3 примеров в то, что мне нужно, начиная с basic example using miserable.json data, а затем добавить:изготовления макет d3 сила работы с помеченными данными

  1. использования ключевой функции для данных присоединяется к
  2. модификации основного графа ala this example
  3. делая ссылку linkDistance() функций зависит от атрибута графа по ссылкам
  4. добавления меток к узлам ala this example

Пока что я всего лишь 3 из 4: что-то об использовании элементов g - используя код, взятый непосредственно с the Mike's "Labeled Force Layout" example - разрывает вещи, а узлы не нарисованы. Я могу заставить его работать, если я присоединяюсь к circle элементам напрямую, но не, если я вставляю g элементы с прикрепленными кругами и текстовыми элементами.

Код, приведенный ниже, является моим лучшим усилием на минимальном примере. Этот пример работает, но нет, если я заменю строку .enter().append("circle") линиями .enter().append("g").

Кто-нибудь знает, почему?

var Width = 200; 
var Height = 200; 
var Pix2Len = 10; 
var color = d3.scale.category10(); 

var svg = d3.select("body").append("svg") 
.attr("width", Width) 
.attr("height", Height); 

var force = d3.layout.force() 
.size([Width, Height]) 

var graph = { 
    "nodes":[ 
    {"name":"Myriel","idx":0}, 
    {"name":"Napoleon","idx":1}, 
    {"name":"Mlle.Baptistine","idx":2}, 
    {"name":"Mme.Magloire","idx":3} 
    ], 
    "links":[ 
    {"source":1,"target":0,"len":1,"idx":"1-0"}, 
    {"source":2,"target":1,"len":4,"idx":"2-1"}, 
    {"source":2,"target":0,"len":8,"idx":"2-0"}, 
    {"source":3,"target":0,"len":10,"idx":"3-0"}, 
    {"source":3,"target":1,"len":4,"idx":"3-1"}, 
    {"source":3,"target":2,"len":6,"idx":"3-2"} 
    ] 
} 

console.log("data loaded. nnode="+graph.nodes.length+" nlinks="+graph.links.length); 

force 
.nodes(graph.nodes) 
.links(graph.links) 
.size([Width, Height]) 
.linkDistance(function(link) { 
    // console.log("link: "+link.source.name+' '+link.target.name+' '+link.idx+' '+link.len) 
    return link.len * Pix2Len}) 
    .on("tick", tick); 

var link = svg.selectAll(".link") 
.data(graph.links, function(d) {return d.idx; }) 
.enter().append("line") 
.attr("class", "link"); 

var node = svg.selectAll(".node") 
.data(graph.nodes, function(d) {return d.idx; }) 

// THIS WORKS 
.enter().append("circle").attr("r", 8).style("fill", function(d) { return color(0); }); 

// BUT THIS DOES NOT 
// modeled after http://bl.ocks.org/mbostock/950642 
// 
//.enter().append("g") 
//.attr("class", "node") 
//.attr("cx", function(d) { return d.x; }) 
//.attr("cy", function(d) { return d.y; }); 
// 
//node.append("circle") 
//.attr("r", 10) 
//.style("fill", function(d) { return color(0); }); 
// 
//node.append("text") 
//.attr("dx", 12) 
//.attr("dy", ".35em") 
//.text(function(d) { return d.name }); 

// 1. Begin with graph from JSON data 
setTimeout(function() { 
    start(); 
}, 0); 

// 2. Change graph topology 
setTimeout(function() { 
    var new4 = {"name":"CountessdeLo","idx":4} 
    var new5 = {"name":"Geborand","idx":5} 
    graph.nodes.push(new4,new5); 
    var link40 = {"source":4,"target":0,"len":1,"idx":"4-0"}; 
    var link43 = {"source":4,"target":3,"len":4,"idx":"4-3"}; 
    var link50 = {"source":5,"target":0,"len":1,"idx":"5-0"}; 
    var link52 = {"source":5,"target":2,"len":4,"idx":"5-2"}; 
    graph.links.push(link40,link43,link50,link52); 

    start(); 
}, 3000); 

//3. Change some link lengths 

setTimeout(function() { 

    // force.links().forEach(function(link) { 
    graph.links.forEach(function(link) { 
     if (link.idx == '1-0') 
      {link.len=10; } 
     else if (link.idx == '3-0') 
      {link.len=2; } 
     else if (link.idx == '5-0') 
      {link.len=10; }; 
    }); // eo-forEach 
    start(); 
}, 6000); 

function start() { 
    link = link.data(force.links(), function(d) { return d.idx; }); 
    link.enter().insert("line", ".node").attr("class", "link"); 
    link.exit().remove(); 

    node = node.data(force.nodes(), function(d) { return d.idx;}); 
    node.enter().append("circle").attr("class", function(d) { 
    // tried with the <g> version above 
// node.enter().append("g").attr("class", function(d) { 
     console.log('start:'+' '+d.name); 
     return d.idx; }).attr("r", 5).style("fill", function(d) { return color(1); }); 
    node.exit().remove(); 

    force.start(); 
} 

function tick() { 
    node.attr("cx", function(d) { 
     // console.log('tick:'+' '+d.name); 
     return d.x; }) 
    .attr("cy", function(d) { return d.y; }) 

    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; }); 
} 
//} // eo-ready() 

ответ

2

В своем коде вы устанавливаете cx и cy атрибуты для g элемента. Элементы g не поддерживают никаких атрибутов позиции, таких как x, y или cx, cy. Чтобы переместить содержимое элемента g, вам нужно будет использовать атрибут transform.

Ваш код

var node = svg.selectAll(".node") 
    .data(graph.nodes, function(d) {return d.idx; }) 
    .enter().append("g") 
    .attr("class", "node") 
    .attr("cx", function(d) { return d.x; }) //will not work 
    .attr("cy", function(d) { return d.y; }); //will not work 

Решение

var node = svg.selectAll(".node") 
    .data(graph.nodes, function(d) {return d.idx; }) 
    .enter().append("g") 
    .attr("class", "node"); 

node.append("circle") 
    .attr("r", 10) 
    .style("fill", function(d) { return color(0); }); 

node.append("text") 
    .attr("dx", 12) 
    .attr("dy", ".35em") 
    .text(function(d) { return d.name }); 

Используйте функцию перевода, как показано ниже, чтобы переместить элементы группы.

function tick() { 
    //Moving <g> elements using transform attribute 
    node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 

    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; }); 
} 

JSFiddle

+0

спасибо за ваш быстрый ответ @Gilsha; это похоже на работу. Я обновлял 'node.attr (« cx »)' в 'tick()', следуя тому, что, на мой взгляд, рассматривал как пример макета канонической силы Майка (http://bl.ocks.org/mbostock/4062045), и поэтому я «Не знаю, почему он работает там, а не здесь? но он работает, и я сохраню эту тайну еще на один день. – rikb

+0

В этом примере 'node' представляет собой набор кругов, и здесь' node' представляет собой набор элементов группы. Вот почему он работает там. – Gilsha

+0

, конечно (спасибо за вашу помощь и терпение. – rikb

 Смежные вопросы

  • Нет связанных вопросов^_^