Skip to content

Instantly share code, notes, and snippets.

@LukeKuenneke
Last active November 1, 2017 21:00
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 LukeKuenneke/0d403a56e38bb2aa636b712f86e0a16c to your computer and use it in GitHub Desktop.
Save LukeKuenneke/0d403a56e38bb2aa636b712f86e0a16c to your computer and use it in GitHub Desktop.
Sankey Wimsatt Design Seed Josh
<p id="chart">
function getViewPortWidth() {
return Math.max(document.documentElement.clientWidth, window.innerWidth || 0) * 0.99;
}
function getViewPortHeight() {
return Math.max(document.documentElement.clientHeight, window.innerHeight || 0) * 0.985;
}
var margin = {
top: 1,
right: 1,
bottom: 6,
left: 1
},
width = getViewPortWidth() - margin.left - margin.right,
height = getViewPortHeight() - margin.top - margin.bottom;
var formatNumber = d3.format(",.0f"),
format = function (d) {
return formatNumber(d) + " TWh";
},
color = d3.scale.category20();
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var sankey = d3.sankey()
.nodeWidth(20)
.nodePadding(50)
.size([width, height]);
var path = sankey.link();
var json_data = {
nodes: [
// Columns
{ "id": 0, "name": "Object" },
{ "id": 1, "name": "Behavior" },
{ "id": 2, "name": "System" },
{ "id": 3, "name": "Enviornment" },
{ "id": 4, "name": "Purpose" },
{ "id": 5, "name": "Theory" },
{ "id": 6, "name": "Consequence" },
// NULL Nodes
{ "id": 7, "name": "NULL Object" },
{ "id": 8, "name": "NULL Behavior" },
{ "id": 9, "name": "NULL System" },
{ "id": 10, "name": "NULL Enviornment" },
{ "id": 11, "name": "NULL Purpose" },
{ "id": 12, "name": "NULL Theory" },
{ "id": 13, "name": "NULL Consequence" },
// Objects
{ "id": 14, "name": "Housing" },
{ "id": 15, "name": "3 Layers of Struct" },
{ "id": 16, "name": "Military Base" },
{ "id": 17, "name": "Hardened Underground Structures" },
{ "id": 18, "name": "Much Smaller" },
{ "id": 19, "name": "No Docks" },
{ "id": 20, "name": "Tarmac" },
{ "id": 21, "name": "Tower" },
{ "id": 22, "name": "Helicopter Hangar" },
// Behaviors
{ "id": 23, "name": "More Fortified Than USA, France, Japan" },
{ "id": 24, "name": "Ongoing Construction" },
{ "id": 25, "name": "No Docks" },
{ "id": 26, "name": "All False" },
// Systems
{ "id": 27, "name": "China" },
{ "id": 28, "name": "Djibouti" },
{ "id": 29, "name": "Hardened Underground Structures" },
{ "id": 30, "name": "Much Smaller" },
// Enviornments
{ "id": 31, "name": "Chinese Deception" },
{ "id": 32, "name": "Horn of Africa Resources" },
{ "id": 33, "name": "Much Smaller" },
{ "id": 34, "name": "Pirates In The Region" },
// Purposes
{ "id": 35, "name": "Humanitarian" },
{ "id": 36, "name": "Anti Piracy" },
{ "id": 37, "name": "Global Naval Force" },
{ "id": 38, "name": "Unknown Purpose of Underground Facilities" },
{ "id": 39, "name": "Military!" },
{ "id": 40, "name": "Presence Among Other Nations (Allied Partners)" },
{ "id": 41, "name": "Masked by Construction" },
{ "id": 42, "name": "Deception" },
// Theories
{ "id": 43, "name": "Global Naval Force" },
{ "id": 44, "name": "Naval Force Have Mark of A Super Power" },
{ "id": 45, "name": "Small Naval Force" },
{ "id": 46, "name": "Non Military" },
{ "id": 47, "name": "Non Civil or Military O/D Posture" },
{ "id": 48, "name": "Level of Security Preperation" },
{ "id": 49, "name": "Facade" },
// Consequences
{ "id": 50, "name": "Establishing a Global Naval Force" },
{ "id": 51, "name": "Humanitarian Aid / Anti-Piracy Policing" },
{ "id": 52, "name": "Establishing a Global Military Force" },
{ "id": 53, "name": "Draw Attention" },
],
"links": [
// Headers
{ "source": 0, "target": 1, "value": 1 },
{ "source": 1, "target": 2, "value": 1 },
{ "source": 2, "target": 3, "value": 1 },
{ "source": 3, "target": 4, "value": 1 },
{ "source": 4, "target": 5, "value": 1 },
{ "source": 5, "target": 6, "value": 1 },
// Null Nodes
{ "source": 7, "target": 8, "value": 1 },
{ "source": 8, "target": 9, "value": 1 },
{ "source": 9, "target": 10, "value": 1 },
{ "source": 10, "target": 11, "value": 1 },
{ "source": 11, "target": 12, "value": 1 },
{ "source": 12, "target": 13, "value": 1 },
// Object -> Behavior
// Housing, More Fortified
{ "source": 14, "target": 23, "value": 1 },
// Housing, Ongoing Construction
{ "source": 14, "target": 24, "value": 1 },
// Housing, No Docks
{ "source": 14, "target": 25, "value": 1 },
// 3 Layers of Struct, More Fortified
{ "source": 15, "target": 23, "value": 1 },
// 3 Layers of Struct, Ongoing Construction
{ "source": 15, "target": 24, "value": 1 },
// 3 Layers of Struct, No Docks
{ "source": 15, "target": 25, "value": 1 },
// Military Base, More Fortified
{ "source": 16, "target": 23, "value": 1 },
// Military Base, Ongoing Construction
{ "source": 16, "target": 24, "value": 1 },
// Military Base, No Docks
{ "source": 16, "target": 25, "value": 1 },
// Hardened Underground Structures, More Fortified
{ "source": 17, "target": 23, "value": 1 },
// Hardened Underground Structures, Ongoing Construction
{ "source": 17, "target": 24, "value": 1 },
// Hardened Underground Structures, No Docks
{ "source": 17, "target": 25, "value": 1 },
// Much Smaller, Ongoing Construction
{ "source": 18, "target": 24, "value": 1 },
// Much Smaller, No Docks
{ "source": 18, "target": 25, "value": 1 },
// No Docks, Ongoing Construction
{ "source": 19, "target": 24, "value": 1 },
// No Docks, No Docks
{ "source": 19, "target": 25, "value": 1 },
// Tarmac, More Fortified
{ "source": 20, "target": 23, "value": 1 },
// Tarmac, Ongoing Construction
{ "source": 20, "target": 24, "value": 1 },
// Tower, More Fortified
{ "source": 21, "target": 23, "value": 1 },
// Tower, Ongoing Construction
{ "source": 21, "target": 24, "value": 1 },
// Tower, No Docks
{ "source": 21, "target": 25, "value": 1 },
// Helicopter Hangar, More Fortified
{ "source": 22, "target": 23, "value": 1 },
// Helicopter Hangar, Ongoing Construction
{ "source": 22, "target": 24, "value": 1 },
// Helicopter Hangar, No Docks
{ "source": 22, "target": 25, "value": 1 },
// Helicopter Hangar, All False
{ "source": 22, "target": 26, "value": 1 },
// Behavior -> System
// More Fortified, China
{ "source": 23, "target": 27, "value": 1 },
// More Fortified, Djibouti
{ "source": 23, "target": 28, "value": 1 },
// More Fortified, Hardened Underground Structures
{ "source": 23, "target": 29, "value": 1 },
// Ongoing Construction, China
{ "source": 24, "target": 27, "value": 1 },
// Ongoing Construction, Djibouti
{ "source": 24, "target": 28, "value": 1 },
// Ongoing Construction, Hardened Underground Structures
{ "source": 24, "target": 29, "value": 1 },
// Ongoing Construction, Much Smaller
{ "source": 24, "target": 30, "value": 1 },
// No Docks, China
{ "source": 25, "target": 27, "value": 1 },
// No Docks, Djibouti
{ "source": 25, "target": 28, "value": 1 },
// No Docks, Hardened Underground Structures
{ "source": 25, "target": 29, "value": 1 },
// No Docks, Much Smaller
{ "source": 25, "target": 30, "value": 1 },
// All False, China
{ "source": 26, "target": 27, "value": 1 },
// All False, Djibouti
{ "source": 26, "target": 28, "value": 1 },
// All False, Hardened Underground Structures
{ "source": 26, "target": 29, "value": 1 },
// All False, Much Smaller
{ "source": 26, "target": 30, "value": 1 },
// System -> Environment
// China, Chinese Deception
{ "source": 27, "target": 31, "value": 1 },
// China, Horn of Africa Resources
{ "source": 27, "target": 32, "value": 1 },
// China, Much Smaller
{ "source": 27, "target": 33, "value": 1 },
// Djibouti, Chinese Deception
{ "source": 28, "target": 31, "value": 1 },
// Djibouti, Horn of Africa Resources
{ "source": 28, "target": 32, "value": 1 },
// Djibouti, Much Smaller
{ "source": 28, "target": 33, "value": 1 },
// Djibouti, Pirates in the region
{ "source": 28, "target": 34, "value": 1 },
// Hardened Underground Structures, Chinese Deception
{ "source": 29, "target": 31, "value": 1 },
// Hardened Underground Structures, Horn of Africa Resources
{ "source": 29, "target": 32, "value": 1 },
// Hardened Underground Structures, Much Smaller
{ "source": 29, "target": 33, "value": 1 },
// Much Smaller, Chinese Deception
{ "source": 30, "target": 31, "value": 1 },
// Much Smaller, Horn of Africa Resources
{ "source": 30, "target": 32, "value": 1 },
// Much Smaller, Much Smaller
{ "source": 30, "target": 33, "value": 1 },
// Environment -> Purpose
// Chinese Deception, Masked by Construction
{ "source": 31, "target": 41, "value": 1 },
// Chinese Deception, Deception
{ "source": 31, "target": 42, "value": 1 },
// Chinese Deception, Anti Piracy
{ "source": 31, "target": 36, "value": 1 },
// Chinese Deception, Global Navy Force
{ "source": 31, "target": 37, "value": 1 },
// Chinese Deception, Masked by Construction
{ "source": 31, "target": 41, "value": 1 },
// Chinese Deception, Unknown Purpose of Underground Facilities
{ "source": 31, "target": 38, "value": 1 },
// Horn of Africa, Anti Piracy
{ "source": 32, "target": 36, "value": 1 },
// Horn of Africa, Global Navy Force
{ "source": 32, "target": 37, "value": 1 },
// Horn of Africa, Unknown Purpose of Underground Facilities
{ "source": 32, "target": 38, "value": 1 },
// Much Smaller, Global Naval Force
{ "source": 33, "target": 37, "value": 1 },
// Much Smaller, Unknown Purpose of Underground Facilities
{ "source": 33, "target": 38, "value": 1 },
// Pirates in The Region. Humanitarian
{ "source": 34, "target": 35, "value": 1 },
// Pirates in The Region. Anti Piracy
{ "source": 34, "target": 36, "value": 1 },
//NULL Environment, Military!
{ "source": 10, "target": 39, "value": 1 },
//NULL Environment, Presence Among Other Allied Nations
{ "source": 10, "target": 40, "value": 1 },
// Purpose -> Theory
// Humanitarian, Non Military
{ "source": 35, "target": 46, "value": 1 },
// Humanitarian, Facade
{ "source": 35, "target": 49, "value": 1 },
// Anti Piracy, Facade
{ "source": 36, "target": 49, "value": 1 },
// Anti Piracy, Non Military
{ "source": 36, "target": 46, "value": 1 },
// Global Naval Force, Global Naval Force
{ "source": 37, "target": 43, "value": 1 },
// Global Naval Force, Naval Force Hallmark of a Super Power
{ "source": 37, "target": 44, "value": 1 },
// Global Naval Force, Small Naval Force
{ "source": 37, "target": 45, "value": 1 },
// Unknown Purpose of Underground Facilities, Facade
{ "source": 38, "target": 49, "value": 1 },
// Unknown Purpose of Underground Facilities, Non Civil / Military O/D Posture
{ "source": 38, "target": 47, "value": 1 },
// Unknown Purpose of Underground Facilities, Level of Security / Preparation
{ "source": 38, "target": 48, "value": 1 },
// Military!, Facade
{ "source": 39, "target": 49, "value": 1 },
// Military!, Non Civil / Military O/D Posture
{ "source": 39, "target": 47, "value": 1 },
// Military!, Level of Security / Preparation
{ "source": 39, "target": 48, "value": 1 },
// Presence Among Other Allied Nations, Non Civil / Military O/D Posture
{ "source": 40, "target": 47, "value": 1 },
// Presence Among Other Allied Nations, Level of Security / Preparation
{ "source": 40, "target": 48, "value": 1 },
// Masked By Construction, Facade
{ "source": 41, "target": 49, "value": 1 },
// Deception, Facade
{ "source": 42, "target": 49, "value": 1 },
// Theory -> Consequence
// Global Naval Force, Establishing a Global Naval Force
{ "source": 43, "target": 50, "value": 1 },
// Naval Force Hallmark of a Super Power, Establishing a Global Naval Force
{ "source": 44, "target": 50, "value": 1 },
// Small Naval Force, Establishing a Global Naval Force
{ "source": 45, "target": 50, "value": 1 },
// Non Military, Humanitarian Aid / Anti Piracy
{ "source": 46, "target": 51, "value": 1 },
// Non Civil / Military O/D Posture, Establish Global Military Force
{ "source": 47, "target": 52, "value": 1 },
// Level of Security / Preparation. Establish Global Military Force
{ "source": 48, "target": 52, "value": 1 },
// Facade, Draw Attention
{ "source": 49, "target": 53, "value": 1 },
]
};
d3.json(JSON.stringify(json_data), function (error) {
sankey
.nodes(json_data.nodes)
.links(json_data.links)
.layout(32);
var link = svg.append("g").selectAll(".link")
.data(json_data.links)
.enter().append("path")
.attr("class", "link")
.attr("d", path)
.attr("id", function(d,i){
d.id = i;
return "link-"+i;
})
.style("stroke-width", function(d) { return Math.max(1, d.dy); })
.sort(function(a, b) { return b.dy - a.dy; });
link.append("title")
.text(function(d) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); });
var node = svg.append("g").selectAll(".node")
.data(json_data.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.on("click", highlightNodeLinks)
.call(d3.behavior.drag()
.origin(function(d) { return d; })
.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", function(d) { return d3.rgb(d.color).darker(2); })
.append("title")
.text(function(d) { return d.name + "\n" + format(d.value); });
node.append("text")
.attr("x", -6)
.attr("y", function(d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "end")
.attr("transform", null)
.text(function(d) { return d.name; })
.filter(function(d) { return d.x < width / 2; })
.attr("x", 6 + sankey.nodeWidth())
.attr("text-anchor", "start");
function dragmove(d) {
d3.select(this).attr("transform", "translate(" + (d.x = Math.max(0, Math.min(width - d.dx, d3.event.x))) + "," + (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + ")");
sankey.relayout();
link.attr("d", path);
}
function highlightNodeLinks(node,i){
var remainingNodes=[],
nextNodes=[];
var stroke_opacity = 0;
if( d3.select(this).attr("data-clicked") == "1" ){
d3.select(this).attr("data-clicked","0");
stroke_opacity = 0.2;
}else{
d3.select(this).attr("data-clicked","1");
stroke_opacity = 0.5;
}
var traverse = [{
linkType : "sourceLinks",
nodeType : "target"
},{
linkType : "targetLinks",
nodeType : "source"
}];
traverse.forEach(function(step){
node[step.linkType].forEach(function(link) {
remainingNodes.push(link[step.nodeType]);
highlight_link(link.id, stroke_opacity);
});
while (remainingNodes.length) {
nextNodes = [];
remainingNodes.forEach(function(node) {
node[step.linkType].forEach(function(link) {
nextNodes.push(link[step.nodeType]);
highlight_link(link.id, stroke_opacity);
});
});
remainingNodes = nextNodes;
}
});
}
function highlight_link(id,opacity){
d3.select("#link-"+id).style("stroke-opacity", opacity);
}
});
<script src="https://d3js.org/d3.v2.min.js?2.9.1"></script>
<script src="https://bost.ocks.org/mike/sankey/sankey.js"></script>
#chart {
height: 500px;
}
.node rect {
cursor: move;
fill-opacity: .9;
shape-rendering: crispEdges;
}
.node text {
pointer-events: none;
text-shadow: 0 1px 0 #fff;
}
.link {
fill: none;
stroke: #000;
stroke-opacity: .2;
}
.link:hover {
stroke-opacity: .5 !important;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment