@pmndrs/handle
Version:
framework agnostic expandable handle implementation for threejs
66 lines (65 loc) • 2.59 kB
JavaScript
import { Vector3 } from 'three';
import { clamp } from 'three/src/math/MathUtils.js';
import { applyDampedScreenCameraState, applyScreenCameraState, createScreenCameraStore, } from './camera.js';
import { filterForOnePointerLeftClick, filterForOnePointerRightClickOrTwoPointer } from './index.js';
import { PanScreenHandleStore } from './pan.js';
import { RotateScreenHandleStore } from './rotate.js';
import { ZoomScreenHandleStore } from './zoom.js';
const vectorHelper = new Vector3();
export function defaultMapHandlesScreenCameraApply(update, store) {
if (update.pitch != null) {
update.pitch = clamp(update.pitch, -Math.PI / 2, 0);
}
store.setState(update);
}
export class MapHandles {
rotate;
pan;
zoom;
store;
getCamera;
updateDamping;
damping = false;
constructor(canvas, camera, store) {
if (store == null) {
store = createScreenCameraStore();
const resolvedCamera = typeof camera === 'function' ? camera() : camera;
store.getState().setCameraPosition(...resolvedCamera.getWorldPosition(vectorHelper).toArray());
}
this.store = store;
this.getCamera = typeof camera === 'function' ? camera : () => camera;
this.updateDamping = applyDampedScreenCameraState(store, this.getCamera, () => this.damping);
this.rotate = new RotateScreenHandleStore(store, this.getCamera, filterForOnePointerRightClickOrTwoPointer, defaultMapHandlesScreenCameraApply);
this.pan = new PanScreenHandleStore(canvas, store, this.getCamera, filterForOnePointerLeftClick, defaultMapHandlesScreenCameraApply, 1, 'xz');
this.zoom = new ZoomScreenHandleStore(store, this.getCamera, undefined, defaultMapHandlesScreenCameraApply);
}
getStore() {
return this.store;
}
update(deltaTime) {
this.rotate.update();
this.pan.update();
this.zoom.update();
this.updateDamping(deltaTime);
}
bind(scene, damping = false) {
const unbindRotate = this.rotate.bind(scene);
const unbindPan = this.pan.bind(scene);
const unbindZoom = this.zoom.bind(scene);
let unsubscribeCamera;
if (damping === false) {
unsubscribeCamera = applyScreenCameraState(this.store, this.getCamera);
}
this.damping = damping;
return () => {
unbindRotate();
unbindPan();
unbindZoom();
unsubscribeCamera?.();
};
}
}
/**
* @deprecated use MapHandles instead
*/
export const MapControls = MapHandles;