projectstorm / react-diagrams

a super simple, no-nonsense diagramming library written in react that just works
https://projectstorm.cloud/react-diagrams
MIT License
8.65k stars 1.17k forks source link

Dagre won't account for true dimension of nodes if window is not in view #561

Open xiaopow opened 4 years ago

xiaopow commented 4 years ago

If you use auto distribute to distribute the diagram, the page needs to be in view to provide actual node dimensions to dagre. If the page is not in view, the autodistribute result will be much smaller than it is supposed to be because the dimensions of the nodes are smaller.

When page not in view Screenshot 2020-03-07 at 5 53 43 PM

Expected behaviour Screenshot 2020-03-07 at 5 53 47 PM

ruben0626 commented 4 years ago

Any news on this ?

xiaopow commented 4 years ago

no news yet, haven't dived in to hack a solution yet

dalmo3 commented 3 years ago

I had this same problem, and fixed* it with a combination of state and setTimeout:


const engine = createEngine();
engine.setModel(new DiagramModel());

const Diagram = () => {
  const [shouldDistribute, setShoudDistribute] = useState(false);
  const isVisible = useWindowVisibility();

  useEffect(() => {

    < ... populate model ... >

    setShoudDistribute(true);
  }, []);

  useLayoutEffect(() => {
    if (isVisible && shouldDistribute) {
      setTimeout(() => distribute(engine)); // hack to wait for the page to be in view
      setShoudDistribute(false);
    }
  }, [isVisible, shouldDistribute]);

  return (
      <CanvasWidget engine={engine} className="canvas" />;
  );
};

const useWindowVisibility = () => {
  const [isVisible, setIsVisible] = useState(!document.hidden);

  useEffect(() => {
    const handleVisitbility = () => setIsVisible(!document.hidden);

    document.addEventListener('visibilitychange', handleVisitbility);

    return () =>
      document.removeEventListener('visibilitychange', handleVisitbility);
  });

  return isVisible;
};

const distribute = (engine: DiagramEngine) => {
  const dagreEngine = new DagreEngine({
    graph: {
      rankdir: 'TB',
      ranker: 'longest-path',
      marginx: 25,
      marginy: 25,
      width: 150,
      height: 150
    },
    includeLinks: true
  });

  dagreEngine.redistribute(engine.getModel());
  engine.repaintCanvas();
};

*I still get a very brief FOUC before redistribution.