Namespace viewController

xeokit View Controller


Mouse, touch, and keyboard controller for a View's Camera. Three navigation modes (orbit, first-person, plan-view), context-aware movement scaling, pivot-about-pick, and per-event mouse / touch hooks.


The viewController module adds interactive camera navigation to a View. One ViewController per View, configured with a navigation mode and optional pick / key-map overrides.


%%{init:{"theme":"dark"}}%% classDiagram direction TB class ViewController { +view : View +navMode : OrbitNav | FirstPersonNav | PlanViewNav +keyMap : Record~action, KeyCode[]~ +pick : CameraControlPickFn +active : boolean +onHover / onHoverEnter / onHoverOut / onHoverOff +onPicked / onPickedSurface / onPickedNothing +onDoublePicked / onDoublePickedSurface / onDoublePickedNothing +onRightClick +destroy() } class ViewControllerParams { +active? : boolean +navMode? : NavMode +keyMap? : Record~action, KeyCode[]~ +pick? : CameraControlPickFn +constrainVertical? : boolean +smartPivot? : SmartPivotSpec } class ViewControllerEvents { +onHover / onPicked / onDoublePicked / onRightClick } class View { <<viewer>> } class Camera { <<viewer>> } ViewController ..> ViewControllerParams : reads ViewController "1" *-- "1" ViewControllerEvents ViewController o-- View : controls Camera in View *-- Camera
%%{init:{"theme":"default"}}%% classDiagram direction TB class ViewController { +view : View +navMode : OrbitNav | FirstPersonNav | PlanViewNav +keyMap : Record~action, KeyCode[]~ +pick : CameraControlPickFn +active : boolean +onHover / onHoverEnter / onHoverOut / onHoverOff +onPicked / onPickedSurface / onPickedNothing +onDoublePicked / onDoublePickedSurface / onDoublePickedNothing +onRightClick +destroy() } class ViewControllerParams { +active? : boolean +navMode? : NavMode +keyMap? : Record~action, KeyCode[]~ +pick? : CameraControlPickFn +constrainVertical? : boolean +smartPivot? : SmartPivotSpec } class ViewControllerEvents { +onHover / onPicked / onDoublePicked / onRightClick } class View { <<viewer>> } class Camera { <<viewer>> } ViewController ..> ViewControllerParams : reads ViewController "1" *-- "1" ViewControllerEvents ViewController o-- View : controls Camera in View *-- Camera
classDiagram
    direction TB
    class ViewController {
      +view    : View
      +navMode : OrbitNav | FirstPersonNav | PlanViewNav
      +keyMap  : Record~action, KeyCode[]~
      +pick    : CameraControlPickFn
      +active  : boolean
      +onHover / onHoverEnter / onHoverOut / onHoverOff
      +onPicked / onPickedSurface / onPickedNothing
      +onDoublePicked / onDoublePickedSurface / onDoublePickedNothing
      +onRightClick
      +destroy()
    }
    class ViewControllerParams {
      +active?            : boolean
      +navMode?           : NavMode
      +keyMap?            : Record~action, KeyCode[]~
      +pick?              : CameraControlPickFn
      +constrainVertical? : boolean
      +smartPivot?        : SmartPivotSpec
    }
    class ViewControllerEvents {
      +onHover / onPicked / onDoublePicked / onRightClick
    }
    class View {
      <<viewer>>
    }
    class Camera {
      <<viewer>>
    }
    ViewController ..> ViewControllerParams : reads
    ViewController "1" *-- "1" ViewControllerEvents
    ViewController o-- View : controls Camera in
    View *-- Camera

  • Three navigation modesOrbitNavigationMode (orbit around a focus point), FirstPersonNavigationMode (free WASD walking), PlanViewNavigationMode (top-down pan + zoom). Switch live via viewController.navMode = ....
  • Pointer-following — dynamic camera target tracking that responds to where the cursor is pointing.
  • Context-aware movement scaling — speed bigger in open spaces, smaller in confined spaces; computed from the under-cursor depth so the user doesn't need to tune speed manually.
  • Pivot-about-pick — orbit around the picked world point instead of a global origin, so rotating around a detail keeps the detail centred.
  • Axis-aligned-view shortcutsKEY_NUM_1KEY_NUM_6 snap to top / bottom / front / back / left / right views.
  • Per-event hooksonHover, onPicked, onDoublePicked, onRightClick, with onHoverEnter / onHoverOut for transition-only handlers.
  • Configurable key mapQWERTYLayout (default) and AZERTYLayout ship; arbitrary remaps via the keyMap parameter on construction or live mutation afterwards.
  • Vertical constraintconstrainVertical: true clamps pitch to [-90°, 90°] so the camera never flips upside-down.

