chart = {
const height = 1200;
const labelwidth = 200;
const margin = { top: 120, right: 30, bottom: 30, left: 40 };
const velocity = 0.4;
const xScale = d3
.scaleLinear()
.domain([0, data[0].results.length - 1])
.range([margin.left + labelwidth, width - margin.right]);
const yScale = d3
.scaleLinear()
.domain([0, data.length - 1])
.range([margin.top, height - margin.bottom]);
const svg = d3.create("svg").attr("width", width).attr("height", height);
svg
.append("rect")
.attr("width", width)
.attr("height", height)
.attr("fill", "#f0ebd8");
let colors = {
cat: "#05A8AA",
p: "#F07167",
at: "#00487C",
opp: "#445552",
film: "#8A4F7D"
};
svg
.append("text")
.attr("y", 60)
.attr("x", margin.left)
.attr("font-size", 54)
.attr("text-anchor", "start")
.attr("dominant-baseline", "middle")
.text("Google Search Trends in Norway 2024");
svg
.selectAll("text.l")
.data(data)
.join("text")
.attr("class", "l")
.attr("fill", (d) => colors[cat[d.txt]])
.attr("y", (d, i) => yScale(i) + 4)
.attr("x", margin.left + labelwidth - 5)
.attr("text-anchor", "end")
.text((d, i) => d.txt);
// Add a center line for each violin
svg
.selectAll("line.center-line")
.data(data)
.join("line")
.attr("class", "center-line")
.attr("x1", xScale(0))
.attr("x2", xScale(49))
.attr("y1", (d, i) => yScale(i))
.attr("y2", (d, i) => yScale(i))
.attr("stroke", (d) => colors[cat[d.txt]])
.attr("stroke-width", 1);
svg
.selectAll("path.violin")
.data(data)
.join("path")
.attr("class", "violin")
.attr("fill", (d) => colors[cat[d.txt]])
.attr("stroke", (d) => colors[cat[d.txt]])
//.attr("opcacity", 0.2)
.attr("d", (d, i) => {
const results = d.results; // Processed values defining the height of the violin
const y = yScale(i); // Center point for this category
const x = xScale; // X scale for the results
// Generate the path for the violin
const path = d3.path();
const controlOffset = 5; // Adjust for smoother rounding
// Start at the center bottom
path.moveTo(x(0), y);
let values = results.map((d) => d.value);
let sum = 1 / Math.log(d3.mean(values));
console.log("text", d.txt, "results", sum);
// Top edge with rounded corners
for (let idx = 0; idx < results.length - 1; idx++) {
const x1 = x(idx);
const x2 = x(idx + 1);
const y1 = y - sum * velocity * results[idx].value;
const y2 = y - sum * velocity * results[idx + 1].value;
// Use quadratic curve for smoothing
const xc = (x1 + x2) / 2;
const yc = (y1 + y2) / 2;
path.quadraticCurveTo(x1, y1, xc, yc);
}
// Mirror bottom edge with rounded corners
for (let idx = results.length - 1; idx > 0; idx--) {
const x1 = x(idx);
const x2 = x(idx - 1);
const y1 = y + sum * velocity * results[idx].value;
const y2 = y + sum * velocity * results[idx - 1].value;
// Use quadratic curve for smoothing
const xc = (x1 + x2) / 2;
const yc = (y1 + y2) / 2;
path.quadraticCurveTo(x1, y1, xc, yc);
}
// Return to the center bottom with a sharp edge
path.lineTo(x(0), y);
path.closePath(); // Close the shape
return path.toString();
});
return svg.node();
}