timeSoundSpiral = {
const svg = d3.create("svg").attr("width", width).attr("height", height);
svg
.selectAll(".bars")
.data(barCoordinates)
.enter()
.append("path")
.attr("d", (d, i) => d)
.attr("stroke-width", 1)
.attr("fill", "none")
.attr("stroke", "black")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
svg
.selectAll(".staves")
.data(spiralCoordinates)
.enter()
.append("path")
.attr("d", (d) => spiralGen(d))
.attr("stroke", (d, i) => d3.interpolatePlasma(i / categoryCount))
.attr("stroke-width", staveStrokeWidth)
.attr("fill", "none")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
svg
.selectAll(".notes")
.data(noteArcs)
.enter()
.append("path")
.attr("d", (d) => spiralGen(d))
.attr("stroke", (d) => d3.interpolatePlasma(d[0].category / categoryCount))
.attr("stroke-width", noteStrokeWidth)
.attr("fill", "none")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.on("mouseover", (e, d) => {
d3.select("#tooltip")
.transition()
.attr("opacity", 1)
.attr("transform", "translate(" + e.offsetX + "," + e.offsetY + ")");
d3.select("#tooltipText").text(
d[0].timing.start.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit"
}) +
" => " +
d[0].timing.end.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit"
}) +
" | " +
d[0].category
);
})
.on("mouseout", (e, d) => {
d3.select("#tooltip").transition().attr("opacity", 0);
});
const g = svg
.append("g")
.attr("id", "tooltip")
.attr("pointer-events", "none")
.attr("opacity", 0)
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
g.append("rect")
.attr("x", -100)
.attr("y", -15)
.attr("width", 200)
.attr("height", 30)
.attr("stroke", "orange")
.attr("fill", "white");
g.append("text")
.text("")
.attr("id", "tooltipText")
.attr("font-family", "courier")
.attr("font-size", 12)
.attr("text-anchor", "middle")
.attr("dominant-baseline", "middle");
return svg.node();
}