You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-Konva中Shape与Stage的onClick事件冲突问题咨询

解决React-Konva中Stage与Shape的onClick事件冲突问题

方案1:阻止Shape事件冒泡

在Shape的点击回调中阻止事件向上冒泡,这样点击Shape时就不会触发Stage的点击事件:

const Basic = ({points}) => {
  const onBasicClick = (e) => {
    console.log("onBasicClick");
    // 阻止事件冒泡到Stage
    e.cancelBubble = true;
  };
  return (
    <Shape
      points={points}
      onClick={onBasicClick}
      sceneFunc={(context, shape) => {
          // 自定义形状绘制逻辑,示例绘制一个以点击点为中心的矩形
          context.beginPath();
          context.rect(points.x - 20, points.y - 20, 40, 40);
          context.fillStrokeShape(shape);
      }}
      stroke="#C879E6"
      strokeWidth={1}
      fill='#F6DEFF'
    />
  );
};

方案2:在Stage的点击事件中判断目标元素

通过判断点击事件的目标是否为Stage本身,仅在点击空白区域时添加新形状:

function App() {
  const [basicFigure, setBasic] = useState([]);
  const onSolveClick = (e) => {
    // 仅当点击对象是Stage本身时,执行添加逻辑
    if (e.target === e.target.getStage()) {
      const pos = e.target.getStage().getPointerPosition();
      const newBasicFigure = [...basicFigure, pos];
      setBasic(newBasicFigure);
    }
  };
  return (
    <>
      <Stage width={w} height={h} onClick={onSolveClick}>
        <Layer>
          {basicFigure.map(item => (
            <Basic 
              points={item}
              key={`${item.x}-${item.y}`}
            />
          ))}
        </Layer>
      </Stage>
    </>
  );
}

方案3:通过点击位置检测已有形状(你的思路落地)

利用Konva的getIntersection方法,检查点击位置是否被已有形状覆盖,若有则不添加新形状:

function App() {
  const [basicFigure, setBasic] = useState([]);
  const layerRef = useRef(null);

  const onSolveClick = (e) => {
    const stage = e.target.getStage();
    const pos = stage.getPointerPosition();
    // 检测点击位置是否命中Layer内的任意形状
    const hitShape = layerRef.current?.getIntersection(pos);
    if (!hitShape) {
      // 未命中任何形状,添加新形状
      const newBasicFigure = [...basicFigure, pos];
      setBasic(newBasicFigure);
    }
  };

  return (
    <>
      <Stage width={w} height={h} onClick={onSolveClick}>
        <Layer ref={layerRef}>
          {basicFigure.map(item => (
            <Basic 
              points={item}
              key={`${item.x}-${item.y}`}
            />
          ))}
        </Layer>
      </Stage>
    </>
  );
}

注意:此方案要求sceneFunc中正确定义了形状的路径,Konva的命中检测依赖于该路径的准确性。

内容的提问来源于stack exchange,提问作者sieun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:13:26