作為3D看房的補充,在這里,我們講一下如何實現房屋的切換,我這里提供兩種思路,
- 切換貼圖,
- 切換場景,
接下我們按照較復雜的場景切換來講,切換貼圖也就水到渠成:
- 初始化場景:創建多個場景,并根據需求切換。
- 處理點擊事件:通過射線投射(Raycasting)檢測點擊位置與對象的交點。
- 動態更新場景:根據點擊事件的結果切換場景或執行其他邏輯。
以下是詳細的實現步驟和代碼示例:
1. 初始化多個場景
首先,我們需要創建多個場景。每個場景可以包含不同的對象、燈光和相機設置。
import * as THREE from 'three'// 創建場景1
const scene1 = new THREE.Scene()
scene1.background = new THREE.Color(0x0000ff) // 藍色背景
const cube1 = new THREE.Mesh(new THREE.BoxGeometry(),new THREE.MeshBasicMaterial({ color: 0xff0000 })
)
cube1.position.set(0, 0, 0)
scene1.add(cube1)// 創建場景2
const scene2 = new THREE.Scene()
scene2.background = new THREE.Color(0x00ff00) // 綠色背景
const sphere = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32),new THREE.MeshBasicMaterial({ color: 0xffff00 })
)
sphere.position.set(0, 0, 0)
scene2.add(sphere)// 當前場景
let currentScene = scene1
2. 處理點擊事件
使用射線投射(Raycasting)檢測用戶點擊的對象。如果點擊了特定對象,則可以觸發場景切換或其他邏輯。
// 相機和渲染器
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)// 射線投射器
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()// 點擊事件處理函數
function onCanvasClick(event: MouseEvent) {// 計算標準化設備坐標mouse.x = (event.clientX / window.innerWidth) * 2 - 1mouse.y = -(event.clientY / window.innerHeight) * 2 + 1// 設置射線投射器raycaster.setFromCamera(mouse, camera)// 檢測當前場景中的交點const intersects = raycaster.intersectObjects(currentScene.children)if (intersects.length > 0) {const clickedObject = intersects[0].objectconsole.log('點擊的對象:', clickedObject)// 如果點擊的是立方體,則切換到場景2if (clickedObject === cube1) {console.log('切換到場景2')currentScene = scene2}}
}// 監聽畫布點擊事件
window.addEventListener('click', onCanvasClick)
3. 渲染循環
在渲染循環中,確保渲染當前場景的內容。
function animate() {requestAnimationFrame(animate)// 渲染當前場景renderer.render(currentScene, camera)
}
animate()
4. 完整代碼示例
以下是完整的代碼示例,展示了如何初始化多個場景、處理點擊事件并動態切換場景:
import * as THREE from 'three'// 創建場景1
const scene1 = new THREE.Scene()
scene1.background = new THREE.Color(0x0000ff) // 藍色背景
const cube1 = new THREE.Mesh(new THREE.BoxGeometry(),new THREE.MeshBasicMaterial({ color: 0xff0000 })
)
cube1.position.set(0, 0, 0)
scene1.add(cube1)// 創建場景2
const scene2 = new THREE.Scene()
scene2.background = new THREE.Color(0x00ff00) // 綠色背景
const sphere = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32),new THREE.MeshBasicMaterial({ color: 0xffff00 })
)
sphere.position.set(0, 0, 0)
scene2.add(sphere)// 當前場景
let currentScene = scene1// 相機和渲染器
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)// 射線投射器
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()// 點擊事件處理函數
function onCanvasClick(event: MouseEvent) {// 計算標準化設備坐標mouse.x = (event.clientX / window.innerWidth) * 2 - 1mouse.y = -(event.clientY / window.innerHeight) * 2 + 1// 設置射線投射器raycaster.setFromCamera(mouse, camera)// 檢測當前場景中的交點const intersects = raycaster.intersectObjects(currentScene.children)if (intersects.length > 0) {const clickedObject = intersects[0].objectconsole.log('點擊的對象:', clickedObject)// 如果點擊的是立方體,則切換到場景2if (clickedObject === cube1) {console.log('切換到場景2')currentScene = scene2}}
}// 監聽畫布點擊事件
window.addEventListener('click', onCanvasClick)// 渲染循環
function animate() {requestAnimationFrame(animate)// 渲染當前場景renderer.render(currentScene, camera)
}
animate()
關鍵點說明
-
場景切換:
- 使用一個變量(如
currentScene
)來跟蹤當前活動的場景。 - 在點擊事件中,根據條件切換
currentScene
的值。
- 使用一個變量(如
-
射線投射(Raycasting):
- 使用
THREE.Raycaster
和鼠標位置計算點擊的對象。 - 根據點擊結果執行邏輯(如切換場景或高亮對象)。
- 使用
-
渲染循環:
- 在渲染循環中,始終渲染
currentScene
,以確保顯示正確的場景。
- 在渲染循環中,始終渲染
注意事項
-
只讀屬性問題:
- 如果你遇到類似
hotspot.name = 'hotspot-1'
的錯誤,請檢查hotspot
是否被凍結或標記為只讀。 - 解決方法包括避免直接修改只讀屬性,或者創建新的對象來更新值。
- 如果你遇到類似
-
性能優化:
- 如果場景中有大量對象,可以通過優化射線投射的檢測范圍(如僅檢測特定對象組)來提高性能。