在 Web 开发中,使用 3D 组件展示内容已经变得越来越普遍,通常希望通过鼠标滚轮来对 3D 组件进行缩放操作,但在同一页面上,y轴滚动条也可能存在,这样一来,当滚轮操作时,既会触发 3D 组件的缩放,又会导致页面的滚动,那么如何优雅地解决这个问题?
问题描述:
页面中包含 3D 组件展示区以及一些其他内容,滚动鼠标滚轮时,不仅会对 3D 组件进行缩放,同时页面也会跟着滚动,如下图所示:
修改前
解决方案概述:
- 要实现的目标:
- 在用户鼠标放置 3D 组件展示区滚动鼠标滚轮时 3D 组件跟随缩放,但页面不会跟着滚动。
- 当用户鼠标放置在 3D 组件展示区之外滚动鼠标滚轮时,3D 组件不会跟随缩放,页面会上下滚动。
- 实现这一目标,采取以下思路:
- 确保只有当鼠标位于 3D 组件区域时,才阻止页面滚动。
具体实现:
1. 添加鼠标滚轮事件监听器:
const containerRef = useRef(null);
useEffect(() => {
const container: any = containerRef.current;
//passive: false在特定情况下阻止页面滚动
container.addEventListener('wheel', handleWheel, { passive: false });
return () => {
container.removeEventListener('wheel', handleWheel);
};
}, []);
containerRef 为页面滚动区域的元素。
2. 使用 closest
方法判断事件目标:
为了确保只有当鼠标位于 3D 组件区域时才阻止页面滚动,使用 closest
方法来判断 event.target
是否属于我们定义的 3D 组件容器。
const handleWheel = useCallback((event: any) => {
// 阻止页面默认的滚动行为
if (event.target.closest('#rootGeo3DCanvas')) {
event.preventDefault();
}
}, []);
event.target.closest('#3d-container')
会从事件的目标元素开始向上查找,直到找到与选择器 #rootGeo3DCanvas
匹配的祖先元素。如果找到了,则表示鼠标当前位于 3D 组件区域内。通过 event.preventDefault()
来阻止页面默认的滚动行为。
解决后的效果:
修改后