A non-photorealistically rendered network visualization utilizing (d3.sketchy)[https://github.com/sebastian-meier/d3.sketchy] along with some custom sketchy functions showing data from Bostock's (Chord Example of the Euro Debt Crisis)[/mbostock/1308257].
xxxxxxxxxx
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<title>All the Datavizzes</title>
<meta charset="utf-8" />
<link type="text/css" rel="stylesheet" href="noceiling.css" />
<style type="text/css">
g.sketchy-stroke > path {
fill: none;
stroke: black;
stroke-width: 1px;
stroke-opacity: 0.75;
}
path.sketchy-stroke, path.sketchy-fill, path.original {
fill: none;
stroke: black;
stroke-width: 1px;
stroke-opacity: 0.75;
}
svg {
height: 1000px;
width: 1000px;
}
</style>
</head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js" charset="utf-8" type="text/javascript"></script>
<script src="d3.sketchy.js" charset="utf-8" type="text/javascript"></script>
<script>
sketchy = d3sketchy();
function cheapSketchy(path) {
var length = path.getTotalLength();
var drawCode = "";
var x = 0;
var step = 2;
while (x < length / 2) {
var start = path.getPointAtLength(x);
var end = path.getPointAtLength(length - x);
drawCode += " M" + (start.x + (Math.random() * step - step/2)) + " " + (start.y + (Math.random() * step - step/2)) + "L" + (end.x + (Math.random() * step - step/2)) + " " + (end.y + (Math.random() * step - step/2));
x += step + (Math.random() * step);
}
return drawCode;
}
function jitterLine(pathNode) {
var length = pathNode.getTotalLength();
var j = 2;
var x = j + (Math.random() * (j * 5));
var jitteredPoints = [];
var lineGen = d3.svg.line()
.x(function (d) {return d.x})
.y(function (d) {return d.y}).interpolate("basis");
var newPoint = pathNode.getPointAtLength(0);
jitteredPoints.push(newPoint);
while (x < length) {
newPoint = pathNode.getPointAtLength(x);
var newX = newPoint.x + ((Math.random() * j) - j/2);
var newY = newPoint.y + ((Math.random() * j) - j/2)
jitteredPoints.push({x: newX, y: newY})
x += j + (Math.random() * (j * 5));
}
newPoint = pathNode.getPointAtLength(length);
jitteredPoints.push(newPoint);
return lineGen(jitteredPoints);
}
function forceNetwork() {
d3.csv("debt.csv", drawNetwork);
}
function drawNetwork(data) {
var nodes = [];
var nodeHash = {};
var edges = [];
data.forEach(function (link) {
if (!nodeHash[link.creditor]) {
nodeHash[link.creditor] = {id: link.creditor, r: 7};
nodes.push(nodeHash[link.creditor]);
}
if (!nodeHash[link.debtor]) {
nodeHash[link.debtor] = {id: link.debtor, r: 7};
nodes.push(nodeHash[link.debtor]);
}
if (link.amount > 50) {
var newEdge = {source: nodeHash[link.creditor], target: nodeHash[link.debtor], amount: parseFloat(link.amount), risk: parseInt(link.risk)};
edges.push(newEdge);
}
});
weightscale = d3.scale.linear().domain([0,10]).range([5,25]);
amountscale = d3.scale.linear().domain([50,300]).range([2,6]);
edgescale = d3.scale.quantile().domain(
edges.map(function(d) {return d.amount}))
.range(["#fdbe85","#fd8d3c","#d94701"]);
force = d3.layout.force()
.links(edges)
.nodes(nodes)
.charge(-2000)
.linkStrength(function (d) {return amountscale(d.amount) * 0.05})
.gravity(0.2)
.size([500, 500])
.on("tick", updateNetwork);
d3.select("svg").selectAll("g.edge")
.data(edges)
.enter()
.append("g")
.attr("class", "edge")
.append("path")
.attr("class", "original")
.style("fill", "none")
.style("stroke", function (d) {return edgescale(d.amount)})
.style("stroke-linecap", "round")
.style("stroke-width", function(d) {return amountscale(d.amount)});
d3.select("svg").selectAll("g.node")
.data(nodes)
.enter()
.append("g")
.call(force.drag)
.attr("class", "node")
.append("path")
.attr("class", "original")
.attr("d", "M 1.5081697,-5.2415042 A 6.0326772,6.0326772 0 1 1 -10.557185,-5.2415042 6.0326772,6.0326772 0 1 1 1.5081697,-5.2415042 z")
function updateNetwork() {
d3.selectAll("g.edge")
.select("path.original")
.attr("d", function (d) {return "M " + d.source.x + "," + d.source.y + " L" + d.target.x + "," + d.target.y})
.attr("d", function (d) {return jitterLine(this)});
d3.selectAll("g.node")
.attr("transform", function (d) {return "translate(" + (d.x + 5) + "," + (d.y + 5) + ")" })
.each(function (d) {
d.r = weightscale(d.weight);
d3.select(this).selectAll("path, g").remove();
sketchy.circleStroke({svg: d3.select(this), x:-(d.r/2), y:-(d.r/2), r:d.r, density:3, sketch:1.3});
d3.select(this).select("path.sketchy-stroke").style("stroke-width", "2px");
d3.select(this).insert("path", "g").attr("class", "sketchy-fill")
.style("fill", "none")
.style("stroke-width", "2px")
.style("stroke-linecap", "round")
.style("stroke", "blue")
.attr("transform", "translate(" + (-d.r/2) +","+(-d.r/2) + ")")
.attr("d", cheapSketchy(d3.select(this).select("path.sketchy-stroke").node()));
});
}
force.start();
}
</script>
<body onload="forceNetwork();">
<div id="viz">
<svg style="background:white;" height=1000 width=1000>
</svg>
</div>
<footer>
</footer>
</body>
</html>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js