R3F场景中Locomotive-scroll模态框滚动失效问题求助
解决React Three Fiber模态框中Locomotive Scroll滚动阻塞问题
核心问题分析
在R3F场景中,Three.js的canvas默认会捕获鼠标/触摸事件,可能拦截模态框的滚动事件;同时Locomotive Scroll容器样式配置不当、模态框动态显示时未正确初始化滚动实例,都会导致平滑滚动失效,只能使用原生滚动条。
修复步骤
1. 配置正确的容器样式
Locomotive Scroll需要容器具备明确的尺寸和溢出设置,确保滚动区域可被识别:
.modal_infos { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; background: rgba(0,0,0,0.8); z-index: 9999; /* 确保模态框层级高于R3F canvas */ display: flex; align-items: center; justify-content: center; } .modal-scroll-container { width: 80%; height: 80vh; overflow: hidden; /* 隐藏原生滚动条 */ position: relative; } .text_modale_div { padding: 2rem; }
2. 阻止R3F canvas捕获模态框区域的滚动事件
在R3F的Canvas组件上添加事件过滤,模态框显示时禁止canvas处理滚动/触摸事件:
import { Canvas } from '@react-three/fiber'; import { useState } from 'react'; function Scene() { const [modalVisible, setModalVisible] = useState(false); const handlePointerEvent = (e) => { if (modalVisible) e.stopPropagation(); }; return ( <> <Canvas onWheel={handlePointerEvent} onTouchStart={handlePointerEvent} onTouchMove={handlePointerEvent} > {/* 你的3D内容 */} </Canvas> <Modal visible={modalVisible} onClose={() => setModalVisible(false)} /> </> ); }
3. 修正Locomotive Scroll初始化逻辑
模态框为动态显示组件,需在可见时初始化滚动实例,隐藏时销毁,避免内存泄漏:
import React, { useEffect, useRef } from 'react'; import locomotiveScroll from "locomotive-scroll"; export default function Modal({ visible, onClose }) { const scrollRef = useRef(null); const scrollInstance = useRef(null); useEffect(() => { if (visible && scrollRef.current) { scrollInstance.current = new locomotiveScroll({ el: scrollRef.current, smooth: true, direction: 'vertical', gestureDirection: 'vertical' }); return () => scrollInstance.current?.destroy(); } else if (!visible && scrollInstance.current) { scrollInstance.current.destroy(); scrollInstance.current = null; } }, [visible]); if (!visible) return null; return ( <div className="modal_infos"> <div className="modal-scroll-container" ref={scrollRef} data-scroll-container> <div className="close_icon" title="Fermer la fenêtre" onClick={onClose}> <svg xmlns="http://www.w3.org/2000/svg" width="46" height="46" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round" className="icon icon-tabler icons-tabler-outline icon-tabler-x"> <path stroke="none" d="M0 0h24v24H0z" fill="none"/> <path d="M18 6l-12 12" /> <path d="M6 6l12 12" /> </svg> </div> <div className="text_modale_div" data-scroll-section> <div className="text_page"> <h1 id="title_page" data-scroll data-scroll-speed="3" data-scroll-position="top"> Some txt to try </h1> <p id="first_text__page"> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Atque eum est dolor repellat deleniti commodi debitis blanditiis cumque sed molestias facilis nesciunt cupiditate, quasi porro? Rerum, maiores. Sapiente, quia ducimus! </p> <div id="second_div_text_page"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellat quod culpa sit, ad sunt doloribus assumenda voluptates accusamus labore temporibus distinctio. Esse eius est, maiores at aspernatur impedit molestias numquam? </div> <p> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Sed earum aut voluptates natus repellat sit possimus maxime? Earum perspiciatis sit alias, eveniet, recusandae animi esse hic blanditiis fugit unde quos! </p> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Recusandae debitis dolores eligendi neque ex, dolorum sint? Recusandae provident suscipit architecto ad dolorem aliquid, eligendi quisquam culpa corrupti nostrum corporis accusantium. </p> </div> </div> <div className="text_modale_div" id="metro_div" data-scroll-section> <h1>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Recusandae debitis dolores eligendi neque ex, dolorum sint? Recusandae provident suscipit architecto ad dolorem aliquid, eligendi quisquam culpa corrupti nostrum corporis accusantium.</h1> </div> </div> </div> ); }
4. 用React状态替代jQuery操作
移除jQuery的DOM操作,改用React的props和状态控制模态框显示/隐藏,确保与Locomotive Scroll的生命周期同步。
关键注意事项
- 模态框的
z-index必须高于R3F canvas,防止事件被canvas优先捕获 - Locomotive Scroll容器必须设置
overflow: hidden,避免原生滚动条干扰平滑滚动 - 动态组件需在可见时初始化滚动实例,隐藏时销毁,避免内存泄漏
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

