countyChart = datum => {
const chartWidth = 400
const chartHeight = chartWidth * 0.5
const margin = { left: 40, right: 40, top: 10, bottom: 20 }
const formatNumber = d3.format('.2r')
const xScale = d3.scaleTime()
.domain(d3.extent(datum.days, d => d.date))
.range([margin.left, chartWidth - margin.right])
const yScale = d3.scaleLinear()
.domain([0, d3.max(datum.days, d => d.newCases)])
.range([chartHeight - margin.bottom, margin.top])
const linearRegressionLine = ss.linearRegressionLine({
m: datum.regression.m * datum.totalPopulation,
b: datum.regression.b * datum.totalPopulation,
})
const perDay = datum.regression.m * datum.totalPopulation
const slope = Math.atan(
(yScale(linearRegressionLine(0)) - yScale(linearRegressionLine(14)))
/
(margin.left - chartWidth + margin.right)
) * 180 / Math.PI
const xLabelTicks = xScale.ticks(d3.timeDay.every(2))
const xGridTicks = xScale.ticks(d3.timeDay.every(1))
return html`
<svg viewbox="0 0 ${chartWidth} ${chartHeight}">
<!-- grid -->
<g>
${xLabelTicks.map(date => svg`
<text
x="${xScale(date)}"
y="${chartHeight - margin.bottom + 15}"
font-size="11"
font-family="var(--sans-serif)"
text-anchor="middle"
>${d3.timeFormat('%-m/%-d')(date)}</text>
`)}
${xGridTicks.map(date => svg`
<line
x1="${xScale(date)}"
x2="${xScale(date)}"
y1="0"
y2="${xLabelTicks.find(d => dfns.isEqual(d, date)) ? chartHeight - margin.bottom : chartHeight}"
stroke="#EEE"
/>
`)}
</g>
<!-- data points -->
<g>
${datum.days.map(d => svg`
<circle cx="${xScale(d.date)}" cy="${yScale(d.newCases)}" r="3" fill="#666" />
<text
x="${xScale(d.date) + 6}"
y="${yScale(d.newCases) + 4}"
font-size="11"
font-family="var(--sans-serif)"
fill="#CCC"
>${d.newCases}</text>
`)}
</g>
<!-- regression line -->
<line
x1="${margin.left}"
x2="${chartWidth - margin.right}"
y1="${yScale(linearRegressionLine(0))}"
y2="${yScale(linearRegressionLine(14))}"
stroke="#444"
stroke-dasharray="3"
/>
<!-- regression label -->
<text
x="${margin.left + chartWidth / 2 - margin.right}"
y="${yScale(linearRegressionLine(7)) - 7}"
transform-origin="${margin.left + chartWidth / 2 - margin.right} ${yScale(linearRegressionLine(7)) - 7}"
text-anchor="middle"
transform="rotate(${slope})"
font-size="12"
font-family="var(--sans-serif)"
paint-order="stroke"
stroke="#FFF"
stroke-width="4"
>
daily cases ${perDay > 0 ? 'rising' : 'falling'} by
<tspan font-weight="bold">
~${formatNumber(Math.abs(perDay))}
</tspan>
per day
</text>
<!-- start and end indicators -->
<circle cx="${margin.left}" cy="${yScale(linearRegressionLine(0))}" r="2" fill="#444" />
<text
x="${margin.left - 5}"
y="${yScale(linearRegressionLine(0)) + 5}"
text-anchor="end"
font-size="12"
font-family="sans-serif"
>${formatNumber(linearRegressionLine(0))}</text>
<circle cx="${chartWidth - margin.right}" cy="${yScale(linearRegressionLine(14))}" r="2" fill="#444" />
<text
x="${chartWidth - margin.right + 5}"
y="${yScale(linearRegressionLine(14)) + 3}"
font-size="12"
font-family="sans-serif"
text-anchor="start"
>${formatNumber(linearRegressionLine(14))}</text>
</svg>
`
}