Javascript 使d3力布局与标记数据一起工作

Javascript 使d3力布局与标记数据一起工作,javascript,d3.js,label,force-layout,Javascript,D3.js,Label,Force Layout,我一直在尝试将各种d3示例中的想法粘合到我需要的内容中,从开始,然后添加: 对数据联接使用键函数 修改基础图 使链接的链接距离函数依赖于图形链接的属性 向节点添加标签 到目前为止,我只有四分之三:关于使用g元素的东西——使用直接从中获取的代码——会破坏东西,而不会绘制节点。如果我直接连接圆元素,我可以使它工作,但如果我插入带有附加圆和文本元素的g元素,则不行 function tick() { //Moving <g> elements using transform att

我一直在尝试将各种d3示例中的想法粘合到我需要的内容中,从开始,然后添加:

对数据联接使用键函数 修改基础图 使链接的链接距离函数依赖于图形链接的属性 向节点添加标签 到目前为止,我只有四分之三:关于使用g元素的东西——使用直接从中获取的代码——会破坏东西,而不会绘制节点。如果我直接连接圆元素,我可以使它工作,但如果我插入带有附加圆和文本元素的g元素,则不行

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; });
}
下面的代码是我在一个最小的示例中所做的最大努力。此示例有效,但如果我将.enter.appendcircle行替换为.enter.appendg行,则不起作用

有人知道为什么吗

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()

在代码中,您正在为g元素设置cx和cy属性。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
解决方案

使用下面的“平移”功能移动组元素

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

感谢您的快速回复@Gilsha;这似乎奏效了。我是按照我认为的那样更新node.attrcx的,所以我不确定为什么它在那里工作而在这里不工作?但它起作用了,我会把这个谜团留到下一天。在那个例子中,node是一个圆的集合,这里node是一个组元素的集合。这就是它在那里工作的原因。