Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Re-centering tree in div on clicking a node #151

Closed
amad-person opened this issue Oct 16, 2018 · 9 comments
Closed

[Question] Re-centering tree in div on clicking a node #151

amad-person opened this issue Oct 16, 2018 · 9 comments

Comments

@amad-person
Copy link

amad-person commented Oct 16, 2018

I'm using the CenteredTree recipe to render the tree in the center of the parent div on the initial render.

I wanted to know if it is possible to scale and re-center the rendered tree inside its parent component every time a node is expanded?

@bkrem
Copy link
Owner

bkrem commented Oct 19, 2018

Hi @amad-person,

No this unfortunately isn't part of the feature set at the moment since the translate & zoom props are intended to set up the graph in a useful position for the user and letting them move freely from that point onwards.

An autoScale prop would definitely be cool to have, although on a graph of significant size the nodes would quickly become almost unclickable due to them becoming very small as the graph auto-scales. My concern here is that the UX would be tricky to get right if the user would be zooming back in again to click a node, just to then be auto-scaled back to a zoom level where all nodes are in the view.

@bkrem bkrem added the question label Oct 19, 2018
@amad-person
Copy link
Author

That makes sense, thanks @bkrem!

@bkrem
Copy link
Owner

bkrem commented Oct 25, 2018

No problem, sorry I can't help much right now for your use case.

I'm going to leave this open for further discussion since someone else may have a good approach for this.

@mwilde345
Copy link

mwilde345 commented Dec 7, 2018

Couple thoughts:

  • use onclick event, get click x and y, modify graph transform based on some factor of those values
    • ReactDOM.findDOMNode(this).firstChild.firstChild.firstChild.setAttribute('transform', `translate(${someX},${someY}) scale(0.7)`);
  • Store an object that tracks the nodes' coordinates in the container, according to their 'id'. Updates would be expensive
  • When a node component mounts, add its x and y values to the actual node data object for later transforms. Update the entire data object (very expensive)

I guess what I'm trying to say is moving x and y shouldn't be too bad. I've got it working for me with the onclick event, getting the target node x and y, setting the entire graph translate based on that (note I have to put it in a timeout to wait for the actual node expand transition). So it's pretty ugly. but i guess it works.

@mwilde345
Copy link

mwilde345 commented Dec 10, 2018

@bkrem If i update the state.translate property after the graph is rendered, it is not re-rendered with the new values. Where is this in the code?
Let me give more context.
In my onclick handler, I get the coordinates of the current node:

...
// I use SVG.js to adopt the first 'g' element (the one that get's the original translate values)
this.state.graphObject = SVG.adopt(ReactDOM.findDOMNode(this).firstChild.firstChild.firstChild)
...
// I get the X and Y of the currently clicked node
let circleCoords = event.target.getBoundingClientRect();
...
//using circleCoords and the current state.translate values, I update the position of the first 'g' element.
this.state.graphObject.animate(200,'<>').translate(x,y);

Then i update the state.translate values to the newly calculated ones.

No whenever I pan or zoom, the graph jumps. Similar to what you reference in this issue:
#10
Doesn't seem like the state translate values that I updated are taken into account.
Could I get some guidance here?

@npetzall
Copy link

npetzall commented Sep 1, 2020

@mwilde345 I was actually looking into this and the prop seems to be set, but react doesn't seem to re-render it.

So I did some fiddling, I've done react for a cpl of weeks, so I might be waaay off on the solution. I added a key to the g component rendered by NodeWrapper. The key was just translate.x, translate.y+scale as a string. This caused the g component to re-render when translate was set.

<g className={props.className} transform={props.transform}>

@franklx2
Copy link

franklx2 commented Nov 9, 2020

like @npetzall noted above, updating the HTML attribute for transform=translate(x,y) directly doesn't affect the component's translate state. Once you drag the canvas, the component resumes updating translate again. I was updating the position of the tree by manually updating the first 'g' as you were, however, to get around the jumpiness behavior I've just gone with updating this.state.translate:

this.state.translate = { x: applied.x, y: applied.y }

I don't know how to do smooth transitions with this approach, however. I might just forgo it

@bkrem
Copy link
Owner

bkrem commented Mar 5, 2022

This has been implemented via #381 and shipped as part of https://github.com/bkrem/react-d3-tree/releases/tag/v3.3.0 🚀

Centering nodes can be achieved by setting the new dimensions prop.

Closing.

@bkrem
Copy link
Owner

bkrem commented Mar 6, 2022

Update

https://github.com/bkrem/react-d3-tree/releases/tag/v3.3.1 ships a fix for a calculation bug when centering nodes via dimensions in horizontal orientation.

Please update to v3.3.1 instead if you want to use this feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants