我是D3新手,正在玩D3网络图。我可以成功地创建一个网络图,并使其可以拖动,但我无法为节点添加标签。我找了一下答案,我觉得我的代码应该可以用。下面是代码。
注意:网络的布局在这里没有正确地呈现出来(但节点可以拖动以看到正确的布局),但当它在完整的网页上运行时,它正确地呈现出来(没有标签)。
请指出我哪里做错了。
非常感谢。
亚历克斯
var data = {
"name": "A1",
"children": [{
"name": "B1",
"children": [{
"name": "C1",
"value": 100
},
{
"name": "C2",
"value": 300
},
{
"name": "C3",
"value": 200
}
]
},
{
"name": "B2",
"value": 200
}
]
};
var root = d3.hierarchy(data);
function dragged(d) {
d.x = d3.event.x, d.y = d3.event.y;
d3.select(this).attr("cx", d.x).attr("cy", d.y);
link.filter(function(l) {
return l.source === d;
}).attr("x1", d.x).attr("y1", d.y);
link.filter(function(l) {
return l.target === d;
}).attr("x2", d.x).attr("y2", d.y);
}
// Nodes
var node = d3.select('#network g.nodes')
.selectAll('circle.node')
.data(root.descendants())
.enter()
.append('circle')
.classed('node', true)
.attr('cx', function(d) {
return d.x;
})
.attr('cy', function(d) {
return d.y;
})
.attr('r', 4)
.each(function(d) {
console.log(d);
d3.select(this)
.append('text')
.text(d.data.name);
})
.call(d3.drag().on("drag", dragged));
// Links
var link = d3.select('#network g.links')
.selectAll('line.link')
.data(root.links())
.enter()
.append('line')
.classed('link', true)
.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;
});
/*
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) {
console.log(d);
return d.data.name;
});
*/
circle {
cursor: pointer;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1px;
}
svg text {
color: #000;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.2/d3.min.js"></script>
<svg id="network" width="400" height="220">
<g transform="translate(20, 5)">
<g class="links"></g>
<g class="nodes"></g>
</g>
</svg>
下面是@AndrewReid建议的示例。该 text
和 circle
归入和 <g>
元素。函数 dragged
更新 transform
的属性。
var data = {
"name": "A1",
"children": [
{
"name": "B1",
"children": [
{
"name": "C1",
"value": 100
},
{
"name": "C2",
"value": 300
},
{
"name": "C3",
"value": 200
}
]
},
{
"name": "B2",
"value": 200
}
]
};
var root = d3.hierarchy(data);
function dragged(d) {
// Get coords relative to svg
[d.x, d.y] = d3.mouse(this.parentNode.parentNode);
d3.select(this.parentNode).attr("transform", 'translate(' + d.x + ',' + d.y + ')');
link.filter(function(l) {
return l.source === d;
}).attr("x1", d.x).attr("y1", d.y);
link.filter(function(l) {
return l.target === d;
}).attr("x2", d.x).attr("y2", d.y);
}
// Nodes
var nodeg = d3.select('#network g.nodes')
.selectAll('circle.node')
.data(root.descendants())
.enter()
.append('g');
nodeg.append('circle')
.classed('node', true)
.attr('cx', function(d) {
return d.x;
})
.attr('cy', function(d) {
return d.y;
})
.attr('r', 4)
.each(function(d) {
d3.select(this)
.append('text')
.text(d.data.name);
})
.call(d3.drag().on("drag", dragged));
// Links
var link = d3.select('#network g.links')
.selectAll('line.link')
.data(root.links())
.enter()
.append('line')
.classed('link', true)
.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 texts = nodeg.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) {
//console.log(d);
return d.data.name;
});
circle {
cursor: pointer;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1px;
}
svg text {
color: #000;
cursor: pointer;
}
<svg id="network" width="400" height="220">
<g transform="translate(20, 5)">
<g class="links"></g>
<g class="nodes"></g>
</g>
</svg>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.2/d3.min.js"></script>
根据@AndrewReid的评论,我修改了以下代码,工作正常。基本上,我需要打破链锁,使不同的元素附加到合适的父元素。
var node = d3.select('#network g.nodes')
.selectAll('circle.node')
.data(root.descendants())
.enter()
.append('g');
var circle = node.append('circle')
.classed('node', true)
.attr('cx', function(d) {return d.x;})
.attr('cy', function(d) {return d.y;})
.attr('r', 6)
.call(d3.drag().on("drag", dragged))
;
// Links
var link = d3.select('#network g.links')
.selectAll('line.link')
.data(root.links())
.enter()
.append('line')
.classed('link', true)
.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 text= node.append("text")
.attr('x', function(d) {return d.x;})
.attr('y', function(d) {return d.y;})
.attr("dx", 12)
.attr("dy", ".25em")
.text(function(d) {
return d.data.name;
});
function dragged(d) {
d.x = d3.event.x, d.y = d3.event.y;
d3.select(this).attr("cx", d.x).attr("cy", d.y);
text
.attr('x', function(d) {return d.x;})
.attr('y', function(d) {return d.y;})
link.filter(function(l) {return l.source === d; }).attr("x1",
d.x).attr("y1", d.y);
link.filter(function(l) { return l.target === d; }).attr("x2",
d.x).attr("y2", d.y);
}