hmpps-open-layers-map
Version:
A native Web Component for displaying maps using OpenLayers.
74 lines (73 loc) • 2.6 kB
JavaScript
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { GeoJSON } from 'ol/format';
import { Fill, Stroke, Text, Style } from 'ol/style';
// Style function that renders numbers from a feature property
function createNumberingStyle(value, options) {
return new Style({
text: new Text({
textAlign: 'left',
textBaseline: 'middle',
font: options.font ?? 'bold 12px "Inter", system-ui, sans-serif',
fill: new Fill({ color: options.fillColor ?? 'black' }),
stroke: new Stroke({
color: options.strokeColor ?? 'white',
width: options.strokeWidth ?? 2,
}),
text: value,
offsetX: options.offsetX ?? 12,
offsetY: options.offsetY ?? 1,
}),
});
}
function toOlSource(geoJson) {
const formatter = new GeoJSON();
const features = formatter.readFeatures(geoJson, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857',
});
return new VectorSource({ features });
}
export class NumberingLayer {
id;
options;
olLayer;
constructor(options) {
this.options = options;
this.id = options.id ?? 'numbering';
}
getNativeLayer() {
return this.olLayer;
}
attach(adapter) {
if (adapter.mapLibrary !== 'openlayers') {
console.warn(`[NumberingLayer] MapLibre support is not implemented yet (layer "${this.id}")`);
return;
}
const { map } = adapter.openlayers;
const property = this.options.numberProperty ?? 'sequenceNumber';
const vectorLayer = new VectorLayer({
source: toOlSource(this.options.geoJson),
style: feature => {
const value = feature.get(property);
return value ? createNumberingStyle(String(value), this.options) : undefined;
},
properties: { title: this.options.title ?? this.id },
});
const resolvedVisible = this.options.visible ?? false;
const resolvedZIndex = this.options.zIndex;
vectorLayer.setVisible(resolvedVisible);
if (resolvedZIndex !== undefined)
vectorLayer.setZIndex(resolvedZIndex);
map.addLayer(vectorLayer);
this.olLayer = vectorLayer;
}
detach(adapter) {
if (adapter.mapLibrary !== 'openlayers')
return;
if (this.olLayer) {
adapter.openlayers.map.removeLayer(this.olLayer);
this.olLayer = undefined;
}
}
}