Guest User

Sankey

a guest
Sep 13th, 2021
443
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import * as d3 from 'd3';
  2. import { sankey, sankeyJustify, sankeyLinkHorizontal } from 'd3-sankey';
  3. import { createRef, useEffect } from 'react';
  4.  
  5. import * as data from '../../../sankeyData.json';
  6.  
  7. const Sankey = () => {
  8.     const d3Ref = createRef<HTMLDivElement>();
  9.  
  10.     useEffect(() => {
  11.         const width = d3Ref.current?.getBoundingClientRect().width!;
  12.         const height = d3Ref.current?.getBoundingClientRect().height! / 2;
  13.  
  14.         const color = () => {
  15.             const color = d3.scaleOrdinal(d3.schemeCategory10);
  16.             return (d: any) => color(d.category);
  17.         };
  18.  
  19.         const format = () => {
  20.             const format = d3.format(',.0f');
  21.             return data.units ? (d: any) => `${format(d)} ${data.units}` : format;
  22.         };
  23.  
  24.         const chart = () => {
  25.             const svg = d3.create('svg').attr('viewBox', `${[0, 0, width, height]}`);
  26.  
  27.             const sankeyConstructor = sankey()
  28.                 //@ts-ignore
  29.                 .nodeId((d) => d.name)
  30.                 .nodeAlign(sankeyJustify)
  31.                 .nodeWidth(10)
  32.                 .nodePadding(10)
  33.                 .extent([
  34.                     [1, 5],
  35.                     [width - 1, height - 5],
  36.                 ]);
  37.  
  38.             const createSankey = (data: any) => {
  39.                 return sankeyConstructor({
  40.                     nodes: data.nodes.map((d: any) => Object.assign({}, d)),
  41.                     links: data.links.map((d: any) => Object.assign({}, d)),
  42.                 });
  43.             };
  44.  
  45.             const { nodes, links }: any = createSankey(data);
  46.  
  47.             svg
  48.                 .append('g')
  49.                 // .attr('stroke', '#000')
  50.                 .selectAll('rect')
  51.                 .data(nodes)
  52.                 .join('rect')
  53.                 .attr('x', (d: any) => d.x0)
  54.                 .attr('y', (d: any) => d.y0)
  55.                 .attr('height', (d: any) => d.y1 - d.y0)
  56.                 .attr('width', (d: any) => d.x1 - d.x0)
  57.                 .attr('fill', color())
  58.                 .append('title')
  59.                 .text((d: any) => `${d.name}\n${format(d)}`);
  60.  
  61.             const link = svg
  62.                 .append('g')
  63.                 .attr('fill', 'none')
  64.                 .attr('stroke-opacity', 0.5)
  65.                 .selectAll('g')
  66.                 .data(links)
  67.                 .join('g')
  68.                 .style('mix-blend-mode', 'difference');
  69.             // const gradient = link
  70.             //  .append('linearGradient')
  71.             //  // .attr('id', (d: any) => (d.uid = d3.DOM.uid('link')).id)
  72.             //  .attr('gradientUnits', 'userSpaceOnUse')
  73.             //  .attr('x1', (d: any) => d.source.x1)
  74.             //  .attr('x2', (d: any) => d.target.x0);
  75.  
  76.             // gradient
  77.             //  .append('stop')
  78.             //  .attr('offset', '0%')
  79.             //  //@ts-ignore
  80.             //  .attr('stop-color', (d) => '#123'); //color()
  81.  
  82.             // gradient
  83.             //  .append('stop')
  84.             //  .attr('offset', '100%')
  85.             //  //@ts-ignore
  86.             //  .attr('stop-color', (d) => '#123'); //color()
  87.  
  88.             link
  89.                 .append('path')
  90.                 //@ts-ignore
  91.                 .attr('d', sankeyLinkHorizontal())
  92.                 .attr('stroke', '#888') //(d: any) => d.value
  93.                 .attr('stroke-width', (d: any) => Math.max(1, d.width - 8));
  94.  
  95.             link.append('title').text((d: any) => `${d.source.name} → ${d.target.name}\n${format(d.value)}`); //may need d.value
  96.  
  97.             svg
  98.                 .append('g')
  99.                 .attr('font-family', 'sans-serif')
  100.                 .attr('font-size', 12)
  101.                 .selectAll('text')
  102.                 .data(nodes)
  103.                 .join('text')
  104.                 .attr('x', (d: any) => (d.x0 < width / 2 ? d.x1 + 2 : d.x0 - 2))
  105.                 .attr('y', (d: any) => (d.y1 + d.y0) / 2)
  106.                 .attr('dy', '0.35em')
  107.                 .attr('text-anchor', (d: any) => (d.x0 < width / 2 ? 'start' : 'end'))
  108.                 .text((d: any) => d.name);
  109.  
  110.             return svg.node();
  111.         };
  112.  
  113.         d3.select(d3Ref.current).append(chart);
  114.     }, []);
  115.  
  116.     return <div ref={d3Ref} className="w-4/5 h-screen"></div>;
  117. };
  118.  
  119. export default Sankey;
  120.  
Advertisement
Add Comment
Please, Sign In to add comment