D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
tomshanley
Full window
Github gist
Sankey sort
Built with
blockbuilder.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://d3js.org/d3.v4.min.js"></script> <script src="https://unpkg.com/d3-sankey"></script> </head> <body> <svg id="diagram" height="150" width="600"></svg> <button onclick="updateSankey()">Click Me!</button> <style> #diagram{ border: 1px solid black; } </style> <script> var target = 0; var sankeyLinks; var sankeyData = {nodes:[], links:[]}; calculateLinks(); initSankey(); updateSankey(); function initSankey() { svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); formatNumber = d3.format(",.0f"), format = function (d) { return formatNumber(d) + " %"; }, sankey = d3.sankey() .nodeWidth(15) .nodePadding(10) .size([width - 1, height - 6]) t = d3.transition() .duration(1500) .ease(d3.easeLinear); //set attributes for all links titleGroup = svg.append("g") .attr("class", "titles") .attr("font-family", "sans-serif") .attr("font-size", "150%"); diagram= svg.append("g") .attr("class", "sankey") svg.append("defs") linkGroup = diagram.append("g") .attr("class", "links") .attr("fill", "none"); //set attributes for all nodes nodeGroup = diagram.append("g") .attr("class", "nodes") .attr("font-family", "sans-serif") .attr("font-size", 10); } function calculateLinks() { if(target == 0) { target = 1; sankeyLinks = [ {name: "firstsecond",source:0, target:1, value:5}, {name: "firstthird",source:0, target:2, value:10}, {name: "firstfourth",source:0, target:3, value:15}]; } else { target = 0; sankeyLinks = [ {name: "firstthird", source:0, target:2, value:15}, {name: "firstsecond", source:0, target:1, value:20}, {name: "firstfourth", source:0, target:3, value:10} ]; } } function updateSankey() { calculateLinks(); sankeyData.links = sankeyLinks; sankeyData.nodes = [{name: "first"}, {name:"second"}, {name:"third"}, {name: "fourth"}]; sankey(sankeyData); var pathGradient = svg.select("defs").selectAll("linearGradient") .data(sankeyData.links, function(d){ return d.name }) .enter() .append("linearGradient") .attr("id",function (d) { return "grad" + d.name; }) .attr("gradientUnit","userSpaceOnUse") .attr("x1","0%") .attr("x2","100%") .attr("y1","0%") .attr("y2","0%"); pathGradient.append("stop") .attr("class","from") .attr("offset","0%") .attr("style", function (d) { var color = setColor(d.source); return "stop-color:" + color; }); pathGradient.append("stop") .attr("class","to") .attr("offset","100%") .attr("style",function (d) { var color = setColor(d.target); return "stop-color:" + color; }); var links = linkGroup.selectAll('path') .data(sankeyData.links, function(d){ return d.name }); //Set attributes for each link separately var linksenter = links.enter() .append("g") .attr("id",function (d) {return "path" + d.name;}) .append("path") .style("stroke", "#000") .style("stroke-opacity", 0.15) .attr("stroke-width", function (d) {return Math.max(1, d.width); }) .on("mouseover",function (d) { var pathGroup = svg.select('#path' + d.name); var path = pathGroup.select("path"); path.style("stroke","url(#grad" + d.name + ")") .style("stroke-opacity","0.95"); }) .on("mouseout",function (d, id) { pathGroup = svg.select('#path' + d.source.name + d.target.name); var path = pathGroup.select("path"); path.style("stroke","#000") .style("stroke-opacity","0.15"); }) linksenter.merge(links).attr("d", d3.sankeyLinkHorizontal()) links.transition(t) .attr("d", d3.sankeyLinkHorizontal()) .attr("stroke-width", function (d) { return Math.max(1, d.width); }) .select('title') .text(function (d) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); }); var nodes = nodeGroup.selectAll('.node') .data(sankeyData.nodes, function(d){ return d.name }); var nodesEnter = nodes.enter() .append("g") .attr('class', 'node'); nodesEnter.append("rect") .attr("x", function (d) { return d.x0; }) .attr("y", function (d) { return d.y0; }) .attr("height", function (d) { return d.y1 - d.y0; }) .attr("width", function (d) { var width = d.x1 - d.x0; return width; }) .attr("fill", setColor) .attr("stroke", "#000") .attr("fill-opacity", 0.5) //specify Pop-Up when hovering over node nodesEnter.append("title") .text(function (d) { return d.name + "\n" + format(d.value); }); //Update selection var nodesUpdate = nodes.transition(t); //same as the links we have to state the methods again in the update nodesUpdate.select("rect") .attr("y", function (d) { return d.y0; }) .attr("x", function (d) { return d.x0; }) .attr("height", function (d) { return d.y1 - d.y0; }); nodesUpdate.select("title") .text(function (d) { return d.name + "\n" + format(d.value); }); } function setColor(d) { switch (d.name) { case "first": return "#f00"; case "second": return "#ff0"; case "third": return "#f0f"; case "fourth": return "#0ff"; default: return "#0f0"; } } </script> </body> </html>
https://d3js.org/d3.v4.min.js
https://unpkg.com/d3-sankey