chart = {
const width = height * aspectRatio;
const svg = d3
.create("svg")
.style("background", "#fff")
.attr("width", width)
.attr("height", height);
svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height)
.style("fill", "white")
.style("stroke", "black");
const widthChart = width - padding_chart * 2,
heightChart = height - padding_chart * 2;
let cx = widthChart / 2 + padding_chart / 2;
let cy = heightChart / 2 + padding_chart / 2;
const sankey = d3
.sankey()
.nodeId((d) => d.name)
.nodeAlign(d3.sankeyLeft)
.nodeWidth(5)
.nodePadding(padding)
.extent([
[1, 1],
[heightChart, widthChart - 1]
])
.nodeSort((a, b) => d3.descending(a.value, b.value));
const { nodes, links } = sankey({
nodes: data.nodes.map((d) => Object.assign({}, d)),
links: data.links.map((d) => Object.assign({}, d))
});
const plot = svg
.append("g")
.attr("class", "sankey")
.attr(
"transform",
`translate(${padding_chart}, ${
padding_chart * 2
}) rotate(90, ${cx}, ${cy})`
);
const link = plot
.append("g")
.attr("class", "links")
.attr("fill", "none")
.selectAll("g")
.data(links)
.join("g")
.attr("opacity", 0.4)
.attr("stroke", (d) => {
if (!d.color) return "black";
return d.color;
})
.style("mix-blend-mode", "multiply");
link
.append("path")
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke", (d) => d.uid)
.attr("stroke-width", (d) => Math.max(1, d.width))
plot
.append("g")
.attr("class", "nodes")
.selectAll("rect")
.data(nodes)
.join("rect")
.attr("x", (d) => d.x0)
.attr("y", (d) => d.y0)
.attr("height", (d) => d.y1 - d.y0)
.attr("width", (d) => d.x1 - d.x0)
.attr("stroke", (d) => {
if (d.color === "") return "black";
return d.color;
})
.attr("fill", (d) => {
if (d.color === "") return "black";
return d.color;
});
return svg.node();
}