Skip to content

Instantly share code, notes, and snippets.

@wiesson
Forked from mbostock/.block
Last active June 6, 2017 13:48
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 wiesson/87c7714081e1b1f24e5b36b4335b09c2 to your computer and use it in GitHub Desktop.
Save wiesson/87c7714081e1b1f24e5b36b4335b09c2 to your computer and use it in GitHub Desktop.
Sankey Diagram
border: no
license: gpl-3.0
{
"nodes": [
{
"node": 0,
"name": "Summary"
},
{
"node": 1,
"name": "Elevator Room_room"
},
{
"node": 2,
"name": "Lobby_room"
},
{
"node": 3,
"name": "Electrical Room_room"
},
{
"node": 4,
"name": "Parking_room"
},
{
"node": 5,
"name": "Parking Garage_room"
},
{
"node": 6,
"name": "Stairwell_room"
},
{
"node": 7,
"name": "Corridors_room"
},
{
"node": 8,
"name": "Driveway_room"
},
{
"node": 9,
"name": "Unknown Room"
},
{
"node": 10,
"name": "Light Fixtures_type"
},
{
"node": 11,
"name": "Ventilation Fans_type"
},
{
"node": 12,
"name": "Water Pump_type"
},
{
"node": 13,
"name": "Other Equipment Type_type"
},
{
"node": 14,
"name": "Space Heaters_type"
},
{
"node": 15,
"name": "Car Charger_type"
},
{
"node": 16,
"name": "Air Conditioning, Room_type"
},
{
"node": 17,
"name": "Elevators_type"
},
{
"node": 18,
"name": "Unknown Equipment-Type"
}
],
"links": [
{
"target": 1,
"source": 0,
"value": 29.96280424660086
},
{
"target": 2,
"source": 0,
"value": 0.5719408294581831
},
{
"target": 3,
"source": 0,
"value": 21.43934895742314
},
{
"target": 4,
"source": 0,
"value": 20.990812664321197
},
{
"target": 5,
"source": 0,
"value": 73.45653630669118
},
{
"target": 6,
"source": 0,
"value": 34.50337156676293
},
{
"target": 7,
"source": 0,
"value": 26.97600977021831
},
{
"target": 8,
"source": 0,
"value": 15.453038509986847
},
{
"target": 9,
"source": 0,
"value": 63.24336843194733
},
{
"target": 10,
"source": 1,
"value": 0.11335325729195697
},
{
"target": 10,
"source": 5,
"value": 73.45653630669118
},
{
"target": 10,
"source": 8,
"value": 15.453038509986847
},
{
"target": 10,
"source": 3,
"value": 0.06682631257344346
},
{
"target": 11,
"source": 1,
"value": 5.380958994788458
},
{
"target": 11,
"source": 6,
"value": 34.50337156676293
},
{
"target": 12,
"source": 1,
"value": 7.929732921089741
},
{
"target": 13,
"source": 2,
"value": 0.5719408294581831
},
{
"target": 13,
"source": 3,
"value": 0.020202968294043052
},
{
"target": 14,
"source": 1,
"value": 0.23720628698672272
},
{
"target": 15,
"source": 4,
"value": 20.990812664321197
},
{
"target": 16,
"source": 3,
"value": 21.352319676555577
},
{
"target": 16,
"source": 7,
"value": 26.97600977021831
},
{
"target": 16,
"source": 1,
"value": 9.000710702176777
},
{
"target": 17,
"source": 1,
"value": 7.300842084267336
},
{
"target": 18,
"source": 9,
"value": 63.24336843194733
}
]
}
<!DOCTYPE html>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/d3-sankey@0.6"></script>
<script>
const getColor = d => d.color = color(d.name.replace(/ .*/, ""));
const svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
const formatNumber = d3.format(",.0f");
const format = d => `${formatNumber(d)} kWh`;
const color = d3.scaleOrdinal(d3.schemeCategory10);
const sankey = d3.sankey()
.nodeWidth(15)
.nodePadding(10)
.extent([[1, 1], [width - 1, height - 6]]);
let link = svg.append("g")
.attr("class", "links")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.4)
.selectAll("path");
let node = svg.append("g")
.attr("class", "nodes")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.selectAll("g");
d3.json("energy.json", function (error, energy) {
if (error) throw error;
sankey(energy);
const defs = svg.append('defs');
link = link
.data(energy.links)
.enter().append("path")
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke-width", d => Math.max(1, d.width));
link.append("title")
.text(d => `${d.source.name} → ${d.target.name} \n ${format(d.value)}`)
node = node
.data(energy.nodes)
.enter().append("g");
node.append("rect")
.attr("x", d => d.x0)
.attr("y", d => d.y0)
.attr("height", d => d.y1 - d.y0)
.attr("width", d => d.x1 - d.x0)
.attr("fill", d => getColor(d))
.attr("stroke-width", 0);
node.append("text")
.attr("x", d => d.x0 - 6)
.attr("y", d => (d.y1 + d.y0) / 2)
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.text(d => d.name)
.filter(d => d.x0 < width / 2)
.attr("x", d => d.x1 + 6)
.attr("text-anchor", "start");
node.append("title")
.text(d => `${d.name} \n ${format(d.value)}`)
link.style('stroke', (d, i) => {
console.log('d from gradient stroke func', d);
// make unique gradient ids
const gradientId = `gradient${i}`;
const startColor = d.source.color;
const stopColor = d.target.color;
// console.log('startColor', startColor);
// console.log('stopColor', stopColor);
const linearGradient = defs.append('linearGradient')
.attr('id', gradientId);
linearGradient.selectAll('stop')
.data([
{ offset: '20%', color: startColor },
{ offset: '80%', color: stopColor }
])
.enter().append('stop')
.attr('offset', d => d.offset)
.attr('stop-color', d => d.color);
return `url(#${gradientId})`;
})
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment