react-flow-chart icon indicating copy to clipboard operation
react-flow-chart copied to clipboard

Change the zoom point

Open georginaso opened this issue 5 years ago • 5 comments

Thank you for your great job! 👏

Actually, the zoom point is in the top-left corner:

zoom-point-center

It would be great to use the center of the screen (or allow configuration for it).

georginaso avatar May 28 '20 09:05 georginaso

or maybe it's possible having the zoom-center where the mouse arrow is? i think this is the most common behaviour for zooming, isn't it? (at least for mouse-wheel/gesture zooming)

altran-fabian avatar May 28 '20 12:05 altran-fabian

@altran-fabian I guess that the desired behavior is the Google maps one 🤩. Using the buttons, the zoom point is the center of the screen, and using the mouse, is the cursor.

georginaso avatar May 28 '20 12:05 georginaso

Here is a basic solution, which you can use without changing the library (by the way, it can be a great start point for a PR):

componentDidUpdate(prevProps: Readonly<Props>, prevState: Readonly<IChart>) {
    if(this.state.scale !== this.props.scale) {
        const div = document.getElementById('graph-wrapper') as any;
        const centerX = div.offsetWidth / 2 - this.state.offset.x;
        const centerY = div.offsetHeight / 2 - this.state.offset.y;
        const deltaX = centerX/this.props.scale - centerX/this.state.scale;
        const deltaY = centerY/this.props.scale - centerY/this.state.scale;
        this.setState(state => ({
            ...state,
            scale: this.props.scale,
            offset: {
                x: this.state.offset.x + deltaX*this.props.scale,
                y: this.state.offset.y + deltaY*this.props.scale
            }
        }))
    }
}

Requirements:

  • use the chart with an external state
  • wrap the chart inside a div, and set CSS to make it the size of the visible viewport (eg. position absolute with 100% width and height). you can create a ref, if you have multiple charts, etc.
  • div.offsetWidth / 2 is for zooming to center, if you need to zoom to mouse position, then use the mouse position relative to the wrapper div.
  • this.props.scale is the new scale value, while this.state.scale is the old, so you can use any step size you wish. My implementation controls zoom from the outside, as I have a toolbar with zoom buttons, but you can do this inside to handle mouse too. (For me, it is more logical to use scroll for translate, so I won't implement the mouse version.)

ajuhos avatar May 30 '20 15:05 ajuhos

@ajuhos thank you :) I'm gonna try!

georginaso avatar Jun 02 '20 17:06 georginaso

@ajuhos thanks for this solution :) i will try to use your example as a starting point for a react-hooks implementation.

el-j avatar Jun 19 '20 22:06 el-j