maplibre-gl-layer-control 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +99 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +99 -44
- package/dist/index.mjs.map +1 -1
- package/dist/types/index.d.ts +9 -5
- package/package.json +2 -5
package/dist/index.cjs
CHANGED
|
@@ -156,12 +156,23 @@ function getOpacityProperty(layerType) {
|
|
|
156
156
|
return "raster-opacity";
|
|
157
157
|
case "background":
|
|
158
158
|
return "background-opacity";
|
|
159
|
+
case "heatmap":
|
|
160
|
+
return "heatmap-opacity";
|
|
161
|
+
case "fill-extrusion":
|
|
162
|
+
return "fill-extrusion-opacity";
|
|
163
|
+
case "hillshade":
|
|
164
|
+
return "hillshade-exaggeration";
|
|
165
|
+
case "color-relief":
|
|
166
|
+
return null;
|
|
159
167
|
default:
|
|
160
168
|
return `${layerType}-opacity`;
|
|
161
169
|
}
|
|
162
170
|
}
|
|
163
171
|
function getLayerOpacity(map, layerId, layerType) {
|
|
164
172
|
const opacityProp = getOpacityProperty(layerType);
|
|
173
|
+
if (opacityProp === null) {
|
|
174
|
+
return 1;
|
|
175
|
+
}
|
|
165
176
|
if (Array.isArray(opacityProp)) {
|
|
166
177
|
const opacity2 = map.getPaintProperty(layerId, opacityProp[0]);
|
|
167
178
|
return opacity2 !== void 0 && opacity2 !== null ? opacity2 : 1;
|
|
@@ -171,6 +182,9 @@ function getLayerOpacity(map, layerId, layerType) {
|
|
|
171
182
|
}
|
|
172
183
|
function setLayerOpacity(map, layerId, layerType, opacity) {
|
|
173
184
|
const opacityProp = getOpacityProperty(layerType);
|
|
185
|
+
if (opacityProp === null) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
174
188
|
if (Array.isArray(opacityProp)) {
|
|
175
189
|
opacityProp.forEach((prop) => {
|
|
176
190
|
map.setPaintProperty(layerId, prop, opacity);
|
|
@@ -180,7 +194,16 @@ function setLayerOpacity(map, layerId, layerType, opacity) {
|
|
|
180
194
|
}
|
|
181
195
|
}
|
|
182
196
|
function isStyleableLayerType(layerType) {
|
|
183
|
-
return [
|
|
197
|
+
return [
|
|
198
|
+
"fill",
|
|
199
|
+
"line",
|
|
200
|
+
"circle",
|
|
201
|
+
"symbol",
|
|
202
|
+
"raster",
|
|
203
|
+
"heatmap",
|
|
204
|
+
"fill-extrusion",
|
|
205
|
+
"hillshade"
|
|
206
|
+
].includes(layerType);
|
|
184
207
|
}
|
|
185
208
|
function getLayerType(map, layerId) {
|
|
186
209
|
try {
|
|
@@ -703,9 +726,9 @@ class LayerControl {
|
|
|
703
726
|
}
|
|
704
727
|
const allLayerIds = style.layers.map((layer) => layer.id);
|
|
705
728
|
if (this.targetLayers.length === 0) {
|
|
706
|
-
const originalSourceIds = this.getOriginalStyleSourceIds();
|
|
707
729
|
const userAddedLayers = [];
|
|
708
730
|
const backgroundLayerIds = [];
|
|
731
|
+
const userAddedSourceIds = this.detectUserAddedSources();
|
|
709
732
|
allLayerIds.forEach((layerId) => {
|
|
710
733
|
const layer = this.map.getLayer(layerId);
|
|
711
734
|
if (!layer) return;
|
|
@@ -714,10 +737,10 @@ class LayerControl {
|
|
|
714
737
|
return;
|
|
715
738
|
}
|
|
716
739
|
const sourceId = layer.source;
|
|
717
|
-
if (
|
|
718
|
-
backgroundLayerIds.push(layerId);
|
|
719
|
-
} else {
|
|
740
|
+
if (sourceId && userAddedSourceIds.has(sourceId)) {
|
|
720
741
|
userAddedLayers.push(layerId);
|
|
742
|
+
} else {
|
|
743
|
+
backgroundLayerIds.push(layerId);
|
|
721
744
|
}
|
|
722
745
|
});
|
|
723
746
|
if (backgroundLayerIds.length > 0) {
|
|
@@ -792,58 +815,90 @@ class LayerControl {
|
|
|
792
815
|
this.targetLayers = Object.keys(this.state.layerStates);
|
|
793
816
|
}
|
|
794
817
|
/**
|
|
795
|
-
*
|
|
796
|
-
*
|
|
818
|
+
* Detect which sources are user-added (not from the basemap style)
|
|
819
|
+
* User-added sources are identified by:
|
|
820
|
+
* - GeoJSON sources with inline data objects (not URL strings)
|
|
821
|
+
* - Image, video, canvas sources (always user-added)
|
|
822
|
+
* - Raster, raster-dem, vector sources from non-basemap tile providers
|
|
797
823
|
*/
|
|
798
|
-
|
|
799
|
-
const
|
|
824
|
+
detectUserAddedSources() {
|
|
825
|
+
const userAddedSources = /* @__PURE__ */ new Set();
|
|
800
826
|
const style = this.map.getStyle();
|
|
801
|
-
if (!style || !style.sources) return
|
|
827
|
+
if (!style || !style.sources) return userAddedSources;
|
|
828
|
+
const basemapDomains = /* @__PURE__ */ new Set();
|
|
829
|
+
const knownBasemapProviders = [
|
|
830
|
+
"demotiles.maplibre.org",
|
|
831
|
+
"api.maptiler.com",
|
|
832
|
+
"tiles.stadiamaps.com",
|
|
833
|
+
"api.mapbox.com",
|
|
834
|
+
"basemaps.cartocdn.com",
|
|
835
|
+
"tiles.mapbox.com",
|
|
836
|
+
"a.basemaps.cartocdn.com",
|
|
837
|
+
"b.basemaps.cartocdn.com",
|
|
838
|
+
"c.basemaps.cartocdn.com",
|
|
839
|
+
"d.basemaps.cartocdn.com",
|
|
840
|
+
"tiles.arcgis.com",
|
|
841
|
+
"server.arcgisonline.com",
|
|
842
|
+
"services.arcgisonline.com"
|
|
843
|
+
];
|
|
802
844
|
const spriteUrl = style.sprite;
|
|
803
|
-
|
|
804
|
-
let styleBaseDomain = "";
|
|
805
|
-
if (spriteUrl) {
|
|
845
|
+
if (spriteUrl && typeof spriteUrl === "string") {
|
|
806
846
|
try {
|
|
807
|
-
const url = new URL(
|
|
808
|
-
|
|
847
|
+
const url = new URL(spriteUrl);
|
|
848
|
+
basemapDomains.add(url.hostname);
|
|
809
849
|
} catch {
|
|
810
850
|
}
|
|
811
|
-
}
|
|
851
|
+
}
|
|
852
|
+
if (style.glyphs) {
|
|
812
853
|
try {
|
|
813
|
-
const url = new URL(
|
|
814
|
-
|
|
854
|
+
const url = new URL(style.glyphs.replace("{fontstack}", "x").replace("{range}", "x"));
|
|
855
|
+
basemapDomains.add(url.hostname);
|
|
815
856
|
} catch {
|
|
816
857
|
}
|
|
817
858
|
}
|
|
818
|
-
Object.entries(style.sources)
|
|
859
|
+
for (const [sourceId, source] of Object.entries(style.sources)) {
|
|
819
860
|
const src = source;
|
|
820
|
-
|
|
821
|
-
if (
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
return;
|
|
861
|
+
const sourceType = src.type;
|
|
862
|
+
if (sourceType === "image" || sourceType === "video" || sourceType === "canvas") {
|
|
863
|
+
userAddedSources.add(sourceId);
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
if (sourceType === "geojson") {
|
|
867
|
+
if (src.data && typeof src.data === "object") {
|
|
868
|
+
userAddedSources.add(sourceId);
|
|
869
|
+
} else if (src.data && typeof src.data === "string") {
|
|
870
|
+
try {
|
|
871
|
+
const url = new URL(src.data);
|
|
872
|
+
const isBasemap = knownBasemapProviders.some((p) => url.hostname.includes(p)) || basemapDomains.has(url.hostname);
|
|
873
|
+
if (!isBasemap) {
|
|
874
|
+
userAddedSources.add(sourceId);
|
|
875
|
+
}
|
|
876
|
+
} catch {
|
|
877
|
+
userAddedSources.add(sourceId);
|
|
838
878
|
}
|
|
839
|
-
} catch {
|
|
840
879
|
}
|
|
880
|
+
continue;
|
|
841
881
|
}
|
|
842
|
-
if (
|
|
843
|
-
|
|
882
|
+
if (sourceType === "raster" || sourceType === "raster-dem" || sourceType === "vector") {
|
|
883
|
+
const tileUrl = src.url || src.tiles && src.tiles[0] || "";
|
|
884
|
+
if (tileUrl) {
|
|
885
|
+
try {
|
|
886
|
+
const url = new URL(tileUrl.replace(/{[^}]+}/g, "0"));
|
|
887
|
+
const hostname = url.hostname;
|
|
888
|
+
const isKnownBasemap = knownBasemapProviders.some(
|
|
889
|
+
(provider) => hostname === provider || hostname.endsWith("." + provider)
|
|
890
|
+
);
|
|
891
|
+
const matchesBasemapDomain = basemapDomains.has(hostname);
|
|
892
|
+
if (!isKnownBasemap && !matchesBasemapDomain) {
|
|
893
|
+
userAddedSources.add(sourceId);
|
|
894
|
+
}
|
|
895
|
+
} catch {
|
|
896
|
+
userAddedSources.add(sourceId);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
844
899
|
}
|
|
845
|
-
}
|
|
846
|
-
return
|
|
900
|
+
}
|
|
901
|
+
return userAddedSources;
|
|
847
902
|
}
|
|
848
903
|
/**
|
|
849
904
|
* Generate a friendly display name from a layer ID
|
|
@@ -2172,9 +2227,9 @@ class LayerControl {
|
|
|
2172
2227
|
return;
|
|
2173
2228
|
}
|
|
2174
2229
|
const currentMapLayerIds = new Set(style.layers.map((layer) => layer.id));
|
|
2175
|
-
const originalSourceIds = this.getOriginalStyleSourceIds();
|
|
2176
2230
|
const isAutoDetectMode = this.targetLayers.length === 0 || this.targetLayers.length === 1 && this.targetLayers[0] === "Background" || this.targetLayers.every((id) => id === "Background" || this.state.layerStates[id]);
|
|
2177
2231
|
const newLayers = [];
|
|
2232
|
+
const userAddedSourceIds = isAutoDetectMode ? this.detectUserAddedSources() : /* @__PURE__ */ new Set();
|
|
2178
2233
|
currentMapLayerIds.forEach((layerId) => {
|
|
2179
2234
|
if (layerId !== "Background" && !this.state.layerStates[layerId]) {
|
|
2180
2235
|
const layer = this.map.getLayer(layerId);
|
|
@@ -2184,7 +2239,7 @@ class LayerControl {
|
|
|
2184
2239
|
return;
|
|
2185
2240
|
}
|
|
2186
2241
|
const sourceId = layer.source;
|
|
2187
|
-
if (!sourceId ||
|
|
2242
|
+
if (!sourceId || !userAddedSourceIds.has(sourceId)) {
|
|
2188
2243
|
return;
|
|
2189
2244
|
}
|
|
2190
2245
|
}
|