d3.js

Upgrading d3-sankey chart to latest version shows issue with layout method


how to resolve issue with d3-sankey chart? I am upgrading sankey chart from 0.4.2 version to latest version, which gives error with layout method which is deprecated in latest version.

Code:

sankey
  .nodes(graph.nodes)
  .links(graph.links)
  .layout(32);

after removing layout methods error is as below

attr.js:30 Error: <g> attribute transform: Expected number, "translate(undefined,undefi…".
(anonymous) @ attr.js:30

Tried using sankey() method instead of layout but did not work.


Solution

  • No layout method: The layout() method is no longer part of the API. Instead, the sankey() generator computes node and link positions directly.

    Declarative API: Nodes and links are passed as input objects, and the generator returns updated positions for rendering.

    extent replaces chart size settings: The extent method defines the bounds of the Sankey diagram.

    sankeyLinkHorizontal for link paths: A helper function generates smooth horizontal link paths.

     // Set dimensions and margins
        const width = 800;
        const height = 600;
    
        // Data
        const graph = {
          nodes: [
            { name: "Node A" },
            { name: "Node B" },
            { name: "Node C" },
            { name: "Node D" }
          ],
          links: [
            { source: 0, target: 1, value: 10 },
            { source: 1, target: 2, value: 15 },
            { source: 0, target: 3, value: 5 },
            { source: 3, target: 2, value: 5 }
          ]
        };
    
        // Create an SVG canvas
        const svg = d3.select("svg");
    
        // Sankey generator configuration
        const sankeyGenerator = d3.sankey()
          .nodeWidth(20)
          .nodePadding(20)
          .extent([[10, 10], [width - 10, height - 10]]);
    
        // Compute the Sankey layout
        const { nodes, links } = sankeyGenerator({
          nodes: graph.nodes.map(d => Object.assign({}, d)),
          links: graph.links.map(d => Object.assign({}, d))
        });
    
        // Define color scale
        const color = d3.scaleOrdinal(d3.schemeCategory10);
    
        // Render links
        svg.append("g")
          .selectAll("path")
          .data(links)
          .enter()
          .append("path")
          .attr("class", "link")
          .attr("d", d3.sankeyLinkHorizontal())
          .style("stroke", d => color(d.source.name))
          .style("stroke-width", d => Math.max(1, d.width));
    
        // Render nodes
        const node = svg.append("g")
          .selectAll("g")
          .data(nodes)
          .enter()
          .append("g")
          .attr("class", "node");
    
        node.append("rect")
          .attr("x", d => d.x0)
          .attr("y", d => d.y0)
          .attr("width", d => d.x1 - d.x0)
          .attr("height", d => d.y1 - d.y0)
          .style("fill", d => color(d.name))
          .style("stroke", "#000");
    
        node.append("text")
          .attr("x", d => d.x0 - 6)
          .attr("y", d => (d.y1 + d.y0) / 2)
          .attr("dy", "0.35em")
          .attr("text-anchor", "end")
          .text(d => d.name)
          .filter(d => d.x0 < width / 2)
          .attr("x", d => d.x1 + 6)
          .attr("text-anchor", "start");
    .node rect {
          stroke: #000;
        }
        .link {
          fill: none;
          stroke-opacity: 0.3;
        }
    <script src="https://d3js.org/d3.v7.min.js"></script>
     <script src="https://unpkg.com/d3-sankey@0.12.3/dist/d3-sankey.min.js"></script>
     <svg width="800" height="600"></svg>