Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@carlvlewis
Last active March 1, 2017 22:14
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 carlvlewis/602fce4722b82991aa7d6938e40230fe to your computer and use it in GitHub Desktop.
Save carlvlewis/602fce4722b82991aa7d6938e40230fe to your computer and use it in GitHub Desktop.
A mock sales trend set of small multiple area charts
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="author" content="@carlvlewis">
<!--This is so bootstrap knows how to handle viewports hassle-free-->
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Sales Trend by Month - Axis Group</title>
<!--C. 2017, Carl V. Lewis. All code MIT Licensed. Keeping my custom JS, CSS and markup all in a single file for, well, good old time's sake. -->
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<!--Going to want to employ some basic custom CSS not included in bootstrap to prettify the visualization-->
<style>
body {
font: 16px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #fff;
shape-rendering: crispEdges;
}
.area {
fill: #badcfe;
}
.line {
fill: none;
stroke: #8ba5be;
stroke-width: 1.5px;
}
.dot {
fill: white;
stroke: steelblue;
stroke-width: 1.5px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 45px;
color: #fff;
height: 20px;
padding: 1px;
font: 14px sans-serif;
background: #272822;
border: 0px;
border-radius: 2px;
pointer-events: none;
}
g text {
font-size: 12px;
}
.x.axis1 .tick:first-child text{
display: none;
}
.x.axis2 .tick:nth-last-child() text{
display: none;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
</head>
<body>
<!--good old fashioned bootstrap navbar-->
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="http://carlvlewis.net"><strong>MONTHLY SALES</strong></a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
</li>
<li class="nav-item">
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#myModal">About</button>
</li>
</ul>
</div>
<div class="modal" id="myModal" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel1" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title" id="myModalLabel1">About this visualization</h4>
</div>
<div class="modal-body">
This visualization was created by <a href="http://carlvlew.is">Carl V. Lewis</a> –– lover of civic-tech, Chobani yogurt, catchy Taylor Swift songs and data visualization. It's the result of a few hours of time in <a href="http://sublimetext.com">Sublime Text</a> playing in the great big <a href="http://d3js.org">d3.js</a> playground of fun visualization stuff. The data behind this project is absolutely fake, and is meant only to serve as an example of a technique. Specifically, what makes this d3.js data visualization novel is its approach to creating a chart that appears to the user almost as 'series of charts,' although it's generated from a single set of data. In some ways, it's akin to <a href="http://edwardtufte.com">Edward Tufte</a>'s beloved <em>small multiples</em>. In others, it's just a single area chart broken up by dimension with `break;` tags added in to provide padding and visual space between the chart elements. It was given birth to on Feb. 21, 2017. </div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</nav><br><br>
<div class="container-fluid">
<h6><strong>Year-Over-Year Trend in Number of Sales Monthly (in millions)</strong></h6>
<p> <em> Horizontal lines intersecting each chart represent the mean value of sales in that month between 2011-2015. Hover or touch tooltips for precise values.</em>
<!--now let's start javascripting-->
<!--Including JSON data not only in same format as provided, but also inline, too, rather than in external JSON file. This allows ease of portability, but admittedly creats messy index.html files when there's a large dataset-->
<script>
var scale = 0.8;
var jsonData = [{"Year":2011,"Month":"Jan","Sales":320},
{"Year":2011,"Month":"Feb","Sales":230},
{"Year":2011,"Month":"Mar","Sales":365},
{"Year":2011,"Month":"Apr","Sales":385},
{"Year":2011,"Month":"May","Sales":300},
{"Year":2012,"Month":"Jan","Sales":380},
{"Year":2012,"Month":"Feb","Sales":180},
{"Year":2012,"Month":"Mar","Sales":275},
{"Year":2012,"Month":"Apr","Sales":450},
{"Year":2012,"Month":"May","Sales":410},
{"Year":2013,"Month":"Jan","Sales":320},
{"Year":2013,"Month":"Feb","Sales":170},
{"Year":2013,"Month":"Mar","Sales":375},
{"Year":2013,"Month":"Apr","Sales":510},
{"Year":2013,"Month":"May","Sales":390},
{"Year":2014,"Month":"Jan","Sales":420},
{"Year":2014,"Month":"Feb","Sales":125},
{"Year":2014,"Month":"Mar","Sales":310},
{"Year":2014,"Month":"Apr","Sales":450},
{"Year":2014,"Month":"May","Sales":410},
{"Year":2015,"Month":"Jan","Sales":460},
{"Year":2015,"Month":"Feb","Sales":195},
{"Year":2015,"Month":"Mar","Sales":360},
{"Year":2015,"Month":"Apr","Sales":410},
{"Year":2015,"Month":"May","Sales":385}];
// drawing out our svg elements, including axes, area fill and setting domain/range for data
function draw(){
var margin = {top: 50, right: 50, bottom: 50, left: 50},
width = $(window).width() - margin.left - margin.right,
height = $(window).height() * scale - margin.top - margin.bottom;
var averages = [];
var data = getData(jsonData);
var x = d3.scaleLinear()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var line = d3.line()
.defined(function(d) { return d; })
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
var area = d3.area()
.defined(line.defined())
.x(line.x())
.y1(line.y())
.y0(y(0));
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("body").append("svg")
.datum(data)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("path")
.attr("class", "area")
.attr("d", area);
// appending svg g, then apppending text element to that, then assigning the month labels to the text element to insert them essentially as annotated text into the d3 chart
svg.append("g")
.attr("transform", "translate("+width/12+",0)")
.append("text")
.text("Jan");
svg.append("g")
.attr("transform", "translate("+(width/12 + width/5)+",0)")
.append("text")
.text("Feb");
svg.append("g")
.attr("transform", "translate("+(width/12 + width*2/5)+",0)")
.append("text")
.text("March");
svg.append("g")
.attr("transform", "translate("+(width/12 + width*3/5)+",0)")
.append("text")
.text("April");
svg.append("g")
.attr("transform", "translate("+(width/12 + width*4/5)+",0)")
.append("text")
.text("May");
var xAxis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// using selectAll to remove pre-populated linear data ticks on x-axis
xAxis.selectAll("text").remove();
xAxis.selectAll("g").remove();
var yAxis = svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(y));
yAxis.selectAll("text").remove();
yAxis.selectAll("g").remove();
svg.append("path")
.attr("class", "line")
.attr("d", line)
.attr("stroke-width", 2)
.attr("stroke", "#ccc");
// using standard d3.scaleLinear to set domain and range according to data at hand, then appending svg g onto the yAxis with 6 tickmarks
var yScale = d3.scaleLinear()
.domain([0, 600])
.range([height, 0]);
var yAxis = svg.append("g")
.attr("class", "y axis1")
.call(d3.axisLeft(yScale).ticks(6));
// since the x-axis labels we want to display in this instance are not linear/ordinal, there is no need to set a domain. Because we have five buckets/date ranges to display, we;re simply adding the tick marks now
var xScale1 = d3.scaleLinear()
.range([0, width]);
var xAxis1 = svg.append("g")
.attr("class", "x axis2")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale1)
.tickFormat("")
.ticks(5));
//dynamically calculated mean/average per each month added as a line on y-axis - using svg g to append the lines to all five chart sections whose x-axis positioning is calculated by x1 and x2 based on width of chart overall; then dynamically calculating averages of data to define the position on y-axis
d3.select("g").append("line")
.attr("x1", 0)
.attr("x2", width/5)
.attr("y1", averages[0])
.attr("y2", averages[0])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width/5)
.attr("x2", width*2/5)
.attr("y1", averages[1])
.attr("y2", averages[1])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*2/5)
.attr("x2", width*3/5)
.attr("y1", averages[2])
.attr("y2", averages[2])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*3/5)
.attr("x2", width*4/5)
.attr("y1", averages[3])
.attr("y2", averages[3])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*4/5)
.attr("x2", width*5/5)
.attr("y1", averages[4])
.attr("y2", averages[4])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
// let's plot some circles based upon the data points for 'Sales' to give users a visual cue where they can hover or touch for details-on-demand
var circles = svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
var circleAttributes = circles
.attr("cx", function(d) {
return d ? d.x * width : null;
})
.attr("cy", function(d) {
return d ? height - d.y * height : null;
})
.attr("r", function(d) {
return d ? 4 : 0;
})
.style("fill", "#4682b4")
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(parseInt(d.y * 600))
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
// Conditional statement to append axis labels at dynamically calculated positions; this allows us both to center the labels at the start and end points of the data rather than on the tickmarks, as well as to adjust the '15' label positioning slightly to the left when the size of the viewport is less than 768 so as to prevent overlap.
for(var i = 0 ; i < 5 ; i ++){
d3.select("g").append("text")
.text("'11")
.attr("x", width*i/5 + width/50)
.attr("y", height + 25);
}
for(var i = 0 ; i < 5 ; i ++){
if (width < 768) {
d3.select("g").append("text")
.text("'15")
.attr("x", width*i/5 + width*7/50)
.attr("y", height + 25);
}else{
d3.select("g").append("text")
.text("'15")
.attr("x", width*i/5 + width*8/50)
.attr("y", height + 25);
}
}
// we use svg g to append the axis tickmarks, setting a different x-axis coordinate
d3.select("g").append("line")
.attr("x1", width/5)
.attr("x2", width/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*2/5)
.attr("x2", width*2/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*3/5)
.attr("x2", width*3/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*4/5)
.attr("x2", width*4/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*5/5)
.attr("x2", width*5/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
// Segmenting the dataset according the value for 'Month" field, then using `break;` to add padding between each segment.
function getData(jsonData){
var data = [];
var twoData = [[], [], [], [], []];
for(var i = 0 ; i < jsonData.length ; i ++){
switch(jsonData[i].Month){
case "Jan":
twoData[0].push(jsonData[i].Sales);
break;
case "Feb":
twoData[1].push(jsonData[i].Sales);
break;
case "Mar":
twoData[2].push(jsonData[i].Sales);
break;
case "Apr":
twoData[3].push(jsonData[i].Sales);
break;
case "May":
twoData[4].push(jsonData[i].Sales);
break;
}
}
for(var i = 0 ; i < 5 ; i ++){
twoData[i].push(null);
}
data.push(null);
var val = 1/((jsonData.length-1) * 2);
for(var i = 0 ; i < 5 ; i ++)
{
for(var j = 0 ; j < 6 ; j ++)
{
if (twoData[i][j]) {
data.push({x: val, y: twoData[i][j] / 600});
val += 1/(jsonData.length + 0.5);
} else {
data.push(null);
val += 1/((jsonData.length + 1) * 10);
}
}
}
for(var i = 0 ; i < 5 ; i ++)
{
averages[i] = height - twoData[i].reduce(sum, 0)*height / 3000;
}
return data;
}
function sum(a, b)
{
return a+b;
}
}
// moment of truth: let's execute the chart and draw it
draw();
// now let's take some considerations for screen-size and scaling to make it all responsive-like.
$(window).on("resize", function() {
d3.select("svg").remove();
if ($(window).width() < 768) {
scale = 0.5;
draw();
} else {
scale = 0.8;
draw();
}
});
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-92809052-1', 'auto');
ga('send', 'pageview');
</script>
</div>
</body>
</html>
{"Year":2011,"Month":"May","Sales":300},
{"Year":2012,"Month":"Jan","Sales":380},
{"Year":2012,"Month":"Feb","Sales":180},
{"Year":2012,"Month":"Mar","Sales":275},
{"Year":2012,"Month":"Apr","Sales":450},
{"Year":2012,"Month":"May","Sales":410},
{"Year":2013,"Month":"Jan","Sales":320},
{"Year":2013,"Month":"Feb","Sales":170},
{"Year":2013,"Month":"Mar","Sales":375},
{"Year":2013,"Month":"Apr","Sales":510},
{"Year":2013,"Month":"May","Sales":390},
{"Year":2014,"Month":"Jan","Sales":420},
{"Year":2014,"Month":"Feb","Sales":125},
{"Year":2014,"Month":"Mar","Sales":310},
{"Year":2014,"Month":"Apr","Sales":450},
{"Year":2014,"Month":"May","Sales":410},
{"Year":2015,"Month":"Jan","Sales":460},
{"Year":2015,"Month":"Feb","Sales":195},
{"Year":2015,"Month":"Mar","Sales":360},
{"Year":2015,"Month":"Apr","Sales":410},
{"Year":2015,"Month":"May","Sales":385}];
function draw(){
var margin = {top: 50, right: 50, bottom: 50, left: 50},
width = $(window).width() - margin.left - margin.right,
height = $(window).height() * scale - margin.top - margin.bottom;
var averages = [];
var data = getData(jsonData);
var x = d3.scaleLinear()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var line = d3.line()
.defined(function(d) { return d; })
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
var area = d3.area()
.defined(line.defined())
.x(line.x())
.y1(line.y())
.y0(y(0));
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("body").append("svg")
.datum(data)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("path")
.attr("class", "area")
.attr("d", area);
svg.append("g")
.attr("transform", "translate("+width/12+",0)")
.append("text")
.text("Jan");
svg.append("g")
.attr("transform", "translate("+(width/12 + width/5)+",0)")
.append("text")
.text("Feb");
svg.append("g")
.attr("transform", "translate("+(width/12 + width*2/5)+",0)")
.append("text")
.text("March");
svg.append("g")
.attr("transform", "translate("+(width/12 + width*3/5)+",0)")
.append("text")
.text("April");
svg.append("g")
.attr("transform", "translate("+(width/12 + width*4/5)+",0)")
.append("text")
.text("May");
var xAxis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
xAxis.selectAll("text").remove();
xAxis.selectAll("g").remove();
var yAxis = svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(y));
yAxis.selectAll("text").remove();
yAxis.selectAll("g").remove();
svg.append("path")
.attr("class", "line")
.attr("d", line)
.attr("stroke-width", 2)
.attr("stroke", "#ccc");
var yScale = d3.scaleLinear()
.domain([0, 600])
.range([height, 0]);
var yAxis = svg.append("g")
.attr("class", "y axis1")
.call(d3.axisLeft(yScale).ticks(6));
var xScale1 = d3.scaleLinear()
.range([0, width]);
var xAxis1 = svg.append("g")
.attr("class", "x axis2")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale1)
.tickFormat(function(d) {
if (d < 0.2) {
return "2011";
} else if (d > 0.8) {
return "2015";
} else {
return "2015 2011";
}
})
.ticks(5));
//average line
d3.select("g").append("line")
.attr("x1", 0)
.attr("x2", width/5)
.attr("y1", averages[0])
.attr("y2", averages[0])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width/5)
.attr("x2", width*2/5)
.attr("y1", averages[1])
.attr("y2", averages[1])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*2/5)
.attr("x2", width*3/5)
.attr("y1", averages[2])
.attr("y2", averages[2])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*3/5)
.attr("x2", width*4/5)
.attr("y1", averages[3])
.attr("y2", averages[3])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*4/5)
.attr("x2", width*5/5)
.attr("y1", averages[4])
.attr("y2", averages[4])
.attr("stroke", "#979797")
.attr("stroke-width", 2);
var circles = svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
var circleAttributes = circles
.attr("cx", function(d) {
return d ? d.x * width : null;
})
.attr("cy", function(d) {
return d ? height - d.y * height : null;
})
.attr("r", function(d) {
return d ? 4 : 0;
})
.style("fill", "#8393a6")
.on("mouseover", function(d) {
div.transition()
.duration(300)
.style("opacity", .9);
div .html(parseInt(d.y * 600))
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
d3.select("g").append("line")
.attr("x1", width/5)
.attr("x2", width/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*2/5)
.attr("x2", width*2/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*3/5)
.attr("x2", width*3/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*4/5)
.attr("x2", width*4/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
d3.select("g").append("line")
.attr("x1", width*5/5)
.attr("x2", width*5/5)
.attr("y1", 0)
.attr("y2", height)
.attr("stroke", "#ccc")
.attr("stroke-width", 2);
function getData(jsonData){
var data = [];
var twoData = [[], [], [], [], []];
for(var i = 0 ; i < jsonData.length ; i ++){
switch(jsonData[i].Month){
case "Jan":
twoData[0].push(jsonData[i].Sales);
break;
case "Feb":
twoData[1].push(jsonData[i].Sales);
break;
case "Mar":
twoData[2].push(jsonData[i].Sales);
break;
case "Apr":
twoData[3].push(jsonData[i].Sales);
break;
case "May":
twoData[4].push(jsonData[i].Sales);
break;
}
}
for(var i = 0 ; i < 5 ; i ++){
twoData[i].push(null);
}
data.push(null);
var val = 1/((jsonData.length-1) * 2);
for(var i = 0 ; i < 5 ; i ++)
{
for(var j = 0 ; j < 6 ; j ++)
{
if (twoData[i][j]) {
data.push({x: val, y: twoData[i][j] / 600});
val += 1/(jsonData.length + 0.5);
} else {
data.push(null);
val += 1/((jsonData.length + 1) * 10);
}
}
}
for(var i = 0 ; i < 5 ; i ++)
{
averages[i] = height - twoData[i].reduce(sum, 0)*height / 3000;
}
console.log(data);
return data;
}
function sum(a, b)
{
return a+b;
}
}
draw();
$(window).on("resize", function() {
d3.select("svg").remove();
if ($(window).width() < 768) {
scale = 0.5;
draw();
} else {
scale = 0.8;
draw();
}
});
</script>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment