I'm developing a map (green rectangle ) and a path drawn over it ( black lines ) in Konva:
The map has a fixed dimensions while the path is get from an API call.
I want to be able to zoom the map either with the mousescroll or by clicking the buttons + o - that I created.
I follow this example how to react-konva zooming on scroll in order to implement the zoom, but when I scroll, also the buttons change their positions, see image below.
I would like to keep the buttons fixed at the bottom side of the map.
This is a piece of my code, I defined some custom components as Map, Ground, WholePath, GroundButtons and Button:
export const Map = ( props ) => {
    const [mouseScale, setMouseScale] = useState(1);
    const [x0, setX0] = useState(0);
    const [y0, setY0] = useState(0);
    const scaleBy = 1.02;
    const handleWheel = (e)  => {
      const group = e.target.getStage();
      e.evt.preventDefault();
      const mousePointTo = {
        x: group.getPointerPosition().x / mouseScale - group.x() / mouseScale,
        y: group.getPointerPosition().y / mouseScale - group.y() / mouseScale
      };
      const newScale = e.evt.deltaY < 0 ? mouseScale * scaleBy : mouseScale / scaleBy;
      setMouseScale(newScale);
      setX0(-(mousePointTo.x - group.getPointerPosition().x / newScale) * newScale );
      setY0(-(mousePointTo.y - group.getPointerPosition().y / newScale) * newScale );
    };
    const SimulateMouseWheel = (e, BtnType, mScale = scaleBy) => {
      const newScale = BtnType > 0 ? mouseScale * mScale : mouseScale / mScale;
      setMouseScale(newScale);
    };
    const onClickPlus = (e) => {
        SimulateMouseWheel(e, +1, 1.08);
    };
    const onClickMinus = (e) => {
        SimulateMouseWheel(e, -1, 1.08);
    };
    return (
        <Stage
            width={800}
            height={400}
            draggable={true}
            onWheel={handleWheel}
            scaleX={mouseScale}
            scaleY={mouseScale}
            x={x0}
            y={y0}
        >
            <Layer>
                <Ground pitch={props.pitch}/>
                <WholePath path={props.path}/>
            </Layer>
            <Layer>
                <GroundButtons reference={props.reference} onClickMinus={onClickMinus} onClickPlus={onClickPlus} />
            </Layer>
        </Stage>
    )
}
const GroundButtons = ( props ) => {
    return (
        <Group>
            <Button xText={10} yText={5} text={"+"} x={790} y={360}  side={30} onClick={props.onClickPlus}/>
            <Button xText={12} yText={5} text={"-"} x={790} y={360}  side={30} onClick={props.onClickMinus}/>
        </Group>
    )
}
const Button = props => {
    return (
            <Group x={props.x} y={props.y} onClick={props.onClick}>
                <Rect
                    width={props.side}
                    height={props.side}
                    fill='#f2f1f0'
                    stroke='#777'
                    strokeWidth={1}
                />
                <Text
                  x={props.xText}
                  y={props.yText}
                  fontSize={20}
                  text={props.text}
                  stroke='#777'
                  align="center"
                  strokeWidth={1}
                />
            </Group>
    )
}
This is the solution I implemented: Thanks to Ondolin's answer.
export const Map = ( props ) => {
    const [mouseScale, setMouseScale] = useState(1);
    const [x0, setX0] = useState(0);
    const [y0, setY0] = useState(0);
    const scaleBy = 1.02;
    const handleWheel = (e)  => {
      const group = e.target.getStage();
      e.evt.preventDefault();
      const mousePointTo = {
        x: group.getPointerPosition().x / mouseScale - group.x() / mouseScale,
        y: group.getPointerPosition().y / mouseScale - group.y() / mouseScale
      };
      const newScale = e.evt.deltaY < 0 ? mouseScale * scaleBy : mouseScale / scaleBy;
      setMouseScale(newScale);
      setX0(-(mousePointTo.x - group.getPointerPosition().x / newScale) * newScale );
      setY0(-(mousePointTo.y - group.getPointerPosition().y / newScale) * newScale );
    };
    const SimulateMouseWheel = (e, BtnType, mScale = scaleBy) => {
      const newScale = BtnType > 0 ? mouseScale * mScale : mouseScale / mScale;
      setMouseScale(newScale);
    };
    const onClickPlus = (e) => {
        SimulateMouseWheel(e, +1, 1.08);
    };
    const onClickMinus = (e) => {
        SimulateMouseWheel(e, -1, 1.08);
    };
    return (
        <div>
        <Stage
            width={800}
            height={400}
            draggable={true}
            onWheel={handleWheel}
            scaleX={mouseScale}
            scaleY={mouseScale}
            x={x0}
            y={y0}
        >
            <Layer>
                <Ground pitch={props.pitch}/>
                <WholePath path={props.path}/>
            </Layer>
            <Layer>
                <GroundButtons reference={props.reference} onClickMinus={onClickMinus} onClickPlus={onClickPlus} />
            </Layer>
        </Stage>
            <button className="ground_controls" onClick={onClickPlus}><i className="fa fa-plus" aria-hidden="true"></i></button>
            <button className="ground_controls" onClick={onClickMinus}><i className="fa fa-minus" aria-hidden="true"></i></button>
        </div>
    )
}


 
    