diff --git a/src/mol-canvas3d/camera.ts b/src/mol-canvas3d/camera.ts
index 702006bf2cd63b1e3d368e4dc2156d2dcb5d1f02..09914b2dd2625c78a6eba2769b2501129e479b2b 100644
--- a/src/mol-canvas3d/camera.ts
+++ b/src/mol-canvas3d/camera.ts
@@ -278,6 +278,7 @@ namespace Camera {
             fog: 50,
             clipFar: true,
             minNear: 5,
+            minFar: 0,
         };
     }
 
@@ -294,6 +295,7 @@ namespace Camera {
         fog: number
         clipFar: boolean
         minNear: number
+        minFar: number
     }
 
     export function copySnapshot(out: Snapshot, source?: Partial<Snapshot>) {
@@ -311,6 +313,7 @@ namespace Camera {
         if (typeof source.fog !== 'undefined') out.fog = source.fog;
         if (typeof source.clipFar !== 'undefined') out.clipFar = source.clipFar;
         if (typeof source.minNear !== 'undefined') out.minNear = source.minNear;
+        if (typeof source.minFar !== 'undefined') out.minFar = source.minFar;
 
         return out;
     }
@@ -323,6 +326,7 @@ namespace Camera {
             && a.fog === b.fog
             && a.clipFar === b.clipFar
             && a.minNear === b.minNear
+            && a.minFar === b.minFar
             && Vec3.exactEquals(a.position, b.position)
             && Vec3.exactEquals(a.up, b.up)
             && Vec3.exactEquals(a.target, b.target);
@@ -390,18 +394,14 @@ function updatePers(camera: Camera) {
 }
 
 function updateClip(camera: Camera) {
-    let { radius, radiusMax, mode, fog, clipFar, minNear } = camera.state;
+    let { radius, radiusMax, mode, fog, clipFar, minNear, minFar } = camera.state;
     if (radius < 0.01) radius = 0.01;
 
-    const normalizedFar = clipFar ? radius : radiusMax;
+    const normalizedFar = Math.max(clipFar ? radius : radiusMax, minFar);
     const cameraDistance = Vec3.distance(camera.position, camera.target);
     let near = cameraDistance - radius;
     let far = cameraDistance + normalizedFar;
 
-    const fogNearFactor = -(50 - fog) / 50;
-    const fogNear = cameraDistance - (normalizedFar * fogNearFactor);
-    const fogFar = far;
-
     if (mode === 'perspective') {
         // set at least to 5 to avoid slow sphere impostor rendering
         near = Math.max(Math.min(radiusMax, minNear), near);
@@ -417,6 +417,10 @@ function updateClip(camera: Camera) {
         far = near + 0.01;
     }
 
+    const fogNearFactor = -(50 - fog) / 50;
+    const fogNear = cameraDistance - (normalizedFar * fogNearFactor);
+    const fogFar = far;
+
     camera.near = near;
     camera.far = 2 * far; // avoid precision issues distingushing far objects from background
     camera.fogNear = fogNear;
diff --git a/src/mol-canvas3d/controls/trackball.ts b/src/mol-canvas3d/controls/trackball.ts
index 1a702684f6e6a58e122290d8749c8dd7a04caa3f..08647f650748495102273cf365518354ff0ea358 100644
--- a/src/mol-canvas3d/controls/trackball.ts
+++ b/src/mol-canvas3d/controls/trackball.ts
@@ -451,8 +451,8 @@ namespace TrackballControls {
             }
 
             if (p.flyMode || input.pointerLock) {
-                const ds = Vec3.distance(scene.boundingSphereVisible.center, camera.position);
-                camera.setState({ radius: Math.max(ds, camera.state.radius) });
+                const cameraDistance = Vec3.distance(camera.position, scene.boundingSphereVisible.center);
+                camera.setState({ minFar: cameraDistance + scene.boundingSphereVisible.radius });
             }
         }
 
@@ -715,11 +715,30 @@ namespace TrackballControls {
             const minDistance = Math.max(camera.state.minNear, p.minDistance);
             Vec3.setMagnitude(moveEye, moveEye, minDistance);
             Vec3.sub(camera.target, camera.position, moveEye);
+
+            const cameraDistance = Vec3.distance(camera.position, scene.boundingSphereVisible.center);
+            camera.setState({ minFar: cameraDistance + scene.boundingSphereVisible.radius });
+        }
+
+        function resetCameraMove() {
+            const { center, radius } = scene.boundingSphereVisible;
+            const cameraDistance = Vec3.distance(camera.position, center);
+            if (cameraDistance > radius) {
+                const focus = camera.getFocus(center, radius);
+                camera.setState({ ...focus, minFar: 0 });
+            } else {
+                camera.setState({
+                    minFar: 0,
+                    radius: scene.boundingSphereVisible.radius,
+                });
+            }
         }
 
         function onLock(isLocked: boolean) {
             if (isLocked) {
                 initCameraMove();
+            } else {
+                resetCameraMove();
             }
         }
 
@@ -811,8 +830,12 @@ namespace TrackballControls {
                 if (props.animate?.name === 'rock' && p.animate.name !== 'rock') {
                     resetRock(); // start rocking from the center
                 }
-                if (props.flyMode && !p.flyMode) {
-                    initCameraMove();
+                if (props.flyMode !== undefined && props.flyMode !== p.flyMode) {
+                    if (props.flyMode) {
+                        initCameraMove();
+                    } else {
+                        resetCameraMove();
+                    }
                 }
                 Object.assign(p, props);
                 Object.assign(b, props.bindings);