Skip to content

Instantly share code, notes, and snippets.

@sbrreed
Last active February 6, 2019 21:51
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 sbrreed/6191cb2e55d3dcd360780325a0d1e157 to your computer and use it in GitHub Desktop.
Save sbrreed/6191cb2e55d3dcd360780325a0d1e157 to your computer and use it in GitHub Desktop.
Responsive small Multiples Area chart
license: mit

This chart uses JQuery to apply height, width and margins using those specified in CSS. That way, these elements can be adjusted to make the chart screen size responsive. Note: I have only tested it in Firefox so far.

Built with blockbuilder.org

date symbol price
November Aspen 4.192307692
December Aspen 7.11025641
January Aspen 9.85
February Aspen 12.77105263
March Aspen 15.98157895
April Aspen 17.81578947
May Aspen 15.22105263
November Breckenridge 4.282051282
December Breckenridge 7.325641026
January Breckenridge 10.05526316
February Breckenridge 12.74736842
March Breckenridge 15.87368421
April Breckenridge 19.37631579
May Breckenridge 20.57105263
November Crested Butte 2.961538462
December Crested Butte 5.774358974
January Crested Butte 8.726315789
February Crested Butte 11.73684211
March Crested Butte 14.51842105
April Crested Butte 15.49210526
May Crested Butte 11.27105263
November Eldora 2.55
December Eldora 4.78
January Eldora 7.066666667
February Eldora 9.505128205
March Eldora 12.36923077
April Eldora 13.18717949
May Eldora 8.005
November Jackson 1.234210526
December Jackson 5.763157895
January Jackson 11.41842105
February Jackson 16.91052632
March Jackson 21.75789474
April Jackson 26.70263158
May Jackson 27.23947368
November Loveland 4.18974359
December Loveland 7.384615385
January Loveland 10.37368421
February Loveland 13.42631579
March Loveland 16.65526316
April Loveland 18.82105263
May Loveland 16.81315789
November Monarch 3.356097561
December Monarch 6.365853659
January Monarch 9.475
February Monarch 12.68
March Monarch 15.65
April Monarch 16.85
May Monarch 13.7825
November Mt Baker 0.64375
December Mt Baker 9.25625
January Mt Baker 19.98125
February Mt Baker 32.05625
March Mt Baker 42.84375
April Mt Baker 58.18125
May Mt Baker 64.9125
November Powderhorn 6.324390244
December Powderhorn 11.41707317
January Powderhorn 16.22
February Powderhorn 21.215
March Powderhorn 26.76
April Powderhorn 30.0175
May Powderhorn 29.03846154
November Purgatory 2.187804878
December Purgatory 5.187804878
January Purgatory 8.8325
February Purgatory 12.4825
March Purgatory 14.295
April Purgatory 10.685
May Purgatory 2.1975
November Revelstoke 9.511336032
December Revelstoke 18.09156627
January Revelstoke 26.94246795
February Revelstoke 34.55804954
March Revelstoke 42.93148936
April Revelstoke 48.76532951
May Revelstoke 46.32939633
November Snowbird 1.7
December Snowbird 6.7
January Snowbird 13.4
February Snowbird 21.9
March Snowbird 29.7
April Snowbird 37.8
May Snowbird 41.9
November Snowmass 3.241176471
December Snowmass 6.506060606
January Snowmass 10.1969697
February Snowmass 14.47878788
March Snowmass 17.43636364
April Snowmass 17.07272727
May Snowmass 9.881818182
November Squaw 1.239473684
December Squaw 7.368421053
January Squaw 19.81578947
February Squaw 31.17368421
March Squaw 42.29736842
April Squaw 50.23684211
May Squaw 44.13157895
November Steamboat 11.1875
December Steamboat 19.13
January Steamboat 27.15384615
February Steamboat 34.94871795
March Steamboat 42.17692308
April Steamboat 48.76153846
May Steamboat 50.41794872
November Telluride 5.738461538
December Telluride 9.784615385
January Telluride 13.65
February Telluride 17.97368421
March Telluride 22.90526316
April Telluride 26.18684211
May Telluride 24.44473684
November Vail 4.66097561
December Vail 8.1
January Vail 11.875
February Vail 15.4775
March Vail 19.825
April Vail 23.185
May Vail 22.5875
November Whistler 9.741907261
December Whistler 18.50691511
January Whistler 26.4811887
February Whistler 32.26303587
March Whistler 41.15962927
April Whistler 45.35433071
May Whistler 43.81929134
November Winter Park 3.985365854
December Winter Park 7.4225
January Winter Park 10.8075
February Winter Park 14.11
March Winter Park 18.23
April Winter Park 21.9575
May Winter Park 22.0325
November Wolf Creek 7.651515152
December Wolf Creek 12.96060606
January Wolf Creek 18.4625
February Wolf Creek 24.25625
March Wolf Creek 29.259375
April Wolf Creek 32.79375
May Wolf Creek 32.05
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v5.js"></script>
<script
src="https://code.jquery.com/jquery-3.3.1.js"
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
crossorigin="anonymous"></script>
<style>
#smallMultiplesSnow {
font: 10px sans-serif;
margin: 0px 40px 30px 80px;
text-anchor: end;
width: 70%;
}
.SnowMultiplesline {
fill: none;
stroke: #bfd3e6;
stroke-width: 2px;
}
.SnowMultiplesarea {
fill: #8c96c6;
}
.snowMultiplesaxis text {
font-size: 12px;
}
.mountainNames {
font: 2em serif;
color: #ffffff;
fill: #ffffff;
}
</style>
</head>
<body>
<div class="detailPageDiv">
<h2>Mean Snow Water Equivalent per Month for all Years Reporting</h2>
<div id="smallMultiplesSnow"></div>
</div>
<script>
//this line allows the margins to be set in CSS. This helps with making the charts responsive.
//parseInt converts a string into an integer. This is needed because the margin value comes in
// as a string. The .replace() part removes the "px". CSS needs the "px" but D3 can't take it.
// The 10 at the end is part of parseInt and tells it what base to convert the number in.
// these could be done directly in the margin declarations below but this seems cleaner?
var leftMarginMultiples = parseInt($("#smallMultiplesSnow").css("margin-left").replace("px",""), 10),
rightMarginMultiples = parseInt($("#smallMultiplesSnow").css("margin-right").replace("px",""), 10),
topMarginMultiples = parseInt($("#smallMultiplesSnow").css("margin-top").replace("px",""), 10),
bottomMarginMultiples = parseInt($("#smallMultiplesSnow").css("margin-bottom").replace("px",""), 10)
// Set the dimensions of the canvas / graph
//THis section gets the div that will contain the SVG and it's width and height. That way,
//when the screen is smaller the graphic will react
var SnowMultiplescontainer = d3.select("#smallMultiplesSnow");
var multiplesWindowwidth = SnowMultiplescontainer.node().getBoundingClientRect().width
var Multiplesmargin = {
top: topMarginMultiples,
right: rightMarginMultiples,
bottom: bottomMarginMultiples,
left: leftMarginMultiples
},
width = multiplesWindowwidth - Multiplesmargin.left - Multiplesmargin.right,
height = 90 - Multiplesmargin.top - Multiplesmargin.bottom;
console.log(width, "smaallMultipl");
//ScalePoint is crucial here. ScaleBand works similarly as they both create bands across
// the x-axis that are mapped to the months in the
//domain. ScaleOrdinal, seems like it would work but instead maps November-->0, December-->960 etc.
//ScaleBand doesn't work as it splits the range into n bands (where n is the number of values in the domain array).
// This causes there to be space to the left of the first element in the axis and to the right of the last.
// Finally, scalePoint solves all of these problems and puts November at the farthest most left point on the
// x axis and May at the farthest most right point.
//It's also tempting to use rangeRound. This causes strange things at the ends of the axis as well, so just use
// range.
var xMultiples = d3.scalePoint()
.range([0, width])
var x_axisMultiples = d3.axisBottom()
.scale( xMultiples);
d3.csv("allMountains_monthly_allYears.csv", type).then(function (data) {
// if (error) throw error;
var symbols = d3.nest()
.key(function (d) {
return d.symbol;
})
.entries(data);
//Create months array to be used for the x axis?
// var months=[];
// for(i=0;i<symbols[0].values.length; i++){
// currentMonth = symbols[0].values[i].date;
// months.push(currentMonth);
// }
//the map function performs the same action as the for loop above. It creates
//an array of just the dates.
xMultiples.domain(data.map(function (d) {
return d.date
}));
console.log( xMultiples.step());
var SnowMultiplesSvg = d3.select("#smallMultiplesSnow")
.selectAll("svg")
.data(symbols)
.enter().append("svg")
.attr("class","snowMultiplesSVG")
.attr("width", width + Multiplesmargin.left + Multiplesmargin.right)
.attr("height", height + Multiplesmargin.top + Multiplesmargin.bottom)
.append("g")
.attr("transform", "translate(" + Multiplesmargin.left + "," + Multiplesmargin.top + ")")
//multiple is called here for each element in symbols. This creates
// the individual charts because an SVG is created for each one.
.each(multiple)
//add the chart names (mountain names)
SnowMultiplesSvg.append("text")
.attr("class", "mountainNames")
.attr("x", width/2)
.attr("y", height - 6)
.attr("text-anchor", "center")
.text(function (d) {
return d.key;
});
});
// in this case symbol is going to be the "each" from above. The "each" call
// will cycle through symbols and pass each one to multiple
function multiple(symbol, ) {
var SnowMultiplesSvg = d3.select(this);
// the x scale was ordinal but the y is continuous so we use a Linear scale.
var yMultiples = d3.scaleLinear()
.domain([0, d3.max(symbol.values, function (d) {
return d.price;
})])
.range([height, 0]);
//.area is one of the SVG primitives (https://github.com/d3/d3-shape#symbols)
var area = d3.area()
.x(function (d) {
return xMultiples(d.date);
})
.y0(height)
.y1(function (d) {
return yMultiples(d.price);
});
//.line is another primitive
var line = d3.line()
.x(function (d) {
return xMultiples(d.date);
})
.y(function (d) {
return yMultiples(d.price);
});
//even though this is creating the area, a "path" is appended. Changing this to
//"area" makes the area go away. Use the area variable created above. Call
// symbol.values instead of d.values because "symbol" is what was passed
// to this function
SnowMultiplesSvg.append("path")
.attr("class", "SnowMultiplesarea")
.attr("d", area(symbol.values));
SnowMultiplesSvg.append("path")
.attr("class", "SnowMultiplesline")
.attr("d", line(symbol.values));
//append the x-axis. Make sure to move the axis down by the height of the
// chart as otherwise it will sit on top of the chart. Fix any margins to
// get all text to show up right.
SnowMultiplesSvg.append("g")
.attr("class", "SnowMultiplesaxis")
.attr("transform", "translate(0," + height + ")")
.call( x_axisMultiples)
};
//define the types of the data. the +d.price sets the price to a numeric
//putting this within the data area messes with the chart.
function type(d) {
d.price = +d.price;
d.date = d.date;
return d;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment