tisoap / react-flow-smart-edge

Custom Edge for React Flow that never intersects with other nodes
https://tisoap.github.io/react-flow-smart-edge/
MIT License
242 stars 26 forks source link

Create a Smart equivalent to React Flow's Floating Edge #13

Open AnhHuy02 opened 2 years ago

AnhHuy02 commented 2 years ago

There is a case that two adjacent nodes are not showing a straight edge. Instead it just move around and connect behind the node. image

tisoap commented 2 years ago

Hey @AnhHuy02 , could you expand more on the problem you're experiencing? From the screenshot you shared it looks like everything is correct: for the edge at the top of "Strategist" node to connect to the bottom of "generating" node it needs to take this path to avoid intersections. Maybe you meant to connect bottom -> top instead of top -> bottom to create a straight line?

AnhHuy02 commented 2 years ago

Yes. But can you add a Floating Edge from React Flow documentation with Smart Edge feature? It will be cool to see the diagram. https://reactflow.dev/examples/floating-edges

tisoap commented 2 years ago

I see, so you'd like to see an "smart" equivalent of of React Flow's floating edge. I'm not sure if it would be possible, but I'll add to the backlog and leave this issue open

vaibhav-systango commented 2 years ago

any luck on this @tisoap @AnhHuy02

tisoap commented 2 years ago

@vaibhav-systango Didn't started working on this yet

vaibhav-systango commented 2 years ago

it'll be a great help if we can do this, can you guide me the direction incase you're keeping occupied I can try some approach for this. It'll be the coolest to have smart floating edges feature @tisoap @AnhHuy02

tisoap commented 2 years ago

@vaibhav-systango I've just launched version 2.0.0 of this library that exposes a getSmartEdge function instead of factories, check the README.

Looking at how the Floating Edges example was created, I think it's just a case of feeding the output of the example's getEdgeParams function into the getSmartEdge input, but I haven't tested it.

vaibhav-systango commented 2 years ago

This doesn't seem to help @tisoap

ctooley21 commented 1 year ago

@vaibhav-systango I've just launched version 2.0.0 of this library that exposes a getSmartEdge function instead of factories, check the README.

Looking at how the Floating Edges example was created, I think it's just a case of feeding the output of the example's getEdgeParams function into the getSmartEdge input, but I haven't tested it.

Feeding the output of getEdgeParams into getSmartEdge worked perfect, thanks for the note!

Attached is my working solution below:

import React, { useCallback } from "react";
import { useNodes, BezierEdge, useStore } from "reactflow";
import { getSmartEdge } from "@tisoap/react-flow-smart-edge";
import { getEdgeParams } from "./utils";

const myOptions = {
    // your configuration goes here
    nodePadding: 20,
    gridRatio: 15,
};

export default function SmartEdgeWithButtonLabel(props: any) {
    const { style, markerStart, markerEnd, source, target } = props;

    const sourceNode = useStore(
        useCallback((store) => store.nodeInternals.get(source), [source])
    );
    const targetNode = useStore(
        useCallback((store) => store.nodeInternals.get(target), [target])
    );

    const nodes = useNodes();

    const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(
        sourceNode,
        targetNode
    );

    const getSmartEdgeResponse = getSmartEdge({
        sourcePosition: sourcePos,
        targetPosition: targetPos,
        sourceX: sx,
        sourceY: sy,
        targetX: tx,
        targetY: ty,
        nodes,
        // Pass down options in the getSmartEdge object
        options: myOptions,
    });

    // If the value returned is null, it means "getSmartEdge" was unable to find
    // a valid path, and you should do something else instead
    if (getSmartEdgeResponse === null) {
        return <BezierEdge {...props} />;
    }

    const { svgPathString } = getSmartEdgeResponse;

    return (
        <>
            <path
                style={style}
                className="react-flow__edge-path"
                d={svgPathString}
                markerEnd={markerEnd}
                markerStart={markerStart}
            />
        </>
    );
}