D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
jrzief
Full window
Github gist
Small Multiples - State Unemployment2
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js" charset="utf-8"></script> <style> .axis path, .axis line { stroke: #ccc; } .axis line { stroke-dasharray: 2; } .axis text { fill: #ccc; } .state text { font-weight: 600; } </style> </head> <body> <script> var width = 250; var height = 200; var margin = {top: 20, right: 30, bottom: 20, left: 30}; var xScale = d3.scaleLinear().range([0, width]); var yScale = d3.scaleLinear().range([height, 0]); var xAxis = d3.axisBottom() .scale(xScale) .ticks(5) .tickFormat(d => "'" + new String(d).slice(2)) .tickSizeInner(-height) .tickSizeOuter(0) .tickPadding(6); var yAxis = d3.axisLeft() .scale(yScale) .ticks(5) .tickFormat(d => d + '%') .tickSizeInner(-width) .tickSizeOuter(0) .tickPadding(6); var line = d3.line() .x(d => xScale(d.year)) .y(d => yScale(d.value)); var red = '#d8472b'; d3.json('data.json', function(err, data) { // get the data ready, currently grouped by // year, so create a flat array with attributes // state, value, year var flatData = []; var flatData2 = []; _.forEach(data, function(rowobj, index) { var year = +rowobj.date; _.forEach(rowobj, function(value,key) { if (key === 'date' || key === 'avg') { return } flatData2.push({ state: key, value: +rowobj[key], year: year, }); }); console.log('flatdata2', flatData2) }); data.forEach(function(obj) { var year = +obj.date; // cannot use forEach on an obj, can only for-in // (good reason to use lodash) for (var state in obj) { if (state === 'date' || state === 'avg') continue; flatData.push({ state: state, value: +obj[state], year: year, }); } console.log('flatdata', flatData); }); // now that all the data is flat, create scales var xDomain = d3.extent(flatData2, d => d.year); var yDomain = d3.extent(flatData2, d => d.value); xScale.domain(xDomain); yScale.domain(yDomain).nice(); // and now group the data by state var dataByState = d3.nest() .key(function(d) {return d.state}) .entries(flatData2); console.log('dataByState: ', dataByState) var states = d3.select('body').selectAll('.state') .data(dataByState, d => d.key) .enter() .append('svg') .classed('state', true) .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom) .append('g') .attr('transform', 'translate(' + [margin.left, margin.top] + ')'); // axis states.append('g') .classed('x axis', true) .attr('transform', 'translate(' + [0, height] + ')') .call(xAxis); states.append('g') .classed('y axis', true) .call(yAxis); // state title states.append('text') .attr('x', 15) .attr('y', 5) .attr('dy', '1em') .attr('font-size', 14) .text(d => d.key.toUpperCase()); // path states.append('path') .datum(d => d.values) .attr('d', line) .attr('fill', 'none') .attr('stroke', red) .attr('stroke-width', 2); // circle & text for hover var hover = states.append('g') .datum(d => { var last = d.values.slice(-1)[0]; return { values: d.values, last: last, } }).attr('transform', d => 'translate(' + [xScale(d.last.year), yScale(d.last.value)] + ')'); var circle = hover.append('circle') .attr('fill', red) .attr('r', 3); var text = hover.append('text') .attr('text-anchor', 'middle') .attr('y', -10) .style('font-size', 12) .text(d => "'" + new String(d.last.year).slice(2) + ': ' + d3.format('.1f')(d.last.value) + '%') }); </script> </body>
https://d3js.org/d3.v4.min.js