React Native中r3f-native-orbitcontrols多画布适配及安卓兼容问题
问题2:安卓Expo上手指移出Canvas时相机目标异常重置
原因
这不是设计预期,完全是Web与React Native触摸事件机制的差异导致:
- Web环境中,触摸移出Canvas会触发
touchleave/touchend事件,OrbitControls能正常收尾交互并保留当前状态; - Expo安卓环境中,触摸移出Canvas所在View时,RN不会触发标准的
touchend,而是直接中断事件流,导致OrbitControls无法正确结束交互,进而意外重置相机目标。
解决方案
通过手动监听触摸中断事件,维护相机目标状态,避免重置:
步骤1:创建Controls引用数组
在组件内添加用于保存每个Controls实例的ref数组:
const controlsRefs = useMemo(() => Array.from({ length: nCubes }, () => useRef(null)), [nCubes] );
步骤2:修改事件处理逻辑
改写触摸事件,在触摸取消时手动恢复目标位置:
const controlsAndEvents = Array.from({ length: nCubes }, (_, index) => { const [OrbitControls, events] = useControls(); const controlRef = controlsRefs[index]; const modifiedEvents = { ...events, // 触摸正常结束时保存当前目标 onTouchEnd: (e) => { events.onTouchEnd(e); if (controlRef.current) { controlRef.current._savedTarget = controlRef.current.target.clone(); } }, // 触摸被取消(比如移出View)时,恢复之前保存的目标 onTouchCancel: (e) => { if (controlRef.current && controlRef.current._savedTarget) { controlRef.current.target.copy(controlRef.current._savedTarget); } events.onTouchCancel(e); } }; // 初始化时保存初始目标位置 useEffect(() => { if (controlRef.current) { controlRef.current._savedTarget = controlRef.current.target.clone(); } }, [controlRef]); return { OrbitControls, events: modifiedEvents, index, controlRef }; });
步骤3:绑定Ref到OrbitControls
在渲染OrbitControls时添加ref属性:
<OrbitControls key={index} ref={controlRef} enabled={true} enableZoom={false} enablePan={false} dampingFactor={0.5} enableRotate={true} rotateSpeed={0.5} {...OrbitControls} />
内容的提问来源于stack exchange,提问作者MainzerKaiser
相关产品推荐
相关产品推荐

