Built with blockbuilder.org
forked from anonymous's block: Color Scale Incorrect after Link Severing
forked from anonymous's block: Color Scale Incorrect after Link Severing
forked from anonymous's block: Color Scale Incorrect after Link Severing
license: mit |
Built with blockbuilder.org
forked from anonymous's block: Color Scale Incorrect after Link Severing
forked from anonymous's block: Color Scale Incorrect after Link Severing
forked from anonymous's block: Color Scale Incorrect after Link Severing
<!DOCTYPE html> | |
<head> | |
<meta charset = "UTF-8"> | |
<link rel = "stylesheet" type = "text/css" href = "network.css?<?php echo time(); ?>"/> | |
</head> | |
<svg width="600" height="400"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> | |
<script src="d3-tip.js"></script> | |
<script> | |
var svg = d3.select("svg"), | |
width = +svg.attr("width"), | |
height = +svg.attr("height"); | |
var simulation = d3.forceSimulation() | |
.force("link", d3.forceLink().id(function(d) { return d.id; })) | |
.force("charge", d3.forceManyBody().strength(-200)) | |
.force("center", d3.forceCenter(width / 2, height / 2)); | |
d3.json("test.json", function(error, graph) { | |
if (error) throw error; | |
var color = d3.scaleSequential().domain([d3.min(graph.links, function(d) {return d.value; }), d3.max(graph.links, function(d) {return d.value; })]).interpolator(d3.interpolateBlues); | |
svg.append("svg:defs").selectAll("marker") | |
.data(["end"]) | |
.enter().append("svg:marker") | |
.attr("id", String) | |
.attr("viewBox", "0 -5 10 10") | |
.attr("refX", 15) | |
.attr("refY", -1.5) | |
.attr("markerWidth", 2) | |
.attr("markerHeight", 2) | |
.attr("orient", "auto") | |
.append("svg:path") | |
.attr("d", "M0,-5L10,0L0,5"); | |
var link = svg.append("g") | |
.attr("class", "links") | |
.attr("marker-end", "url(#end)") | |
.selectAll("path") | |
.data(graph.links, function(d){ return d.value}) | |
.enter().append("path") | |
.style("stroke", function(d) { return color(d.value); }) | |
.style("fill", "none") | |
.style("stroke-width", "3px"); | |
var node = svg.append("g") | |
.attr("class", "nodes") | |
.selectAll("circle") | |
.data(graph.nodes) | |
.enter().append("circle") | |
.attr("r", 4) | |
.call(d3.drag() | |
.on("start", dragstart) | |
.on("drag", dragged) | |
.on("end", dragend)); | |
node.append("title") | |
.text(function(d) { return d.id; }); | |
simulation | |
.nodes(graph.nodes) | |
.on("tick", tick); | |
simulation.force("link") | |
.links(graph.links); | |
graph.links.sort(function(a,b) { | |
if (a.source > b.source) {return 1;} | |
else if (a.source < b.source) {return -1;} | |
else { | |
if (a.target > b.target) {return 1;} | |
if (a.target < b.target) {return -1;} | |
else {return 0;} | |
} | |
}); | |
for (var i=0; i<graph.links.length; i++) { | |
if (i != 0 && | |
graph.links[i].source == graph.links[i-1].source && | |
graph.links[i].target == graph.links[i-1].target) { | |
graph.links[i].linknum = graph.links[i-1].linknum + 1; | |
} | |
else {graph.links[i].linknum = 1;}; | |
}; | |
function tick() { | |
link.attr("d", linkArc); | |
node.attr("transform", transform); | |
//text.attr("transform", transform); | |
} | |
function linkArc(d) { | |
var curve=2; | |
var homogeneous=3.2; | |
var dx = d.target.x - d.source.x, | |
dy = d.target.y - d.source.y, | |
dr = Math.sqrt(dx*dx+dy*dy)*(d.linknum+homogeneous)/(curve*homogeneous); //linknum is defined above | |
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y; | |
} | |
function transform(d) { | |
return "translate(" + d.x + "," + d.y + ")"; | |
} | |
function dragstart(d, i) { | |
simulation.stop() | |
} | |
function dragged(d) { | |
d.fx = d3.event.x; | |
d.fy = d3.event.y; | |
} | |
function dragend(d, i) { | |
simulation.alpha(0.3).restart(); | |
} | |
// A slider (using only d3 and HTML5) that removes nodes below the input threshold. | |
var slider = d3.select('body').append('p').text('Edge Weight Threshold: '); | |
slider.append('label') | |
.attr('for', 'threshold') | |
.text(''); | |
slider.append('input') | |
.attr('type', 'range') | |
.attr('min', d3.min(graph.links, function(d) {return d.value; })) | |
.attr('max', d3.max(graph.links, function(d) {return d.value; })) | |
.attr('value', d3.min(graph.links, function(d) {return d.value; })) | |
.attr('id', 'threshold') | |
.style('width', '50%') | |
.style('display', 'block') | |
.on('input', function () { | |
var threshold = this.value; | |
d3.select('label').text(threshold); | |
// Find the links that are at or above the threshold. | |
var newData = []; | |
graph.links.forEach( function (d) { | |
if (d.value >= threshold) {newData.push(d); }; | |
}); | |
color.domain([d3.min(newData, function(d) {return d.value; }), d3.max(newData, function(d) {return d.value; })]); | |
// Data join with only those new links. | |
link = link.data(newData, function(d){ return d.value}); | |
link.exit().remove(); | |
var linkEnter = link.enter().append("path") | |
.style("stroke", function(d) { return color(d.value); }) | |
.style("fill", "none") | |
.style("stroke-width", "3px"); | |
link = linkEnter.merge(link).style("stroke", function(d) { return color(d.value); }); | |
node = node.data(graph.nodes); | |
// Restart simulation with new link data. | |
simulation.nodes(graph.nodes) | |
.on('tick', tick) | |
simulation.force("link") | |
.links(newData); | |
simulation.alphaTarget(0.1).restart(); | |
}); | |
}); | |
</script> |
{"nodes": [{"id": "Jim Halpert"}, {"id": "Pam Beasley"}, {"id": "Dwight Schrute"}, {"id": "Stanley Hudson"}, {"id": "Ryan Howard"}, {"id": "Kevin Malone"}, {"id": "Angela"}, {"id": "Michael Scott"}], "links": [{"source": "Michael Scott", "target": "Stanley Hudson", "value": 177}, {"source": "Michael Scott", "target": "Jim Halpert", "value": 164}, {"source": "Dwight Schrute", "target": "Michael Scott", "value": 166}, {"source": "Kevin Malone", "target": "Michael Scott", "value": 177}, {"source": "Ryan Howard", "target": "Michael Scott", "value": 179}, {"source": "Pam Beasley", "target": "Michael Scott", "value": 165}, {"source": "Jim Halpert", "target": "Michael Scott", "value": 168}, {"source": "Angela", "target": "Michael Scott", "value": 179}]} |