d3 / d3-sankey

Visualize flow between nodes in a directed acyclic network.
https://observablehq.com/collection/@d3/d3-sankey
BSD 3-Clause "New" or "Revised" License
826 stars 255 forks source link

Is it possible to sort source or target nodes in one column? #118

Closed lhf552004 closed 1 year ago

lhf552004 commented 1 year ago

As can be seen in the picture of the demo. I want to sort the left-most nodes, or right-most nodes in one column. I can sort the left-most nodes:

const sankey = d3.sankey()
  .nodeId(d => d.id)
  .nodeWidth(24)
  .nodePadding(8)
  .extent([[1, 1], [width - 1, height - 6]])
  .nodeSort((a, b) => {
    // Sort nodes based on custom criteria
    // For example, alphabetically by name:
    return d3.ascending(a.id, b.id);
  })

But I need help to sort the right-most nodes by their type, which is in the parentheses. Is there some way to achieve that?

image

It achieves half, the same type of nodes are together, but the order is incorrect. Here is the sort method:

 function sortByLinkTarget(a, b) {
    if (a.sourceLinks.length === 0) return -1;
    if (b.sourceLinks.length === 0) return 1;

    const aTargetNames = Array.from(
      new Set(a.sourceLinks.map((link) => extractNameFromId(link.target.id)))
    )
      .sort()
      .join("|");
    const bTargetNames = Array.from(
      new Set(b.sourceLinks.map((link) => extractNameFromId(link.target.id)))
    )
      .sort()
      .join("|");
    return d3.ascending(
      (aTargetNames + a.id).toLowerCase(),
      (bTargetNames + b.id).toLowerCase()
    );
  }

This is debugging info:

image

Thanks