This is an interactive line chart written with d3.js v5 and based on the examples from Interactive Data Visualization for the Web and the D3 Graph Gallery.
Last active
July 10, 2019 05:52
-
-
Save sabrinamochi/f10e6bf76a39281f9c38a80b78ba0f2e to your computer and use it in GitHub Desktop.
CO2 Line Chart
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 lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
#dangerNotice { | |
position: absolute; | |
top: 250px; | |
left: 75px; | |
} | |
#dangerNotice p { | |
font-size: 12px; | |
color: red; | |
font-family: Arial, Helvetica, sans-serif; | |
opacity: 0.8; | |
} | |
.focus-text { | |
color: gray; | |
font-family: Arial, Helvetica, sans-serif; | |
font-size: 16px; | |
opacity: 0; | |
} | |
.circle { | |
stroke-width: 2px; | |
stroke-opacity: 0; | |
} | |
.safeLevel { | |
stroke: red; | |
stroke-dasharray: 2, 3; | |
stroke-width: :1; | |
opacity: 0.8; | |
} | |
.danger-line { | |
stroke: red; | |
fill: none; | |
stroke-width: 2px; | |
} | |
.line { | |
stroke: teal; | |
fill: none; | |
stroke-width: 2px; | |
} | |
.source { | |
position: absolute; | |
top: 450px; | |
left: 65px; | |
font-size: 10px; | |
} | |
.title, | |
.subtitle { | |
position: relative; | |
left: 55px; | |
} | |
</style> | |
<title>CO2 line chart</title> | |
<script type="text/javascript" src='https://d3js.org/d3.v5.min.js'></script> | |
<link rel="stylesheet" href="style.css"> | |
</head> | |
<body> | |
<h1 class='title'>Monthly Average Values of CO<sub>2</sub> (ppm) </h1> | |
<p class='subtitle'>measured at the Mauna Loa Observatory in Hawaii</p> | |
<p class='source'>(source: https://bit.ly/2JKNRhB)</p> | |
<div id='dangerNotice' class='hidden'> | |
<p>Over 350 ppm</p> | |
</div> | |
<script type="text/javascript"> | |
var w = 1000; | |
var h = 350; | |
var padding = 30; | |
var rowConverter = function(d) { | |
return { | |
date: new Date(+d.year, (+d.month - 1)), | |
average: parseFloat(d.average) | |
}; | |
}; | |
//declare a variable 'dataset' globally | |
d3.csv('https://raw.githubusercontent.com/alignedleft/d3-book/master/chapter_11/mauna_loa_co2_monthly_averages.csv', rowConverter).then(function(data) { | |
dataset = data; | |
console.table(dataset, ['date', 'average']); | |
xScale = d3.scaleTime() | |
.domain([ | |
d3.min(dataset, function(d) { | |
return d.date; | |
}), | |
d3.max(dataset, function(d) { | |
return d.date; | |
}) | |
]) | |
.range([padding * 2, w - padding * 2]); | |
yScale = d3.scaleLinear() | |
.domain([300, d3.max(dataset, function(d) { | |
return d.average; | |
})]) | |
.range([h - padding * 2, padding]); | |
xAxis = d3.axisBottom() | |
.scale(xScale) | |
.ticks(10); | |
yAxis = d3.axisLeft() | |
.scale(yScale) | |
.ticks(10) | |
// define a line generator | |
var line = d3.line() | |
.defined(function(d) { | |
return d.average >= 0 && d.average <= 350; | |
}) | |
.x(function(d) { | |
return xScale(d.date); | |
}) | |
.y(function(d) { | |
return yScale(d.average); | |
}); | |
var dangerLine = d3.line() | |
.defined(function(d) { | |
return d.average >= 350; | |
}) | |
.x(function(d) { | |
return xScale(d.date); | |
}) | |
.y(function(d) { | |
return yScale(d.average); | |
}); | |
var area = d3.area() | |
.defined(function(d) { | |
return d.average >= 0; | |
}) | |
.x(function(d) { | |
return xScale(d.date); | |
}) | |
.y0(function() { | |
return yScale.range()[0]; | |
}) | |
.y1(function(d) { | |
return yScale(d.average); | |
}) | |
var dangerArea = d3.area() | |
.defined(function(d) { | |
return d.average >= 350; | |
}) | |
.x(function(d) { | |
return xScale(d.date); | |
}) | |
.y0(function(d) { | |
return yScale(350); | |
}) | |
.y1(function(d) { | |
return yScale(d.average); | |
}) | |
var bisect = d3.bisector(function(d) { | |
return d.date | |
}).left; | |
var svg = d3.select('body') | |
.append('svg') | |
.attr('width', w) | |
.attr('height', h); | |
svg.append('path') | |
.datum(dataset) | |
.attr('class', 'line') | |
.attr('d', line); | |
svg.append('path') | |
.datum(dataset) | |
.attr('class', 'danger-line') | |
.attr('d', dangerLine); | |
svg.append('rect') | |
.attr('fill', 'none') | |
.attr('width', w) | |
.attr('height', h) | |
.style('pointer-events', 'all') | |
.on('mouseover', mouseover) | |
.on('mousemove', mousemove); | |
svg.append('line') | |
.attr('class', 'safeLevel') | |
.attr('x1', padding * 2) | |
.attr('y1', yScale(350)) | |
.attr('x2', w - padding * 2) | |
.attr('y2', yScale(350)); | |
svg.append('g') | |
.attr('class', 'xaxis') | |
.attr('transform', 'translate(0,' + (h - padding * 2) + ')') | |
.call(xAxis); | |
svg.append('g') | |
.attr('class', 'yaxis') | |
.attr('transform', 'translate(' + padding * 2 + ', 0 )') | |
.call(yAxis); | |
var focus = svg.append('circle') | |
.attr('class', 'circle') | |
.attr('r', 3) | |
var focusText = svg.append('text') | |
.attr('class', 'focus-text') | |
function mouseover() { | |
focus.style('stroke-opacity', 1); | |
focusText.style('opacity', 1); | |
} | |
function mousemove() { | |
var x0 = xScale.invert(d3.mouse(this)[0]); | |
var i = bisect(dataset, x0, 1); | |
var selectedData = dataset[i]; | |
focus.attr('stroke', function() { | |
if (+selectedData.average >= 350) { | |
return 'red'; | |
} else { | |
return 'teal'; | |
} | |
}) | |
.attr('fill', function() { | |
if (+selectedData.average >= 350) { | |
return 'red'; | |
} else { | |
return 'teal'; | |
} | |
}) | |
.attr('cx', xScale(selectedData.date)) | |
.attr('cy', yScale(selectedData.average)); | |
focusText.attr('x', xScale(selectedData.date)) | |
.attr('y', yScale(selectedData.average) + 30) | |
.text(selectedData.average); | |
}; | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment