{
const svg = d3.create("svg").attr("width", width).attr("height", height);
const bg = svg
.append("rect")
.attr("width", width)
.attr("height", height)
.attr("fill", "#445");
svg
.selectAll(".timelines")
.data(cleanedData)
.enter()
.append("line")
.attr("stroke", "white")
.attr("x1", margin)
.attr("x2", width - margin)
.attr("y1", (d) => productScale(d.name))
.attr("y2", (d) => productScale(d.name));
for (let product of cleanedData) {
svg
.selectAll(".reviewDots")
.data(product.reviews)
.enter()
.append("circle")
.attr("fill", (d) => d3.interpolateMagma(d.stars / 5))
.attr("cx", (d) => timeScale(d.date))
.attr("cy", (d) => productScale(product.name))
.attr("r", 3)
.attr("opacity", 0.5);
}
svg
.selectAll(".labels")
.data(boundaryDates)
.enter()
.append("text")
.attr("x", (d) => timeScale(d))
.attr("y", margin / 2)
.attr("fill", "white")
.attr("text-anchor", "middle")
.text((d) => d.toLocaleString().split(",")[0]);
return svg.node();
}