xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<style>
.active {
stroke: #000;
stroke-width: 2px;
}
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
text {
font-family: verdana;
pointer-events: none;
}
</style>
</head>
<body>
<div id="container">
<div id="graph">
</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var bugs_data = [
{
"name": "Redhot",
"attributes": [
{"attribute":"Legs",
"name":"100"},
{"attribute":"Teeth",
"name":"0"},
{"attribute":"Color",
"name":"Red"},
{"attribute":"Habitat",
"name":"Desert"},
{"attribute":"Diet",
"name":"Insects"}
]
},
{
"name": "Dwarf Mantid",
"attributes": [
{"attribute":"Legs",
"name":"4"},
{"attribute":"Teeth",
"name":"4"},
{"attribute":"Color",
"name":"Purple"},
{"attribute":"Habitat",
"name":"Grasslands"},
{"attribute":"Diet",
"name":"Insects"}
]
},
{
"name": "Click Flipper",
"attributes": [
{"attribute":"Legs",
"name":"6"},
{"attribute":"Teeth",
"name":"4"},
{"attribute":"Color",
"name":"Black"},
{"attribute":"Feature",
"name":"Red Stripe"},
{"attribute":"Habitat",
"name":"Desert"},
{"attribute":"Diet",
"name":"Sap"}
]
}
];
var width = 960;
var height = 500;
var radius = 50;
var small_radius = radius * (2/3);
var node_color = "#BBDD44";
var link_distance = radius * 1.68;
var allNodes = [];
var bugNodes = [];
var attributeNodes = [];
var links_data = [];
var graph = d3.select('#graph');
var svg = graph.append('svg')
.attr('width', width)
.attr('height', height);
bugs_data.map(function(entry){
var b = {};
b.name = entry.name;
b.label = entry.name;
b.type = "bug";
b.attributes = entry.attributes;
bugNodes.push(b);
});
bugNodes.forEach(function(bugNode){
bugNode.attributes.map(function(entry){
var atrb = {};
atrb.name = bugNode.name + entry.attribute + entry.name;
atrb.label = entry.name;
atrb.type = "attribute";
atrb.attribute = entry.attribute;
attributeNodes.push(atrb);
var link = {};
link.source = bugNode.name;
link.target = atrb.name;
links_data.push(link);
});
});
allNodes = bugNodes.concat(attributeNodes);
var linkSelection = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(links_data)
.enter()
.append("line")
.attr("stroke-width", 2);
var nodeSelection = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(allNodes)
.enter()
.append("circle")
.attr("r", function(d) {
if(d.type == 'attribute')
return small_radius;
else
return radius;
})
.attr("fill", node_color)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.attr("cx", width/2)
.attr("cx", height/2);
var labelSelection = svg.append("g")
.attr("class", "labels")
.selectAll("text")
.data(allNodes)
.enter()
.append("text")
.text(function(d){ return d.label })
.style("text-anchor", "middle");
var link_force = d3.forceLink(links_data)
.id(function(d) { return d.name; })
.distance(link_distance);
var simulation = d3.forceSimulation()
.nodes(allNodes);
simulation
.force("charge_force", d3.forceManyBody());
// .force("center_force", d3.forceCenter(width/2, height/2));
simulation.force("nodes", link_force);
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
if (!d3.event.active){
simulation.alphaTarget(0.3).restart();
}
}
function dragged(d) {
d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("active", false);
}
function tick(){
nodeSelection
.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
labelSelection
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; });
linkSelection
.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; });
}
simulation.on("tick", tick);
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js