Closed techniq closed 6 years ago
@sghall - any tips on how to use react-move to produce something similar to https://bl.ocks.org/mbostock/4339083?
@hshoff / @sghall - It seems like to be able to make this work we would need to be able to add a <NodeGroup />
here
Maybe if <Tree/>
/ <Cluster/>
receives a children function, we call it instead? Such as:
<Tree
top={margin.top}
left={margin.left}
root={hierarchy(data, d => d.isExpanded ? d.children : null)}
size={[
height - margin.top - margin.bottom,
width - margin.left - margin.right
]}
>
({ links, descendants }) => (
// magic here
)
</Tree>
@techniq yup that’s a great solution. I’ve been busy with interactions, will get to this when i can. Happy to a review a PR if anyone wants to take a swing at this.
@hshoff No promises, but I'll see if I can get a PR pushed up soonish (should be fairly trivial) but currently this is me just kicking around vx so my other tasks have higher priority.
Seems we would want the same with vx-network and maybe other layouts. I've only recently been getting into d3 beyond the basics so I'm not aware of all the different layouts and their intricacies and how vx has integrated them.
I would love to hear if @sghall has any feedback on this with regards to react-move.
Lastly, I wonder if the child function / render prop should be embraced whole-heartedly throughout vx, in place of some HOCs (such as replacing withTooltip
, withParentSize
, withScreenSize
, ...). I've had good success with it in my react-fetch-component and downshift, and I know Michael Jackson has been a big proponent of it lately
Also, just leaving this for later reference, but it would be nice if the <Tree />
example could, along with being collapsible, show how to reveal a node, similar to Search Collapsible Tree. This drag and drop and pannable example would be nice as well (maybe after from of your current vx-drag / vx-zoom work)
Hey. Off the top of my head, I'd say it's two NodeGroups for nodes and links. Do the links first so the nodes are on top in the SVG...something like...
<Tree
top={margin.top}
left={margin.left}
root={hierarchy(data, d => d.isExpanded ? d.children : null)}
size={[
height - margin.top - margin.bottom,
width - margin.left - margin.right
]}
>
({ links, descendants }) => (
<NodeGroup
data={links}
...
</NodeGroup>
<NodeGroup
data={descendants}
...
</NodeGroup>
)
</Tree>
He's doing some magic here with stashing the last layout and using the "diagonal" path generator to get those nice curved lines. You can pass a custom interpolator to react-move to handle that.
This flubber example is using a custom interpolator... https://react-move.js.org/#/documentation/animate
Also, this piece storing if the children are collapsed is a little sticky. Need some state somewhere with that.
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
root.children.forEach(collapse);
update(root);
If you get something committed I can jump in there and hack on it a little if there's issues.
Thanks @sghall. I have the expand/collapse working currently in this codesandbox and was looking to moving to the next step of animating.
Once I or @hshoff get the child function in place I'll take a stab at the transition but maybe ping you with a WIP codesandbox if I get stuck (especially the the interpolation)?
Looking at the d3 example (linked in the first post), it looks like Mike is using...
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
...for the interpolation so we might be able to do something similar...
Actually d3.svg.diagonal()
was replaced in d3 v4 with linkVertical (or horizontal/radial) and is what vx's LinkVertical uses
@hshoff @sghall I've made some progress using react-move to animate the expand/collapse animations of a <Tree />
after the render prop was exposed (thanks again @hshoff )
There is still some work to do:
d3.linkVertical
/ d3.linkHorizontal
as a custom interpolator for nodes so they slide along the link paths instead of a straight lineCleanup the example and probably refine the approach (not using this.forceUpdate()
, etc)
I currently have it running locally but can move it out to codesandbox.io once a new version of vx-hierarchy is released (I couldn't figure out how to use a git sha version on codesandbox, and also struggled locally with the same, but ended up getting npm link
to work and have been tweaking the vx-demo
for Tree).
I don't know if I'll get much more time to iterate on this till next week so once I get it on codesandbox, feel free to fork and tweak if you want.
awesome!
Some progress animating links and nodes now collapse to closing parent/grandparent/etc (not just the parent). I've updated my codesandbox with these changes if you want to take a look at the code.
While collapsing a grandparent will fold all children/grandchildren/etc into the node, expanding currently only transitions from each children's parent's location. This is best demonstrated with an example. Notice when expanding T, nodes A1, A2, A3, C, and others (and their links) do not appear to be sourced from T.
Based on how I'm saving x0/y0 only when a node is expanding, if a sibling node is expanded and then the original node is collapsed, the transitions are incorrect. For example,
There may be other issues as well, especially when compared to the canonical d3 example, but it's progressing. If anyone has any suggestions (alternative approaches) to resolve these issues I'm interested.
I created a radial tree example derived from the cartesian layout version and based on the Radial Tidy Tree d3 example
The only changes needed to support this layout was to:
Tree
to the center (i.e <Group top={width / 2} left={height / 2}>
)LinkRadial
from @vx/shape
instead of LinkHorizontal
for linksd3-shape
to translate the each node's x
/y
to the radial layout. I also used a simple function to return an {x, y}
object instead of an array of [x, y]
This example also has the same quirks/issues as mentioned in previous comment, but so far I'm really enjoying using vx and react-move together.
@techniq nice! i added a link to your example to the in the wild
section of the readme here: https://github.com/hshoff/vx/commit/ee2da22fdb246060b0536771330b599e5b339aa9
(looks like your radial example link goes to the same place as the cartesian example, happy to add that as well once you have an updated link)
Oops, link fixed above (and thanks)
Btw, if you or @sghall (probably more likely) have any ideas on the transition quirks, I'm all ears as I'm a bit stumped at the moment.
Hello dears, I use this tree to display data, and I want to thank you for this work. There is one problem, please help. With large data When the layout is polar and the link is a curve nodes overlap each other (you can see here https://codesandbox.io/s/p5pkn9jwx on Expand A ). It is possible to do something to fix this problem? Thanks.
@Vaga91 you could adjust the separation prop. The larger you make the ratio, the greater the spread between sibling nodes.
separation={(a, b) => (a.parent == b.parent ? 1 : .5) / a.depth}
separation={(a, b) => (a.parent == b.parent ? 1 : 5) / a.depth}
Feel free to experiment with other values.
You might also want to look into enlarging your rendered size and allowing pan/zoom. We have a component coming soon, but you might want to look at this PanZoom component in the short term.
Closing this as examples were added in https://github.com/hshoff/vx/pull/234. Can view them here: https://vx-demo.now.sh/linkTypes
@Vaga91 feel free to continue the discussion here.
@techniq I've been experimenting these few days. And here is the result Tree
I added separation={(a, b) => ((a.children === b.children) && (a.parent === b.parent) ? 1 : 7) / a.depth }
It works, but needs to be improved.
Thank you :)
hey @techniq do you remember this example? i've been working on top of what you had done, updating it (packages and to typescript(which in hindsight might have not been the best idea) )trying to expand it a little bit to fit some of my needs (node selection, adding removal, filtering, etc, click around to see) - https://codesandbox.io/s/vx-collapsible-tree-typescript-oxewc but i have a some concerns, mostly related to performance and possible over-complexity, see I need it to be "responsive" since the tree will be representing a tree data structure built and maintained by a backoffice user, right now i'm using react-measure for responsive Tree Canvas size and an injected ref into the Text element with getBoundingClientRect() for responsive node size -these things also require rerendering for the correction of positions, i know of #375 and also of https://vx-demo.now.sh/responsive (but this one seems quite similar to react-measure), i'm bothering you with this because i thought that maybe you developed it more since last time and could give me some tips
Hey @UltimateForm, I do remember that example, but it's been a while since I've looked at it. I like the features you've added to it, especially the node selection with path. Sadly, I haven't worked on this in some time, and my usage was mostly for a one off for a presentation. With that said, I do have plans to use this in an upcoming feature in one of our applications, but it's not currently on the roadmap (probably a few months out at least). If I make any improvements (I plan to push them down to vx
if they make sense) I will try to remember to ping you in this thread.
With that said, the demo seems to interact well, but I'm assuming you have many more nodes than I'm creating using the tool? I know my tree was made up of ~3000 nodes (personnel structure of a decent size company) and it seems to function well (but I would never expand more than a handful of nodes at a time). I mostly ran into canvas size constraints as well, and might have opened more if I used @vx/zoom that it wasn't available at the time.
Let me know if you make any more progress on your side, and I'll be sure to do the same on mine.
Thanks for the quick reply @techniq 🙏 I didn't quite understand what you meant by
I'm assuming you have many more nodes than I'm creating using the tool
on the condesandbox i sent the nodes are only created on user input, if you're talking about the growth potential, I have not tested the tool with that many nodes, mainly because the usecase im doing this for does not benefit from that many nodes, i'd even say it suffers, but i should, for test purposes at least use a pre-built data structure with tons of nodes, i'm sure the current performance issues would be more noticeable that way
besides vx/responsive i'm also considering using vx/zoom and vx/drag to add more maneuverability to the tree
Either way, i'm really happy to know you're planning on revisiting this, I'll keep working on my side as well. best of luck 🙏
edit: https://github.com/UltimateForm/vx-collapsible-tree-tsx the repo, in case you feel like checking any future work on it
@techniq Hi. I using you sample, but i need help with collapse all tree's elements at init. How can i do this, with visible links?
@mindceb I'm having trouble following what you're asking, do you mean to only show the root node at the first (although this is what my example does so I don't think it's that.
Can you create a CodeSandbox with your current progress?
@techniq Any chance you've gotten the entire tree to animate out on page load? I know you can expand onClick but am looking to have it start expanded out and be collapsable. Let me know, thanks!
@alexschachne I do not. Currently that example stores the isExpanded
as a prop on each Node, but I think it might be best to track it in a separate state array.
instead of...
const root = hierarchy(data, d => (d.isExpanded ? d.children : null))
something like...
const [expandedIds, setExpandedIds = useState([]);
const root = hierarchy(data, d => expandedIds.includes(d.id) ? d.children : null))
and then use an useEffect()
to expand all the items (might also be able to use root.each:
useEffect(() => {
setExpandedIds(d.map(x => x.id))
}, []);
and update the onClick
on the node rect to add/remove that node's id from the array (would remove the forceUpdate
as well).
Let me know if this works.
Side note, I've been experimenting with various hierarchy layouts and vx (including animations and such). Each layout is in a various state of experimentation (and none are by any means "done". I also haven't added all the layouts I plan to, include Tree, Circle Pack, Chord, etc). https://github.com/techniq/vx-hierarchy-examples https://nxmen.csb.app/
@alexschachne Actually it may be harder than this...
I added a quick Tree
example (based on that old codesandbox and some some changes I made within my projects) and updated to store expandedNodeKeys instead of adding isExpanded
to the node itself... this worked good, but attempting to expand all the nodes at startup causes a react-spring error:
I also tried not filtering any of the children so the full tree would be rendered, but it too threw the error.
Probably since it tween's from the parent/last position.
@alexschachne The problem was due to the Links (if you commented them out, the Nodes animated correctly). I think I have this fixed now, but the example tree I'm using is rather heavy. Need to test with a smaller tree (I have issues with react-spring and the tree when running in dev mode (seems to do better when using a prod build).
Anyways, it's not perfect, but might get you closer (and the pattern to track the ids in a separate array is a better pattern.. using a Set
and Set.has()
would be more performance than Array.includes
and doing scans, but the number of expanded items should be pretty small.
I derived a simple example from https://vx-demo.now.sh/trees available here: https://codesandbox.io/s/n3w687vmqj
I'm not overly happy with the
forceUpdate()
and would like to have it animate similar to https://bl.ocks.org/mbostock/4339083, but it's a start