react-d3-graph
react-d3-graph copied to clipboard
Add x,y to onClickGraph callback
Is your feature request related to a problem? Please describe. No.
Describe the solution you'd like I would like x and y coordinates to be passed in to the callback
Describe your use case I would like to create a new node at a specific user-defined point on the canvas. It is much easier to do this graphically by clicking instead of adding a node, adding it randomly on the page and dragging it to my desired position.
Describe alternatives you've considered I've been adding nodes with the interaction as above.
Additional context
I'm not super familiar with the codebase but I've checked the SyntheticBaseEvent
that is returned by the onClickGraph
function and couldn't find numbers that resembled the coords that I need.
Could I double-check with you if this is the functionality you're looking for?
In order to provide x,y
coordinates when creating a node, check our example in the project sandbox where we attribute random coordinates to newly added nodes.
Hi @danielcaldas, Thanks for looking at my feature request.
It's not exactly what I'm looking for. I was hoping the user can click on a blank space on the graph to create a node at that coordinate.
I'm able to create the nodes at a given x,y coordinate but I'm unable to get the coordinates when the user clicks on the graph.
The callback that I found was onClickGraph
but I couldn't find a way to get the coordinates from it.
Hmmm... @Taresin still looks like something you should be able to achieve on your own without react-d3-graph. Look at my example, maybe it clears the ideas for you.
Quick & dirty implementation
⚠️ Please don't copy&paste this as it is, just a demonstration.
import React, { useState } from "react";
import "./styles.css";
import { Graph } from "react-d3-graph";
export default function App() {
// graph payload (with minimalist structure)
const [data, setData] = useState({
nodes: [{ id: "Harry" }, { id: "Sally" }, { id: "Alice" }],
links: [
{ source: "Harry", target: "Sally" },
{ source: "Harry", target: "Alice" }
]
});
// the graph configuration, just override the ones you need
const myConfig = {
nodeHighlightBehavior: true,
freezeAllDragEvents: true,
node: {
color: "lightgreen",
size: 120,
highlightStrokeColor: "blue"
},
link: {
highlightColor: "lightblue"
}
};
const onClickNode = function (nodeId) {
window.alert(`Clicked node ${nodeId}`);
};
document.addEventListener("click", (event) => {
console.log(event);
const { clientX, clientY } = event;
const newNode = {
id: `${Date.now()}`,
x: clientX,
y: clientY
};
setData({
...data,
nodes: [...data.nodes, newNode]
});
});
return (
<Graph
id="graph-id" // id is mandatory
data={data}
config={myConfig}
onClickNode={onClickNode}
/>
);
}
But when the canvas is moved or scaled the nodes will not appear in the exact canvas position, we need to shift and rescale according to the translation. The way I found to access the translation values from the event is quite messy so maybe a feature should be added. Nevertheless, this is what I think you are looking for:
const onClickGraph = function(event) {
var screen_x = event.nativeEvent.layerX;
var screen_y = event.nativeEvent.layerY;
var trans_x = 0
var trans_y = 0
var trans_scale = 1
if (event.target.childNodes[1].transform.baseVal.length > 0) {
trans_x = event.target.childNodes[1].transform.baseVal[0].matrix.e;
trans_y = event.target.childNodes[1].transform.baseVal[0].matrix.f;
trans_scale = event.target.childNodes[1].transform.baseVal[1].matrix.a;
}
var canvas_x = (screen_x - trans_x)/trans_scale;
var canvas_y = (screen_y - trans_y)/trans_scale;
console.log(canvas_x)
console.log(canvas_y)
const newNode = {
id: `${Date.now()}`,
x: canvas_x,
y: canvas_y
};
setGraphData((state, props) => {
var newNodes = state.nodes;
newNodes.push(newNode);
return {
nodes: newNodes,
links: state.links
}
});
};