chart = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, config.width, config.height])
.attr("width", config.width)
.attr("height", config.height)
.attr("style", "max-width: 100%; height: auto; font: 13px sans-serif;");
const defs = svg.append("defs");
const filter = defs
.append("filter")
.attr("id", "drop-shadow")
.attr("height", "150%");
filter
.append("feGaussianBlur")
.attr("in", "SourceAlpha")
.attr("stdDeviation", 5);
filter
.append("feOffset")
.attr("dx", 8)
.attr("dy", 8)
.attr("result", "offsetblur");
filter
.append("feComponentTransfer")
.append("feFuncA")
.attr("type", "linear")
.attr("slope", 1);
filter
.append("feMerge")
.selectAll("feMergeNode")
.data(["offsetblur", "SourceGraphic"])
.enter()
.append("feMergeNode")
.attr("in", (d) => d);
const leaf = svg
.selectAll("g")
.data(leaves)
.join("g")
.attr("transform", (d) => `translate(${d.x0},${d.y0})`);
const uid = `O-${Math.random().toString(16).slice(2)}`;
leaf
.append("clipPath")
.attr("id", (d) => (d.clipUid = `${uid}-${d.data.id}`))
.append("rect")
.attr("width", (d) => d.x1 - d.x0)
.attr("height", (d) => d.y1 - d.y0);
const format = d3.format(",d");
leaf.append("title").text((d) => d.data.kapittel);
leaf
.append("rect")
.attr("fill", (d) => colorScale(d.data.data.diff))
.attr("fill-opacity", 0.6)
.attr("opacity", 0.4)
.attr("width", (d) => d.x1 - d.x0)
.attr("height", (d) => d.y1 - d.y0)
.attr("filter", (d) =>
d.data.data.kapittel === "Sikt" && highlightSikt
? "url(#drop-shadow)"
: null
);
const ytpos = (d, i) => {
return ttsizes[d.size] * (i + 1.4);
};
leaf
.append("text")
.attr("clip-path", (d) => `url(#${d.clipUid})`)
.attr("x", (d) => 4)
.attr("y", (d) => ytpos(d, 0))
.attr("font-size", (d) => ttsizes[d.size])
.attr("opacity", (d) => (d.h > 20 ? 1 : 0))
.attr("font-weight", "bold")
.text((d) => d.data.data.kapittel);
leaf
.append("text")
.attr("clip-path", (d) => `url(#${d.clipUid})`)
.attr("x", (d) => 4)
.attr("y", (d) => ytpos(d, 1))
.attr("font-size", (d) => ttsizes[d.size])
.attr("opacity", (d) => (d.h > 30 ? 1 : 0))
.text((d) => d.data.data.post);
leaf
.append("text")
.attr("clip-path", (d) => `url(#${d.clipUid})`)
.attr("x", (d) => 4)
.attr("y", (d) => ytpos(d, 2))
.attr("font-size", (d) => ttsizes[d.size])
.attr("opacity", (d) => (d.h > 36 ? 1 : 0))
.text((d) => numFmt(d.data.data.sum25));
leaf
.append("text")
.attr("clip-path", (d) => `url(#${d.clipUid})`)
.attr("x", (d) => 4)
.attr("y", (d) => ytpos(d, 3))
.attr("font-size", (d) => ttsizes[d.size])
.attr("opacity", (d) => d.h > ytpos(d, 4) + 2)
.text((d) => (d.data.data.diff ? diffFmt(d.data.data.diff) : "Nytt 2025"));
return svg.node();
}