Skip to content

Commit 523c645

Browse files
committed
feat: add cesium-walk
1 parent 76d96b1 commit 523c645

5 files changed

Lines changed: 261 additions & 0 deletions

File tree

demos/cesium-walk.html

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<script src="https://cesium.com/downloads/cesiumjs/releases/1.124/Build/Cesium/Cesium.js"></script>
7+
<link href="https://cesium.com/downloads/cesiumjs/releases/1.124/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
8+
<style>
9+
html, body, #cesiumContainer {
10+
height: 100%;
11+
margin: 0;
12+
}
13+
#activate {
14+
position: absolute;
15+
right: 30px;
16+
top: 30px;
17+
font-family: monospace;
18+
font-weight: bold;
19+
font-size: 1.6em;
20+
}
21+
</style>
22+
</head>
23+
24+
<body>
25+
<div id="cesiumContainer"></div>
26+
<button id="activate" type="button">Activate !</button>
27+
<script type="module">
28+
import {createViewer} from './setup.js';
29+
import CesiumWalk from '../packages/cesium-walk/cesium-walk.js';
30+
31+
createViewer('cesiumContainer').then(viewer => {
32+
const mode = new CesiumWalk(viewer);
33+
document.querySelector('#activate').addEventListener('click', () => mode.active = !mode.active);
34+
});
35+
</script>
36+
</body>
37+
38+
</html>

packages/cesium-walk/LICENSE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
BSD 3-Clause License
2+
3+
Copyright (c) 2024-present, camptocamp SA
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
1. Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
3. Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

packages/cesium-walk/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# walk mode for CesiumJS
2+
3+
Control the camera in CesiumJS as if you were walking around.
4+
Use `w`, `a`, `s` and `d` keys to move.
5+
6+
## Demo
7+
8+
[Demo](https://geoblocks.github.io/cesium-helpers/cesium-walk.html)
9+
10+
## Installation
11+
12+
```bash
13+
npm i --save @geoblocks/cesium-walk
14+
```
15+
16+
### Usage
17+
18+
```js
19+
import {Viewer} from 'cesium';
20+
import WalkCameraMode from '@geoblocks/cesium-walk';
21+
22+
const viewer = new Viewer(...);
23+
const mode = new WalkCameraMode(viewer.scene);
24+
25+
// ...
26+
mode.active = true;
27+
```
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
export default class CesiumWalk {
2+
/**
3+
* @param {import('cesium').Viewer} viewer
4+
* @param {number} [speed=1.6] Walk speed in meters per second.
5+
*/
6+
constructor(viewer, speed = 1.6, height = 2.0) {
7+
/**
8+
* @type {import('cesium').Viewer}
9+
*/
10+
this.viewer = viewer;
11+
12+
/**
13+
* @type {number}
14+
*/
15+
this.speed = speed;
16+
17+
/**
18+
* @type {number}
19+
*/
20+
this.height = height;
21+
22+
/**
23+
* @type {boolean}
24+
*/
25+
this.active_ = false;
26+
27+
/**
28+
* @type {number}
29+
*/
30+
this.lastTick;
31+
32+
/**
33+
* @type {{forward: boolean, left: boolean, backward: boolean, right: boolean}}
34+
*/
35+
this.buttons = {
36+
forward: false,
37+
left: false,
38+
backward: false,
39+
right: false,
40+
};
41+
42+
/**
43+
* @type {function(KeyboardEvent): void}
44+
*/
45+
this.handleKeyUpDownFunction = this.handleKeyUpDown.bind(this);
46+
47+
/**
48+
* @type {function(): void}
49+
*/
50+
this.handleTickFunction = this.handleTick.bind(this);
51+
}
52+
53+
get active() {
54+
return this.active_;
55+
}
56+
57+
set active(active) {
58+
this.active_ = active;
59+
if (this.active_) {
60+
document.addEventListener("keydown", this.handleKeyUpDownFunction);
61+
document.addEventListener("keyup", this.handleKeyUpDownFunction);
62+
this.viewer.clock.onTick.addEventListener(this.handleTickFunction);
63+
this.clampCameraToTerrain();
64+
} else {
65+
document.removeEventListener("keydown", this.handleKeyUpDownFunction);
66+
document.removeEventListener("keyup", this.handleKeyUpDownFunction);
67+
this.viewer.clock.onTick.removeEventListener(this.handleTickFunction);
68+
}
69+
this.enableNavigation(!this.active_);
70+
}
71+
72+
/**
73+
* @param {KeyboardEvent} event
74+
*/
75+
handleKeyUpDown(event) {
76+
const pressed = event.type === "keydown";
77+
switch (event.key) {
78+
case "w":
79+
this.buttons.forward = pressed;
80+
break;
81+
case "a":
82+
this.buttons.left = pressed;
83+
break;
84+
case "s":
85+
this.buttons.backward = pressed;
86+
break;
87+
case "d":
88+
this.buttons.right = pressed;
89+
break;
90+
}
91+
}
92+
93+
handleTick() {
94+
const timestamp = performance.now();
95+
if (this.needsTick()) {
96+
const camera = this.viewer.camera;
97+
const deltaTime = timestamp - this.lastTick;
98+
99+
const distance = (this.speed * deltaTime) / 1000;
100+
101+
if (this.buttons.forward) {
102+
camera.moveForward(distance);
103+
}
104+
if (this.buttons.left) {
105+
camera.moveLeft(distance);
106+
}
107+
if (this.buttons.backward) {
108+
camera.moveBackward(distance);
109+
}
110+
if (this.buttons.right) {
111+
camera.moveRight(distance);
112+
}
113+
this.clampCameraToTerrain();
114+
}
115+
116+
this.lastTick = timestamp;
117+
}
118+
119+
clampCameraToTerrain() {
120+
const camera = this.viewer.camera;
121+
const terrainHeight = this.viewer.scene.globe.getHeight(
122+
camera.positionCartographic
123+
);
124+
const cameraHeight = camera.positionCartographic.height;
125+
126+
camera.moveDown(cameraHeight - terrainHeight - this.height);
127+
}
128+
129+
/**
130+
* @return {boolean}
131+
*/
132+
needsTick() {
133+
return (
134+
this.buttons.forward ||
135+
this.buttons.left ||
136+
this.buttons.backward ||
137+
this.buttons.right
138+
);
139+
}
140+
141+
/**
142+
* Enable or disable cesium navigation interactions.
143+
* @param {boolean} enable
144+
*/
145+
enableNavigation(enable) {
146+
const controller = this.viewer.scene.screenSpaceCameraController;
147+
controller.enableTranslate = enable;
148+
controller.enableZoom = enable;
149+
controller.enableRotate = enable;
150+
controller.enableTilt = enable;
151+
}
152+
}

packages/cesium-walk/package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "@geoblocks/cesium-walk",
3+
"version": "0.0.0",
4+
"license": "BSD-3-Clause",
5+
"repository": {
6+
"type": "git",
7+
"url": "https://github.com/geoblocks/cesium-helpers/",
8+
"directory": "packages/cesium-walk"
9+
},
10+
"main": "cesium-walk.js",
11+
"module": "cesium-walk.js",
12+
"publishConfig": {
13+
"access": "public"
14+
}
15+
}

0 commit comments

Comments
 (0)