<script>
import { LayerCake, Svg } from 'layercake';
import Sankey from './_components/Sankey.svelte';
import data from './_data/sankey-data.js';
</script>
<div class="chart-container">
<LayerCake {data}>
<Svg>
<Sankey getNodeFill={() => '#00bbff'} getLinkStroke={() => '#00bbff35'} />
</Svg>
</LayerCake>
</div>
<style>
.chart-container {
width: 100%;
height: 250px;
}
</style>
<script>
import * as Sankey from 'd3-sankey';
import { getLayerCakeContext } from 'layercake';
const k = getLayerCakeContext();
let {
getLinkStroke = () => 'rgba(0, 0, 0, .2)',
getNodeFill = () => '#333',
getTextFill = () => '#263238',
nodeWidth = 5,
nodePadding = 10,
linkSort = undefined,
nodeId = d => d.id,
nodeAlign = Sankey.sankeyLeft
} = $props();
const linkPath = Sankey.sankeyLinkHorizontal();
let sankeyData = $derived.by(() => {
const sankey = Sankey.sankey()
.nodeAlign(nodeAlign)
.nodeWidth(nodeWidth)
.nodePadding(nodePadding)
.nodeId(nodeId)
.size([k.width, k.height])
.linkSort(linkSort);
const graph = {
nodes: k.data.nodes.map(d => ({ ...d })),
links: k.data.links.map(d => ({ ...d }))
};
return (sankey(graph));
});
let fontSize = $derived(k.width <= 320 ? 8 : 12);
</script>
<g class="sankey-layer">
<g class="link-group">
{#each sankeyData.links as d}
<path
d={linkPath(d)}
fill="none"
stroke={getLinkStroke(d)}
stroke-opacity="0.5"
stroke-width={d.width}
/>
{/each}
</g>
<g class="rect-group">
{#each sankeyData.nodes as d}
<rect x={d.x0} y={d.y0} height={d.y1 - d.y0} width={d.x1 - d.x0} fill={getNodeFill(d)} />
<text
x={d.x0 < k.width / 4 ? d.x1 + 6 : d.x0 - 6}
y={(d.y1 + d.y0) / 2}
dy={fontSize / 2 - 2}
style="fill: {getTextFill(d)};
font-size: {fontSize}px;
text-anchor: {d.x0 < k.width / 4 ? 'start' : 'end'};"
>
{d.id}
</text>
{/each}
</g>
</g>
<style>
text {
pointer-events: none;
}
</style>export default {
nodes: [
{ id: 'A1' },
{ id: 'A2' },
{ id: 'A3' },
{ id: 'B1' },
{ id: 'B2' },
{ id: 'B3' },
{ id: 'B4' },
{ id: 'C1' },
{ id: 'C2' },
{ id: 'C3' },
{ id: 'D1' },
{ id: 'D2' }
],
links: [
{ source: 'A1', target: 'B1', value: 27 },
{ source: 'A1', target: 'B2', value: 9 },
{ source: 'A2', target: 'B2', value: 5 },
{ source: 'A2', target: 'B3', value: 11 },
{ source: 'A3', target: 'B2', value: 12 },
{ source: 'A3', target: 'B4', value: 7 },
{ source: 'B1', target: 'C1', value: 13 },
{ source: 'B1', target: 'C2', value: 10 },
{ source: 'B4', target: 'C2', value: 5 },
{ source: 'B4', target: 'C3', value: 2 },
{ source: 'B1', target: 'D1', value: 4 },
{ source: 'C3', target: 'D1', value: 1 },
{ source: 'C3', target: 'D2', value: 1 }
]
};