Skip to content

Instantly share code, notes, and snippets.

Created June 12, 2017 23:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/59f0783654d89e5a45c55ecf150032bc to your computer and use it in GitHub Desktop.
Save anonymous/59f0783654d89e5a45c55ecf150032bc to your computer and use it in GitHub Desktop.
Color Scale Incorrect after Link Severing
license: mit
<!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}]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment