Three.js中3D房间对象循环位置切换:Button +2功能实现需求
核心思路
原Button +1通过将数组最后一个元素移到开头,让每个房间对应的位置索引前进1,实现1个房间间隔的切换。要实现2个房间间隔的切换,只需要将数组最后两个元素移到数组开头即可,这样每个房间对应的位置索引会前进2,对应到预设的positions数组中,就实现了2间隔的位置切换。
修改后的完整代码
import React, { Suspense, useEffect, useMemo, useState } from "react"; import { Canvas } from "@react-three/fiber"; import { ContactShadows, OrbitControls } from "@react-three/drei"; import "./PartOne.css"; import { RoomOne } from "../assets/Room1"; import { Room2 } from "../assets/Room2"; import { Room3 } from "../assets/Room3"; import { Room4 } from "../assets/Room4"; import { Room5 } from "../assets/Room5"; import { Room6 } from "../assets/Room6"; import { Room7 } from "../assets/Room7"; import { Room8 } from "../assets/Room8"; const PartOne = () => { const [rooms, setRooms] = useState([ RoomOne, Room2, Room3, Room4, Room5, Room6, Room7, Room8 ]); const positions = useMemo(() => [ [0.0, 0.0, 0.0], [-3.6, -2.7, 0.0], [-0.0, -2.7, 3.6], [-7.2, -5.4, 0.0], [-3.6, -5.4, 3.6], [-0.0, -5.4, 7.2], [-7.2, -8.1, 3.6], [-3.6, -8.11, 7.2] ], []); useEffect(() => { console.log("rooms state:", rooms); }, [rooms]); return ( <div className="wrapper"> <button onClick={() => { let arr = [...rooms]; arr.unshift(arr.pop()); setRooms(arr); }} > Button +1 </button> <button onClick={() => { let arr = [...rooms]; // 截取最后2个元素放到数组开头 const newRooms = [...arr.slice(-2), ...arr.slice(0, -2)]; setRooms(newRooms); }} > Button +2 </button> <Canvas shadows camera={{ fov: 70, position: [0, 0, 30] }}> <Suspense fallback={null}> <ambientLight intensity={0.3} /> <directionalLight castShadow receiveShadow intensity={2} position={[80, 80, 80]} shadow-normalBias={0.1} shadow-camera-left={-12} shadow-camera-right={12} shadow-camera-top={12} shadow-camera-bottom={-12} shadow-camera-near={0.5} shadow-camera-far={200} /> {rooms.map((room, roomIndex) => room({ position: positions[roomIndex] }) )} <ContactShadows /> </Suspense> <OrbitControls enablePan={true} enableZoom={true} enableRotate={true} /> </Canvas> </div> ); }; export default PartOne;
关键修改点说明
- Button +2的点击逻辑:
使用数组slice方法,arr.slice(-2)获取最后2个元素,arr.slice(0, -2)获取前面所有元素,拼接后得到新数组,一次完成2间隔的切换逻辑,比两次执行unshift(pop())更高效清晰。 - 补全useMemo依赖数组:
原代码useMemo未传依赖数组,会导致每次渲染都重建positions数组,补全空数组后,positions仅在组件初始化时创建一次,优化性能。
内容的提问来源于stack exchange,提问作者Sayedul Karim
相关产品推荐
相关产品推荐

