【问题标题】:How to create drag behaviour for overlapping SVG elements in React如何在 React 中为重叠的 SVG 元素创建拖动行为
【发布时间】:2019-08-30 23:20:54
【问题描述】:

问题在 https://codesandbox.io/s/dragging-overlapping-svgs-1jd5m

中说明

我想做一些非常简单的事情:在我的 React 应用程序中的 SVG 元素中实现拖动行为。所以我最初的想法是通过onMouseDown和onMouseUp事件捕获开始和停止拖动,并在onMouseMove事件中实现更新。原则上是这样的:

  <circle
    ...
    onMouseDown={() => startDrag()}
    onMouseUp={() => endDrag()}
    onMouseMove={event => dragging && drag(event)}
  />

在我的 React 类 Circ 中,我实现了如下行为:

const Circ = ({ cx, cy, r, fill, stroke }) => {
  const [draggingPosition, setDraggingPosition] = useState({ x: 0, y: 0 });

  const startDrag = () => {
    setDragging(true);
  };
  const endDrag = () => {
    setDragging(false);
  };
  const drag = event => {
    event.stopPropagation();
    setDraggingPosition({
      x: draggingPosition.x + event.movementX,
      y: draggingPosition.y + event.movementY
    });
  };
  ...
}

嗯,这基本上奏效了。但是现在当我的 SVG 包含多个 重叠 元素时,它开始崩溃:

const SVG = () => (
  <svg width={617} height={316} viewBox="0 0 400 400">
    <g>
      <Circ cx={108} cy={108} r="100" fill="#0ff" stroke="#000" />
      <Circ cx={180} cy={209} r="100" fill="#ff0" stroke="#000" />
      <Circ cx={220} cy={109} r="100" fill="#f0f" stroke="#000" />
    </g>
  </svg>
);

当我拖动蓝色圆圈时,它的行为很好,直到重叠的圆圈捕获鼠标事件并且我的拖动停止。

所以我的问题是:如何确保一旦开始拖动,鼠标事件仅限于当前元素?理想情况下,当编辑器中还有我的Circ 类不一定知道的其他元素(Rect、G 等...)时?

【问题讨论】:

  • 问题是由其他 SVG 触发的 onMouseMove 引起的。建议/提示:保留焦点圈的信息,并在drag 函数中检查是否由焦点圈触发。
  • 将所有其他元素设置为指针事件:拖动期间无。
  • 谢谢@RobertLongson,这很好。这意味着全局注册一个“拖动”变量并将其传递给每个孩子,对吗?我希望有一个可以仅限于对象本身的解决方案。
  • 我会通过修改一个 css 类或创建一些 css 来做到这一点,如 * { pointer-events: none } 并将其应用于页面以及当前元素的覆盖。
  • 啊,这是处理全局变量的好方法!

标签: reactjs svg


【解决方案1】:

我现在正在通过在全局级别注册拖动来解决它 pointerEvents={ globalDragging ? "none" : "auto"} 在我所有的元素上。我对这个解决方案不是很满意,所以我仍然很高兴听到替代方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 2017-01-25
    相关资源
    最近更新 更多