mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-11-15 07:07:07 +00:00
extension api v2, ref #395
This commit is contained in:
1 parent
7474f892ce
commit
4050420b3c
8 files changed
+989
-58
No files matched your search
@@ -1,4 +1,89 @@
|
||||
import type { LayerTreeType } from '$lib/data/layers';
|
||||
import type { LayerSpecification, StyleSpecification } from 'maplibre-gl';
|
||||
|
||||
/** Parts of a style that apply to a whole map, not to an overlay. */
|
||||
const ignoredStyleProperties = ['sprite', 'glyphs', 'terrain', 'sky', 'light', 'projection'];
|
||||
/** The overlays that were warned about those: a style at a URL is read again and again. */
|
||||
const warnedOverlays = new Set<string>();
|
||||
|
||||
/**
|
||||
* A copy of the style of an overlay whose sources and layers have ids of their own, so that they
|
||||
* cannot clash with the ones of gpx.studio or of another overlay.
|
||||
*/
|
||||
export function prefixStyle(overlayId: string, style: StyleSpecification): StyleSpecification {
|
||||
if (typeof style !== 'object' || style === null || !Array.isArray(style.layers)) {
|
||||
throw new Error(`The style of overlay ${overlayId} must have a list of layers.`);
|
||||
}
|
||||
const ignored = ignoredStyleProperties.filter((property) => Object.hasOwn(style, property));
|
||||
if (ignored.length > 0 && !warnedOverlays.has(overlayId)) {
|
||||
warnedOverlays.add(overlayId);
|
||||
console.warn(`Overlay ${overlayId} ignores these style properties: ${ignored.join(', ')}.`);
|
||||
}
|
||||
|
||||
const prefixed = (id: string) => `${overlayId}/${id}`;
|
||||
const sources = style.sources ?? {};
|
||||
const layerIds = new Set<string>();
|
||||
const layers = style.layers.map((layer) => {
|
||||
if (!layer.id || layerIds.has(layer.id)) {
|
||||
throw new Error(`Overlay ${overlayId} has a missing or repeated layer id.`);
|
||||
}
|
||||
layerIds.add(layer.id);
|
||||
if ('source' in layer) {
|
||||
if (!Object.hasOwn(sources, layer.source)) {
|
||||
throw new Error(
|
||||
`Layer ${layer.id} of overlay ${overlayId} uses unknown source ${layer.source}.`
|
||||
);
|
||||
}
|
||||
return { ...layer, id: prefixed(layer.id), source: prefixed(layer.source) };
|
||||
}
|
||||
return { ...layer, id: prefixed(layer.id) };
|
||||
}) as LayerSpecification[];
|
||||
|
||||
return {
|
||||
...style,
|
||||
sources: Object.fromEntries(
|
||||
Object.entries(sources).map(([id, source]) => [prefixed(id), source])
|
||||
),
|
||||
layers,
|
||||
};
|
||||
}
|
||||
|
||||
/** The paint properties that make a layer transparent, by type of layer. */
|
||||
const opacityProperties: Partial<Record<LayerSpecification['type'], string[]>> = {
|
||||
background: ['background-opacity'],
|
||||
circle: ['circle-opacity', 'circle-stroke-opacity'],
|
||||
'color-relief': ['color-relief-opacity'],
|
||||
fill: ['fill-opacity'],
|
||||
'fill-extrusion': ['fill-extrusion-opacity'],
|
||||
heatmap: ['heatmap-opacity'],
|
||||
line: ['line-opacity'],
|
||||
raster: ['raster-opacity'],
|
||||
symbol: ['icon-opacity', 'text-opacity'],
|
||||
};
|
||||
|
||||
/**
|
||||
* The paint properties that give a layer an opacity. The opacity of an overlay applies on top of
|
||||
* those of its layers, so that they stay different from one another. A value that is computed
|
||||
* (an expression) cannot always be scaled: the opacity replaces it, unless it is left at 1.
|
||||
*/
|
||||
export function getOpacityPaint(
|
||||
layer: LayerSpecification,
|
||||
opacity: number
|
||||
): Record<string, unknown> {
|
||||
if (layer.type === 'hillshade') {
|
||||
return { 'hillshade-exaggeration': opacity / 2 };
|
||||
}
|
||||
const paint = (layer.paint ?? {}) as Record<string, unknown>;
|
||||
return Object.fromEntries(
|
||||
(opacityProperties[layer.type] ?? []).map((property) => {
|
||||
const value = paint[property];
|
||||
if (typeof value === 'number') {
|
||||
return [property, value * opacity];
|
||||
}
|
||||
return [property, value !== undefined && opacity === 1 ? value : opacity];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export function anySelectedLayer(node: LayerTreeType) {
|
||||
return (
|
||||
|
||||
Reference in new issue
Block a user