@mattilsynet/designsystem-svelte
Version:
Design system for Mattilsynet
92 lines (91 loc) • 3.11 kB
JavaScript
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import {} from 'ol/Feature';
import { Circle, Fill, Style, Text } from 'ol/style';
import { Cluster } from 'ol/source';
import { DEFAULT_CLUSTER_DISPLACEMENT, DEFAULT_CLUSTER_OFFSET_X, DEFAULT_CLUSTER_OFFSET_Y, DEFAULT_CLUSTER_RADIUS, DEFAULT_CLUSTER_SIZE_SCALE } from '../../../ts/mapUtils';
import { addMarkersToSource, createMarkerStyle, MARKER } from './marker';
import { markers as svg } from '../../../ts';
export const LAYER_ID = 'layerId';
export const VECTOR_LAYER_ID = 'clusterLayer';
export function createClusterLayer(markers, options, markerOptions) {
const source = addMarkersToSource(new VectorSource(), markers, markerOptions);
const cluster = createCluster(options.distance, options.minDistance, source);
const vectorLayer = new VectorLayer({
source: cluster,
visible: true,
style: createClusterStyle
});
vectorLayer.set(LAYER_ID, VECTOR_LAYER_ID);
return vectorLayer;
}
export function createMarkerLayer(markers, markerOptions) {
const source = addMarkersToSource(new VectorSource(), markers, markerOptions);
return new VectorLayer({
source,
visible: true
});
}
function createClusterStyle(feature) {
const features = feature.get('features');
const size = features.length;
if (size <= 1) {
return features?.[0]?.style_;
}
else if (hasSameMarkerStatus(features)) {
return [getClusterStyleFromMarkerStatus(features[0]), createClusterSizeStyle(size)];
}
else {
return [
createMarkerStyle({
src: `data:image/svg+xml;utf8,${encodeURIComponent(svg.cluster.default)}`
}),
createClusterSizeStyle(size)
];
}
}
export function getClusterStyleFromMarkerStatus(feature) {
const status = feature.get(MARKER).status;
return createMarkerStyle({
src: `data:image/svg+xml;utf8,${encodeURIComponent(svg.cluster[status] ?? svg.cluster.default)}`
});
}
function hasSameMarkerStatus(features) {
let prevStatus;
for (const feature of features) {
// @ts-ignore
const currStatus = feature.get(MARKER).status;
if (prevStatus && prevStatus !== currStatus) {
return false;
}
prevStatus = currStatus;
}
return true;
}
function createClusterSizeStyle(size) {
return new Style({
image: new Circle({
radius: DEFAULT_CLUSTER_RADIUS,
fill: new Fill({
color: 'white'
}),
displacement: DEFAULT_CLUSTER_DISPLACEMENT
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: '#032C30'
}),
scale: DEFAULT_CLUSTER_SIZE_SCALE,
offsetX: DEFAULT_CLUSTER_OFFSET_X,
offsetY: DEFAULT_CLUSTER_OFFSET_Y
})
});
}
function createCluster(distance, minDistance, source) {
return new Cluster({
distance,
minDistance,
source: source
});
}