A sankey diagram where connection between nodes are represented by goo.
forked from emeeks's block: Gooey Sankey
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Gooey Sankey</title>
<style>
.node rect {
cursor: move;
fill-opacity: .9;
shape-rendering: crispEdges;
}
.node text {
pointer-events: none;
text-shadow: 0 1px 0 #fff;
}
.link {
fill: none;
}
svg {
position: absolute;
}
canvas {
position: absolute;
}
</style>
</head>
<body>
<canvas width="1000" height="1000" ></canvas>
<svg width="1000" height="1000" ></svg>
<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.sankey.js" charset="utf-8" type="text/javascript"></script>
<script src="d3-glyphEdge.js" charset="utf-8" type="text/javascript"></script>
<script type="text/javascript">
var margin = {top: 1, right: 1, bottom: 6, left: 1},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatNumber = d3.format(",.0f"),
format = function(d) { return formatNumber(d) + " TWh"; },
color = d3.scale.category20b();
var svg = d3.select("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var filter = d3.select("svg").append("defs").append("filter").attr("id", "gooeyCodeFilter");
filter.append("feGaussianBlur").attr("id", "gaussblurrer").attr("in", "SourceGraphic").attr("stdDeviation", 6).attr("color-interpolation-filters", "sRGB").attr("result", "blur");
filter.append("feColorMatrix").attr("in", "blur").attr("mode", "matrix").attr("values", "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 34 -7").attr("result", "gooey");
var unfilteredbaseG = d3.select("svg").append("g")
.attr("class", "bg")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
svg = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.style("filter", "url(#gooeyCodeFilter)")
var sankey = d3.sankey()
.nodeWidth(15)
.nodePadding(10)
.size([width, height]);
var path = sankey.link();
var freqCounter = 1;
d3.json("energy.json", function(energy) {
energy.links.forEach(function (d) {
d.o_value = d.value;
d.value = 1;
})
sankey
.nodes(energy.nodes)
.links(energy.links)
.layout(32);
var linkExtent = d3.extent(energy.links, function (d) {return d.o_value});
var frequencyScale = d3.scale.linear().domain(linkExtent).range([0.01,0.5]);
var particleSize = d3.scale.linear().domain(linkExtent).range([1,5]);
unfilteredbaseG.selectAll("path.link")
.data(energy.links)
.enter()
.append("path")
.attr("d", path)
.style("stroke", "lightgray")
.style("fill", "none")
.style("stroke-opacity", 0.25)
.style("stroke-width", function(d) { return Math.max(1, d.dy); })
.each(function (link) {
link.particleSize = 3;
link.particleColor = link.source.color;
link.particles = [];
link.frequency = frequencyScale(link.o_value);
link.speed = (Math.random() + 1) * 5;
})
var linkG = svg
.selectAll("g.link")
.data(energy.links)
.enter()
.append("g")
.attr("class", "link")
d3.selectAll("g.link")
.append("path")
.attr("d", path)
.style("stroke", "none")
.style("stroke-width", function(d) { return Math.max(1, d.dy); })
.each(function (link) {
link.particleSize = 3;
link.particleColor = link.source.color;
link.particles = [];
link.frequency = frequencyScale(link.o_value);
link.speed = Math.random() + 1;
})
var node = svg.append("g").selectAll(".node")
.data(energy.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.call(d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", function() { this.parentNode.appendChild(this); })
.on("drag", dragmove));
node.append("rect")
.attr("height", function(d) { return d.dy; })
.attr("width", sankey.nodeWidth())
.style("fill", function(d) { return d.color = color(d.name.replace(/ .*/, "")); })
.style("stroke", "none")
.append("title")
.text(function(d) { return d.name + "\n" + format(d.o_value); });
function dragmove(d) {
d3.select(this).attr("transform", "translate(" + d.x + "," + (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + ")");
sankey.relayout();
d3.selectAll("g.link > path").attr("d", path);
}
var start
function step(timestamp) {
particles();
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
function particles() {
d3.selectAll("g.link")
.each(function (d, i) {
d3_glyphEdge.mutate.particle(d, d3.select(this).select("path").node(), d.frequency, d.speed);
d3.select(this).selectAll("circle")
.data(d.particles)
.enter()
.append("circle")
.style("fill", d.source.color)
.attr("r", 5);
d3.select(this).selectAll("circle")
.data(d.particles)
.exit()
.remove();
d3.select(this).selectAll("circle")
.attr("cx", function (p) {return p.x})
.attr("cy", function (p) {return p.y});
})
}
});
</script>
</body>
</html>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js