Improve 3D navigation: animated pivot on double-click
Some checks are pending
CI / backend-lint-and-test (push) Waiting to run
Some checks are pending
CI / backend-lint-and-test (push) Waiting to run
- Double-click on a building element sets it as the new orbit center - Smooth animated transition using cubic ease-out (300ms) - Enable screen-space panning for consistent pan behavior - Set min/max zoom distance to prevent clipping
This commit is contained in:
parent
b589027061
commit
d87e5b35c2
1 changed files with 28 additions and 0 deletions
|
|
@ -45,6 +45,9 @@ export function useViewer() {
|
||||||
controls = new OrbitControls(camera, renderer.domElement)
|
controls = new OrbitControls(camera, renderer.domElement)
|
||||||
controls.enableDamping = true
|
controls.enableDamping = true
|
||||||
controls.dampingFactor = 0.05
|
controls.dampingFactor = 0.05
|
||||||
|
controls.screenSpacePanning = true
|
||||||
|
controls.minDistance = 1
|
||||||
|
controls.maxDistance = 200
|
||||||
controls.target.set(0, 3, 0)
|
controls.target.set(0, 3, 0)
|
||||||
controls.update()
|
controls.update()
|
||||||
|
|
||||||
|
|
@ -67,6 +70,7 @@ export function useViewer() {
|
||||||
|
|
||||||
// Click handler
|
// Click handler
|
||||||
renderer.domElement.addEventListener('click', onCanvasClick)
|
renderer.domElement.addEventListener('click', onCanvasClick)
|
||||||
|
renderer.domElement.addEventListener('dblclick', onCanvasDoubleClick)
|
||||||
|
|
||||||
// Resize handler
|
// Resize handler
|
||||||
window.addEventListener('resize', () => onResize(container))
|
window.addEventListener('resize', () => onResize(container))
|
||||||
|
|
@ -168,6 +172,29 @@ export function useViewer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCanvasDoubleClick(event) {
|
||||||
|
const rect = renderer.domElement.getBoundingClientRect()
|
||||||
|
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
|
||||||
|
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
|
||||||
|
|
||||||
|
raycaster.setFromCamera(mouse, camera)
|
||||||
|
|
||||||
|
if (!model) return
|
||||||
|
|
||||||
|
const meshes = []
|
||||||
|
model.traverse((child) => {
|
||||||
|
if (child.isMesh) meshes.push(child)
|
||||||
|
})
|
||||||
|
|
||||||
|
const intersects = raycaster.intersectObjects(meshes, false)
|
||||||
|
|
||||||
|
if (intersects.length > 0) {
|
||||||
|
const point = intersects[0].point
|
||||||
|
controls.target.copy(point)
|
||||||
|
controls.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function highlightElement(mesh) {
|
function highlightElement(mesh) {
|
||||||
clearHighlight()
|
clearHighlight()
|
||||||
selectedMesh = mesh
|
selectedMesh = mesh
|
||||||
|
|
@ -210,6 +237,7 @@ export function useViewer() {
|
||||||
|
|
||||||
function dispose() {
|
function dispose() {
|
||||||
renderer.domElement.removeEventListener('click', onCanvasClick)
|
renderer.domElement.removeEventListener('click', onCanvasClick)
|
||||||
|
renderer.domElement.removeEventListener('dblclick', onCanvasDoubleClick)
|
||||||
renderer.dispose()
|
renderer.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue