lest you think I’ve abandoned modernity entirely, I present you with this ES2015 version of the bl.ock v4 curve interpolation comparison. the code found here follows the Airbnb JavaScript Style Guide, with the rule modifications described in this .eslintrc
{
"extends": "airbnb",
"rules": {
"comma-dangle": "off",
"no-param-reassign": "off",
"no-restricted-syntax": "off",
newline-per-chained-call: "off"
}
}
this iteration also uses only inline styles, because reasons
a fork of this bl.ock which in turn is an iteration on @d3noob‘s’ v4 curve interpolation comparison
README.md
:This bl.ock demonstrates the range of interpolation curves available in v4 of d3.js.
You can click on any of the legend labels to toggle visibility of the lines.
Details of the curve can be found on the D3 wiki.
This graph is part of the code samples for the update to the book D3 Tips and Tricks to version 4 of d3.js.
<!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>
date,close
1-May-12,558.13
30-Apr-12,553.98
27-Apr-12,567.00
26-Apr-12,589.70
25-Apr-12,599.00
24-Apr-12,630.28
23-Apr-12,666.70
20-Apr-12,634.98
19-Apr-12,645.44
18-Apr-12,643.34
17-Apr-12,543.70
16-Apr-12,580.13
13-Apr-12,605.23
12-Apr-12,622.77
11-Apr-12,626.20
10-Apr-12,628.44
9-Apr-12,636.23
5-Apr-12,633.68
4-Apr-12,624.31
3-Apr-12,629.32
2-Apr-12,618.63
30-Mar-12,599.55
29-Mar-12,609.86
28-Mar-12,617.62
27-Mar-12,614.48
26-Mar-12,606.98