【问题标题】:react konva keep one layer fixed while zoom on stage反应 konva 在舞台上放大时保持一层固定
【发布时间】:2021-05-31 20:50:35
【问题描述】:

我正在 Konva 中开发地图(绿色矩形)和在其上绘制的路径(黑线):

地图具有固定尺寸,而路径是通过 API 调用获取的。

我希望能够使用鼠标滚动或单击我创建的按钮 + o - 来缩放地图。

我按照这个例子how to react-konva zooming on scroll 来实现缩放,但是当我滚动时,按钮也会改变它们的位置,见下图。

我想将按钮固定保留在地图的底部。

这是我的一段代码,我定义了一些自定义组件为 MapGroundWholePathGroundButtons em> 和 按钮

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>
    )
}

这是我实施的解决方案: 感谢 Ondolin 的回答。

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>
    )
}

【问题讨论】:

    标签: reactjs konvajs react-konva konva konvajs-reactjs


    【解决方案1】:

    我强烈建议您不要使用在画布(舞台)上绘制的按钮。您应该使用标准的 HTML 按钮。您可以使用 css (Positon absolute) 将它们放置在舞台顶部。

    如果你这样做,对你有很多好处。例如。您可以更轻松更好地设计它。另外,效率更高,也解决了这个问题的问题。

    【讨论】:

    • 感谢您的评论!我是这样做的,它有效!现在我编辑上面插入我的实现的问题。
    • 您还有其他问题吗,或者您为什么没有将问题标记为已完成?
    猜你喜欢
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 2021-04-09
    • 2018-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多