Skip to content
Development
Skill

/cesiumjs-interaction

CesiumJS interaction and picking - ScreenSpaceEventHandler, multi-key KeyboardEventModifier input actions, Scene.pick, Scene.drillPick, Scene.pickPosition, Scene.snap edge snapping (1.144), mouse and touch events. Use when handling user clicks on the globe, selecting entities or

From plugin
cesiumjs-skills
19415 skills1 hook1 MCP

Claude Code

$ npx -y skills add CesiumGS/cesiumjs-skills --skill cesiumjs-interaction --agent claude-code

SKILL.md

cesiumjs-interaction.SKILL.md
name: cesiumjs-interaction
description: "CesiumJS interaction and picking - ScreenSpaceEventHandler, multi-key KeyboardEventModifier input actions, Scene.pick, Scene.drillPick, Scene.pickPosition, Scene.snap edge snapping (1.144), mouse and touch events. Use when handling user clicks on the globe, selecting entities or 3D Tiles features, registering modifier-key shortcuts, implementing hover effects, snapping to model edges for measurement, or building drag-based interactions."

CesiumJS Interaction & Picking

Version baseline: CesiumJS v1.144 (ES module imports, Ion token required).

ScreenSpaceEventHandler

Central class for mouse, touch, and pointer events on the Cesium canvas. **Always construct a new `ScreenSpaceEventHandler` bound to `viewer.scene.canvas` for interaction logic** -- it isolates your listeners from Cesium's default camera/selection handlers and is the idiomatic pattern shown across all recipes below.

import { ScreenSpaceEventHandler, ScreenSpaceEventType,
  KeyboardEventModifier, defined } from "cesium";

let handler = new ScreenSpaceEventHandler(viewer.scene.canvas);

// Register a click handler
handler.setInputAction((event) => {
  console.log("Clicked at", event.position.x, event.position.y);
}, ScreenSpaceEventType.LEFT_CLICK);

// With keyboard modifier (Shift+Click)
handler.setInputAction((event) => {
  console.log("Shift+Click at", event.position);
}, ScreenSpaceEventType.LEFT_CLICK, KeyboardEventModifier.SHIFT);

// With multiple modifiers (Ctrl+Shift+Click, 1.142+)
handler.setInputAction((event) => {
  console.log("Ctrl+Shift+Click at", event.position);
}, ScreenSpaceEventType.LEFT_CLICK, [
  KeyboardEventModifier.CTRL,
  KeyboardEventModifier.SHIFT,
]);

// Query or remove actions
const clickAction = handler.getInputAction(ScreenSpaceEventType.LEFT_CLICK);
const ctrlShiftClickAction = handler.getInputAction(ScreenSpaceEventType.LEFT_CLICK, [
  KeyboardEventModifier.SHIFT,
  KeyboardEventModifier.CTRL, // order does not matter
]);
if (defined(clickAction) && defined(ctrlShiftClickAction)) {
  console.log("Click handlers registered");
}
handler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK);
handler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK, [
  KeyboardEventModifier.CTRL,
  KeyboardEventModifier.SHIFT,
]);

// Always destroy when done to avoid memory leaks
handler = handler && handler.destroy();

The Viewer also exposes a built-in handler at `viewer.screenSpaceEventHandler` which drives default behavior (entity selection, double-click tracking). You *can* attach to it, but for any non-trivial interaction prefer constructing your own `new ScreenSpaceEventHandler(viewer.scene.canvas)` so your handlers are independently disposable and do not collide with Cesium defaults.

ScreenSpaceEventType Reference

