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

react-archer arrow wrong scale after zoom change and window resize #57

Open
quellen opened this issue Aug 26, 2019 · 7 comments
Open

react-archer arrow wrong scale after zoom change and window resize #57

quellen opened this issue Aug 26, 2019 · 7 comments
Labels
bug Something isn't working

Comments

@quellen
Copy link

quellen commented Aug 26, 2019

Thank you for this arrow library it has been useful but I am struggling to figure out a scaling issue.

I am using react-easy-panzoom as a wrapper component around react-archer elements to be able to pan and zoom around a large flow chart. I have had similar results with different pan-zoom libraries.

At PanZoom zoom level of "1" (no zoom) I can click->drag and pan around the chart and resize the containing window and everything works fine.

The issue is that if I zoom out with the mouse wheel using the PanZoom functionality the react-archer arrows scale properly and I can pan without issue, but then after resizing the window while zoomed out the react-archer arrows seem to rerender at the wrong scale. The further I zoom out and then resize the window the smaller the arrows will scale down to.

https://codesandbox.io/s/react-easy-panzoom-svg-scaling-behavior-g8vcn?fontsize=14

        <div>
          <ArcherContainer strokeColor="red">
            <div style={gridWrapper}>
              <ArcherElement
                id="source"
                relations={[
                  {
                    targetId: "target",
                    targetAnchor: "left",
                    sourceAnchor: "right"
                  }
                ]}
              >
                <div style={boxStyle}>Root</div>
              </ArcherElement>
              <ArcherElement id="target" relations={[]}>
                <div style={boxStyle}>Root</div>
              </ArcherElement>
            </div>
          </ArcherContainer>
        </div>
      </PanZoom>

PanZoom zoom level 1 https://i.imgur.com/xr9RRQr.jpg

zoom out https://i.imgur.com/UjHUJ1m.jpg

resize after zoom out https://i.imgur.com/QcGzQWj.jpg

@pierpo
Copy link
Owner

pierpo commented Aug 27, 2019

Hi!

Thank you for the very detailed and reproducible issue 😊
I'll have a look at this when I have some time but I am quite busy these days 😞

Feel free to dive in the library's code and have a look too if you want to go faster.

My guesses: when you zoom in and out without changing the window size, react-archer does not re-render because nothing changes from its perspective.

However, when you resize the window, the main component is re-rendered. see

So any re-render while zoomed in becomes buggy, because the computed positions become erroneous.
I guess that we could confirm this hypothesis by adding a new element while zoomed in and validating that we see the problem as well.

The goal is then to understand why the positions are not correct when the panzoom is active 🤔

@quellen
Copy link
Author

quellen commented Aug 28, 2019

This may not be relevant to a permanent solution for the react-archer library but I came up with a workaround I'll share in case it is useful. I have only a basic understanding of javascript and so this probably has some issues but it seems to work for my usecase.

I got a scale value used in the PanZoom transform and inverted it to later pass into the ArcherContainer

    var scale = 1.0
    if(this.mainPanzoomRef.current !== null){
      scale = 1 / this.mainPanzoomRef.current.state.scale
      scale = scale
    }
ref={this.mainPanzoomRef}
...
<ArcherContainer scale={scale}>

I replaced the return line in getPointCoordinatesFromAnchorPosition and applied the passed in scale multiplier

return absolutePosition.substract(parentCoordinates);

    var retPos = absolutePosition.substract(parentCoordinates);
    retPos.x = retPos.x * this.props.scale
    retPos.y = retPos.y * this.props.scale

    return retPos;

I commented out the setState call in refreshScreen. Without this uncommented a rerender of the arrows triggered by a button seemed to look like it is the right scale and position however a screen resize still had similar behavior as before, but commenting out this line fixed the issue for me.

refreshScreen = (): void => {
    //this.setState({ ...this.state });
  };

@pierpo
Copy link
Owner

pierpo commented Aug 31, 2019

Glad that you have a workaround! I need to think this through and see if there's something cleaner, there must be 🤔
I might have done something wrong with the core of the library itself.

@pierpo pierpo added the bug Something isn't working label Sep 2, 2019
@tsnolan23
Copy link

Any update on this by chance? I'm having the exact same issue:

  • I attempted the workaround described above, but didn't have any luck with it
  • As an alternative, I called the refreshScreen method whenever the zoom level changed in attempt to mimic the window re-sizing, but no luck there either

Going to continue to dig into the calculation in the meantime and see if I can figure anything out!

@pierpo
Copy link
Owner

pierpo commented Mar 12, 2020

Hi @tsnolan23 !

I had a quick look but couldn't manage to identify the issue. I had not prioritized since there was a workaround.

I don't have much time to investigate unfortunately 😞

Does it happen only on Chrome or on all browsers?

@tsnolan23
Copy link

@pierpo Seems to be all browsers - tested in Chrome, Firefox and Safari

@MatthiasCartelDkt
Copy link

Hi, some modifications or workarounds about this bug ???

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants