UNPKG

@polygonjs/plugin-mapbox

Version:

Mapbox plugin for the 3D engine https://polygonjs.com

399 lines (398 loc) 12.1 kB
import { TypedCameraObjNode, CameraMainCameraParamConfig } from "@polygonjs/polygonjs/dist/src/engine/nodes/obj/_BaseCamera"; import mapboxgl from "mapbox-gl"; import { CoreMapboxClient } from "../../../core/mapbox/Client"; import { ParamConfig, NodeParamsConfig } from "@polygonjs/polygonjs/dist/src/engine/nodes/utils/params/ParamsConfig"; import { isBooleanTrue } from "@polygonjs/polygonjs/dist/src/core/Type"; import { Poly } from "@polygonjs/polygonjs/dist/src/engine/Poly"; import { MapboxPerspectiveCamera } from "../../../core/mapbox/MapboxPerspectiveCamera"; import { MAPBOX_CAMERA_OBJ_NODE_TYPE, registerMapboxCamera } from "../../../core/mapbox/registerMapboxCamera"; import { NodeContext } from "@polygonjs/polygonjs/dist/src/engine/poly/NodeContext"; import { RopType } from "@polygonjs/polygonjs/dist/src/engine/poly/registers/nodes/types/Rop"; import { CameraCSSRendererSopOperation } from "@polygonjs/polygonjs/dist/src/engine/operations/sop/CameraCSSRenderer"; const PRESETS = { LONDON: { style: "mapbox://styles/mapbox/dark-v10", lngLat: [-0.07956, 51.5146] }, SAN_FRANCISCO: { style: "mapbox://styles/mapbox/dark-v10", lngLat: [-122.4726194, 37.7577627] }, MOUNTAIN: { style: "mapbox://styles/mapbox-map-design/ckhqrf2tz0dt119ny6azh975y", lngLat: [-114.34411, 32.6141] } }; const PRESET = PRESETS.LONDON; class MapboxCameraObjParamConfig extends CameraMainCameraParamConfig(NodeParamsConfig) { constructor() { super(...arguments); this.style = ParamConfig.STRING(PRESET.style, { callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_update_style(node); } }); this.lngLat = ParamConfig.VECTOR2(PRESET.lngLat, { callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_update_nav(node); } }); this.zoom = ParamConfig.FLOAT(15.55, { range: [0, 24], rangeLocked: [true, true], callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_update_nav(node); } }); this.zoomRange = ParamConfig.VECTOR2([0, 24], { callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_update_nav(node); } }); this.pitch = ParamConfig.FLOAT(60, { range: [0, 85], rangeLocked: [true, true], callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_update_nav(node); } }); this.bearing = ParamConfig.FLOAT(60.373613, { range: [0, 360], callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_update_nav(node); } }); this.updateParamsFromMap = ParamConfig.BUTTON(null, { label: "Set Navigation Params as Default", callback: (node, param) => { MapboxCameraObjNode.PARAM_CALLBACK_update_params_from_map(node); } }); this.allowDragRotate = ParamConfig.BOOLEAN(1, { callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_update_nav(node); } }); this.addZoomControl = ParamConfig.BOOLEAN(1, { callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_update_nav(node); } }); this.tlayerBuildings = ParamConfig.BOOLEAN(0); this.tlayer3D = ParamConfig.BOOLEAN(0); this.tlayerSky = ParamConfig.BOOLEAN(0); this.setCSSRenderer = ParamConfig.BOOLEAN(0, { callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_updateCameraAttributes(node); } }); this.CSSRenderer = ParamConfig.NODE_PATH("", { visibleIf: { setCSSRenderer: 1 }, nodeSelection: { context: NodeContext.ROP, types: [RopType.CSS2D, RopType.CSS3D] }, dependentOnFoundNode: true, callback: (node) => { MapboxCameraObjNode.PARAM_CALLBACK_updateCameraAttributes(node); } }); } } const ParamsConfig = new MapboxCameraObjParamConfig(); export class MapboxCameraObjNode extends TypedCameraObjNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._maps_by_container_id = /* @__PURE__ */ new Map(); this._map_containers_by_container_id = /* @__PURE__ */ new Map(); this._canvases_by_container_id = /* @__PURE__ */ new Map(); this._controls_by_container_id = /* @__PURE__ */ new Map(); this._moving_maps = false; } static type() { return MAPBOX_CAMERA_OBJ_NODE_TYPE; } integration_data() { return CoreMapboxClient.integration_data(); } createObject() { return new MapboxPerspectiveCamera(); } async cook() { this.updateMaps(); this._updateCameraAttributes(); this.cookController.endCook(); } static PARAM_CALLBACK_updateCameraAttributes(node) { node._updateCameraAttributes(); } _updateCameraAttributes() { const objects = [this._object]; const node = this; CameraCSSRendererSopOperation.updateObject({ objects, params: { node: this.pv.CSSRenderer }, node, active: this.pv.setCSSRenderer }); } createMap(container) { const map = new mapboxgl.Map({ style: this.pv.style, container, center: this.pv.lngLat.toArray(), zoom: this.pv.zoom, minZoom: this.pv.zoomRange.x, maxZoom: this.pv.zoomRange.y, pitch: this.pv.pitch, bearing: this.pv.bearing, dragRotate: this.pv.allowDragRotate, pitchWithRotate: this.pv.allowDragRotate, antialias: true }); this._updateCameraAttributes(); this._addRemoveControls(map, container.id); this._maps_by_container_id.set(container.id, map); this._map_containers_by_container_id.set(container.id, container); this._canvases_by_container_id.set(container.id, container.querySelector("canvas")); return map; } updateMaps() { this._maps_by_container_id.forEach((map, container_id) => { this.updateMapFromContainerId(container_id); }); this._updateCameraAttributes(); } updateMapFromContainerId(container_id) { const map = this._maps_by_container_id.get(container_id); if (!map) { return; } this.updateMapNav(map); this._addRemoveControls(map, container_id); map.setStyle(this.pv.style); } updateMapNav(map) { map.jumpTo(this.cameraOptionsFromParams()); map.setMinZoom(this.pv.zoomRange.x); map.setMaxZoom(this.pv.zoomRange.y); const drag_rotate_handler = map.dragRotate; if (isBooleanTrue(this.pv.allowDragRotate)) { drag_rotate_handler.enable(); } else { drag_rotate_handler.disable(); } } firstMap() { let first_map; this._maps_by_container_id.forEach((map, id) => { if (!first_map) { first_map = map; } }); return first_map; } firstId() { let first_id; this._maps_by_container_id.forEach((map, id) => { if (!first_id) { first_id = id; } }); return first_id; } firstMapElement() { const id = this.firstId(); if (id) { return this._map_containers_by_container_id.get(id); } } bounds() { const map = this.firstMap(); if (map) { return map.getBounds(); } } zoom() { const map = this.firstMap(); if (map) { return map.getZoom(); } } center() { const map = this.firstMap(); if (map) { return map.getCenter(); } } horizontal_lng_lat_points() { const id = this.firstId(); if (id) { const map = this._maps_by_container_id.get(id); const element = this._canvases_by_container_id.get(id); if (map && element) { const y = element.clientHeight / 2; return [map.unproject([0, y]), map.unproject([100, y])]; } } } centerLngLatPoint() { const id = this.firstId(); if (id) { const map = this._maps_by_container_id.get(id); const element = this._canvases_by_container_id.get(id); if (map && element) { const x = element.clientWidth * 0.5; const y = element.clientHeight * 0.5; return map.unproject([x, y]); } } } verticalFarLngLatPoints() { const id = this.firstId(); if (id) { const map = this._maps_by_container_id.get(id); const element = this._canvases_by_container_id.get(id); if (map && element) { const x = element.clientWidth; const y = 0; return [map.unproject([0, y]), map.unproject([x, y])]; } } } verticalNearLngLatPoints() { const id = this.firstId(); if (id) { const map = this._maps_by_container_id.get(id); const element = this._canvases_by_container_id.get(id); if (map && element) { const x = element.clientWidth; const y = element.clientHeight; return [map.unproject([0, y]), map.unproject([x, y])]; } } } removeMap(container) { if (container) { const map = this._maps_by_container_id.get(container.id); if (map) { map.remove(); this._maps_by_container_id.delete(container.id); this._map_containers_by_container_id.delete(container.id); this._canvases_by_container_id.delete(container.id); this._controls_by_container_id.delete(container.id); } } } onMoveEnd(container) { if (this._moving_maps === true) { return; } this._moving_maps = true; if (container != null) { const triggering_map = this._maps_by_container_id.get(container.id); if (triggering_map != null) { const camera_options = this.cameraOptionsFromMap(triggering_map); this._maps_by_container_id.forEach((map, container_id) => { if (container_id !== container.id) { const map2 = this._maps_by_container_id.get(container_id); map2 == null ? void 0 : map2.jumpTo(camera_options); } }); } } this.object.dispatchEvent({ type: "moveend" }); this._moving_maps = false; } lngLat() { const val = this.pv.lngLat; return { lng: val.x, lat: val.y }; } cameraOptionsFromParams() { return { center: this.lngLat(), pitch: this.pv.pitch, bearing: this.pv.bearing, zoom: this.pv.zoom }; } cameraOptionsFromMap(map) { return { center: map.getCenter(), pitch: map.getPitch(), bearing: map.getBearing(), zoom: map.getZoom() }; } _addRemoveControls(map, container_id) { let nav_control = this._controls_by_container_id.get(container_id); if (nav_control) { if (!isBooleanTrue(this.pv.addZoomControl)) { map.removeControl(nav_control); this._controls_by_container_id.delete(container_id); } } else { if (isBooleanTrue(this.pv.addZoomControl)) { nav_control = new mapboxgl.NavigationControl(); map.addControl(nav_control, "bottom-right"); this._controls_by_container_id.set(container_id, nav_control); } } } updateParamsFromMap() { const map = this.firstMap(); if (map) { const center = map.getCenter(); const zoom = map.getZoom(); const pitch = map.getPitch(); const bearing = map.getBearing(); this.p.lngLat.set([center.lng, center.lat]); this.p.zoom.set(zoom); this.p.pitch.set(pitch); this.p.bearing.set(bearing); } } static PARAM_CALLBACK_update_params_from_map(node) { node.updateParamsFromMap(); } static PARAM_CALLBACK_update_style(node) { node.updateStyle(); } static PARAM_CALLBACK_update_nav(node) { node.updateNav(); } updateStyle() { this._maps_by_container_id.forEach((map, container_id) => { map.setStyle(this.pv.style); }); } updateNav() { this._maps_by_container_id.forEach((map) => { this.updateMapNav(map); }); } async createViewer(options) { const viewer = Poly.camerasRegister.createViewer({ camera: this.object, scene: this.scene() }); let element; if (options && options instanceof HTMLElement) { element = options; } else { element = options == null ? void 0 : options.element; } if (viewer && element) { viewer.mount(element); } return viewer; } } MapboxCameraObjNode.onRegister = registerMapboxCamera;