作为一个起点,我使用this code创建一个D3 v4的有向图。
我想在每个圈子上附上一个文字。我最初的想法是为数据中的每个节点创建一个节点元素,并为它们添加一个圆圈和文本元素(将来可能会有更多的东西)。
但是,圆圈和文本似乎根本没有呈现,即使我更改了tick功能以更新其位置,如下所示:
circle
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
我的实施可以在this jsfiddle及以下地址找到:
// Create somewhere to put the force directed graph
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var radius = 20;
// DATA
var nodes_data = [
{"id": "Lillian", "sex": "F"},
{"id": "Gordon", "sex": "M"},
{"id": "Sylvester", "sex": "M"},
{"id": "Mary", "sex": "F"},
{"id": "Helen", "sex": "F"},
{"id": "Jamie", "sex": "M"},
{"id": "Jessie", "sex": "F"},
{"id": "Ashton", "sex": "M"},
{"id": "Duncan", "sex": "M"},
{"id": "Evette", "sex": "F"},
{"id": "Mauer", "sex": "M"},
{"id": "Fray", "sex": "F"},
{"id": "Duke", "sex": "M"},
{"id": "Baron", "sex": "M"},
{"id": "Infante", "sex": "M"},
{"id": "Percy", "sex": "M"},
{"id": "Cynthia", "sex": "F"},
{"id": "Feyton", "sex": "M"},
{"id": "Lesley", "sex": "F"},
{"id": "Yvette", "sex": "F"},
{"id": "Maria", "sex": "F"},
{"id": "Lexy", "sex": "F"},
{"id": "Peter", "sex": "M"},
{"id": "Ashley", "sex": "F"},
{"id": "Finkler", "sex": "M"},
{"id": "Damo", "sex": "M"},
{"id": "Imogen", "sex": "F"}];
var links_data = [
{"source": "Sylvester", "target": "Gordon", "type":"A" },
{"source": "Sylvester", "target": "Lillian", "type":"A" },
{"source": "Sylvester", "target": "Mary", "type":"A"},
{"source": "Sylvester", "target": "Jamie", "type":"A"},
{"source": "Sylvester", "target": "Jessie", "type":"A"},
{"source": "Sylvester", "target": "Helen", "type":"A"},
{"source": "Helen", "target": "Gordon", "type":"A"},
{"source": "Mary", "target": "Lillian", "type":"A"},
{"source": "Ashton", "target": "Mary", "type":"A"},
{"source": "Duncan", "target": "Jamie", "type":"A"},
{"source": "Gordon", "target": "Jessie", "type":"A"},
{"source": "Sylvester", "target": "Fray", "type":"E"},
{"source": "Fray", "target": "Mauer", "type":"A"},
{"source": "Fray", "target": "Cynthia", "type":"A"},
{"source": "Fray", "target": "Percy", "type":"A"},
{"source": "Percy", "target": "Cynthia", "type":"A"},
{"source": "Infante", "target": "Duke", "type":"A"},
{"source": "Duke", "target": "Gordon", "type":"A"},
{"source": "Duke", "target": "Sylvester", "type":"A"},
{"source": "Baron", "target": "Duke", "type":"A"},
{"source": "Baron", "target": "Sylvester", "type":"E"},
{"source": "Evette", "target": "Sylvester", "type":"E"},
{"source": "Cynthia", "target": "Sylvester", "type":"E"},
{"source": "Cynthia", "target": "Jamie", "type":"E"},
{"source": "Mauer", "target": "Jessie", "type":"E"},
{"source": "Duke", "target": "Lexy", "type":"A"},
{"source": "Feyton", "target": "Lexy", "type":"A"},
{"source": "Maria", "target": "Feyton", "type":"A"},
{"source": "Baron", "target": "Yvette", "type":"E"},
{"source": "Evette", "target": "Maria", "type":"E"},
{"source": "Cynthia", "target": "Yvette", "type":"E"},
{"source": "Maria", "target": "Jamie", "type":"E"},
{"source": "Maria", "target": "Lesley", "type":"E"},
{"source": "Ashley", "target": "Damo", "type":"A"},
{"source": "Damo", "target": "Lexy", "type":"A"},
{"source": "Maria", "target": "Feyton", "type":"A"},
{"source": "Finkler", "target": "Ashley", "type":"E"},
{"source": "Sylvester", "target": "Maria", "type":"E"},
{"source": "Peter", "target": "Finkler", "type":"E"},
{"source": "Ashley", "target": "Gordon", "type":"E"},
{"source": "Maria", "target": "Imogen", "type":"E"}];
// Set up the simulation and add forces
var simulation = d3.forceSimulation()
.nodes(nodes_data);
var link_force = d3.forceLink(links_data)
.id(function(d) { return d.id; });
var charge_force = d3.forceManyBody()
.strength(-200);
var center_force = d3.forceCenter(width / 2, height / 2);
simulation
.force("charge_force", charge_force)
.force("center_force", center_force)
.force("links",link_force);
// Add tick instructions:
simulation.on("tick", tickActions );
// Add encompassing group for the zoom
var g = svg.append("g")
.attr("class", "everything");
// Draw lines for the links
var link = g.append("g")
.attr("class", "links")
.selectAll("line")
.data(links_data)
.enter()
.append("line")
.attr("stroke-width", 2)
.style("stroke", linkColour);
// Draw circles and texts for the nodes
var nodes = g.append("g")
.attr("class", "nodes");
var node = nodes.selectAll("node")
.data(nodes_data)
.enter()
.append("node");
var circle = node.append("circle")
.attr("r", radius)
.attr("fill", circleColour)
.attr("cx", function(d){return d.x})
.attr("cy", function(d){return d.y});
var text = node.append("text")
.text("asdasdasdas")
.attr("cx", function(d){return d.x})
.attr("cy", function(d){return d.y});
// Add drag capabilities
var drag_handler = d3.drag()
.on("start", drag_start)
.on("drag", drag_drag)
.on("end", drag_end);
drag_handler(node);
// Add zoom capabilities
var zoom_handler = d3.zoom()
.on("zoom", zoom_actions);
zoom_handler(svg);
/** Functions **/
function circleColour(d){
if(d.sex == "M"){
return "blue";
} else {
return "pink";
}
}
// Function to choose the line colour and thickness
function linkColour(d){
return "black";
}
// Drag functions
function drag_start(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
// Make sure you can't drag the circle outside the box
function drag_drag(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function drag_end(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
// Zoom functions
function zoom_actions(){
g.attr("transform", d3.event.transform)
}
function tickActions() {
// update node positions each tick of the simulation
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
// update link positions
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; });
}
答案 0 :(得分:3)
您的代码中有三个问题:
没有名为<node>
的SVG元素。因此,而不是......
.append("node");
......应该是:
.append("g");
文字元素没有cx
或cy
属性。
您必须,而不是更改cx
的{{1}}或cy
,而node
没有(因为它是<g>
元素)翻译:
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"
});
总之,这是您更新的代码:
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: black;
stroke-width: 0px;
}
&#13;
<svg width="800" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
// Create somewhere to put the force directed graph
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var radius = 20;
// DATA
var nodes_data = [{
"id": "Lillian",
"sex": "F"
}, {
"id": "Gordon",
"sex": "M"
}, {
"id": "Sylvester",
"sex": "M"
}, {
"id": "Mary",
"sex": "F"
}, {
"id": "Helen",
"sex": "F"
}, {
"id": "Jamie",
"sex": "M"
}, {
"id": "Jessie",
"sex": "F"
}, {
"id": "Ashton",
"sex": "M"
}, {
"id": "Duncan",
"sex": "M"
}, {
"id": "Evette",
"sex": "F"
}, {
"id": "Mauer",
"sex": "M"
}, {
"id": "Fray",
"sex": "F"
}, {
"id": "Duke",
"sex": "M"
}, {
"id": "Baron",
"sex": "M"
}, {
"id": "Infante",
"sex": "M"
}, {
"id": "Percy",
"sex": "M"
}, {
"id": "Cynthia",
"sex": "F"
}, {
"id": "Feyton",
"sex": "M"
}, {
"id": "Lesley",
"sex": "F"
}, {
"id": "Yvette",
"sex": "F"
}, {
"id": "Maria",
"sex": "F"
}, {
"id": "Lexy",
"sex": "F"
}, {
"id": "Peter",
"sex": "M"
}, {
"id": "Ashley",
"sex": "F"
}, {
"id": "Finkler",
"sex": "M"
}, {
"id": "Damo",
"sex": "M"
}, {
"id": "Imogen",
"sex": "F"
}];
var links_data = [{
"source": "Sylvester",
"target": "Gordon",
"type": "A"
}, {
"source": "Sylvester",
"target": "Lillian",
"type": "A"
}, {
"source": "Sylvester",
"target": "Mary",
"type": "A"
}, {
"source": "Sylvester",
"target": "Jamie",
"type": "A"
}, {
"source": "Sylvester",
"target": "Jessie",
"type": "A"
}, {
"source": "Sylvester",
"target": "Helen",
"type": "A"
}, {
"source": "Helen",
"target": "Gordon",
"type": "A"
}, {
"source": "Mary",
"target": "Lillian",
"type": "A"
}, {
"source": "Ashton",
"target": "Mary",
"type": "A"
}, {
"source": "Duncan",
"target": "Jamie",
"type": "A"
}, {
"source": "Gordon",
"target": "Jessie",
"type": "A"
}, {
"source": "Sylvester",
"target": "Fray",
"type": "E"
}, {
"source": "Fray",
"target": "Mauer",
"type": "A"
}, {
"source": "Fray",
"target": "Cynthia",
"type": "A"
}, {
"source": "Fray",
"target": "Percy",
"type": "A"
}, {
"source": "Percy",
"target": "Cynthia",
"type": "A"
}, {
"source": "Infante",
"target": "Duke",
"type": "A"
}, {
"source": "Duke",
"target": "Gordon",
"type": "A"
}, {
"source": "Duke",
"target": "Sylvester",
"type": "A"
}, {
"source": "Baron",
"target": "Duke",
"type": "A"
}, {
"source": "Baron",
"target": "Sylvester",
"type": "E"
}, {
"source": "Evette",
"target": "Sylvester",
"type": "E"
}, {
"source": "Cynthia",
"target": "Sylvester",
"type": "E"
}, {
"source": "Cynthia",
"target": "Jamie",
"type": "E"
}, {
"source": "Mauer",
"target": "Jessie",
"type": "E"
}, {
"source": "Duke",
"target": "Lexy",
"type": "A"
}, {
"source": "Feyton",
"target": "Lexy",
"type": "A"
}, {
"source": "Maria",
"target": "Feyton",
"type": "A"
}, {
"source": "Baron",
"target": "Yvette",
"type": "E"
}, {
"source": "Evette",
"target": "Maria",
"type": "E"
}, {
"source": "Cynthia",
"target": "Yvette",
"type": "E"
}, {
"source": "Maria",
"target": "Jamie",
"type": "E"
}, {
"source": "Maria",
"target": "Lesley",
"type": "E"
}, {
"source": "Ashley",
"target": "Damo",
"type": "A"
}, {
"source": "Damo",
"target": "Lexy",
"type": "A"
}, {
"source": "Maria",
"target": "Feyton",
"type": "A"
}, {
"source": "Finkler",
"target": "Ashley",
"type": "E"
}, {
"source": "Sylvester",
"target": "Maria",
"type": "E"
}, {
"source": "Peter",
"target": "Finkler",
"type": "E"
}, {
"source": "Ashley",
"target": "Gordon",
"type": "E"
}, {
"source": "Maria",
"target": "Imogen",
"type": "E"
}];
// Set up the simulation and add forces
var simulation = d3.forceSimulation()
.nodes(nodes_data);
var link_force = d3.forceLink(links_data)
.id(function(d) {
return d.id;
});
var charge_force = d3.forceManyBody()
.strength(-200);
var center_force = d3.forceCenter(width / 2, height / 2);
simulation
.force("charge_force", charge_force)
.force("center_force", center_force)
.force("links", link_force);
// Add tick instructions:
simulation.on("tick", tickActions);
// Add encompassing group for the zoom
var g = svg.append("g")
.attr("class", "everything");
// Draw lines for the links
var link = g.append("g")
.attr("class", "links")
.selectAll("line")
.data(links_data)
.enter()
.append("line")
.attr("stroke-width", 2)
.style("stroke", linkColour);
// Draw circles and texts for the nodes
var nodes = g.append("g")
.attr("class", "nodes");
var node = nodes.selectAll("node")
.data(nodes_data)
.enter()
.append("g");
var circle = node.append("circle")
.attr("r", radius)
.attr("fill", circleColour);
var text = node.append("text")
.text("asdasdasdas")
.attr("y", -22)
.attr("text-anchor", "middle");
// Add drag capabilities
var drag_handler = d3.drag()
.on("start", drag_start)
.on("drag", drag_drag)
.on("end", drag_end);
drag_handler(node);
// Add zoom capabilities
var zoom_handler = d3.zoom()
.on("zoom", zoom_actions);
zoom_handler(svg);
/** Functions **/
function circleColour(d) {
if (d.sex == "M") {
return "blue";
} else {
return "pink";
}
}
// Function to choose the line colour and thickness
function linkColour(d) {
return "black";
}
// Drag functions
function drag_start(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
// Make sure you can't drag the circle outside the box
function drag_drag(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function drag_end(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
// Zoom functions
function zoom_actions() {
g.attr("transform", d3.event.transform)
}
function tickActions() {
// update node positions each tick of the simulation
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"
});
// update link positions
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;
});
}
</script>
&#13;
答案 1 :(得分:1)
以下是我想要的:https://jsfiddle.net/n504g8vw/1/
我是怎么做到的? 首先,我删除了node元素并将其更改为带有类节点的g元素。
var node = nodes.selectAll("g")
.data(nodes_data)
.enter()
.append("g")
.attr('class', 'node');
好的,现在圈子正在显示但不随图移动。我修改了tick函数来翻译包含圆和文本的g元素。
node.attr('transform', function (d) {
return 'translate(' + d.x + ', ' + d.y + ')';
});
节点现在随图形移动,但圆心不匹配节点的中心。您必须将每个圆的中心设置为0,0。
var circle = node.append("circle")
.attr("r", radius)
.attr("fill", circleColour)
.attr("cx",0)
.attr("cy", 0);
最后你希望文本在节点上居中,这样你就可以在文本上添加一些css,你可以像这样使用D3(或直接在你的css表上)
var text = node.append("text")
.text("asdasdasdas")
.style("text-anchor", "middle");