vasturiano / react-force-graph

React component for 2D, 3D, VR and AR force directed graphs
https://vasturiano.github.io/react-force-graph/example/large-graph/
MIT License
2.21k stars 284 forks source link

double click handler/ id display without hover #53

Open stimilsina opened 5 years ago

stimilsina commented 5 years ago

it would be very helpful if it would be possible to have a different handler for single and double mouse clicks on nodes and edges. Also, ability to display let's say the unique identifier of node/edge without requiring an explicit hover would be great. If there are already ways to do these two operations, please add comments. Thanks.

zachboatwright commented 5 years ago

I agree, having a doubleClick event handler would be really helpful.

As for displaying identifiers for nodes and edges, you can do that by passing a custom canvas/threeJS object into the component to show whatever information you want. If you pass this function into the nodeCanvasObject prop, you should see the node's name show up underneath it:

    (node, ctx, globalScale) => {
    const { hoveredNode } = this.state;

    // create circle
    ctx.beginPath();
    ctx.arc(node.x, node.y, 5, 0, 2 * Math.PI, false);
    ctx.fillStyle = "#636971";
    ctx.fill();

    // create label
    const label = node.name;
    const labelOffsetY = -9;
    ctx.font = `5px Sans-Serif`;
    ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.strokeStyle = "#24272B";
    ctx.lineWidth = 0.5;
    ctx.strokeText(label, node.x, node.y - labelOffsetY);
    ctx.fillStyle = "#636971";
    ctx.fillText(label, node.x, node.y - labelOffsetY);
  }

This will only work in ForceGraph2D, by the way.

jtewright commented 3 years ago
onNodeClick(node, event) {
  if (event.detail == 2) {
    // double click
  }
}
ImadChughtai commented 2 years ago
onNodeClick(node, event) {
  if (event.detail == 2) {
    // double click
  }
}

It's not working. event.detail always gives 0.

ameeena commented 2 years ago

Hi, Any update on this? I need a double click event handler for nodes. Thanks

SamuelHassine commented 2 years ago

@vasturiano any chance you can look at a onNodeDoubleClick callback in the component? For the moment, the event.detail returned by the onNodeClick callback is not relevant even for double click.

It will be really useful to handle easy expand of nodes using double click.

Reference to: https://github.com/OpenCTI-Platform/opencti/issues/1860.

vasturiano commented 2 years ago

@SamuelHassine you should be able to easily implement your own double-click detector on top of the existing onNodeClick method, simply by checking timeouts in between clicks of the same node.

Something similar to:

const DBL_CLICK_TIMEOUT = 500; // ms
const [prevClick, setPrevClick] = useState();
const handleNodeClick = node => {
  const now = new Date();
  if (prevClick && prevClick.node === node && (now - prevClick.time) < DBL_CLICK_TIMEOUT) {
    setPrevClick(null);
    handleNodeDblClick(node);
  }
  setPrevClick({ node, time: now });
};

The implementation of handleNodeDblClick is up to you. 😃

SamuelHassine commented 2 years ago

Thanks a lot for your quick and kind reply @vasturiano. I will try your approach!

sorenhoyer commented 2 years ago

@vasturiano the problem with your suggested solution is that a double click will also count as a normal click. So if you e.g. select the node on click, but also wants to be able to just focus on it (and not select it) when double clicking, then it starts getting a little more complicated. Not that it can't be done, however I'd sure love an onDblClick handler 😎 At least if would be nice to have a example or have it documented somewhere.

Great package btw. 👍

anyuruf commented 1 month ago

I managed to get it working using ChatGpt for single n double click,

function handleClicks (clickTimeout: number,
    setClickTimeout: Dispatch<React.SetStateAction<number>>, ) {
    const doubleClickDelay = 350;
    // Clear the timeout if the click is fast enough
    if (clickTimeout) {
        clearTimeout(clickTimeout);
        setClickTimeout(0);
        //handle double click
    } else {
        // Set a timeout for single click
        const results = window.setTimeout(() => {
            setClickTimeout(0); // Reset timeout
        }, doubleClickDelay);

        setClickTimeout(results);
    }
};
}

clickTimeout and setClickTimeout is react external state to the function