| Event | Callback shape | Notes | |---|---|---| | `LEFT_DOWN` / `LEFT_UP` / `LEFT_CLICK` | `({ position })` | Cartesian2 screen coords | | `LEFT_DOUBLE_CLICK` | `({ position })` | Left only | | `RIGHT_DOWN` / `RIGHT_UP` / `RIGHT_CLICK` | `({ position })` | | | `MIDDLE_DOWN` / `MIDDLE_UP` / `MIDDLE_CLICK` | `({ position })` | | | `MOUSE_MOVE` | `({ startPosition, endPosition })` | Fires on every pointer move | | `WHEEL` | `(delta)` | Positive = scroll up | | `PINCH_START` | `({ position1, position2 })` | Two-finger touch begins | | `PINCH_END` | `()` | Two-finger touch ends | | `PINCH_MOVE` | `({ distance, angleAndHeight })` | Two-finger move |

`KeyboardEventModifier`: `SHIFT`, `CTRL`, `ALT` -- optional third argument to `setInputAction`, `getInputAction`, and `removeInputAction`. In 1.142+, pass a single modifier or an array of modifiers. Modifier arrays are order-independent but exact: a handler registered for `[CTRL, SHIFT]` does not fire when `ALT` is also held.

Scene Picking Methods

pick / pickAsync / drillPick / pickPosition

import { Cartographic, Math as CesiumMath, defined } from "cesium";

// pick -- synchronous, returns top-most object or undefined
const picked = viewer.scene.pick(event.position);

// pickAsync -- non-blocking (WebGL2, v1.136+), falls back to sync on WebGL1
const picked2 = await viewer.scene.pickAsync(movement.endPosition);

// drillPick -- all objects at position, front-to-back; use limit to cap cost
const allPicked = viewer.scene.drillPick(event.position, 5);

// pickPosition -- world Cartesian3 from depth buffer
if (viewer.scene.pickPositionSupported) {
  const cartesian = viewer.scene.pickPosition(event.position);
  if (defined(cartesian)) {
    const c = Cartographic.fromCartesian(cartesian);
    console.log(CesiumMath.toDegrees(c.longitude), CesiumMath.toDegrees(c.latitude), c.height);
  }
}

Set `scene.pickTranslucentDepth = true` to include translucent primitives in `pickPosition`.

pickVoxel (experimental)

// Pick a voxel cell and read its properties
const voxelCell = viewer.scene.pickVoxel(event.position);
if (defined(voxelCell)) {
  console.log(voxelCell.getProperty("temperature"));
}

snap (experimental, 1.144+)

`scene.snap` searches a screen-space region around a window position and returns the best snap target, preferring model edges (from CAD-style `EXT_mesh_primitive_edge_visibility` data) over surfaces; among hits of the same kind, the one nearest the cursor wins. Use it for measurement and inspection tools that should latch onto edges instead of raw cursor hits.

import { defined } from "cesium";

// Search a 25x25 px region centered on the cursor
const result = viewer.scene.snap(movement.endPosition, { width: 25 });
if (defined(result)) {
  // SceneSnapResult: { object, position, screenPosition, isEdge }
  console.log(result.isEdge ? "edge" : "surface", result.position);
}

Only primitives rendered through the Model pipeline (3D Tiles and glTF models) are snappable. Snapping requires WebGL2 with float color attachments (`EXT_color_buffer_float`); when that is unsupported, or the region contains no snappable geometry, `snap` retur

Read more
@cesiumgs
Ships withcesiumjs-skills

Curated agent skills for CesiumJS development — 14 domain skills covering ~551 public symbols across the CesiumJS v1.143 API surface.

19415 skills1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
194
Star history of CesiumGS/cesiumjs-skills on GitHub, a chart by star-history.com

Other skills on cesiumjs-skills.

cesiumjs-camera

cesiumjs-camera

CesiumJS camera control - Camera, flyTo, lookAt, setView, ScreenSpaceCameraController, composable Controller camera controllers…

cesiumjs-imagery

cesiumjs-imagery

CesiumJS imagery layers - ImageryProvider, ImageryLayer, ImageryLayerCollection, WMS, WMTS, Bing, OpenStreetMap, ArcGIS, Mapbox,…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills12d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react3d252k
@facebook@facebookInstall Skill

Questions about cesiumjs-interaction.

Which coding agents can use cesiumjs-interaction?
cesiumjs-interaction installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.