diff --git a/CHANGELOG.md b/CHANGELOG.md
index 05b18f6276784127bd88e32e1638280f6b525bbc..93cc94ca22c91b4f83b06dd845311c8e2dfce517 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Add StructureElement.Loci.forEachLocation
 - Add RepresentationRegistry.clear and ThemeRegistry.clear
 - Add generic Loci support for overpaint, substance, clipping themes
+- Add `.getCenter` and `.center` to `Camera`
 
 ## [v3.28.0] - 2022-12-20
 
diff --git a/src/mol-canvas3d/camera.ts b/src/mol-canvas3d/camera.ts
index 169478586e24ba8d072321be640a24eccfb887e2..50ba8fe635fd7b535c291df209c61a1a25b1616a 100644
--- a/src/mol-canvas3d/camera.ts
+++ b/src/mol-canvas3d/camera.ts
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -137,6 +137,18 @@ class Camera implements ICamera {
         return state;
     }
 
+    getCenter(target: Vec3, radius?: number): Partial<Camera.Snapshot> {
+        Vec3.sub(this.deltaDirection, this.target, this.position);
+        Vec3.sub(this.newPosition, target, this.deltaDirection);
+
+        const state = Camera.copySnapshot(Camera.createDefaultSnapshot(), this.state);
+        state.target = Vec3.clone(target);
+        state.position = Vec3.clone(this.newPosition);
+        if (radius) state.radius = Math.max(radius, 0.01);
+
+        return state;
+    }
+
     getInvariantFocus(target: Vec3, radius: number, up: Vec3, dir: Vec3): Partial<Camera.Snapshot> {
         const r = Math.max(radius, 0.01);
         const targetDistance = this.getTargetDistance(r);
@@ -160,6 +172,10 @@ class Camera implements ICamera {
         }
     }
 
+    center(target: Vec3, durationMs?: number) {
+        this.setState(this.getCenter(target), durationMs);
+    }
+
     /** Transform point into 2D window coordinates. */
     project(out: Vec4, point: Vec3) {
         return cameraProject(out, point, this.viewport, this.projectionView);
diff --git a/src/mol-plugin-state/manager/camera.ts b/src/mol-plugin-state/manager/camera.ts
index b4a4f8fb9a49671df57dfa67f2b1531b9ea67887..10f5583e7c1f3ec243c5c574602d1e31a15579aa 100644
--- a/src/mol-plugin-state/manager/camera.ts
+++ b/src/mol-plugin-state/manager/camera.ts
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2019-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -18,7 +18,7 @@ import { StructureElement } from '../../mol-model/structure';
 const DefaultCameraFocusOptions = {
     minRadius: 5,
     extraRadius: 4,
-    durationMs: 250
+    durationMs: 250,
 };
 
 export type CameraFocusOptions = typeof DefaultCameraFocusOptions
@@ -107,19 +107,19 @@ export class CameraManager {
     }
 
     focusSphere(sphere: Sphere3D, options?: Partial<CameraFocusOptions> & { principalAxes?: PrincipalAxes }) {
+        const { canvas3d } = this.plugin;
+        if (!canvas3d) return;
+
         const { extraRadius, minRadius, durationMs } = { ...DefaultCameraFocusOptions, ...options };
         const radius = Math.max(sphere.radius + extraRadius, minRadius);
 
         if (options?.principalAxes) {
             const { origin, dirA, dirC } = options?.principalAxes.boxAxes;
-            const snapshot = this.plugin.canvas3d?.camera.getFocus(origin, radius, dirA, dirC);
-            this.plugin.canvas3d?.requestCameraReset({ durationMs, snapshot });
-            // this.plugin.canvas3d?.camera.focus(origin, radius, durationMs, dirA, dirC);
+            const snapshot = canvas3d.camera.getFocus(origin, radius, dirA, dirC);
+            canvas3d.requestCameraReset({ durationMs, snapshot });
         } else {
-            const snapshot = this.plugin.canvas3d?.camera.getFocus(sphere.center, radius);
-            this.plugin.canvas3d?.requestCameraReset({ durationMs, snapshot });
-
-            // this.plugin.canvas3d?.camera.focus(sphere.center, radius, durationMs);
+            const snapshot = canvas3d.camera.getFocus(sphere.center, radius);
+            canvas3d.requestCameraReset({ durationMs, snapshot });
         }
     }