【发布时间】: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 } 并将其应用于页面以及当前元素的覆盖。
-
啊,这是处理全局变量的好方法!