Public
Edited
Mar 16, 2021
Insert cell
Insert cell
scale = 2
Insert cell
{
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height)
.style('background-color', secondary)

const container = svg.append('g')
.attr('transform',`translate(${padding.x},${padding.y})`)
const monthsWrap = container
.selectAll('g.wrap')
.data(vizData)
.join('g')
.attr('class', 'wrap')
.attr('transform', d => `translate(${yearScale(d.year)},${monthScale(d.month)})`)
const months = monthsWrap
.selectAll('g.month')
.data(d => [d])
.join('g')
.attr('class', 'month')
.style('transform', d => `rotate(${7*(d.tempAvg - d.avg40)}deg)`)
months
.selectAll('rect.above')
.data(d => [d])
.join('rect')
.attr('class', 'above')
.attr('width', 6)
.attr('height', d => aboveDaysScale(d.above))
// .attr('stroke', primary)
.attr('fill', warmer)

months
.selectAll('rect.below')
.data(d => [d])
.join('rect')
.attr('class', 'below')
.attr('width', 3)
.attr('y', d => aboveDaysScale(d.above))
.attr('height', d => belowDaysScale(d.below))
// .attr('stroke', primary)
.attr('fill', colder)

months
.selectAll('rect.snow')
.data(d => [d.snow.filter(d => d)])
.join('rect')
.attr('class', 'snow')
// .attr('width', snowScale)
// .attr('height', 1)
.attr('x', 6)
.attr('width', d => d3.sum(d) ? snowScale(d3.sum(d)) : 0 )
.attr('y', d => snowDayScale(d.length))
.attr('height', 2)
// .attr('x', 5)
// .attr('stroke', primary)
.attr('fill', snowDepth)
const yearAxis = svg.append('g')
.attr('transform', `translate(${padding.x},0)`)
yearAxis.selectAll('text')
.data(d3.range(startYear, endYear+1))
.join('text')
.style('font-family', 'sans-serif')
.style('font-size', 10)
.attr('dy', '0.7em')
.attr('x', yearScale)
.text(d => d)
const monthAxis = svg.append('g')
.attr('transform', `translate(0,${padding.y})`)
monthAxis.selectAll('text')
.data(['Jan', 'Feb', 'Mar', 'Apr',
'May', 'Jun', 'Jul', 'Aug',
'Sep', 'Oct', 'Nov', 'Dec'])
.join('text')
.style('font-family', 'sans-serif')
.style('font-size', 10)
.attr('dy', '0.2em')
.attr('y', (d,i) => monthScale(i+1) + cellWidth/2)
.text(d => d)
const avgTempContainer = svg.append('g')
.attr('transform', `translate(${padding.x},${padding.y + cellWidth * 12})`)
return svg.node()
}
Insert cell
vizData = data.filter(d => d.year >= startYear)
Insert cell
Insert cell
snowScale(1)
Insert cell
belowDaysScale = d3.scaleLinear()
.domain([0, 31])
.range([0, cellWidth - cellPadding])
Insert cell
aboveDaysScale = d3.scaleLinear()
.domain([0, 31])
.range([0, cellWidth - cellPadding])
Insert cell
snowScale = {
const allSnow = data.map(d => d3.sum(d.snow))

return d3.scaleLinear()
.domain([0, 2])
.range([0, cellWidth - cellPadding])
}
Insert cell
snowDayScale = d3.scaleBand()
.domain(d3.range(0, 32))
.range([cellWidth - cellPadding, 0])
Insert cell
monthScale = d3.scaleOrdinal()
.domain(d3.range(1,13))
.range(d3.range(0, height - 2*padding.y, cellWidth))
Insert cell
yearScale = d3.scaleBand()
.domain(d3.range(startYear, endYear+1))
.range([ 0, width - 2*padding.x - cellWidth ])
Insert cell
cellWidth = (width - 2*padding.y)/(endYear - startYear)
Insert cell
cellPadding = 5 * scale
Insert cell
padding = ({
x: 30,
y: 30
})
Insert cell
startYear = 1987
Insert cell
endYear = 2020
Insert cell
primary = '#1a1a1a'
Insert cell
secondary = '#fff'
Insert cell
colder = '#1f77b4'
Insert cell
warmer = '#d62728'
Insert cell
snowDepth = '#888'
Insert cell
d3.schemeCategory10
Insert cell
width = 1024 * scale
Insert cell
height = 400 * scale
Insert cell
d3 = require('d3@6')
Insert cell
luxon = require("luxon@1/build/amd/luxon.js")
Insert cell
DateTime = luxon.DateTime
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more