viz = {
const svg = d3.create("svg").attr("width", width).attr("height", height);
svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height)
.attr("fill", bgColor);
svg
.selectAll(".rects")
.data(dataMode == "Average" ? birthData : birthDataWithoutFeb29)
.enter()
.append("rect")
.attr("width", rectWidth - internalMargin)
.attr("height", rectHeight - internalMargin)
.attr("x", (d) => dayScale(d.date) + internalMargin / 2)
.attr("y", (d) => monthScale(d.month) + internalMargin / 2)
.attr("fill", (d) =>
d3[colorScale](
birthParameterScale(
dataMode == "Average" ? d.births / d.count : d.births
)
)
)
.attr("class", "rects")
.on("mouseover", (e, d) => showData(svg, d))
.on("mouseout", (e, d) => hideData(svg, d));
svg
.selectAll(".monthLabels")
.data(monthLabels)
.enter()
.append("text")
.text((d) => d)
.attr("x", margin - labelOffset)
.attr("y", (d, i) => monthScale(i + 1) + 0.5 * rectHeight)
.attr("fill", "white")
.attr("alignment-baseline", "middle")
.attr("text-anchor", "end")
.style("text-transform", "uppercase")
.attr("font-family", font)
.attr("font-size", labelFontSize)
.attr("class", "monthLabels");
//day labels
svg
.selectAll(".dayLabels")
.data(dayLabels)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d) => dayScale(d) + rectWidth / 2)
.attr("y", (d, i) => margin - labelOffset)
.attr("fill", "white")
.attr("font-family", font)
.attr("font-size", labelFontSize)
.attr("text-anchor", "middle")
.attr("class", "dayLabels");
//add title
svg
.append("text")
.text(
dataMode == "Average"
? "Average US Births by Day, 1995-2014"
: " Daily US Births, 1995-2014"
)
.attr("x", width - margin)
.attr("y", margin / 2)
.attr("fill", "white")
.attr("font-family", font)
.attr("text-anchor", "end");
//add text element to fill with info when users mouse over rectangles
svg
.append("text")
.text("")
.attr("x", width / 2)
.attr("y", height - margin / 2)
.attr("fill", "white")
.attr("font-family", font)
.attr("text-anchor", "middle")
.attr("id", "textHolder");
//add line to show approximate date of conception
svg
.append("line")
.attr("stroke", "white")
.attr("id", "conceptionLine")
.attr("stroke-width", 5)
.attr("stroke-linecap", "round")
.attr("pointer-events", "none");
//Legends
const legendParams = d3.range(legendBoxCount).map((d) => d / legendBoxCount);
svg
.selectAll(".legendBoxes")
.data(legendParams)
.enter()
.append("rect")
.attr("width", legendSize)
.attr("height", legendSize)
.attr("x", (d, i) => i * legendSize + margin)
.attr("y", (d) => margin / 2 - legendSize / 4)
.attr("fill", (d) => d3[colorScale](d))
.attr("class", "rects");
svg
.selectAll(".legendLabels")
.data(legendParams)
.enter()
.append("text")
.text((d) =>
birthParameterScale
.invert(d)
.toLocaleString(undefined, { maximumFractionDigits: 0 })
)
.attr("x", (d, i) => i * legendSize + margin + legendSize * 0.5)
.attr("y", (d) => margin / 2 - legendSize / 2)
.attr(
"transform",
(d, i) =>
`rotate(-45 ${i * legendSize + margin + legendSize * 0.5} ${
margin / 2 - legendSize / 2
})`
)
.attr("font-family", font)
.attr("font-size", labelFontSize)
.attr("fill", "white")
.attr("class", "rects");
return svg.node();
}