(function () {
'use strict';
var data = [
{
year: 2000,
popularity: 50
},
{
year: 2001,
popularity: 150
},
{
year: 2002,
popularity: 200
},
{
year: 2003,
popularity: 130
},
{
year: 2004,
popularity: 240
},
{
year: 2005,
popularity: 380
},
{
year: 2006,
popularity: 420
}
];
// Create SVG and padding for the chart
const svg = d3
.select("#chart")
.append("svg")
.attr("height", 300)
.attr("width", 600);
const margin = { top: 0, bottom: 20, left: 30, right: 20 };
const chart = svg.append("g").attr("transform", `translate(${margin.left},0)`);
const width = +svg.attr("width") - margin.left - margin.right;
const height = +svg.attr("height") - margin.top - margin.bottom;
const grp = chart
.append("g")
.attr("transform", `translate(-${margin.left},-${margin.top})`);
// Add empty scales group for the scales to be attatched to on update
chart.append("g").attr("class", "x-axis");
chart.append("g").attr("class", "y-axis");
// Add empty path
grp
.append("path")
.attr("transform", `translate(${margin.left},0)`)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5);
function updateScales(data) {
// Create scales
const yScale = d3
.scaleLinear()
.range([height, 0])
.domain([0, d3.max(data, dataPoint => dataPoint.popularity)]);
const xScale = d3
.scaleLinear()
.range([0, width])
.domain(d3.extent(data, dataPoint => dataPoint.year));
return { yScale, xScale };
}
function createLine(xScale, yScale) {
return line = d3
.line()
.x(dataPoint => xScale(dataPoint.year))
.y(dataPoint => yScale(dataPoint.popularity));
}
function updateAxes(data, chart, xScale, yScale) {
chart
.select(".x-axis")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(xScale).ticks(data.length));
chart
.select(".y-axis")
.attr("transform", `translate(0, 0)`)
.call(d3.axisLeft(yScale));
}
function updatePath(data, line) {
const updatedPath = d3
.select("path")
.interrupt()
.datum(data)
.attr("d", line);
const pathLength = updatedPath.node().getTotalLength();
// D3 provides lots of transition options, have a play around here:
// https://github.com/d3/d3-transition
const transitionPath = d3
.transition()
.ease(d3.easeSin)
.duration(2500);
updatedPath
.attr("stroke-dashoffset", pathLength)
.attr("stroke-dasharray", pathLength)
.transition(transitionPath)
.attr("stroke-dashoffset", 0);
}
function updateChart(data) {
const { yScale, xScale } = updateScales(data);
const line = createLine(xScale, yScale);
updateAxes(data, chart, xScale, yScale);
updatePath(data, line);
}
updateChart(data);
// Update chart when button is clicked
d3.select("button").on("click", () => {
// Create new fake data
const newData = data.map(row => {
return { ...row, popularity: row.popularity * Math.random() };
});
updateChart(newData);
});
})();