bkrem / react-d3-tree

:deciduous_tree: React component to create interactive D3 tree graphs
https://bkrem.github.io/react-d3-tree
MIT License
1.09k stars 270 forks source link

Toggle the ability of zooming #217

Open tomashodek opened 5 years ago

tomashodek commented 5 years ago

Hi, my goal was to have leafs as list with a scrollbar. I have many items in leafs, so I am putting them into foreignObject and then using list to display them. And in list I am using scrollbar, so the leaf is not that long.

What is the actual behavior/output?

I am changing the boolean value of zoomable when mouse is over leaf but tree is not reacting at all and is still zoomable.

What is the behavior/output you expect?

When I dynamically change zoomable prop, tree should toggle it's ability of zooming.

What version of react-d3-tree are you using?

1.13.0

TomlDev commented 5 years ago

Can you show some code? I assume that you are using react state?

<Tree
                        zoomable={this.state.zoom}
                        onMouseover={ (prevState) => {
                                                this.setState({ zoomable: !prevState.zoomable })
                        } }
/>

?

tomashodek commented 5 years ago

Yes, I am using foreignObject where I have long list, which I want to be scrollAble, so when mouse is on that node (foreignObject) I am setting zoomAble state to false, because I don't want to zoom the tree instead of scrolling in my list.

This is props of Tree component:

zoomable={zoomAble}
nodeLabelComponent={{
              render: (
                <OrgChartNode
                  className="tree-card"
                  zoomAble={this.toggleZoomAble}
                />
              ),
              foreignObjectWrapper: {
                x: -120,
                y: -20,
                height: 500,
              },
            }}

In OrgChartNode I have event listener which triggers toggleZoomAble method where I'm just toggling the state like you wrote.

edo commented 4 years ago

Hi @tomashodek were you able to resolve this issue? I ran into the same problem: Changing the zoomable bool from false to true correctly works, both the grabhand and the zoom/dragging is correctly disabled and enabled.

But when updating with state, only the grabhand dissapears, but the tree stays zoomable/pannable.

bkrem commented 4 years ago

Hi @tomashodek & @edo,

Thanks for originally filing this issue and bringing it to my attention again now. I've finally found a good chunk of time to address issues and to push towards a v2 release.

I'll look into the shortest path to resolve/implement this. To be honest, when I built the v1 API I simply didn't consider this specific use case, so the zoomable prop wasn't set up for dynamic changes. It should hopefully be a matter of simply re-calling bindZoomListener on componentDidUpdate, or as part of a hook depending on when the refactor to hooks happens.

This will ship as part of v2 (first priority is upgrading D3 deps), once the major breaking changes have been completed on that branch.

I'm doing my best to keep breaking changes to the public API to a minimum for v2, so upgrading should hopefully be fairly painless :) I'll comment back here once there's some progress.

IainWinter commented 1 year ago

I just ran into this exact issue (foreignobject with lists to scroll). I tried to use onNodeMouseOver, but it seems like it doesn't fire? I was thinking the easiest thing would be to block the zoom listener if its target contains a class, but I'm unsure where to do that. Any help is appreciated, thanks!

`
const [draggable, setDraggable] = useState(true);

function whyDoesntThisFire(node: HierarchyPointNode<TreeNodeDatum>, y: SyntheticEvent) {
    setDraggable(false);
}

return (
      <Tree 
        data={nodes}
        collapsible={false}
        draggable={draggable}
        renderCustomNodeElement={node}
        pathFunc={path}
        onNodeMouseOver={whyDoesntThisFire}
        nodeSize={{x: 300, y:400}}
      />
  );`

Edit: Seems like the way to do this is to use custom onMouseOver/onMouseOut on the components themselves if renderCustomNodeElement uses foreignObjects