chart = {
const svg = d3.select(DOM.svg(width, height));
svg.attr('viewBox', `0 0 ${width} ${height}`);
svg.attr('preserveAspectRatio', 'xMidYMid meet');
svg.style('max-width', '100%').style('height', 'auto');
const showDGS = selectedType.includes('DGS');
const showStock = selectedType.includes('stock');
svg.append('g').call(title('DGS vs. Stock'));
svg.append('g').call(xAxis('Date'));
if (showDGS) {
svg.append('g').call(yAxis('DGS'));
}
if (showStock) {
svg.append('g').call(yAxis2('Stock'));
}
svg.append('g').call(xGrid);
svg.append('g').call(yGrid);
if (showDGS) {
svg
.append('g')
.selectAll('path')
.data(data1)
.join('path')
.attr('d', d => dsgLine(d))
.attr('class', 'total-cases');
svg
.append('g')
.selectAll('total-circle')
.data(data1)
.join('circle')
.style('pointer-events', 'none')
.style('fill', '#eb6f2d')
.attr('r', 3)
.attr('cx', d => xScale(d.DATE))
.attr('cy', d => yScale(d.DGS10));
}
// Daily cases.
if (showStock) {
svg
.append('g')
.selectAll('path')
.data(data2)
.join('path')
.attr('d', d => stockLine(d))
.attr('class', 'daily-cases');
svg
.append('g')
.selectAll('daily-circle')
.data(data2)
.join('circle')
.style('pointer-events', 'none')
.style('fill', '#54abb3')
.attr('r', 3)
.attr('cx', d => xScale(d.Date))
.attr('cy', d => yScale2(d.Close));
}
svg
.append('rect')
.style('fill', 'none')
//.style('opacity', 0.5)
.style('pointer-events', 'all')
.attr('width', width - margin.left - margin.right)
.attr('height', height - margin.top - margin.bottom)
.attr('transform', `translate(${margin.left},${margin.top})`)
.on('touchmove mousemove', mousemove);
//.on('touchend mouseout', mouseout)
const line = svg
.append('line')
.style('stroke', '#999')
.style('pointer-events', 'none')
.style('opacity', 0);
const circle1 = svg
.append('circle')
.style('stroke', '#eb6f2d')
.style('stroke-width', 4)
.style('fill', '#fff')
.attr('r', 5)
.style('opacity', 0);
const circle2 = svg
.append('circle')
.style('stroke', '#54abb3')
.style('stroke-width', 4)
.style('fill', '#fff')
.attr('r', 5)
.style('opacity', 0);
const dateText = svg
.append('text')
.attr('class', 'tooltip-text')
.attr('x', margin.left + 20)
.attr('y', margin.top + 20);
const totalCasesText = svg
.append('text')
.attr('class', 'tooltip-text')
.attr('x', margin.left + 20)
.attr('y', margin.top + 40);
const dailyCasesText = svg
.append('text')
.attr('class', 'tooltip-text')
.attr('x', margin.left + 20)
.attr('y', margin.top + (showDGS ? 60 : 40));
function mousemove() {
const d = bisect(d3.mouse(this)[0] + margin.left);
line
.attr('x1', xScale(d.DATE))
.attr('x2', xScale(d.DATE))
.attr('y1', margin.top)
.attr('y2', height - margin.bottom)
.style('opacity', 0.8);
circle1
.style('pointer-events', 'none')
.attr('cx', xScale(d.DATE))
.attr('cy', yScale(d.DGS10))
.style('opacity', showDGS ? 1 : 0);
circle2
.style('pointer-events', 'none')
.attr('cx', xScale(d.date))
.attr('cy', yScale2(d.Close))
.style('opacity', showStock ? 1 : 0);
dateText
.text('Date: ' + d3.timeFormat('%m/%d')(d.DATE))
.style('opacity', 1);
totalCasesText
.text('Total Cases: ' + d3.format(',')(d.DGS10))
.style('opacity', showDGS ? 1 : 0);
dailyCasesText
.text('New Cases: ' + d3.format(',')(d.Close))
.style('opacity', showStock ? 1 : 0);
}
return svg.node();
}