|
<!DOCTYPE html> |
|
<meta charset='utf-8'> |
|
<body> |
|
<!-- load the d3.js library --> |
|
<script src='https://d3js.org/d3.v4.min.js'></script> |
|
<!-- load the babel ES2015 to ES5 transpiler library --> |
|
<script src='https://npmcdn.com/babel-core@5.8.34/browser.min.js'></script> |
|
<script lang='babel' type='text/babel'> |
|
// set the dimensions and margins of the graph |
|
const margin = { top: 20, right: 150, bottom: 30, left: 50 }; |
|
const width = 960 - margin.left - margin.right; |
|
const height = 470 - margin.top - margin.bottom; |
|
|
|
// array of curve functions and titles |
|
const curveArray = [ |
|
{ |
|
d3Curve: d3.curveLinear, |
|
curveTitle: 'curveLinear' |
|
}, |
|
{ |
|
d3Curve: d3.curveStep, |
|
curveTitle: 'curveStep' |
|
}, |
|
{ |
|
d3Curve: d3.curveStepBefore, |
|
curveTitle: 'curveStepBefore' |
|
}, |
|
{ |
|
d3Curve: d3.curveStepAfter, |
|
curveTitle: 'curveStepAfter' |
|
}, |
|
{ |
|
d3Curve: d3.curveBasis, |
|
curveTitle: 'curveBasis' |
|
}, |
|
{ |
|
d3Curve: d3.curveCardinal, |
|
curveTitle: 'curveCardinal' |
|
}, |
|
{ |
|
d3Curve: d3.curveMonotoneX, |
|
curveTitle: 'curveMonotoneX' |
|
}, |
|
{ |
|
d3Curve: d3.curveCatmullRom, |
|
curveTitle: 'curveCatmullRom' |
|
} |
|
]; |
|
|
|
// parse the date and time |
|
const parseTime = d3.timeParse('%d-%b-%y'); |
|
|
|
// set the range of the scales |
|
const x = d3.scaleTime() |
|
.range([0, width]); |
|
|
|
const y = d3.scaleLinear() |
|
.range([height, 0]); |
|
|
|
// append the svg object to the body of the page |
|
// append a 'group' element to 'svg' |
|
// move the 'group' element to the top left margin |
|
const svg = d3.select('body').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})`); |
|
|
|
// get the data |
|
d3.csv('data-3.csv', (error, data) => { |
|
if (error) throw error; |
|
|
|
// format the data |
|
data.forEach(d => { |
|
d.date = parseTime(d.date); |
|
d.close = +d.close; |
|
}); |
|
|
|
// set the color scale |
|
const color = d3.scaleOrdinal(d3.schemeCategory10); |
|
|
|
curveArray.forEach((daCurve, i) => { |
|
// scale the range of the data |
|
x.domain(d3.extent(data, d => d.date)); |
|
y.domain(d3.extent(data, d => d.close)); |
|
|
|
// create and configure line pathstring generator |
|
const line = d3.line() |
|
.curve(daCurve.d3Curve) |
|
.x(d => x(d.date)) |
|
.y(d => y(d.close)); |
|
|
|
// add the paths with different curves |
|
svg.append('path') |
|
.datum(data) |
|
.attr('class', 'line') |
|
.style('stroke', () => { |
|
// Add the colors dynamically |
|
daCurve.color = color(daCurve.curveTitle); |
|
return daCurve.color; |
|
}) |
|
.attr('id', `tag${i}`) // assign an ID |
|
.attr('d', line); |
|
|
|
// add the legend |
|
svg.append('text') |
|
.attr('x', width + 5) // space the legend |
|
.attr('y', margin.top + 20 + (i * 20)) |
|
.attr('class', 'legend') // style the legend |
|
.style('fill', () => { |
|
// add the colors dynamically |
|
daCurve.color = color(daCurve.curveTitle); |
|
return daCurve.color; |
|
}) |
|
.on('click', () => { |
|
// determine if current line is visible |
|
const active = daCurve.active !== true; |
|
const newOpacity = active ? 0 : 1; |
|
// hide or show the elements based on the ID |
|
d3.select(`#tag${i}`) |
|
.transition() |
|
.duration(100) |
|
.style('opacity', newOpacity); |
|
// update whether or not the elements are active |
|
daCurve.active = active; |
|
}) |
|
.text(daCurve.curveTitle); |
|
}); |
|
|
|
// add the 'all' option to the Legend |
|
svg.append('text') |
|
.attr('x', width + 5) // space the legend |
|
.attr('y', margin.top + 20 + (8 * 20)) |
|
.attr('class', 'legend') // style the legend |
|
.style('fill', () => d3.schemeCategory10[8]) // add the colors dynamically |
|
.on('click', () => { |
|
d3.selectAll('.line') |
|
.transition() |
|
.duration(100) |
|
.style('opacity', 1); |
|
}) |
|
.text('all'); |
|
|
|
// add the 'none'option to the Legend |
|
svg.append('text') |
|
.attr('x', width + 5) // space the legend |
|
.attr('y', margin.top + 20 + (9 * 20)) |
|
.attr('class', 'legend') // style the legend |
|
.style('fill', () => d3.schemeCategory10[9]) // add the colors dynamically |
|
.on('click', () => { |
|
d3.selectAll('.line') |
|
.transition() |
|
.duration(100) |
|
.style('opacity', 0); |
|
}) |
|
.text('none'); |
|
|
|
// add the scatterplot |
|
svg.selectAll('dot') |
|
.data(data) |
|
.enter().append('circle') |
|
.attr('r', 4) |
|
.attr('cx', d => x(d.date)) |
|
.attr('cy', d => y(d.close)); |
|
|
|
// configure the x-axis generator |
|
const xAxis = d3.axisBottom(x) |
|
.tickFormat(d3.timeFormat('%j')); // format as day-of-year |
|
|
|
// add the x-axis |
|
svg.append('g') |
|
.attr('class', 'axis') |
|
.attr('transform', `translate(0, ${height})`) |
|
.call(xAxis); |
|
|
|
// add the y-axis |
|
svg.append('g') |
|
.attr('class', 'axis') |
|
.call(d3.axisLeft(y)); |
|
|
|
// styles |
|
d3.selectAll('.line') |
|
.style('fill', 'none') |
|
.style('stroke-width', '2px'); |
|
|
|
d3.select('body') |
|
.style('font', '12px Arial'); |
|
|
|
d3.selectAll('.legend') |
|
.style('font-size', '16px') |
|
.style('font-weight', 'bold') |
|
.style('text-anchor', 'left'); |
|
}); |
|
</script> |
|
</body> |