mobility-toolbox-js
Version:
Toolbox for JavaScript applications in the domains of mobility and logistics.
96 lines (95 loc) • 4.67 kB
JavaScript
import GeoJSON from 'ol/format/GeoJSON';
import CanvasLayerRenderer from 'ol/renderer/canvas/Layer';
import { composeCssTransform } from 'ol/transform';
const format = new GeoJSON();
/**
* 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 RealtimeLayerRenderer extends CanvasLayerRenderer {
forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback) {
const features = this.getFeaturesAtCoordinate(coordinate, hitTolerance);
features.forEach((feature) => {
// @ts-expect-error defintion to fix
callback(feature, this.layer_, feature.getGeometry());
});
return features === null || features === void 0 ? void 0 : features[0];
}
getData(pixel) {
var _a;
let data;
try {
const { pixelRatio } = this.getLayer();
const context = (_a = this.canvas) === null || _a === void 0 ? void 0 : _a.getContext('2d', {
willReadFrequently: true,
});
data =
(context === null || context === void 0 ? void 0 : context.getImageData(pixel[0] * (pixelRatio || 1), pixel[1] * (pixelRatio || 1), 1, 1).data) || null; // [3];
return data;
}
catch (err) {
console.error('error getting data', err);
}
return null;
}
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) {
if (!coordinate) {
return [];
}
const layer = this.getLayer();
const featureCollection = layer.engine.getVehiclesAtCoordinate(coordinate, {
hitTolerance,
nb: layer.maxNbFeaturesRequested,
});
return format.readFeatures(featureCollection);
}
prepareFrame() {
return true;
}
renderFrame(frameState) {
var _a;
const { canvas, engine, renderedViewState } = this.getLayer();
this.getLayer().engine.pixelRatio = frameState.pixelRatio;
this.ready = !!((_a = engine.renderState) === null || _a === void 0 ? void 0 : _a.renderedTrajectories) && engine.isIdle;
if (!this.container) {
this.container = document.createElement('div');
this.container.className = this.getLayer().getClassName();
this.container.style.position = 'absolute';
this.container.style.width = '100%';
this.container.style.height = '100%';
if (canvas instanceof HTMLCanvasElement) {
canvas.style.position = 'absolute';
canvas.style.top = '0';
canvas.style.left = '0';
canvas.style.transformOrigin = 'top left';
this.container.appendChild(canvas);
}
}
if (renderedViewState) {
const { center, resolution, rotation } = frameState.viewState;
const { center: renderedCenter, resolution: renderedResolution, rotation: renderedRotation, } = renderedViewState;
if (renderedResolution / resolution >= 3) {
// Avoid having really big points when zooming fast.
const context = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d');
if ((canvas === null || canvas === void 0 ? void 0 : canvas.width) && (canvas === null || canvas === void 0 ? void 0 : canvas.height)) {
context === null || context === void 0 ? void 0 : context.clearRect(0, 0, canvas.width, canvas.height);
}
}
else {
const map = this.getLayer().getMapInternal();
const pixelCenterRendered = map === null || map === void 0 ? void 0 : map.getPixelFromCoordinate(renderedCenter);
const pixelCenter = map === null || map === void 0 ? void 0 : map.getPixelFromCoordinate(center);
if (pixelCenterRendered && pixelCenter) {
this.container.style.transform = composeCssTransform(pixelCenterRendered[0] - pixelCenter[0], pixelCenterRendered[1] - pixelCenter[1], renderedResolution / resolution, renderedResolution / resolution, rotation - renderedRotation, 0, 0);
}
}
}
return this.container;
}
}