Created
November 24, 2016 11:14
-
-
Save BMPMS/dc7def5f5b8edbd0f4aa6908dc8f59a4 to your computer and use it in GitHub Desktop.
Waterfall
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*general */ | |
text { | |
font: 10px sans-serif; | |
} | |
/*tooltip */ | |
.line { | |
fill: none; | |
stroke: steelblue; | |
stroke-width: 1.5px; | |
} | |
.tooltip, .area_tooltip { | |
visibility: hidden; | |
position: absolute; | |
text-align: left; | |
border: 1px solid grey; | |
padding: 5px; | |
font: 10px sans-serif; | |
background: white; | |
border-radius: 4px; | |
pointer-events: none; | |
width: 150px; | |
height: 25px; | |
} | |
#waterfall { | |
width: 70px; | |
height: 50px; | |
} | |
/*X and Y axis */ | |
.axis text { | |
font-family: sans-serif; | |
font-size: 10px; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.tick line{ | |
visibility:hidden; | |
} | |
.tick { | |
text-align: left; | |
} | |
/* Z axis - lines inbetween*/ | |
.zaxis line, .zaxis path { | |
fill: none; | |
stroke: lightgrey; | |
shape-rendering: crispEdges; | |
} | |
.zaxis text { display: none; } | |
.area { | |
stroke-width: 0; | |
opacity: 0.2; | |
} | |
.area.selected { | |
opacity: 0.6; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<link rel="stylesheet" type="text/css" href="boom_style.css" /> | |
<head> | |
<meta charset="utf-8"> | |
<title>Test Boomslang</title> | |
</head> | |
<body> | |
<div id='waterfall'></div> | |
</body> | |
<script src="http://d3js.org/d3.v4.js"></script> | |
<script src="waterfall.js"></script> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
d3.json("waterfall.json", function(error, root) { | |
if (error) throw error; | |
var my_data = [], | |
locations = []; | |
//format the data | |
my_data = get_data(root) | |
for (var m in my_data) { | |
if (locations.indexOf(my_data[m].label) == -1) { | |
//build unique array of locations | |
locations.push(my_data[m].label); | |
} | |
} | |
//set responsive width, height and margins | |
var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; | |
var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; | |
var margin = {top: 20, right: 40, bottom: 70, left: 100}, | |
width = width - margin.left - margin.right, | |
height = height - margin.top - margin.bottom, | |
padding = 100; | |
//draw svg | |
var svg = d3.select("#waterfall").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 + ")"); | |
//define scales (x,y and color) | |
var x = d3.scaleLinear().domain([0,100]).rangeRound([0, width]); | |
var y = d3.scaleBand().domain(locations).rangeRound([0, height]); | |
var color = d3.scaleOrdinal(d3.schemeCategory10); | |
//define and append axes | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(d3.axisBottom(x).tickSizeOuter(0).tickFormat(function(d) { return d + "%"; })); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(d3.axisLeft(y).tickSizeOuter(0)); | |
//define tooltip | |
var tooltip = d3.select("body") | |
.append("div") | |
.attr("class", "tooltip") | |
.attr("id","waterfall") | |
.html(""); | |
for (var l in locations){ | |
//for every location, draw a divider line (z axis) | |
//change the height for each location and append axis | |
zheight = height - y(locations[l]) - y.bandwidth() | |
svg.append("g") | |
.attr("class","zaxis") | |
.attr("transform","translate(0," + zheight + ")") | |
.call(d3.axisBottom().scale(x).tickSizeOuter(0)) | |
} | |
function gradient(colour,id,x1,x2,off1,off2,op1,op2){ | |
//gradient function. | |
//defines the gradient | |
svg.append("defs") | |
.append("linearGradient") | |
.attr("id",id) | |
.attr("x1", x1).attr("y1", "0%") | |
.attr("x2", x2).attr("y2", "0%"); | |
idtag = '#'+id | |
//defines the start | |
d3.select(idtag) | |
.append("stop") | |
.attr("stop-color", colour) | |
.attr("class","begin") | |
.attr("offset", off1) | |
.attr("stop-opacity", op1); | |
//and the finish | |
d3.select(idtag) | |
.append("stop") | |
.attr("class","end") | |
.attr("stop-color", colour) | |
.attr("offset", off2) | |
.attr("stop-opacity", op2); | |
} | |
//define bar height | |
var barheight = 44; | |
//draw bars (gradient filled rectangles in between two circles) | |
var bars = svg.selectAll(".bar") | |
.data(my_data) | |
.enter().append("rect") | |
.attr("class", "bar") | |
.style("fill",function(d) { | |
//set the gradient fill | |
//dependent on whether values have gone up or down | |
if(d.end_v>d.start_v){ | |
gradient(color(d.label),'grad'+ d.id,"0%","100%","0%","100%",0.4,1) | |
}else{ | |
gradient(color(d.label),'grad'+ d.id,"100%","0%","0%","100%",0.4,1) | |
}return "url(#grad" + d.id +")"; | |
}) | |
.attr("x", function(d) { return Math.min(x(d.start_v),x(d.end_v)); }) | |
.attr("height", barheight) | |
.attr("y", function(d) { return y(d.label) + (y.bandwidth()/2) - barheight/2}) | |
.attr("width", function(d) { return Math.abs(x(d.start_v)-x(d.end_v)); }) | |
.on("mouseover", function(d){ | |
debugger; | |
//defines the tooltip | |
t_text = d.label + "<br>" + d.start_t + ":" + d.start_v + "%<br>" + d.end_t + ":" + d.end_v + "%<br>Change:" + d.change + "%" | |
tooltip.html(t_text) | |
return tooltip.style("visibility", "visible"); | |
}) | |
.on("mousemove", function(){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");}) | |
.on("mouseout", function(){return tooltip.style("visibility", "hidden");}); | |
//define the circle | |
var circle = svg.selectAll("circle").data(my_data); | |
//add end circles (white fill, colour border, opacity=0) | |
circle.enter().append('circle') | |
.attr("cx",function(d){return x(d.end_v);}) | |
.attr("cy",function(d){return y(d.label) + y.bandwidth()/2;}) | |
.attr("r", '20') | |
.style("fill","white") | |
.style("stroke-width",'4') | |
.style("stroke",function (d) { return color(d.label); }) | |
.on("mouseover", function(d){ | |
//define tooltip | |
t_text = d.label + "<br>" + d.start_t + ":" + d.start_v + "%<br>" + d.end_t + ":" + d.end_v + "%<br>Change:" + d.change + "%" | |
tooltip.html(t_text) | |
return tooltip.style("visibility", "visible"); | |
}) | |
.on("mousemove", function(){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");}) | |
.on("mouseout", function(){return tooltip.style("visibility", "hidden");}); | |
//add end circles (colour fill, opacity 0.4) | |
circle.enter().append('circle') | |
.attr("cx",function(d){return x(d.start_v);}) | |
.attr("cy",function(d){return y(d.label) + y.bandwidth()/2;}) | |
.style("opacity",0.4) | |
.attr("r", '22') | |
.style("fill",function (d) { | |
//gradient for circle. (2nd half of circle has no color so transition smooth) | |
if(d.end_v>d.start_v){ | |
gradient(color(d.label),'circ'+ d.id,"100%","0%","50%","0%",0,1) | |
}else{ | |
gradient(color(d.label),'circ'+ d.id,"0%","100%","50%","0%",0,1) | |
}return "url(#circ" + d.id +")"; }) | |
.on("mouseover", function(d){ | |
//define tooltip | |
t_text = d.label + "<br>" + d.start_t + ":" + d.start_v + "%<br>" + d.end_t + ":" + d.end_v + "%<br>Change:" + d.change + "%" | |
tooltip.html(t_text) | |
return tooltip.style("visibility", "visible"); | |
}) | |
.on("mousemove", function(){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");}) | |
.on("mouseout", function(){return tooltip.style("visibility", "hidden");}); | |
//finally add text (percents) - first for the end circles | |
var text = svg.append("g") | |
.attr("class", "labels") | |
.selectAll("text") | |
.data(my_data) | |
.enter() | |
.append("text") | |
.attr("dx", function(d){return x(d.end_v)+2;}) | |
.attr("dy", function(d){return y(d.label) + (y.bandwidth()/2)+2;}) | |
.attr("text-anchor","middle") | |
.html(function(d){return d.end_v + "%";}); | |
//then for the start circles | |
var text2 = svg.append("g") | |
.attr("class", "labels") | |
.selectAll("text") | |
.data(my_data) | |
.enter() | |
.append("text") | |
.attr("dx", function(d){return x(d.start_v)+2;}) | |
.attr("dy", function(d){return y(d.label) + (y.bandwidth()/2)+2;}) | |
.attr("text-anchor","middle") | |
.html(function(d){return d.start_v + "%";}); | |
function get_data(root,r_scale){ | |
var my_data = [], | |
x=0; | |
for (r in root){ | |
//loop through the data, calculate change and populate my_data | |
start_t = root[r]['start'].t | |
start_v = root[r]['start'].v | |
end_t = root[r]['end'].t | |
end_v = root[r]['end'].v | |
change = Math.abs(start_v - end_v) | |
my_data.push({change: change,id: x,label: root[r].label, start_t: start_t, start_v: start_v,end_t: end_t,end_v: end_v}) | |
x = x + 1 | |
} | |
return my_data | |
}; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"ID:1": { | |
"label": "Data Point 1", | |
"start": { | |
"t": "2007", | |
"v": 58 | |
}, | |
"end": { | |
"t": "2014", | |
"v": 68 | |
} | |
}, | |
"ID:2": { | |
"label": "Data Point 2", | |
"start": { | |
"t": "2007", | |
"v": 59 | |
}, | |
"end": { | |
"t": "2014", | |
"v": 35 | |
} | |
}, | |
"ID:3": { | |
"label": "Data Point 3", | |
"start": { | |
"t": "2007", | |
"v": 62 | |
}, | |
"end": { | |
"t": "2014", | |
"v": 97 | |
} | |
}, | |
"national": { | |
"label": "National Average", | |
"start": { | |
"t": "2007", | |
"v": 86 | |
}, | |
"end": { | |
"t": "2014", | |
"v": 62 | |
} | |
}, | |
"state": { | |
"label": "State Average", | |
"start": { | |
"t": "2007", | |
"v": 88 | |
}, | |
"end": { | |
"t": "2014", | |
"v": 59 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment