Files
grafana/public/app/plugins/panel/geomap/utils/getLayersExtent.ts
Drew Slobodnjak f0a8e86c28 Geomap: WebGL for Marker Layer (#95457)
* Geomap: Implement webgl for marker layer

* Cover rgb color formatting

* Adjust size

* Adjust size and leave todo for adjustment

* Add custom icon example

* Use prepareSVG to handle custom icons

* Apply icon offset

* Add example of text labels for fixed case

* Add text canvas layer and layerGroup

* Use textMarker for text layer style

* Fix geometry calcs

* Only include text layer if needed

* Remove extra line

* Move color functions to utils

* Pass webGL bool to marker maker

* Move webgl symbol style to marker maker

* Get hit detection working for webgl layers

* Improve icon hit detection

* Improve text performance

* Fix types and simplify webgl styling

* Simplify webgl regular shape lookup

* Add comments

* Set fallback color to white

* Fix data fit for initial view

* Update color utils to support colors with alpha

* Add tests for color value function

* Add tests for getWebGLStyle function

* Clean up comments

* Only show text if no symbol is specified

* Remove size multiplier from webgl implementation

* Add size multiplier back for now
2025-03-07 13:16:17 -08:00

81 lines
2.8 KiB
TypeScript

import { createEmpty, extend, Extent } from 'ol/extent';
import LayerGroup from 'ol/layer/Group';
import VectorLayer from 'ol/layer/Vector';
import VectorImage from 'ol/layer/VectorImage';
import WebGLPointsLayer from 'ol/layer/WebGLPoints.js';
import { MapLayerState } from '../types';
export function getLayersExtent(
layers: MapLayerState[] = [],
allLayers = false,
lastOnly = false,
layer: string | undefined
): Extent {
return layers
.filter((l) => l.layer instanceof VectorLayer || l.layer instanceof LayerGroup || l.layer instanceof VectorImage)
.flatMap((ll) => {
const layerName = ll.options.name;
const l = ll.layer;
if (l instanceof LayerGroup) {
// If not all layers check for matching layer name
if (!allLayers && layerName !== layer) {
return [];
}
return getLayerGroupExtent(l, lastOnly);
} else if (l instanceof VectorLayer || l instanceof VectorImage) {
if (allLayers) {
// Return everything from all layers
return [l.getSource().getExtent()];
} else if (lastOnly && layer === layerName) {
// Return last only for selected layer
const feat = l.getSource().getFeatures();
const featOfInterest = feat[feat.length - 1];
const geo = featOfInterest?.getGeometry();
if (geo) {
return [geo.getExtent()];
}
return [];
} else if (!lastOnly && layer === layerName) {
// Return all points for selected layer
return [l.getSource().getExtent()];
}
return [];
} else {
return [];
}
})
.reduce(extend, createEmpty());
}
export function getLayerGroupExtent(lg: LayerGroup, lastOnly: boolean) {
return lg
.getLayers()
.getArray()
.filter((l) => l instanceof VectorLayer || l instanceof VectorImage || l instanceof WebGLPointsLayer)
.map((l) => {
if (l instanceof VectorLayer || l instanceof VectorImage || l instanceof WebGLPointsLayer) {
if (lastOnly) {
// Return last coordinate only
const feat = l.getSource().getFeatures();
const featOfInterest = feat[feat.length - 1];
const geo = featOfInterest?.getGeometry();
if (geo) {
// Look at flatCoordinates for more robust support including route layer
const flatCoordinates = geo.flatCoordinates;
const flatCoordinatesLength = flatCoordinates.length;
if (flatCoordinatesLength > 1) {
const lastX = flatCoordinates[flatCoordinatesLength - 2];
const lastY = flatCoordinates[flatCoordinatesLength - 1];
return [lastX, lastY, lastX, lastY];
}
}
return [];
}
return l.getSource().getExtent() ?? [];
} else {
return [];
}
});
}