Installation

Install the package using npm:

npm install @xeokit/sdk

Usage

This example demonstrates how to set up a Viewer with a WebGLRenderer, a Scene to manage geometry and materials, and an interactive camera controlled via ViewController.

import {SDKInternalException} from "@xeokit/sdk/base/core";
import {Scene} from "@xeokit/sdk/model/scene";
import {OrbitNavigationMode, FirstPersonNavigationMode, PlanViewNavigationMode, QWERTYLayout} from "@xeokit/sdk/base/constants";
import {WebGLRenderer} from "@xeokit/sdk/viewing/webGLRenderer";
import {Viewer} from "@xeokit/sdk/viewing/viewer";
import {ViewController, KEY_A, KEY_D, KEY_W, KEY_S} from "@xeokit/sdk/viewing/viewController";
import {CityJSONLoader} from "@xeokit/sdk/formats/cityjson";

// Create a Scene to manage geometry and materials
const scene = new Scene();

// Create a Viewer instance
const viewer = new Viewer({
scene
});

// Create a WebGLRenderer for rendering the Scene
const renderer = new WebGLRenderer({
viewer
});

// Create a View for rendering
const viewResult = viewer.createView({
id: "myView",
elementId: "myCanvas"
});

const view = viewResult.value;

// Configure the camera's initial position and orientation
view.camera.eye = [1841982.93, 10.03, -5173286.74];
view.camera.look = [1842009.49, 9.68, -5173295.85];
view.camera.up = [0.0, 1.0, 0.0];

// Attach ViewController for interactive navigation
new ViewController(view, {});

// Load a CityJSON model into the Scene
const sceneModelResult = scene.createModel({ id: "myModel" });

const sceneModel = sceneModelResult.value;

fetch("model.json").then(response => response.json()).then(fileData => {
CityJSONLoader({ fileData, sceneModel }).then(() => {
// Loaded
});
});

Navigation Modes

ViewController provides three main navigation modes:

  • Orbit Mode: Enables the camera to orbit around a target point.
  • First-Person Mode: Allows free movement as if walking through the scene.
  • Plan-View Mode: Maintains a top-down perspective while allowing panning and zooming.

To activate orbit mode:

viewController.navMode = OrbitNavigationMode;
  • Orbit: Left-drag the mouse, tap-drag on a touchpad, or use arrow keys.
  • Dolly (Zoom): Scroll the mouse wheel, pinch on a touchpad, or press + and -.
  • Pan: Right-drag the mouse or use SHIFT while left-dragging.

Enables camera movement similar to a first-person video game.

viewController.navMode = FirstPersonNavigationMode;
  • Rotate: Left-drag the mouse or use arrow keys.
  • Move Forward/Backward: Use W and S (QWERTY) or Z and S (AZERTY).
  • Strafe Left/Right: Use A and D.

Keeps the camera locked to a top-down perspective.

viewController.navMode = PlanViewNavigationMode;
  • Pan: Drag the mouse or use keyboard keys (W, A, S, D).
  • Zoom: Scroll the mouse wheel or pinch on a touchpad.

ViewController Events

ViewController triggers events when interacting with ViewObjects using a mouse or touch input.


To subscribe to an event:

const onHoverSub = viewController.onHover.sub(e => {
console.log(e.viewObject, e.canvasPos);
});

To unsubscribe:

viewController.onHover.unsub(onHoverSub);

  • "hover" – Fired when the pointer moves over an entity.
  • "hoverOff" – Fired when the pointer moves over empty space.
  • "hoverEnter" – Fired when the pointer enters an entity.
  • "hoverOut" – Fired when the pointer leaves an entity.
viewController.onHoverEnter.sub(e => console.log(e.viewObject, e.canvasPos));
  • "picked" – Fired on left-click/tap on an entity.
  • "pickedSurface" – Fired on left-click/tap on an entity's surface.
  • "pickedNothing" – Fired on left-click/tap on empty space.
viewController.onPicked.sub(e => console.log(e.entity, e.canvasPos));
  • "doublePicked" – Fired on double-click/tap on an entity.
  • "doublePickedSurface" – Fired on double-click/tap on an entity's surface.
  • "doublePickedNothing" – Fired on double-click/tap on empty space.
