Skip to content

Instantly share code, notes, and snippets.

@emeeks
Last active September 4, 2016 12:13
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 emeeks/fe73cd301a983b84f5ec to your computer and use it in GitHub Desktop.
Save emeeks/fe73cd301a983b84f5ec to your computer and use it in GitHub Desktop.
Ch. 4, Fig. 25 - D3.js in Action

This is the code for Chapter 4, Figure 25 from D3.js in Action showing a simple streamgraph created using d3.svg.area() and setting its .y() and .y0() functions to derive values based on the stacked value at each point. Note that this does not use d3.layout.stack (which you should seriously consider if you're considering making streamgraphs) but that's because the focus here is on understanding how d3.svg.area() works.

<html>
<head>
<title>D3 in Action Chapter 4 - Example 15</title>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
</head>
<style>
svg {
height: 500px;
width: 500px;
border: 1px solid gray;
}
line {
shape-rendering: crispEdges;
stroke: #000000;
}
line.minor {
stroke: #777777;
stroke-dasharray: 2,2;
}
path.domain {
fill: none;
stroke: black;
}
</style>
<body>
<div id="viz">
<svg>
</svg>
</div>
</body>
<footer>
<script>
d3.csv("movies.csv", areaChart)
function areaChart(data) {
expData = data;
xScale = d3.scale.linear().domain([0,11]).range([0,500]);
yScale = d3.scale.linear().domain([-100,100]).range([500,0]);
sizeScale = d3.scale.linear().domain([0,200]).range([20,20]);
yAxis = d3.svg.axis().scale(yScale).orient("right").ticks(8).tickSize(500).tickSubdivide(true);
d3.select("svg").append("g").attr("id", "yAxisG").call(yAxis);
xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(500).ticks(4);
d3.select("svg").append("g").attr("id", "xAxisG").call(xAxis);
fillScale = d3.scale.linear().domain([1,10]).range(["lightgray","black"]);
n = 0;
for (x in data[0]) {
if (x != "day") {
movieArea = d3.svg.area()
.x(function(d) {
return xScale(d.day)
})
.y(function(d) {
return yScale(alternatingStacking(d,x,"top"))
})
.y0(function(d) {
return yScale(alternatingStacking(d,x,"bottom"));
})
.interpolate("basis")
d3.select("svg")
.insert("path",".movie")
.attr("class", "movie")
.style("id", x + "Area")
.attr("d", movieArea(data))
.attr("fill", fillScale(n))
.attr("stroke", "white")
.attr("stroke-width", 1)
.style("opacity", 1)
}
n++;
}
function simpleStacking(incomingData, incomingAttribute) {
var newHeight = 0;
for (x in incomingData) {
if (x != "day") {
newHeight += parseInt(incomingData[x]);
if (x == incomingAttribute) {
break;
}
}
}
return newHeight;
}
function alternatingStacking(incomingData, incomingAttribute,topBottom) {
var newHeight = 0;
var skip = true;
for (x in incomingData) {
if (x != "day") {
if (x == "movie1" || skip == false) {
newHeight += parseInt(incomingData[x]);
if (x == incomingAttribute) {
break;
}
if (skip == false) {
skip = true;
}
else {
n%2 == 0 ? skip = false : skip = true;
}
}
else {
skip = false;
}
}
}
if(topBottom == "bottom") {
newHeight = -newHeight;
}
if (n > 1 && n%2 == 1 && topBottom == "bottom") {
newHeight = 0;
}
if (n > 1 && n%2 == 0 && topBottom == "top") {
newHeight = 0;
}
return newHeight;
}
}
</script>
</footer>
</html>
day movie1 movie2 movie3 movie4 movie5 movie6
1 20 8 3 0 0 0
2 18 5 1 13 0 0
3 14 3 1 10 0 0
4 7 3 0 5 27 15
5 4 3 0 2 20 14
6 3 1 0 0 10 13
7 2 0 0 0 8 12
8 0 0 0 0 6 11
9 0 0 0 0 3 9
10 0 0 0 0 1 8
@duncdrum
Copy link

duncdrum commented Sep 4, 2016

x- and y-axis labels have disappeared.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment