Public
Edited
Aug 29, 2023
5 forks
20 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
colors = {
const countryNames = data.map(d => d[0].name)

return d3.scaleOrdinal(
countryNames,
d3.schemeCategory10
)
}
Insert cell
Insert cell
xScale = {
const startDate = data[0][0].date,
endDate = data[0][data[0].length - 1].date
return d3.scaleTime(
// domain
[ startDate, endDate ],
// range
[ margin.left, width - margin.right ]
)
}
Insert cell
yScale = {
// flatten the data into a single array
const prices = data.flat().map(d => d.price),
// and find the max value from that array
yMax = d3.max( [...prices, 8] )
return d3.scaleLinear(
[ 1, yMax ],
[ height - margin.bottom, margin.top ]
)
}
Insert cell
Insert cell
yAxis = {
const formatter = d3.format('$.2f')
return d3.axisLeft(yScale)
.tickFormat(d => formatter(d))
}
Insert cell
xAxis = d3.axisBottom(xScale)
Insert cell
Insert cell
line = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.price))
.curve(d3.curveNatural)
Insert cell
container = {
const svg = html `<svg width="900" height="500" />`
d3.select(svg)
.selectAll('path')
.data( data )
.join('path')
.attr('class', 'big-mac-line')
// Using our line generator here
.attr('d', line)
// Every data point in the array has a name key
// so we just grab the one from d[0]
.style('stroke', d => colors(d[0].name))
.style('stroke-width', 2)
.style('fill', 'transparent')
// This places the labels to the right of each line
d3.select(svg)
.selectAll('text.label')
.data( data )
.join('text')
.attr('class', 'label')
// place the ticks to the right of the chart
.attr('x', width - margin.right + 5)
// Place the ticks at the same y position as
// the last y value of the line (remember, d is our array of points)
.attr('y', d => yScale( d[d.length - 1].price ) + (d[0].name === 'Sweden' ? -10 : 0))
.attr('dy', '0.35em')
.style('fill', d => colors(d[0].name))
.style('font-family', 'sans-serif')
.style('font-size', 12)
.text(d => d[0].name)
d3.select(svg)
.append('g')
.attr('class', 'x-axis')
.attr('transform', `translate(0,${ height - margin.bottom })`)
.call(xAxis)
d3.select(svg)
.append('g')
.attr('class', 'y-axis')
.attr('transform', `translate(${ margin.left },0)`)
.call(yAxis)
// This removes the vertical line on the axis between the ticks and the rest of the chart.
// Purely an aesthetic choice
.selectAll('.domain').remove()
return svg
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more