let data = { "nodes":[ { "name": "compost Cambridge" }, { "name": "compost Ely" }, { "name": "compost Newmarket" }, { "name": "composting Cambridge" }, { "name": "composting Ely" }, { "name": "composting Newmarket" }, { "name": "farm1" }, { "name": "farm10" }, { "name": "farm11" }, { "name": "farm12" }, { "name": "farm13" }, { "name": "farm14" }, { "name": "farm15" }, { "name": "farm2" }, { "name": "farm3" }, { "name": "farm4" }, { "name": "farm5" }, { "name": "farm6" }, { "name": "farm7" }, { "name": "farm8" }, { "name": "farm9" }, { "name": "inputs" }, ], "links": [ { "source": "farm1", "target": "compost Cambridge", "value": 48.59855125 }, { "source": "farm10", "target": "compost Ely", "value": 35.04813663 }, { "source": "farm11", "target": "compost Cambridge", "value": 43.55273505 }, { "source": "farm12", "target": "compost Newmarket", "value": 30.30288327 }, { "source": "farm13", "target": "compost Newmarket", "value": 21.35420786 }, { "source": "farm14", "target": "compost Cambridge", "value": 36.84493903 }, { "source": "farm15", "target": "compost Ely", "value": 27.62251469 }, { "source": "farm2", "target": "compost Cambridge", "value": 30.84488769 }, { "source": "farm3", "target": "compost Ely", "value": 39.02796387 }, { "source": "farm4", "target": "compost Ely", "value": 49.44235333 }, { "source": "farm6", "target": "compost Ely", "value": 44.56712219 }, { "source": "farm7", "target": "compost Ely", "value": 45.75525246 }, { "source": "farm9", "target": "compost Newmarket", "value": 28.82069916 }, { "source": "inputs", "target": "farm1", "value": 567.7275491 }, { "source": "inputs", "target": "farm10", "value": 481.6395358 }, { "source": "inputs", "target": "farm11", "value": 685.555024 }, { "source": "inputs", "target": "farm12", "value": 426.6291005 }, { "source": "inputs", "target": "farm13", "value": 331.4019733 }, { "source": "inputs", "target": "farm14", "value": 536.4944486 }, { "source": "inputs", "target": "farm15", "value": 503.6943365 }, { "source": "inputs", "target": "farm2", "value": 487.9807371 }, { "source": "inputs", "target": "farm3", "value": 644.50464 }, { "source": "inputs", "target": "farm4", "value": 711.3835365 }, { "source": "inputs", "target": "farm5", "value": 279.5272346 }, { "source": "inputs", "target": "farm6", "value": 683.9626375 }, { "source": "inputs", "target": "farm7", "value": 537.0874814 }, { "source": "inputs", "target": "farm8", "value": 723.8470269 }, { "source": "inputs", "target": "farm9", "value": 457.3217745 }, { "source": "compost Cambridge", "target": "farm1", "value": 243.3118067 }, { "source": "compost Cambridge", "target": "farm11", "value": 293.809296 }, { "source": "compost Cambridge", "target": "farm14", "value": 229.9261923 }, { "source": "compost Cambridge", "target": "farm2", "value": 209.1346016 }, { "source": "compost Ely", "target": "farm10", "value": 206.4169439 }, { "source": "compost Ely", "target": "farm15", "value": 215.8690013 }, { "source": "compost Ely", "target": "farm3", "value": 276.2162743 }, { "source": "compost Ely", "target": "farm4", "value": 304.8786585 }, { "source": "compost Ely", "target": "farm6", "value": 293.1268446 }, { "source": "compost Ely", "target": "farm7", "value": 230.1803492 }, { "source": "compost Newmarket", "target": "farm12", "value": 182.8410431 }, { "source": "compost Newmarket", "target": "farm13", "value": 142.0294171 }, { "source": "compost Newmarket", "target": "farm5", "value": 119.7973863 }, { "source": "compost Newmarket", "target": "farm8", "value": 310.2201544 }, { "source": "compost Newmarket", "target": "farm9", "value": 195.9950462 }, { "source": "composting Cambridge", "target": "compost Cambridge", "value": 1463.512338 }, { "source": "composting Ely", "target": "compost Ely", "value": 897.0501156 }, { "source": "composting Newmarket", "target": "compost Newmarket", "value": 565.9238946 } ] }; var margin = { top: 30, right: 30, bottom: 30, left: 30}; var width = 800; var height = 600; var sankey = d3.sankeyCircular() .nodeWidth(10) .nodePaddingRatio(0.1) .size([width, height]) .nodeId(function (d) { return d.name; }) .nodeAlign(d3.sankeyRight) .iterations(32) .circularLinkGap(2); var svg = d3.select("#chart").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); var g = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") var linkG = g.append("g") .attr("class", "links") .attr("fill", "none") .attr("stroke-opacity", 0.2) .selectAll("path"); var nodeG = g.append("g") .attr("class", "nodes") .attr("font-family", "sans-serif") .attr("font-size", 10) .selectAll("g"); //run the Sankey + circular over the data let sankeyData = sankey(data); let sankeyNodes = sankeyData.nodes; let sankeyLinks = sankeyData.links; console.log(sankeyLinks); let depthExtent = d3.extent(sankeyNodes, function (d) { return d.depth; }); var nodeColour = d3.scaleSequential(d3.interpolateCool) .domain([0,width]); var node = nodeG.data(sankeyNodes) .enter() .append("g"); node.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) { return d.x1 - d.x0; }) .style("fill", function (d) { return nodeColour(d.x0); }) .style("opacity", 0.5) .on("mouseover", function (d) { let thisName = d.name; node.selectAll("rect") .style("opacity", function (d) { return highlightNodes(d, thisName) }) d3.selectAll(".sankey-link") .style("opacity", function (l) { return l.source.name == thisName || l.target.name == thisName ? 1 : 0.3; }) node.selectAll("text") .style("opacity", function (d) { return highlightNodes(d, thisName) }) }) .on("mouseout", function (d) { d3.selectAll("rect").style("opacity", 0.5); d3.selectAll(".sankey-link").style("opacity", 0.7); d3.selectAll("text").style("opacity", 1); }) node.append("text") .attr("x", function (d) { return (d.x0 + d.x1) / 2; }) .attr("y", function (d) { return d.y0 - 12; }) .attr("dy", "0.35em") .attr("text-anchor", "middle") .text(function (d) { return d.name; }); node.append("title") .text(function (d) { return d.name + "\n" + (d.value); }); var link = linkG.data(sankeyLinks) .enter() .append("g") link.append("path") .attr("class", "sankey-link") .attr("d", function(link){ return link.path; }) .style("stroke-width", function (d) { return Math.max(1, d.width); }) .style("opacity", 0.7) .style("stroke", function (link, i) { return link.circular ? "red" : "black" }) link.append("title") .text(function (d) { return d.source.name + " → " + d.target.name + "\n Index: " + (d.index); }); function highlightNodes(node, name) { let opacity = 0.3 if (node.name == name) { opacity = 1; } node.sourceLinks.forEach(function (link) { if (link.target.name == name) { opacity = 1; }; }) node.targetLinks.forEach(function (link) { if (link.source.name == name) { opacity = 1; }; }) return opacity; }