*Update: I'm feeling a bit confused because I don't believe my function is causing this issue. It seems that simply double-clicking without moving the mouse triggers this behavior consistently, even in the Three.js example.
I'm still unsure how to eliminate this behavior or if it's a deliberate feature.
Whenever I double-click on the scene, a function is triggered to smoothly reset the camera to its original position. However, after the reset, any attempt to move with OrbitControls
results in the cursor changing to not-allowed
and the controls barely rotate before coming to a halt. The only way to regain control is by single-clicking on the canvas without dragging, which resets the controls to a functional state.
When I remove the resetPosition
function, which gradually moves the camera back to the origin, the controls mostly work as intended. I've checked the code and can't identify any obvious cause.
*A similar issue occurs inconsistently when double-clicking, especially when quickly dragging the controls on the second click, even without resetPosition
. The presence of resetPosition
just makes the issue more predictable. This behavior can be observed even in this official Three.js example.
View an image of the issue, as I can't directly post images on StackOverflow
How can I prevent this issue? I've come across several Three.js examples that don't have this problem, but I'm unsure what sets them apart.
Here is the relevant code snippet:
this.controls = new OrbitControls(this.camera, this.element)
this.controls.target.set(CONTROLS_TARGET.x, CONTROLS_TARGET.y, CONTROLS_TARGET.z)
this.controls.userRotateSpeed = 3
this.controls.maxDistance = 200
this.controls.minDistance = 10
resetPosition() {
let azimuthalAngle = this.controls.getAzimuthalAngle(),
polarAngle = this.controls.getPolarAngle() - Math.PI / 2,
distance = this.controls.getDistance() - 30,
movement = this.controls.target.clone()
let lerpDelta = LERP_ALPHA ** (1 + this.deltaTime * 60)
if (Math.abs(azimuthalAngle) < 0.001) azimuthalAngle = 0
if (Math.abs(polarAngle) < 0.001) polarAngle = 0
if (Math.abs(distance) < 0.001 && Math.abs(distance) > -0.001) distance = 0
if (movement.distanceTo(CONTROLS_TARGET) < 0.05) movement = CONTROLS_TARGET
this.controls.minAzimuthAngle = lerpDelta * azimuthalAngle
this.controls.maxAzimuthAngle = this.controls.minAzimuthAngle
this.controls.minPolarAngle = Math.PI/2 + lerpDelta * polarAngle
this.controls.maxPolarAngle = this.controls.minPolarAngle
this.controls.minDistance = lerpDelta * distance + 30
this.controls.maxDistance = this.controls.minDistance
movement.lerp(CONTROLS_TARGET, 1.0 - lerpDelta)
this.controls.target.set(movement.x, movement.y, movement.z)
if(azimuthalAngle === 0
&& polarAngle === 0
&& distance === 0
&& movement.equals(CONTROLS_TARGET)
) this.finishReset()
}
finishReset() {
this.controls.minAzimuthAngle = -Infinity
this.controls.maxAzimuthAngle = Infinity
this.controls.minPolarAngle = 0
this.controls.maxPolarAngle = Math.PI
this.controls.minDistance = 10
this.controls.maxDistance = 200
this.doReset = false
}
animate() {
if (this.doReset) this.resetPosition()
this.controls.update()
this.render()
}