mobility-toolbox-js
Version:
Toolbox for JavaScript applications in the domains of mobility and logistics.
104 lines (103 loc) • 4.59 kB
JavaScript
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');
}
}