maplibre-gl-basemap-control 0.13.0 → 0.14.3
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/README.md +62 -0
- package/dist/{BasemapControl-Cdg7HMeU.js → BasemapControl-CSw9YZ4S.js} +268 -28
- package/dist/BasemapControl-CSw9YZ4S.js.map +1 -0
- package/dist/{BasemapControl-Cw1RH7hF.cjs → BasemapControl-nc1awj6S.cjs} +268 -28
- package/dist/BasemapControl-nc1awj6S.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.mjs +1 -1
- package/dist/types/lib/core/BasemapControl.d.ts +6 -0
- package/dist/types/lib/core/BasemapControl.d.ts.map +1 -1
- package/dist/types/lib/core/catalog.d.ts.map +1 -1
- package/dist/types/lib/core/types.d.ts +9 -0
- package/dist/types/lib/core/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/BasemapControl-Cdg7HMeU.js.map +0 -1
- package/dist/BasemapControl-Cw1RH7hF.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ A MapLibre GL JS control for searching and switching public basemaps. It keeps t
|
|
|
9
9
|
|
|
10
10
|
- Search-first basemap picker inspired by QuickMapServices
|
|
11
11
|
- Built-in catalog for common public basemaps, MapTiler styles, Amazon Location styles, Mapbox styles, Maptoolkit styles, Protomaps styles, and Stadia Maps basemaps
|
|
12
|
+
- Tianditu, Amap, and Tencent basemaps, served from inside mainland China
|
|
12
13
|
- Stackable traffic overlays for TomTom, HERE, Mapbox, and Google
|
|
13
14
|
- Custom basemap and provider definitions
|
|
14
15
|
- MapLibre `IControl` implementation
|
|
@@ -151,11 +152,13 @@ destructive style change, so the missing key can be entered and the basemap retr
|
|
|
151
152
|
const control = new BasemapControl({
|
|
152
153
|
defaultBasemapId: 'maptiler-streets',
|
|
153
154
|
mapTilerApiKey: 'YOUR_MAPTILER_API_KEY',
|
|
155
|
+
cartoApiKey: 'YOUR_CARTO_API_KEY',
|
|
154
156
|
amazonApiKey: 'YOUR_AMAZON_LOCATION_API_KEY',
|
|
155
157
|
awsRegion: 'us-east-1',
|
|
156
158
|
mapboxAccessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
|
|
157
159
|
protomapsApiKey: 'YOUR_PROTOMAPS_API_KEY',
|
|
158
160
|
stadiaApiKey: 'YOUR_STADIA_MAPS_API_KEY',
|
|
161
|
+
tiandituApiKey: 'YOUR_TIANDITU_API_KEY',
|
|
159
162
|
});
|
|
160
163
|
```
|
|
161
164
|
|
|
@@ -203,6 +206,61 @@ transparent overlays, so pair them with `allowMultiple: true` to stack them over
|
|
|
203
206
|
> this control always sends `api_key`, so a key is required here. Set `stadiaApiKey` or enter it in
|
|
204
207
|
> the panel's API keys view.
|
|
205
208
|
|
|
209
|
+
### China Basemaps
|
|
210
|
+
|
|
211
|
+
Most of the catalog is hosted outside mainland China with no presence inside it, so for users there
|
|
212
|
+
OpenStreetMap, OpenFreeMap, Protomaps, Carto, Google, and Mapbox range from slow to unreachable. The
|
|
213
|
+
catalog ships three providers that are served from inside China:
|
|
214
|
+
|
|
215
|
+
| Basemap id | Provider | Datum | Credential |
|
|
216
|
+
|------------|----------|-------|------------|
|
|
217
|
+
| `tianditu-vector`, `tianditu-imagery`, `tianditu-terrain` and their `-labels` overlays | Tianditu (天地图) | CGCS2000 | `tiandituApiKey` |
|
|
218
|
+
| `amap-street`, `amap-satellite`, `amap-labels` | Amap (高德地图) | GCJ-02 | none |
|
|
219
|
+
| `tencent-street`, `tencent-dark` | Tencent Maps (腾讯地图) | GCJ-02 | none |
|
|
220
|
+
|
|
221
|
+
They are searchable by their Chinese names as well as their English ones, so typing `天地图`, `高德`,
|
|
222
|
+
or `腾讯` into the panel's filter finds them.
|
|
223
|
+
|
|
224
|
+
> **The datum matters more than the speed.** Chinese law requires public map services to publish in
|
|
225
|
+
> GCJ-02, an offset datum that displaces features by roughly 100-700 m from WGS84. Neither this
|
|
226
|
+
> control nor MapLibre applies the shift, so WGS84 data laid over Amap or Tencent will visibly
|
|
227
|
+
> misalign. **Tianditu is the exception**: it publishes in CGCS2000, which is close enough to WGS84
|
|
228
|
+
> for web mapping, so ordinary data overlays correctly. Prefer Tianditu whenever you are also
|
|
229
|
+
> rendering your own data; reach for Amap or Tencent when the basemap is the whole point, or convert
|
|
230
|
+
> your data to GCJ-02 first.
|
|
231
|
+
|
|
232
|
+
Tianditu is China's official National Platform for Common Geospatial Information Services. Register
|
|
233
|
+
a free key at [console.tianditu.gov.cn](https://console.tianditu.gov.cn/api/key), then set
|
|
234
|
+
`tiandituApiKey` or enter it in the panel's API keys view. Its layers ride the `DataServer`
|
|
235
|
+
endpoint, the xyz-shaped form of its WMTS services:
|
|
236
|
+
|
|
237
|
+
```text
|
|
238
|
+
https://t{0-7}.tianditu.gov.cn/DataServer?T={layer}&x={x}&y={y}&l={z}&tk={api-key}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Tianditu splits every basemap from its labels, so the `-labels` overlays are separate transparent
|
|
242
|
+
layers. Pair them with `allowMultiple: true` to stack them over their base:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const control = new BasemapControl({
|
|
246
|
+
allowMultiple: true,
|
|
247
|
+
tiandituApiKey: 'YOUR_TIANDITU_API_KEY',
|
|
248
|
+
defaultBasemapId: 'tianditu-vector',
|
|
249
|
+
});
|
|
250
|
+
await control.addBasemap('tianditu-vector-labels');
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
The same applies to `amap-labels`, a transparent roads-and-labels overlay meant to sit on top of
|
|
254
|
+
`amap-satellite`. Note that `tianditu-terrain` and `tianditu-terrain-labels` are only published to
|
|
255
|
+
zoom 14, where the vector and imagery layers reach 18, and Amap serves a "no imagery" placeholder
|
|
256
|
+
rather than a 404 past zoom 18, so `amap-satellite` caps there and lets MapLibre overzoom.
|
|
257
|
+
|
|
258
|
+
> **Terms of use.** Tianditu's key-based access is the sanctioned route and the one to build on. The
|
|
259
|
+
> Amap and Tencent tile endpoints are widely used but are not documented public APIs, and carry the
|
|
260
|
+
> same caveat as the keyless Google tiles below: fine for development and demos, but the operators
|
|
261
|
+
> may rate-limit, change, or block them at any time. Obtain a commercial key from the provider before
|
|
262
|
+
> shipping either one.
|
|
263
|
+
|
|
206
264
|
### Traffic Overlays
|
|
207
265
|
|
|
208
266
|
The catalog ships real-time traffic overlays in the `Traffic` category. They are
|
|
@@ -297,11 +355,13 @@ API key and load straight from `https://styles.maptoolkit.org/{styleId}.json`:
|
|
|
297
355
|
| `panelWidth` | `number` | `340` | Floating panel width in pixels |
|
|
298
356
|
| `className` | `string` | `''` | Extra class for the control button container |
|
|
299
357
|
| `mapTilerApiKey` | `string` | `undefined` | Initial MapTiler API key for built-in MapTiler styles |
|
|
358
|
+
| `cartoApiKey` | `string` | `undefined` | Initial CARTO API key for built-in CARTO raster basemaps |
|
|
300
359
|
| `amazonApiKey` | `string` | `undefined` | Initial Amazon Location API key for built-in Amazon styles |
|
|
301
360
|
| `awsRegion` | `string` | `'us-east-1'` | AWS region for built-in Amazon Location styles |
|
|
302
361
|
| `mapboxAccessToken` | `string` | `undefined` | Initial Mapbox access token for built-in Mapbox styles and the Mapbox Traffic overlay |
|
|
303
362
|
| `protomapsApiKey` | `string` | `undefined` | Initial Protomaps API key for built-in Protomaps styles |
|
|
304
363
|
| `stadiaApiKey` | `string` | `undefined` | Initial Stadia Maps API key for built-in Stadia and Stadia x Stamen basemaps |
|
|
364
|
+
| `tiandituApiKey` | `string` | `undefined` | Initial Tianditu API key (`tk`) for the built-in Tianditu basemaps |
|
|
305
365
|
| `tomtomApiKey` | `string` | `undefined` | Initial TomTom API key for the TomTom Traffic overlays |
|
|
306
366
|
| `hereApiKey` | `string` | `undefined` | Initial HERE API key for the HERE Traffic overlay |
|
|
307
367
|
| `googleMapsApiKey` | `string` | `undefined` | Initial Google Maps API key (Map Tiles API) for the Google Traffic overlay and the base Google Maps/Satellite/Terrain/Hybrid basemaps (which fall back to keyless tiles without a key) |
|
|
@@ -366,10 +426,12 @@ const control = new BasemapControl({
|
|
|
366
426
|
- `toggleBasemap(id)` - Add the raster basemap if inactive, otherwise remove it
|
|
367
427
|
- `isBasemapActive(id)` - Whether the basemap is currently active
|
|
368
428
|
- `setMapTilerApiKey(apiKey)` - Set or update the MapTiler API key used by MapTiler styles
|
|
429
|
+
- `setCartoApiKey(apiKey)` - Set or update the CARTO API key used by CARTO raster basemaps
|
|
369
430
|
- `setAmazonCredentials(apiKey, awsRegion)` - Set or update Amazon Location credentials
|
|
370
431
|
- `setMapboxAccessToken(accessToken)` - Set or update the Mapbox access token
|
|
371
432
|
- `setProtomapsApiKey(apiKey)` - Set or update the Protomaps API key used by Protomaps styles
|
|
372
433
|
- `setStadiaApiKey(apiKey)` - Set or update the Stadia Maps API key used by Stadia basemaps
|
|
434
|
+
- `setTiandituApiKey(apiKey)` - Set or update the Tianditu API key used by Tianditu basemaps
|
|
373
435
|
- `setTomTomApiKey(apiKey)` - Set or update the TomTom API key used by TomTom Traffic overlays
|
|
374
436
|
- `setHereApiKey(apiKey)` - Set or update the HERE API key used by the HERE Traffic overlay
|
|
375
437
|
- `setGoogleMapsApiKey(apiKey)` - Set or update the Google Maps API key used by the Google Traffic overlay and the base Google basemaps
|
|
@@ -2,6 +2,7 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
const DEFAULT_BASEMAP_PROVIDERS = [
|
|
5
|
+
{ id: "amap", name: "Amap", category: "Regional" },
|
|
5
6
|
{ id: "amazon", name: "Amazon Location", category: "General" },
|
|
6
7
|
{ id: "carto", name: "Carto", category: "General" },
|
|
7
8
|
{ id: "cyclosm", name: "CyclOSM", category: "Cycling" },
|
|
@@ -21,6 +22,8 @@ const DEFAULT_BASEMAP_PROVIDERS = [
|
|
|
21
22
|
{ id: "protomaps", name: "Protomaps", category: "Vector Styles" },
|
|
22
23
|
{ id: "stadia", name: "Stadia Maps", category: "General" },
|
|
23
24
|
{ id: "swisstopo", name: "Swiss Federal Geoportal", category: "Regional" },
|
|
25
|
+
{ id: "tencent", name: "Tencent Maps", category: "Regional" },
|
|
26
|
+
{ id: "tianditu", name: "Tianditu", category: "Regional" },
|
|
24
27
|
{ id: "tomtom", name: "TomTom", category: "Traffic" },
|
|
25
28
|
{ id: "topplusopen", name: "TopPlusOpen", category: "Regional" },
|
|
26
29
|
{ id: "usgs", name: "USGS", category: "United States" },
|
|
@@ -35,6 +38,7 @@ function rasterBasemap({
|
|
|
35
38
|
attribution,
|
|
36
39
|
tiles,
|
|
37
40
|
maxzoom = 19,
|
|
41
|
+
scheme,
|
|
38
42
|
tags = []
|
|
39
43
|
}) {
|
|
40
44
|
return {
|
|
@@ -49,7 +53,8 @@ function rasterBasemap({
|
|
|
49
53
|
type: "raster",
|
|
50
54
|
tiles,
|
|
51
55
|
tileSize: 256,
|
|
52
|
-
maxzoom
|
|
56
|
+
maxzoom,
|
|
57
|
+
scheme
|
|
53
58
|
},
|
|
54
59
|
tags
|
|
55
60
|
};
|
|
@@ -202,6 +207,35 @@ function stadiaRasterBasemap({
|
|
|
202
207
|
tags: ["stadia", ...stamen ? ["stamen"] : [], ...tags]
|
|
203
208
|
});
|
|
204
209
|
}
|
|
210
|
+
const TIANDITU_HOSTS = [0, 1, 2, 3, 4, 5, 6, 7];
|
|
211
|
+
function tiandituRasterBasemap({
|
|
212
|
+
id,
|
|
213
|
+
name,
|
|
214
|
+
layer,
|
|
215
|
+
category,
|
|
216
|
+
description,
|
|
217
|
+
maxzoom = 18,
|
|
218
|
+
tags = []
|
|
219
|
+
}) {
|
|
220
|
+
return rasterBasemap({
|
|
221
|
+
id,
|
|
222
|
+
name,
|
|
223
|
+
provider: "tianditu",
|
|
224
|
+
category,
|
|
225
|
+
description,
|
|
226
|
+
attribution: TIANDITU_ATTRIBUTION,
|
|
227
|
+
tiles: TIANDITU_HOSTS.map(
|
|
228
|
+
(host) => `https://t${host}.tianditu.gov.cn/DataServer?T=${layer}&x={x}&y={y}&l={z}&tk={api-key}`
|
|
229
|
+
),
|
|
230
|
+
maxzoom,
|
|
231
|
+
tags: ["tianditu", "china", "天地图", ...tags]
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function amapTiles(host, query) {
|
|
235
|
+
return [1, 2, 3, 4].map(
|
|
236
|
+
(index) => `https://${host}0${index}.is.autonavi.com/appmaptile?${query}&x={x}&y={y}&z={z}`
|
|
237
|
+
);
|
|
238
|
+
}
|
|
205
239
|
function sortProviders(providers) {
|
|
206
240
|
return [...providers].sort((a, b) => a.name.localeCompare(b.name));
|
|
207
241
|
}
|
|
@@ -216,6 +250,10 @@ const STADIA_ATTRIBUTION = '© <a href="https://stadiamaps.com/" target="_bl
|
|
|
216
250
|
const STADIA_STAMEN_ATTRIBUTION = '© <a href="https://stadiamaps.com/" target="_blank" rel="noopener">Stadia Maps</a> © <a href="https://stamen.com/" target="_blank" rel="noopener">Stamen Design</a> © <a href="https://openmaptiles.org/" target="_blank" rel="noopener">OpenMapTiles</a> © OpenStreetMap contributors';
|
|
217
251
|
const PROTOMAPS_ATTRIBUTION = '<a href="https://protomaps.com" target="_blank" rel="noopener">Protomaps</a> © <a href="https://openstreetmap.org" target="_blank" rel="noopener">OpenStreetMap</a>';
|
|
218
252
|
const OPENFREEMAP_ATTRIBUTION = "OpenFreeMap © OpenMapTiles Data from OpenStreetMap";
|
|
253
|
+
const TIANDITU_ATTRIBUTION = '© <a href="https://www.tianditu.gov.cn" target="_blank" rel="noopener">天地图 Tianditu</a> (National Platform for Common Geospatial Information Services)';
|
|
254
|
+
const AMAP_ATTRIBUTION = '© <a href="https://www.amap.com" target="_blank" rel="noopener">高德地图 Amap</a>';
|
|
255
|
+
const TENCENT_ATTRIBUTION = '© <a href="https://map.qq.com" target="_blank" rel="noopener">腾讯地图 Tencent Maps</a>';
|
|
256
|
+
const GCJ02_WARNING = "Tiles are in the GCJ-02 datum, so WGS84 data overlaid on them appears offset by roughly 100-700 m.";
|
|
219
257
|
const TOMTOM_ATTRIBUTION = "© TomTom";
|
|
220
258
|
const HERE_ATTRIBUTION = "© HERE";
|
|
221
259
|
const GOOGLE_ATTRIBUTION = "© Google";
|
|
@@ -623,10 +661,10 @@ const DEFAULT_BASEMAPS = [
|
|
|
623
661
|
description: "Light basemap for data overlays.",
|
|
624
662
|
attribution: CARTO_ATTRIBUTION,
|
|
625
663
|
tiles: [
|
|
626
|
-
"https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
|
|
627
|
-
"https://b.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
|
|
628
|
-
"https://c.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
|
|
629
|
-
"https://d.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png"
|
|
664
|
+
"https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png?key={api-key}",
|
|
665
|
+
"https://b.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png?key={api-key}",
|
|
666
|
+
"https://c.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png?key={api-key}",
|
|
667
|
+
"https://d.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png?key={api-key}"
|
|
630
668
|
],
|
|
631
669
|
maxzoom: 20,
|
|
632
670
|
tags: ["carto", "light", "positron"]
|
|
@@ -638,7 +676,7 @@ const DEFAULT_BASEMAPS = [
|
|
|
638
676
|
category: "Light",
|
|
639
677
|
description: "Light basemap without labels.",
|
|
640
678
|
attribution: CARTO_ATTRIBUTION,
|
|
641
|
-
tiles: ["https://a.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png"],
|
|
679
|
+
tiles: ["https://a.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png?key={api-key}"],
|
|
642
680
|
maxzoom: 20,
|
|
643
681
|
tags: ["carto", "light", "no labels"]
|
|
644
682
|
}),
|
|
@@ -650,7 +688,7 @@ const DEFAULT_BASEMAPS = [
|
|
|
650
688
|
description: "Carto Positron labels layer.",
|
|
651
689
|
attribution: CARTO_ATTRIBUTION,
|
|
652
690
|
tiles: [
|
|
653
|
-
"https://a.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png"
|
|
691
|
+
"https://a.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png?key={api-key}"
|
|
654
692
|
],
|
|
655
693
|
maxzoom: 20,
|
|
656
694
|
tags: ["carto", "labels"]
|
|
@@ -663,10 +701,10 @@ const DEFAULT_BASEMAPS = [
|
|
|
663
701
|
description: "Dark basemap for high-contrast overlays.",
|
|
664
702
|
attribution: CARTO_ATTRIBUTION,
|
|
665
703
|
tiles: [
|
|
666
|
-
"https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
|
|
667
|
-
"https://b.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
|
|
668
|
-
"https://c.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
|
|
669
|
-
"https://d.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png"
|
|
704
|
+
"https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png?key={api-key}",
|
|
705
|
+
"https://b.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png?key={api-key}",
|
|
706
|
+
"https://c.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png?key={api-key}",
|
|
707
|
+
"https://d.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png?key={api-key}"
|
|
670
708
|
],
|
|
671
709
|
maxzoom: 20,
|
|
672
710
|
tags: ["carto", "dark", "matter"]
|
|
@@ -678,7 +716,7 @@ const DEFAULT_BASEMAPS = [
|
|
|
678
716
|
category: "Dark",
|
|
679
717
|
description: "Dark basemap without labels.",
|
|
680
718
|
attribution: CARTO_ATTRIBUTION,
|
|
681
|
-
tiles: ["https://a.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png"],
|
|
719
|
+
tiles: ["https://a.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png?key={api-key}"],
|
|
682
720
|
maxzoom: 20,
|
|
683
721
|
tags: ["carto", "dark", "no labels"]
|
|
684
722
|
}),
|
|
@@ -689,7 +727,7 @@ const DEFAULT_BASEMAPS = [
|
|
|
689
727
|
category: "Labels",
|
|
690
728
|
description: "Carto Dark Matter labels layer.",
|
|
691
729
|
attribution: CARTO_ATTRIBUTION,
|
|
692
|
-
tiles: ["https://a.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}.png"],
|
|
730
|
+
tiles: ["https://a.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}.png?key={api-key}"],
|
|
693
731
|
maxzoom: 20,
|
|
694
732
|
tags: ["carto", "dark", "labels"]
|
|
695
733
|
}),
|
|
@@ -701,10 +739,10 @@ const DEFAULT_BASEMAPS = [
|
|
|
701
739
|
description: "Detailed street basemap with subtle styling.",
|
|
702
740
|
attribution: CARTO_ATTRIBUTION,
|
|
703
741
|
tiles: [
|
|
704
|
-
"https://a.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png",
|
|
705
|
-
"https://b.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png",
|
|
706
|
-
"https://c.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png",
|
|
707
|
-
"https://d.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png"
|
|
742
|
+
"https://a.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png?key={api-key}",
|
|
743
|
+
"https://b.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png?key={api-key}",
|
|
744
|
+
"https://c.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png?key={api-key}",
|
|
745
|
+
"https://d.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png?key={api-key}"
|
|
708
746
|
],
|
|
709
747
|
maxzoom: 20,
|
|
710
748
|
tags: ["carto", "street", "voyager"]
|
|
@@ -717,7 +755,7 @@ const DEFAULT_BASEMAPS = [
|
|
|
717
755
|
description: "Carto Voyager without labels.",
|
|
718
756
|
attribution: CARTO_ATTRIBUTION,
|
|
719
757
|
tiles: [
|
|
720
|
-
"https://a.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png"
|
|
758
|
+
"https://a.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png?key={api-key}"
|
|
721
759
|
],
|
|
722
760
|
maxzoom: 20,
|
|
723
761
|
tags: ["carto", "voyager", "no labels"]
|
|
@@ -730,7 +768,7 @@ const DEFAULT_BASEMAPS = [
|
|
|
730
768
|
description: "Carto Voyager labels layer.",
|
|
731
769
|
attribution: CARTO_ATTRIBUTION,
|
|
732
770
|
tiles: [
|
|
733
|
-
"https://a.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}.png"
|
|
771
|
+
"https://a.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}.png?key={api-key}"
|
|
734
772
|
],
|
|
735
773
|
maxzoom: 20,
|
|
736
774
|
tags: ["carto", "voyager", "labels"]
|
|
@@ -743,7 +781,7 @@ const DEFAULT_BASEMAPS = [
|
|
|
743
781
|
description: "Carto Voyager labels-under variant.",
|
|
744
782
|
attribution: CARTO_ATTRIBUTION,
|
|
745
783
|
tiles: [
|
|
746
|
-
"https://a.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png"
|
|
784
|
+
"https://a.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png?key={api-key}"
|
|
747
785
|
],
|
|
748
786
|
maxzoom: 20,
|
|
749
787
|
tags: ["carto", "voyager", "labels"]
|
|
@@ -1216,6 +1254,130 @@ const DEFAULT_BASEMAPS = [
|
|
|
1216
1254
|
maxzoom: 18,
|
|
1217
1255
|
tags: ["switzerland", "imagery"]
|
|
1218
1256
|
}),
|
|
1257
|
+
tiandituRasterBasemap({
|
|
1258
|
+
id: "tianditu-vector",
|
|
1259
|
+
name: "Tianditu Vector",
|
|
1260
|
+
layer: "vec_w",
|
|
1261
|
+
category: "Regional",
|
|
1262
|
+
description: "China's official street map, reachable from mainland China. Published in CGCS2000, so WGS84 data overlays without a datum shift. Pair with Tianditu Vector Labels. Requires a free Tianditu API key.",
|
|
1263
|
+
tags: ["vector", "street", "vec"]
|
|
1264
|
+
}),
|
|
1265
|
+
tiandituRasterBasemap({
|
|
1266
|
+
id: "tianditu-vector-labels",
|
|
1267
|
+
name: "Tianditu Vector Labels",
|
|
1268
|
+
layer: "cva_w",
|
|
1269
|
+
category: "Labels",
|
|
1270
|
+
description: "Place name and road label overlay for Tianditu Vector. Requires a free Tianditu API key.",
|
|
1271
|
+
tags: ["labels", "annotation", "overlay", "cva"]
|
|
1272
|
+
}),
|
|
1273
|
+
tiandituRasterBasemap({
|
|
1274
|
+
id: "tianditu-imagery",
|
|
1275
|
+
name: "Tianditu Imagery",
|
|
1276
|
+
layer: "img_w",
|
|
1277
|
+
category: "Imagery",
|
|
1278
|
+
description: "China's official satellite imagery, reachable from mainland China. Pair with Tianditu Imagery Labels. Requires a free Tianditu API key.",
|
|
1279
|
+
tags: ["imagery", "satellite", "img"]
|
|
1280
|
+
}),
|
|
1281
|
+
tiandituRasterBasemap({
|
|
1282
|
+
id: "tianditu-imagery-labels",
|
|
1283
|
+
name: "Tianditu Imagery Labels",
|
|
1284
|
+
layer: "cia_w",
|
|
1285
|
+
category: "Labels",
|
|
1286
|
+
description: "Place name and road label overlay for Tianditu Imagery. Requires a free Tianditu API key.",
|
|
1287
|
+
tags: ["labels", "annotation", "overlay", "cia"]
|
|
1288
|
+
}),
|
|
1289
|
+
tiandituRasterBasemap({
|
|
1290
|
+
id: "tianditu-terrain",
|
|
1291
|
+
name: "Tianditu Terrain",
|
|
1292
|
+
layer: "ter_w",
|
|
1293
|
+
category: "Terrain",
|
|
1294
|
+
description: "China's official shaded relief terrain map. Pair with Tianditu Terrain Labels. Requires a free Tianditu API key.",
|
|
1295
|
+
// The terrain pair is only published to zoom 14, unlike the vector and
|
|
1296
|
+
// imagery layers, which reach 18.
|
|
1297
|
+
maxzoom: 14,
|
|
1298
|
+
tags: ["terrain", "relief", "hillshade", "ter"]
|
|
1299
|
+
}),
|
|
1300
|
+
tiandituRasterBasemap({
|
|
1301
|
+
id: "tianditu-terrain-labels",
|
|
1302
|
+
name: "Tianditu Terrain Labels",
|
|
1303
|
+
layer: "cta_w",
|
|
1304
|
+
category: "Labels",
|
|
1305
|
+
description: "Place name label overlay for Tianditu Terrain. Requires a free Tianditu API key.",
|
|
1306
|
+
maxzoom: 14,
|
|
1307
|
+
tags: ["labels", "annotation", "overlay", "cta"]
|
|
1308
|
+
}),
|
|
1309
|
+
rasterBasemap({
|
|
1310
|
+
id: "amap-street",
|
|
1311
|
+
name: "Amap Street",
|
|
1312
|
+
provider: "amap",
|
|
1313
|
+
category: "Regional",
|
|
1314
|
+
description: `Amap street map of China, reachable from mainland China. ${GCJ02_WARNING}`,
|
|
1315
|
+
attribution: AMAP_ATTRIBUTION,
|
|
1316
|
+
tiles: amapTiles("wprd", "lang=zh_cn&size=1&scl=1&style=7"),
|
|
1317
|
+
tags: ["amap", "gaode", "高德", "china", "street", "gcj02"]
|
|
1318
|
+
}),
|
|
1319
|
+
rasterBasemap({
|
|
1320
|
+
id: "amap-satellite",
|
|
1321
|
+
name: "Amap Satellite",
|
|
1322
|
+
provider: "amap",
|
|
1323
|
+
category: "Imagery",
|
|
1324
|
+
description: `Amap satellite imagery, reachable from mainland China. Pair with Amap Labels. ${GCJ02_WARNING}`,
|
|
1325
|
+
attribution: AMAP_ATTRIBUTION,
|
|
1326
|
+
tiles: amapTiles("webst", "style=6"),
|
|
1327
|
+
// Past zoom 18 Amap returns a "no imagery" placeholder tile rather than a
|
|
1328
|
+
// 404, so cap here and let MapLibre overzoom instead.
|
|
1329
|
+
maxzoom: 18,
|
|
1330
|
+
tags: ["amap", "gaode", "高德", "china", "satellite", "imagery", "gcj02"]
|
|
1331
|
+
}),
|
|
1332
|
+
rasterBasemap({
|
|
1333
|
+
id: "amap-labels",
|
|
1334
|
+
name: "Amap Labels",
|
|
1335
|
+
provider: "amap",
|
|
1336
|
+
category: "Labels",
|
|
1337
|
+
description: `Transparent Amap road and label overlay, for use over Amap Satellite. ${GCJ02_WARNING}`,
|
|
1338
|
+
attribution: AMAP_ATTRIBUTION,
|
|
1339
|
+
tiles: amapTiles("webst", "style=8"),
|
|
1340
|
+
tags: [
|
|
1341
|
+
"amap",
|
|
1342
|
+
"gaode",
|
|
1343
|
+
"高德",
|
|
1344
|
+
"china",
|
|
1345
|
+
"labels",
|
|
1346
|
+
"roads",
|
|
1347
|
+
"overlay",
|
|
1348
|
+
"gcj02"
|
|
1349
|
+
]
|
|
1350
|
+
}),
|
|
1351
|
+
rasterBasemap({
|
|
1352
|
+
id: "tencent-street",
|
|
1353
|
+
name: "Tencent Street",
|
|
1354
|
+
provider: "tencent",
|
|
1355
|
+
category: "Regional",
|
|
1356
|
+
description: `Tencent street map of China, reachable from mainland China. ${GCJ02_WARNING}`,
|
|
1357
|
+
attribution: TENCENT_ATTRIBUTION,
|
|
1358
|
+
// Tencent numbers tile rows from the bottom, so the source is TMS rather
|
|
1359
|
+
// than xyz; MapLibre flips `{y}` when `scheme` says so.
|
|
1360
|
+
tiles: [0, 1, 2, 3].map(
|
|
1361
|
+
(host) => `https://rt${host}.map.gtimg.com/tile?z={z}&x={x}&y={y}&styleid=1&scene=0`
|
|
1362
|
+
),
|
|
1363
|
+
maxzoom: 18,
|
|
1364
|
+
scheme: "tms",
|
|
1365
|
+
tags: ["tencent", "qq", "腾讯", "china", "street", "gcj02"]
|
|
1366
|
+
}),
|
|
1367
|
+
rasterBasemap({
|
|
1368
|
+
id: "tencent-dark",
|
|
1369
|
+
name: "Tencent Dark",
|
|
1370
|
+
provider: "tencent",
|
|
1371
|
+
category: "Dark",
|
|
1372
|
+
description: `Dark Tencent street map for high-contrast overlays, reachable from mainland China. ${GCJ02_WARNING}`,
|
|
1373
|
+
attribution: TENCENT_ATTRIBUTION,
|
|
1374
|
+
tiles: [0, 1, 2, 3].map(
|
|
1375
|
+
(host) => `https://rt${host}.map.gtimg.com/tile?z={z}&x={x}&y={y}&styleid=4&scene=0`
|
|
1376
|
+
),
|
|
1377
|
+
maxzoom: 18,
|
|
1378
|
+
scheme: "tms",
|
|
1379
|
+
tags: ["tencent", "qq", "腾讯", "china", "dark", "gcj02"]
|
|
1380
|
+
}),
|
|
1219
1381
|
rasterBasemap({
|
|
1220
1382
|
id: "topplusopen-color",
|
|
1221
1383
|
name: "TopPlusOpen Color",
|
|
@@ -1726,6 +1888,10 @@ const MAPTILER_API_KEY_QUERY = "?key";
|
|
|
1726
1888
|
const MAPTILER_API_KEY_EMPTY_QUERY = "?key=";
|
|
1727
1889
|
const AWS_REGION_PLACEHOLDER = "{aws-region}";
|
|
1728
1890
|
const PROVIDER_CREDENTIAL_HELP = {
|
|
1891
|
+
carto: {
|
|
1892
|
+
url: "https://carto.com/basemaps/apikey/",
|
|
1893
|
+
label: "Get a CARTO API key"
|
|
1894
|
+
},
|
|
1729
1895
|
amazon: {
|
|
1730
1896
|
url: "https://docs.aws.amazon.com/location/latest/developerguide/using-apikeys.html",
|
|
1731
1897
|
label: "Get an Amazon API key"
|
|
@@ -1746,6 +1912,10 @@ const PROVIDER_CREDENTIAL_HELP = {
|
|
|
1746
1912
|
url: "https://client.stadiamaps.com/signup/",
|
|
1747
1913
|
label: "Get a Stadia Maps API key"
|
|
1748
1914
|
},
|
|
1915
|
+
tianditu: {
|
|
1916
|
+
url: "https://console.tianditu.gov.cn/api/key",
|
|
1917
|
+
label: "Get a Tianditu API key"
|
|
1918
|
+
},
|
|
1749
1919
|
tomtom: {
|
|
1750
1920
|
url: "https://developer.tomtom.com/how-to-get-tomtom-api-key",
|
|
1751
1921
|
label: "Get a TomTom API key"
|
|
@@ -1759,6 +1929,14 @@ const PROVIDER_CREDENTIAL_HELP = {
|
|
|
1759
1929
|
label: "Get a Google Maps API key"
|
|
1760
1930
|
}
|
|
1761
1931
|
};
|
|
1932
|
+
const RASTER_KEY_LABELS = {
|
|
1933
|
+
carto: "CARTO API key",
|
|
1934
|
+
google: "Google Maps API key",
|
|
1935
|
+
here: "HERE API key",
|
|
1936
|
+
stadia: "Stadia Maps API key",
|
|
1937
|
+
tianditu: "Tianditu API key",
|
|
1938
|
+
tomtom: "TomTom API key"
|
|
1939
|
+
};
|
|
1762
1940
|
const STYLE_AUTH_GRACE_MS = 2500;
|
|
1763
1941
|
const MIN_PANEL_WIDTH = 240;
|
|
1764
1942
|
const MIN_PANEL_HEIGHT = 200;
|
|
@@ -1812,11 +1990,13 @@ class BasemapControl {
|
|
|
1812
1990
|
// stacked raster overlay so each can be added or removed independently.
|
|
1813
1991
|
__publicField(this, "_managedRasters", new globalThis.Map());
|
|
1814
1992
|
__publicField(this, "_mapTilerApiKey", "");
|
|
1993
|
+
__publicField(this, "_cartoApiKey", "");
|
|
1815
1994
|
__publicField(this, "_amazonApiKey", "");
|
|
1816
1995
|
__publicField(this, "_awsRegion", "");
|
|
1817
1996
|
__publicField(this, "_mapboxAccessToken", "");
|
|
1818
1997
|
__publicField(this, "_protomapsApiKey", "");
|
|
1819
1998
|
__publicField(this, "_stadiaApiKey", "");
|
|
1999
|
+
__publicField(this, "_tiandituApiKey", "");
|
|
1820
2000
|
__publicField(this, "_tomtomApiKey", "");
|
|
1821
2001
|
__publicField(this, "_hereApiKey", "");
|
|
1822
2002
|
__publicField(this, "_googleMapsApiKey", "");
|
|
@@ -1876,11 +2056,13 @@ class BasemapControl {
|
|
|
1876
2056
|
});
|
|
1877
2057
|
this._options = { ...DEFAULT_OPTIONS, ...options };
|
|
1878
2058
|
this._mapTilerApiKey = (options == null ? void 0 : options.mapTilerApiKey) ?? "";
|
|
2059
|
+
this._cartoApiKey = (options == null ? void 0 : options.cartoApiKey) ?? "";
|
|
1879
2060
|
this._amazonApiKey = (options == null ? void 0 : options.amazonApiKey) ?? "";
|
|
1880
2061
|
this._awsRegion = (options == null ? void 0 : options.awsRegion) ?? "us-east-1";
|
|
1881
2062
|
this._mapboxAccessToken = (options == null ? void 0 : options.mapboxAccessToken) ?? "";
|
|
1882
2063
|
this._protomapsApiKey = (options == null ? void 0 : options.protomapsApiKey) ?? "";
|
|
1883
2064
|
this._stadiaApiKey = (options == null ? void 0 : options.stadiaApiKey) ?? "";
|
|
2065
|
+
this._tiandituApiKey = (options == null ? void 0 : options.tiandituApiKey) ?? "";
|
|
1884
2066
|
this._tomtomApiKey = (options == null ? void 0 : options.tomtomApiKey) ?? "";
|
|
1885
2067
|
this._hereApiKey = (options == null ? void 0 : options.hereApiKey) ?? "";
|
|
1886
2068
|
this._googleMapsApiKey = (options == null ? void 0 : options.googleMapsApiKey) ?? "";
|
|
@@ -1999,6 +2181,12 @@ class BasemapControl {
|
|
|
1999
2181
|
this._renderContent();
|
|
2000
2182
|
this._emit({ type: "statechange", state: this.getState() });
|
|
2001
2183
|
}
|
|
2184
|
+
setCartoApiKey(apiKey) {
|
|
2185
|
+
this._cartoApiKey = apiKey;
|
|
2186
|
+
this._clearError();
|
|
2187
|
+
this._renderContent();
|
|
2188
|
+
this._emit({ type: "statechange", state: this.getState() });
|
|
2189
|
+
}
|
|
2002
2190
|
setAmazonCredentials(apiKey, awsRegion = this._awsRegion) {
|
|
2003
2191
|
this._amazonApiKey = apiKey;
|
|
2004
2192
|
this._awsRegion = awsRegion;
|
|
@@ -2024,6 +2212,12 @@ class BasemapControl {
|
|
|
2024
2212
|
this._renderContent();
|
|
2025
2213
|
this._emit({ type: "statechange", state: this.getState() });
|
|
2026
2214
|
}
|
|
2215
|
+
setTiandituApiKey(apiKey) {
|
|
2216
|
+
this._tiandituApiKey = apiKey;
|
|
2217
|
+
this._clearError();
|
|
2218
|
+
this._renderContent();
|
|
2219
|
+
this._emit({ type: "statechange", state: this.getState() });
|
|
2220
|
+
}
|
|
2027
2221
|
setTomTomApiKey(apiKey) {
|
|
2028
2222
|
this._tomtomApiKey = apiKey;
|
|
2029
2223
|
this._clearError();
|
|
@@ -2136,12 +2330,16 @@ class BasemapControl {
|
|
|
2136
2330
|
let resolvedStyleUrl;
|
|
2137
2331
|
if (isOverlay) {
|
|
2138
2332
|
await this._waitForStyleReady();
|
|
2333
|
+
const resolvedRasterTiles = basemap.source.type === "raster" ? await this._resolveRasterTiles(basemap) : void 0;
|
|
2334
|
+
if (basemap.source.type === "vector-overlay") {
|
|
2335
|
+
this._resolveVectorOverlaySource(basemap, basemap.source);
|
|
2336
|
+
}
|
|
2139
2337
|
if (effectiveMode === "replace") {
|
|
2140
2338
|
this._removeManagedBasemap();
|
|
2141
2339
|
} else {
|
|
2142
2340
|
this._removeManagedRaster(basemap.id);
|
|
2143
2341
|
}
|
|
2144
|
-
managedRaster = await this._addOverlay(basemap);
|
|
2342
|
+
managedRaster = await this._addOverlay(basemap, resolvedRasterTiles);
|
|
2145
2343
|
} else {
|
|
2146
2344
|
const styleUrl = this._resolveStyleUrl(basemap);
|
|
2147
2345
|
resolvedStyleUrl = styleUrl;
|
|
@@ -2598,6 +2796,23 @@ class BasemapControl {
|
|
|
2598
2796
|
// missing-credential error, so the two never drift (#837).
|
|
2599
2797
|
_providerFieldDefs() {
|
|
2600
2798
|
return [
|
|
2799
|
+
{
|
|
2800
|
+
provider: "carto",
|
|
2801
|
+
label: "CARTO",
|
|
2802
|
+
has: this._hasCartoBasemaps(),
|
|
2803
|
+
fields: [
|
|
2804
|
+
{
|
|
2805
|
+
className: "basemap-control-carto-key",
|
|
2806
|
+
type: "password",
|
|
2807
|
+
placeholder: "CARTO API key",
|
|
2808
|
+
ariaLabel: "CARTO API key",
|
|
2809
|
+
value: this._cartoApiKey,
|
|
2810
|
+
onInput: (value) => {
|
|
2811
|
+
this._cartoApiKey = value;
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
]
|
|
2815
|
+
},
|
|
2601
2816
|
{
|
|
2602
2817
|
provider: "maptiler",
|
|
2603
2818
|
label: "MapTiler",
|
|
@@ -2666,6 +2881,23 @@ class BasemapControl {
|
|
|
2666
2881
|
}
|
|
2667
2882
|
]
|
|
2668
2883
|
},
|
|
2884
|
+
{
|
|
2885
|
+
provider: "tianditu",
|
|
2886
|
+
label: "Tianditu",
|
|
2887
|
+
has: this._hasTiandituBasemaps(),
|
|
2888
|
+
fields: [
|
|
2889
|
+
{
|
|
2890
|
+
className: "basemap-control-tianditu-key",
|
|
2891
|
+
type: "password",
|
|
2892
|
+
placeholder: "Tianditu API key",
|
|
2893
|
+
ariaLabel: "Tianditu API key",
|
|
2894
|
+
value: this._tiandituApiKey,
|
|
2895
|
+
onInput: (value) => {
|
|
2896
|
+
this._tiandituApiKey = value;
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
]
|
|
2900
|
+
},
|
|
2669
2901
|
{
|
|
2670
2902
|
provider: "tomtom",
|
|
2671
2903
|
label: "TomTom",
|
|
@@ -3082,9 +3314,15 @@ class BasemapControl {
|
|
|
3082
3314
|
_hasProtomapsBasemaps() {
|
|
3083
3315
|
return this._basemaps.some((basemap) => basemap.provider === "protomaps");
|
|
3084
3316
|
}
|
|
3317
|
+
_hasCartoBasemaps() {
|
|
3318
|
+
return this._basemaps.some((basemap) => basemap.provider === "carto");
|
|
3319
|
+
}
|
|
3085
3320
|
_hasStadiaBasemaps() {
|
|
3086
3321
|
return this._basemaps.some((basemap) => basemap.provider === "stadia");
|
|
3087
3322
|
}
|
|
3323
|
+
_hasTiandituBasemaps() {
|
|
3324
|
+
return this._basemaps.some((basemap) => basemap.provider === "tianditu");
|
|
3325
|
+
}
|
|
3088
3326
|
_hasTomTomBasemaps() {
|
|
3089
3327
|
return this._basemaps.some((basemap) => basemap.provider === "tomtom");
|
|
3090
3328
|
}
|
|
@@ -3101,7 +3339,7 @@ class BasemapControl {
|
|
|
3101
3339
|
);
|
|
3102
3340
|
}
|
|
3103
3341
|
_hasProviderSettings() {
|
|
3104
|
-
return this._hasMapTilerBasemaps() || this._hasAmazonBasemaps() || this._hasMapboxBasemaps() || this._hasProtomapsBasemaps() || this._hasStadiaBasemaps() || this._hasTomTomBasemaps() || this._hasHereBasemaps() || this._hasGoogleApiKeyBasemaps();
|
|
3342
|
+
return this._hasMapTilerBasemaps() || this._hasCartoBasemaps() || this._hasAmazonBasemaps() || this._hasMapboxBasemaps() || this._hasProtomapsBasemaps() || this._hasStadiaBasemaps() || this._hasTiandituBasemaps() || this._hasTomTomBasemaps() || this._hasHereBasemaps() || this._hasGoogleApiKeyBasemaps();
|
|
3105
3343
|
}
|
|
3106
3344
|
_resolveStyleUrl(basemap) {
|
|
3107
3345
|
if (basemap.source.type !== "style" && basemap.source.type !== "vector-style") {
|
|
@@ -3248,15 +3486,15 @@ class BasemapControl {
|
|
|
3248
3486
|
}
|
|
3249
3487
|
// Add a stackable overlay (raster tiles or a vector overlay) to the map,
|
|
3250
3488
|
// resolving any provider credentials first.
|
|
3251
|
-
async _addOverlay(basemap) {
|
|
3489
|
+
async _addOverlay(basemap, resolvedRasterTiles) {
|
|
3252
3490
|
if (basemap.source.type === "vector-overlay") {
|
|
3253
3491
|
return this._addVectorOverlay(basemap, basemap.source);
|
|
3254
3492
|
}
|
|
3255
|
-
return this._addRasterBasemap(basemap);
|
|
3493
|
+
return this._addRasterBasemap(basemap, resolvedRasterTiles);
|
|
3256
3494
|
}
|
|
3257
|
-
async _addRasterBasemap(basemap) {
|
|
3495
|
+
async _addRasterBasemap(basemap, resolvedTiles) {
|
|
3258
3496
|
if (!this._map || basemap.source.type !== "raster") return void 0;
|
|
3259
|
-
const tiles = await this._resolveRasterTiles(basemap);
|
|
3497
|
+
const tiles = resolvedTiles ?? await this._resolveRasterTiles(basemap);
|
|
3260
3498
|
const sourceId = `${CONTROL_SOURCE_PREFIX}-${basemap.id}`;
|
|
3261
3499
|
const layerId = [CONTROL_LAYER_PREFIX, basemap.id].filter(Boolean).join("-");
|
|
3262
3500
|
const beforeId = this._getBasemapInsertBeforeId();
|
|
@@ -3358,9 +3596,11 @@ class BasemapControl {
|
|
|
3358
3596
|
return tiles.map((tile) => tile.split(API_KEY_PLACEHOLDER).join(encoded));
|
|
3359
3597
|
}
|
|
3360
3598
|
_rasterApiKeyFor(provider) {
|
|
3599
|
+
if (provider === "carto") return this._cartoApiKey.trim();
|
|
3361
3600
|
if (provider === "tomtom") return this._tomtomApiKey.trim();
|
|
3362
3601
|
if (provider === "here") return this._hereApiKey.trim();
|
|
3363
3602
|
if (provider === "stadia") return this._stadiaApiKey.trim();
|
|
3603
|
+
if (provider === "tianditu") return this._tiandituApiKey.trim();
|
|
3364
3604
|
if (provider === "google") return this._googleMapsApiKey.trim();
|
|
3365
3605
|
return "";
|
|
3366
3606
|
}
|
|
@@ -3388,7 +3628,7 @@ class BasemapControl {
|
|
|
3388
3628
|
}
|
|
3389
3629
|
}
|
|
3390
3630
|
_missingRasterKeyError(provider) {
|
|
3391
|
-
const label = provider
|
|
3631
|
+
const label = RASTER_KEY_LABELS[provider] ?? "API key";
|
|
3392
3632
|
const helpProvider = provider in PROVIDER_CREDENTIAL_HELP ? provider : "maptiler";
|
|
3393
3633
|
return new MissingCredentialError(`Enter a ${label} before applying this layer.`, helpProvider);
|
|
3394
3634
|
}
|
|
@@ -3624,4 +3864,4 @@ export {
|
|
|
3624
3864
|
getBasemapCategories as g,
|
|
3625
3865
|
resolveBasemapProviders as r
|
|
3626
3866
|
};
|
|
3627
|
-
//# sourceMappingURL=BasemapControl-
|
|
3867
|
+
//# sourceMappingURL=BasemapControl-CSw9YZ4S.js.map
|