viewController.onDoublePicked.sub(e => console.log(e.entity, e.canvasPos));
  • "rightClick" – Fired on right-click anywhere on the canvas.
viewController.onRightClick.sub(e => console.log(e.event, e.canvasPos));

Custom Keyboard Mappings

The default key mappings can be overridden to fit specific layouts.

viewController.keyMap = QWERTYLayout; // Or set to AZERTYLayout if needed.

Alternatively, define custom mappings:

const keyMap = {};

keyMap[viewController.PAN_LEFT] = [KEY_A];
keyMap[viewController.PAN_RIGHT] = [KEY_D];
keyMap[viewController.PAN_UP] = [KEY_Z];
keyMap[viewController.PAN_DOWN] = [KEY_X];
keyMap[viewController.DOLLY_FORWARDS] = [KEY_W, KEY_ADD];
keyMap[viewController.DOLLY_BACKWARDS] = [KEY_S, KEY_SUBTRACT];
keyMap[viewController.ROTATE_X_POS] = [KEY_DOWN_ARROW];
keyMap[viewController.ROTATE_X_NEG] = [KEY_UP_ARROW];
keyMap[viewController.ROTATE_Y_POS] = [KEY_LEFT_ARROW];
keyMap[viewController.ROTATE_Y_NEG] = [KEY_RIGHT_ARROW];
keyMap[viewController.AXIS_VIEW_RIGHT] = [KEY_NUM_1];
keyMap[viewController.AXIS_VIEW_BACK] = [KEY_NUM_2];
keyMap[viewController.AXIS_VIEW_LEFT] = [KEY_NUM_3];
keyMap[viewController.AXIS_VIEW_FRONT] = [KEY_NUM_4];
keyMap[viewController.AXIS_VIEW_TOP] = [KEY_NUM_5];
keyMap[viewController.AXIS_VIEW_BOTTOM] = [KEY_NUM_6];

viewController.keyMap = keyMap;

Classes

HoverEvent
ViewController
ViewControllerEvents

Interfaces

ViewControllerParams

Type Aliases

CameraControlPickFn

Variables

KEY_A
KEY_ADD
KEY_ALT
KEY_B
KEY_BACK_SLASH
KEY_BACKSPACE
KEY_C
KEY_CAPS_LOCK
KEY_CLOSE_BRACKET
KEY_COMMA
KEY_CTRL
KEY_D
KEY_DASH
KEY_DECIMAL_POINT
KEY_DELETE
KEY_DIVIDE
KEY_DOWN_ARROW
KEY_E
KEY_END
KEY_ENTER
KEY_EQUAL_SIGN
KEY_ESCAPE
KEY_F
KEY_F1
KEY_F10
KEY_F11
KEY_F12
KEY_F2
KEY_F3
KEY_F4
KEY_F5
KEY_F6
KEY_F7
KEY_F8
KEY_F9
KEY_FORWARD_SLASH
KEY_G
KEY_GRAVE_ACCENT
KEY_H
KEY_HOME
KEY_I
KEY_INSERT
KEY_J
KEY_K
KEY_L
KEY_LEFT_ARROW
KEY_LEFT_WINDOW
KEY_M
KEY_MULTIPLY
KEY_N
KEY_NUM_0
KEY_NUM_1
KEY_NUM_2
KEY_NUM_3
KEY_NUM_4
KEY_NUM_5
KEY_NUM_6
KEY_NUM_7
KEY_NUM_8
KEY_NUM_9
KEY_NUM_LOCK
KEY_NUMPAD_0
KEY_NUMPAD_1
KEY_NUMPAD_2
KEY_NUMPAD_3
KEY_NUMPAD_4
KEY_NUMPAD_5
KEY_NUMPAD_6
KEY_NUMPAD_7
KEY_NUMPAD_8
KEY_NUMPAD_9
KEY_O
KEY_OPEN_BRACKET
KEY_P
KEY_PAGE_DOWN
KEY_PAGE_UP
KEY_PAUSE_BREAK
KEY_PERIOD
KEY_Q
KEY_R
KEY_RIGHT_ARROW
KEY_RIGHT_WINDOW
KEY_S
KEY_SCROLL_LOCK
KEY_SELECT_KEY
KEY_SEMI_COLON
KEY_SHIFT
KEY_SINGLE_QUOTE
KEY_SPACE
KEY_SUBTRACT
KEY_T
KEY_TAB
KEY_U
KEY_UP_ARROW
KEY_V
KEY_W
KEY_X
KEY_Y
KEY_Z