forked from riyoyukai's block: BugsWIP03
forked from anonymous's block: BugsWIP03
license: mit |
<!DOCTYPE html> | |
<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> |