UNPKG

mobility-toolbox-js

Version:

Toolbox for JavaScript applications in the domains of mobility and logistics.

104 lines (103 loc) 4.59 kB
import GeoJSON from 'ol/format/GeoJSON'; import { toLonLat } from 'ol/proj'; import LayerRenderer from 'ol/renderer/Layer'; import { VECTOR_TILE_FEATURE_PROPERTY } from '../../common'; /** * @private */ const formats = { 'EPSG:3857': new GeoJSON({ featureProjection: 'EPSG:3857', }), }; /** * This class is a renderer for Maplibre Layer to be able to use the native ol * functionnalities like map.getFeaturesAtPixel or map.hasFeatureAtPixel. * @private */ export default class MaplibreStyleLayerRenderer extends LayerRenderer { forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback) { const features = this.getFeaturesAtCoordinate(coordinate, hitTolerance); features.forEach((feature) => { // @ts-expect-error improve ts types callback(feature, this.layer_, feature.getGeometry()); }); return features === null || features === void 0 ? void 0 : features[0]; } getFeatures(pixel) { var _a, _b; const coordinate = (_b = (_a = this.getLayer()) === null || _a === void 0 ? void 0 : _a.getMapInternal()) === null || _b === void 0 ? void 0 : _b.getCoordinateFromPixel(pixel); return Promise.resolve(this.getFeaturesAtCoordinate(coordinate)); } getFeaturesAtCoordinate(coordinate, hitTolerance = 5) { var _a, _b, _c; if (!coordinate) { return []; } const layer = this.getLayer(); const map = layer.getMapInternal(); const mapLibreMap = (_a = layer.maplibreLayer) === null || _a === void 0 ? void 0 : _a.mapLibreMap; const projection = ((_c = (_b = map === null || map === void 0 ? void 0 : map.getView()) === null || _b === void 0 ? void 0 : _b.getProjection()) === null || _c === void 0 ? void 0 : _c.getCode()) || 'EPSG:3857'; let features = []; if (!formats[projection]) { formats[projection] = new GeoJSON({ featureProjection: projection, }); } if (mapLibreMap === null || mapLibreMap === void 0 ? void 0 : mapLibreMap.isStyleLoaded()) { const pixel = coordinate && mapLibreMap.project(toLonLat(coordinate)); if ((pixel === null || pixel === void 0 ? void 0 : pixel.x) && (pixel === null || pixel === void 0 ? void 0 : pixel.y)) { let pixels = [ pixel.x, pixel.y, ]; if (hitTolerance) { const [x, y] = pixels; pixels = [ [x - hitTolerance, y - hitTolerance], [x + hitTolerance, y + hitTolerance], ]; } // We query features only on style layers used by this layer. let layers = layer.layers || []; if (layer.layersFilter) { layers = mapLibreMap.getStyle().layers.filter(layer.layersFilter); } if (layer.queryRenderedLayersFilter) { layers = mapLibreMap .getStyle() .layers.filter(layer.queryRenderedLayersFilter); } // At this point we get GeoJSON Maplibre feature, we transform it to an OpenLayers // feature to be consistent with other layers. features = mapLibreMap .queryRenderedFeatures(pixels, { layers: layers.map((l) => { return l.id; }), validate: false, // ...layer.queryRenderedFeaturesOptions, }) .map((feature) => { const olFeature = formats[projection].readFeature(feature); if (olFeature) { // We save the original Maplibre feature to avoid losing informations // potentially needed for other functionnality like highlighting // (id, layer id, source, sourceLayer ...) olFeature.set(VECTOR_TILE_FEATURE_PROPERTY, feature); } return olFeature; }); } } return features; } prepareFrame() { return true; } renderFrame(frameState, target) { // Return an empty div as a placeholder since nothing is rendered return target !== null && target !== void 0 ? target : document.createElement('div'); } }