@maptiler/sdk 3.9.1-rc.2 โ 3.10.0-rc.2
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 +606 -348
- package/dist/maptiler-sdk.css +1 -1
- package/dist/maptiler-sdk.mjs +1746 -1720
- package/dist/maptiler-sdk.mjs.map +1 -1
- package/dist/src/ImageViewer/monkeyPatchML.d.ts +2 -3
- package/dist/src/Map.d.ts +5 -0
- package/dist/src/custom-layers/CubemapLayer/loadCubemapTexture.d.ts +1 -0
- package/dist/src/index.d.ts +10 -1
- package/dist/src/ml-types.d.ts +634 -0
- package/dist/src/utils/logSDKVersion.d.ts +1 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,53 +1,78 @@
|
|
|
1
|
-
<
|
|
2
|
-
<a href="https://docs.maptiler.com/sdk-js/">official page โ</a><br>
|
|
3
|
-
<img src="images/maptiler-sdk-logo.svg" width="400px">
|
|
4
|
-
</p>
|
|
1
|
+
<img src="images/maptiler-sdk-logo.svg" alt="Company Logo" height="32"/>
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
The Javascript & TypeScript map SDK tailored for <a href="https://www.maptiler.com/cloud/">MapTiler Cloud</a>
|
|
8
|
-
</p>
|
|
3
|
+
# MapTiler SDK JS
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
The **MapTiler SDK JS** extends MapLibre GL JS, exposes all its features, and adds new ones on top. The SDK is designed to work with the well-established [MapTiler service](https://www.maptiler.com/cloud/), which provides all the data required to fuel a complete web mapping experience: vector tiles, satellite raster tiles, DEM with Terrain RGB, custom styles with an editor, etc.
|
|
6
|
+
|
|
7
|
+
**Why are we creating a new SDK?** To make things simpler for developers working in the MapTiler ecosystem! With **MapTiler SDK JS**, there is no need to load external plugins for the most basic things, copy-paste complex data source URLs, or look up the syntax to enable 3D terrain every time you start a project. All this is built-in, loaded when needed, or exposed with simple functions. Under the hood, this SDK is opinionated as it's being fed by [MapTiler service](https://www.maptiler.com/cloud/) data, but its MapLibre core makes it 100% compatible with other sources.
|
|
8
|
+
|
|
9
|
+
In addition, the MapTiler SDK JS provides well-documented and easy-to-use wrapper functions to the [MapTiler API services](https://docs.maptiler.com/cloud/api) such as: geocoding, static maps, geolocation, as well as a search engine for coordinate reference systems and transforming coordinates from one CRS to another.
|
|
10
|
+
|
|
11
|
+
> ๐ฃ _**Note:**_ If you need <ins>only the API Client library</ins> to use in a headless fashion and without any map display, check out [MapTiler Client JS](https://github.com/maptiler/maptiler-client-js) library for browser and NodeJS.
|
|
12
|
+
|
|
13
|
+
 
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
The **MapTiler SDK JS** extends MapLibre GL JS, exposes all its features, and adds new ones on top. The SDK is designed to work with the well-established [MapTiler Cloud service](https://www.maptiler.com/cloud/), which provides all the data required to fuel a complete web mapping experience: vector tiles, satellite raster tiles, DEM with Terrain RGB, custom styles with an editor, etc.
|
|
15
|
+
---
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
๐ [Documentation](https://docs.maptiler.com/sdk-js/) ๐ฆ [NPM Package](https://www.npmjs.com/package/@maptiler/sdk) ๐ [Website](https://www.maptiler.com/interactive-maps/) ๐ [Get API Key](https://cloud.maptiler.com/account/keys/)
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
> ๐ฃ *__Note:__* If you need <ins>only the API Client library</ins> to use in a headless fashion and without any map display, check out [MapTiler Client JS](https://github.com/maptiler/maptiler-client-js) library for browser and NodeJS.
|
|
19
|
+
---
|
|
24
20
|
|
|
25
|
-
|
|
21
|
+
<br>
|
|
22
|
+
|
|
23
|
+
<details> <summary><b>Table of Contents</b></summary>
|
|
24
|
+
<ul>
|
|
25
|
+
<li><a href="#-installation">Installation</a></li>
|
|
26
|
+
<li><a href="#-basic-usage">Basic Usage</a></li>
|
|
27
|
+
<li><a href="#-related-examples">Examples</a></li>
|
|
28
|
+
<li><a href="#-api-reference">API Reference</a></li>
|
|
29
|
+
<li><a href="#migration-guide">Migration Guide</a></li>
|
|
30
|
+
<li><a href="#-support">Support</a></li>
|
|
31
|
+
<li><a href="#-contributing">Contributing</a></li>
|
|
32
|
+
<li><a href="#-license">License</a></li>
|
|
33
|
+
<li><a href="#-acknowledgements">Acknowledgements</a></li>
|
|
34
|
+
</ul>
|
|
35
|
+
</details>
|
|
36
|
+
|
|
37
|
+
<p align="center">
|
|
38
|
+
<img src="images/screenshots/lake-louise.jpg" alt="Demo Screenshot" width="80%"/>
|
|
39
|
+
<br />
|
|
40
|
+
<a href="https://docs.maptiler.com/sdk-js/examples/ts-get-started/">See live interactive demo</a>
|
|
41
|
+
</p>
|
|
42
|
+
<br>
|
|
43
|
+
|
|
44
|
+
## ๐ฆ Installation
|
|
26
45
|
|
|
27
|
-
# Install
|
|
28
46
|
```shell
|
|
29
47
|
npm install --save @maptiler/sdk
|
|
30
48
|
```
|
|
31
49
|
|
|
32
50
|
โ ๏ธ Please keep in mind that if you use any additional [MapTiler modules](https://docs.maptiler.com/sdk-js/modules/), you must update them to a version that supports MapTiler SDK JS v3.
|
|
33
51
|
|
|
34
|
-
|
|
35
|
-
|
|
52
|
+
From CDN and using the UMD bundle, in the `<head></head>` section of your HTML file:
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<script src="https://cdn.maptiler.com/maptiler-sdk-js/<VERSION>/maptiler-sdk.umd.min.js"></script>
|
|
56
|
+
<link href="https://cdn.maptiler.com/maptiler-sdk-js/<VERSION>/maptiler-sdk.css" rel="stylesheet" />
|
|
57
|
+
```
|
|
36
58
|
|
|
37
|
-
|
|
59
|
+
<br>
|
|
60
|
+
|
|
61
|
+
## ๐ Basic Usage
|
|
62
|
+
|
|
63
|
+
### With ES modules
|
|
38
64
|
|
|
39
|
-
## With ES modules
|
|
40
65
|
**Recommended for:** advanced applications
|
|
41
66
|
|
|
42
67
|
```ts
|
|
43
|
-
import { config, Map } from
|
|
68
|
+
import { config, Map } from "@maptiler/sdk";
|
|
44
69
|
|
|
45
70
|
// Add your MapTiler Cloud API key to the config
|
|
46
71
|
// (Go to https://cloud.maptiler.com/account/keys/ to get one for free!)
|
|
47
|
-
config.apiKey =
|
|
72
|
+
config.apiKey = "YOUR_API_KEY";
|
|
48
73
|
|
|
49
74
|
// Let's say you have a DIV ready to receive a map
|
|
50
|
-
const mapContainer = document.getElementById(
|
|
75
|
+
const mapContainer = document.getElementById("my-container-div");
|
|
51
76
|
|
|
52
77
|
// Instantiate the map
|
|
53
78
|
const map = new Map({
|
|
@@ -56,16 +81,17 @@ const map = new Map({
|
|
|
56
81
|
```
|
|
57
82
|
|
|
58
83
|
Alternatively, the `apiKey` can be set as Map option instead of in the `config` object. Yet, this will still internally propagate to the `config` object:
|
|
84
|
+
|
|
59
85
|
```ts
|
|
60
|
-
import { Map } from
|
|
86
|
+
import { Map } from "@maptiler/sdk";
|
|
61
87
|
|
|
62
88
|
// Let's say you have a DIV ready to receive a map
|
|
63
|
-
const mapContainer = document.getElementById(
|
|
89
|
+
const mapContainer = document.getElementById("my-container-div");
|
|
64
90
|
|
|
65
91
|
// Instantiate the map
|
|
66
92
|
const map = new Map({
|
|
67
93
|
container: mapContainer,
|
|
68
|
-
apiKey:
|
|
94
|
+
apiKey: "YOUR_API_KEY",
|
|
69
95
|
});
|
|
70
96
|
```
|
|
71
97
|
|
|
@@ -74,18 +100,21 @@ By default, the map will be initialized with the style [streets-v2](https://www.
|
|
|
74
100
|
Depending on the framework and environment you are using for your application, you will have to also include the CSS file.
|
|
75
101
|
|
|
76
102
|
For example, with a [NextJS](https://nextjs.org/) app, this can take place at the top of the file `_app.ts/js`:
|
|
103
|
+
|
|
77
104
|
```ts
|
|
78
105
|
import "@maptiler/sdk/dist/maptiler-sdk.css";
|
|
79
106
|
```
|
|
80
107
|
|
|
81
|
-
|
|
108
|
+
#### TypeScript
|
|
109
|
+
|
|
82
110
|
The SDK is fully typed, but it may happen that types defined in Maplibre GL JS are not visible in your project. This is a known issue that comes from Maplibre being a CommonJS bundle.
|
|
83
111
|
|
|
84
112
|
There are mainly two ways to address this issue and access to the complete type definition.
|
|
85
113
|
|
|
86
|
-
1. **With `esModuleInterop`**
|
|
114
|
+
1. **With `esModuleInterop`**
|
|
87
115
|
|
|
88
116
|
Set the following in your `tsconfig.json`:
|
|
117
|
+
|
|
89
118
|
```js
|
|
90
119
|
{
|
|
91
120
|
"compilerOptions": {
|
|
@@ -93,11 +122,12 @@ Set the following in your `tsconfig.json`:
|
|
|
93
122
|
"esModuleInterop": true,
|
|
94
123
|
}
|
|
95
124
|
}
|
|
96
|
-
```
|
|
125
|
+
```
|
|
97
126
|
|
|
98
|
-
2. **With `moduleResolution`**
|
|
127
|
+
2. **With `moduleResolution`**
|
|
99
128
|
|
|
100
129
|
Set the following in your `tsconfig.json`:
|
|
130
|
+
|
|
101
131
|
```js
|
|
102
132
|
{
|
|
103
133
|
"compilerOptions": {
|
|
@@ -105,13 +135,13 @@ Set the following in your `tsconfig.json`:
|
|
|
105
135
|
"moduleResolution": "Bundler",
|
|
106
136
|
}
|
|
107
137
|
}
|
|
108
|
-
```
|
|
109
|
-
Note that this second option is not always possible as some frameworks and other dependencies won't let you use the "Bundler" mode.
|
|
138
|
+
```
|
|
110
139
|
|
|
140
|
+
Note that this second option is not always possible as some frameworks and other dependencies won't let you use the "Bundler" mode.
|
|
111
141
|
|
|
142
|
+
### With CDN
|
|
112
143
|
|
|
113
|
-
|
|
114
|
-
The SDK hosted on our CDN is bundled as *[Universal Module Definition](https://github.com/umdjs/umd)* (UMD) to make it standalone and contain all its dependencies. The CDN also serves the style sheet (CSS).
|
|
144
|
+
The SDK hosted on our CDN is bundled as _[Universal Module Definition](https://github.com/umdjs/umd)_ (UMD) to make it standalone and contain all its dependencies. The CDN also serves the style sheet (CSS).
|
|
115
145
|
|
|
116
146
|
**Recommended for:** simple map integration example and demos
|
|
117
147
|
|
|
@@ -120,7 +150,8 @@ The SDK hosted on our CDN is bundled as *[Universal Module Definition](https://g
|
|
|
120
150
|
<head>
|
|
121
151
|
<title>MapTiler JS SDK example</title>
|
|
122
152
|
<style>
|
|
123
|
-
html,
|
|
153
|
+
html,
|
|
154
|
+
body {
|
|
124
155
|
margin: 0;
|
|
125
156
|
}
|
|
126
157
|
|
|
@@ -132,43 +163,60 @@ The SDK hosted on our CDN is bundled as *[Universal Module Definition](https://g
|
|
|
132
163
|
</style>
|
|
133
164
|
|
|
134
165
|
<!-- Load the SDK CSS -->
|
|
135
|
-
<link rel="stylesheet" href="dist/maptiler-sdk.css"
|
|
166
|
+
<link rel="stylesheet" href="dist/maptiler-sdk.css" />
|
|
136
167
|
</head>
|
|
137
168
|
|
|
138
169
|
<body>
|
|
139
170
|
<div id="map-container"></div>
|
|
140
|
-
|
|
141
|
-
<script src
|
|
142
|
-
|
|
171
|
+
|
|
172
|
+
<script src="dist/maptiler-sdk.umd.min.js"></script>
|
|
173
|
+
|
|
143
174
|
<script>
|
|
144
|
-
// Add your MapTiler
|
|
175
|
+
// Add your MapTiler API key to the config
|
|
145
176
|
// (Go to https://cloud.maptiler.com/account/keys/ to get one for free!)
|
|
146
|
-
maptilersdk.config.apiKey =
|
|
177
|
+
maptilersdk.config.apiKey = "YOUR_API_KEY";
|
|
147
178
|
|
|
148
|
-
const mapContainer = document.getElementById(
|
|
179
|
+
const mapContainer = document.getElementById("my-container-div");
|
|
149
180
|
|
|
150
181
|
const map = new maptilersdk.Map({
|
|
151
182
|
container: mapContainer,
|
|
152
183
|
style: maptilersdk.MapStyle.STREETS_DARK,
|
|
153
184
|
hash: true,
|
|
154
|
-
})
|
|
185
|
+
});
|
|
155
186
|
</script>
|
|
156
187
|
</body>
|
|
157
188
|
</html>
|
|
158
|
-
|
|
159
189
|
```
|
|
160
190
|
|
|
161
191
|
Check out the minimalist code samples in the [demos](demos) directory.
|
|
162
192
|
|
|
193
|
+
<br>
|
|
194
|
+
|
|
195
|
+
## ๐ก Related Examples
|
|
196
|
+
|
|
197
|
+
- [How to use the MapTiler SDK JS](https://docs.maptiler.com/sdk-js/examples/how-to-use/)
|
|
198
|
+
- [Maps SDK with TypeScript](https://docs.maptiler.com/sdk-js/examples/ts-get-started/)
|
|
199
|
+
- [Built-in map styles](https://docs.maptiler.com/sdk-js/examples/built-in-styles/)
|
|
200
|
+
|
|
201
|
+
Check out more than 200 [examples and tutorials](https://docs.maptiler.com/sdk-js/examples/)
|
|
202
|
+
|
|
203
|
+
<br>
|
|
204
|
+
|
|
205
|
+
## ๐ API Reference
|
|
206
|
+
|
|
207
|
+
In addition to the details and examples provided in this readme, check out the [complete API documentation](https://docs.maptiler.com/sdk-js/api/)
|
|
208
|
+
|
|
209
|
+
### Many styles to choose from
|
|
163
210
|
|
|
164
|
-
# Many styles to choose from
|
|
165
211
|
MapTiler teams maintain a few styles that we have decided to expose from the SDK. This has two advantages:
|
|
212
|
+
|
|
166
213
|
- they are easier to remember, no need to type along style URL
|
|
167
214
|
- if we make an update to a style, you will benefit from it without modifying your codebase
|
|
168
215
|
|
|
169
216
|
Here is how it works:
|
|
217
|
+
|
|
170
218
|
```ts
|
|
171
|
-
import { Map, MapStyle } from
|
|
219
|
+
import { Map, MapStyle } from "@maptiler/sdk";
|
|
172
220
|
|
|
173
221
|
// When instanciating a map
|
|
174
222
|
const map = new Map({
|
|
@@ -182,15 +230,14 @@ map.setStyle(MapStyle.STREETS.DARK);
|
|
|
182
230
|
|
|
183
231
|
The styles with a shorthand provided by the SDK are the following:
|
|
184
232
|
|
|
185
|
-
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
233
|
+
| ID | Screenshot | Comment |
|
|
234
|
+
| :---------------------: | :----------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: |
|
|
235
|
+
| `MapStyle.STREETS` | [](https://www.maptiler.com/maps/#style=streets-v2&mode=2d&position=12.52/40.73676/-73.98418) | The classic default style, perfect for urban areas.<p>Also available in **dark** and **light** mode.</p> |
|
|
236
|
+
| `MapStyle.DATAVIZ.DARK` | [](https://www.maptiler.com/maps/#style=dataviz-dark&mode=2d&position=2.01/38.7/-27.0) | A minimalist style for data visualization.<p>Also available in **color** and **light** mode</p> |
|
|
237
|
+
| `MapStyle.SATELLITE` | [](https://www.maptiler.com/maps/#style=hybrid&mode=2d&position=7.87/24.518/-77.411) | Only high resolution satellite raster tiles without any labels |
|
|
238
|
+
| `MapStyle.HYBRID` | [](https://www.maptiler.com/maps/#style=hybrid&mode=2d&position=9.4/-26.175/122.6631) | Satellite tile with labels, landmarks, roads ways and political borders |
|
|
239
|
+
| `MapStyle.OUTDOOR` | [](https://www.maptiler.com/maps/#style=outdoor&mode=2d&position=11.96/46.02591/7.7273) | A solid hiking companion, with peaks, parks, isolines and more |
|
|
240
|
+
| `MapStyle.BASIC` | [](https://www.maptiler.com/maps/#style=basic-v2&mode=2d&position=13.09/37.78734/-122.42025) | A minimalist alternative to `STREETS`, with a touch of flat design.<p>Also available in **dark** and **light** and **pastel** mode.</p> |
|
|
194
241
|
|
|
195
242
|
<details>
|
|
196
243
|
<summary>Know more about built-in map styles</summary>
|
|
@@ -198,6 +245,7 @@ The styles with a shorthand provided by the SDK are the following:
|
|
|
198
245
|
MapTiler provides some **reference styles** as well as some **variants** for each. A **reference style** sets some guidelines about what kind of information is displayed, the granularity of the information, and more generally defines a purpose for which this style is the most relevant: street navigation, outdoor adventure, minimalist dashboard, etc. Then, each **reference style** offers a range of **variants** that contain the same level of information and have the same purpose but use different color schemes.
|
|
199
246
|
|
|
200
247
|
Here is the full list:
|
|
248
|
+
|
|
201
249
|
- `MapStyle.STREETS`, reference style for navigation and city exploration
|
|
202
250
|
- `MapStyle.STREETS.DARK` (variant)
|
|
203
251
|
- `MapStyle.STREETS.LIGHT` (variant)
|
|
@@ -227,7 +275,7 @@ Here is the full list:
|
|
|
227
275
|
- `MapStyle.VOYAGER.DARK` (variant)
|
|
228
276
|
- `MapStyle.VOYAGER.LIGHT` (variant)
|
|
229
277
|
- `MapStyle.VOYAGER.VINTAGE` (variant)
|
|
230
|
-
- `MapStyle.TONER` reference style for very high contrast stylish maps
|
|
278
|
+
- `MapStyle.TONER` reference style for very high contrast stylish maps
|
|
231
279
|
- `MapStyle.TONER.BACKGROUND` (variant)
|
|
232
280
|
- `MapStyle.TONER.LITE` (variant)
|
|
233
281
|
- `MapStyle.TONER.LINES` (variant)
|
|
@@ -240,51 +288,54 @@ Here is the full list:
|
|
|
240
288
|
- `MapStyle.AQUARELLE.VIVID` (variant)
|
|
241
289
|
- `MapStyle.OPENSTREETMAP` (reference style, this one does not have any variants)
|
|
242
290
|
|
|
243
|
-
|
|
244
291
|
All reference styles (instances of `ReferenceMapStyle`) and style variants (instances of `MapStyleVariant`) have methods to know the alternative styles and variants that belong to the same reference style (`.getVariants()`). This is handy to provide a default/dark/light alternative color scheme, yet preserving the same level of details as in the reference style. Read more about about [ReferenceMapStyle](https://docs.maptiler.com/sdk-js/api/map-styles/#referencemapstyle) and [MapStyleVariant](https://docs.maptiler.com/sdk-js/api/map-styles/#mapstylevariant).
|
|
245
|
-
</details>
|
|
246
292
|
|
|
247
|
-
|
|
293
|
+
</details>
|
|
248
294
|
|
|
295
|
+
---
|
|
249
296
|
|
|
250
|
-
You can also use classic styles with just a
|
|
297
|
+
You can also use classic styles with just a _string_ if you know their MapTiler ID:
|
|
251
298
|
|
|
252
299
|
```ts
|
|
253
|
-
map.setStyle(
|
|
300
|
+
map.setStyle("outdoor-v2");
|
|
254
301
|
```
|
|
255
302
|
|
|
256
303
|
And finally, you can use your own custom styles designed with [our style editor](https://cloud.maptiler.com/maps/). Every custom style is given a unique ID, for instance: `c912ffc8-2360-487a-973b-59d037fb15b8`.
|
|
257
304
|
|
|
258
305
|
This ID can be provided as such:
|
|
306
|
+
|
|
259
307
|
```ts
|
|
260
308
|
map.setStyle("c912ffc8-2360-487a-973b-59d037fb15b8");
|
|
261
309
|
```
|
|
262
310
|
|
|
263
311
|
Or in its extended form:
|
|
312
|
+
|
|
264
313
|
```ts
|
|
265
314
|
map.setStyle("https://api.maptiler.com/maps/c912ffc8-2360-487a-973b-59d037fb15b8/style.json");
|
|
266
315
|
// this could be suffixed with the API token as well
|
|
267
316
|
```
|
|
268
317
|
|
|
269
318
|
And can even be provided in the URI form:
|
|
319
|
+
|
|
270
320
|
```ts
|
|
271
321
|
map.setStyle("maptiler://c912ffc8-2360-487a-973b-59d037fb15b8");
|
|
272
322
|
```
|
|
273
323
|
|
|
274
|
-
|
|
275
|
-
The **Web Mercator projection** [*(Wikipedia)*](https://en.wikipedia.org/wiki/Web_Mercator_projection) has been the go-to standard in cartography since the early days or web mapping. Partly for technical reasons but also because it is great for navigation as well as for showing the entire world in one screen, with no hidden face. That being said, Mercator's heavy distorsion at high latitudes, as well a the discontinuity at the poles can be a limitation for data visualization and has been critisized for providing a biased view of the world.
|
|
324
|
+
### Globe or Mercator projection?
|
|
276
325
|
|
|
277
|
-
The **
|
|
326
|
+
The **Web Mercator projection** [_(Wikipedia)_](https://en.wikipedia.org/wiki/Web_Mercator_projection) has been the go-to standard in cartography since the early days or web mapping. Partly for technical reasons but also because it is great for navigation as well as for showing the entire world in one screen, with no hidden face. That being said, Mercator's heavy distorsion at high latitudes, as well a the discontinuity at the poles can be a limitation for data visualization and has been critisized for providing a biased view of the world.
|
|
278
327
|
|
|
328
|
+
The **globe projection**, available starting from MapTiler SDK v3, does not suffer from these biases and can feel overall more playfull than Mercator. It can be a great choice for semi-global data visualization, especially for data close to the poles, thanks to its geographic continuity.
|
|
279
329
|
|
|
280
|
-
|
|
|
281
|
-
|
|
|
330
|
+
| Mercator projection | Globe projection |
|
|
331
|
+
| :----------------------------------------------: | :-------------------------------------------: |
|
|
282
332
|
|  |  |
|
|
283
333
|
|
|
284
334
|
The choice between Mercator and Globe can be done at different levels and moments in the lifecycle of the map, yet, unless stated otherwise, **Mercator remains the default**.
|
|
285
335
|
|
|
286
336
|
- In the style, using the `projection` top-level property.
|
|
287
|
-
For globe:
|
|
337
|
+
For globe:
|
|
338
|
+
|
|
288
339
|
```js
|
|
289
340
|
{
|
|
290
341
|
"version": ...,
|
|
@@ -298,10 +349,12 @@ For globe:
|
|
|
298
349
|
"type": "globe"
|
|
299
350
|
}
|
|
300
351
|
|
|
301
|
-
// ...
|
|
352
|
+
// ...
|
|
302
353
|
}
|
|
303
354
|
```
|
|
355
|
+
|
|
304
356
|
or for Mercator:
|
|
357
|
+
|
|
305
358
|
```js
|
|
306
359
|
{
|
|
307
360
|
"version": ...,
|
|
@@ -315,27 +368,32 @@ or for Mercator:
|
|
|
315
368
|
"type": "mercator"
|
|
316
369
|
}
|
|
317
370
|
|
|
318
|
-
// ...
|
|
371
|
+
// ...
|
|
319
372
|
}
|
|
320
373
|
```
|
|
321
374
|
|
|
322
375
|
- In the constructor of the `Map` class, using the `projection` option. For globe:
|
|
376
|
+
|
|
323
377
|
```ts
|
|
324
378
|
const map = new maptilersdk.Map({
|
|
325
379
|
container: "map",
|
|
326
380
|
projection: "globe", // Force a globe projection
|
|
327
381
|
});
|
|
328
382
|
```
|
|
383
|
+
|
|
329
384
|
or for Mercator:
|
|
385
|
+
|
|
330
386
|
```ts
|
|
331
387
|
const map = new maptilersdk.Map({
|
|
332
388
|
container: "map",
|
|
333
389
|
projection: "mercator", // Force a mercator projection
|
|
334
|
-
})
|
|
390
|
+
});
|
|
335
391
|
```
|
|
392
|
+
|
|
336
393
|
This will overwrite the `projection` property from the style (if any) and will persist it later if the map style was to change.
|
|
337
394
|
|
|
338
395
|
- Use the built-in methods:
|
|
396
|
+
|
|
339
397
|
```ts
|
|
340
398
|
map.enableGlobeProjection();
|
|
341
399
|
// or
|
|
@@ -343,78 +401,88 @@ map.enableMercatorProjection();
|
|
|
343
401
|
```
|
|
344
402
|
|
|
345
403
|
The projection setter built in Maplibre GL JS is also usable:
|
|
404
|
+
|
|
346
405
|
```ts
|
|
347
|
-
map.setProjection({type: "mercator"});
|
|
406
|
+
map.setProjection({ type: "mercator" });
|
|
348
407
|
// or
|
|
349
|
-
map.setProjection({type: "globe"});
|
|
408
|
+
map.setProjection({ type: "globe" });
|
|
350
409
|
```
|
|
351
410
|
|
|
352
411
|
- Using the `MaptilerProjectionControl`. Not mounted by default, it can easily be added with a single option in the `Map` constructor:
|
|
412
|
+
|
|
353
413
|
```ts
|
|
354
414
|
const map = new maptilersdk.Map({
|
|
355
415
|
container: "map",
|
|
356
|
-
projectionControl: true,
|
|
357
|
-
});
|
|
416
|
+
projectionControl: true, // or the position such as "top-left", "top-right",
|
|
417
|
+
}); // "bottom-right" or "bottom-left"
|
|
358
418
|
```
|
|
419
|
+
|
|
359
420
|
This dedicated control will show a globe icon <img src="images/screenshots/globe_icon.png" width="30px"/> to transition from Mercator to globe projection and will show a flat map icon <img src="images/screenshots/mercator_icon.png" width="30px"/> to transition from globe to Mercator projection. The chosen projection persist with future style changes.
|
|
360
421
|
|
|
361
|
-
|
|
362
|
-
|
|
422
|
+
#### Field of view (FOV)
|
|
423
|
+
|
|
424
|
+
The internal camera has a default vertical field of view [_(wikipedia)_](https://en.wikipedia.org/wiki/Field_of_view) of a wide ~36.86 degrees. In globe mode, such a large _FOV_ reduces the amount of the Earth that can be seen at once and exaggerates the central part, comparably to a fisheye lens. In many cases, a narrower _FOV_ is preferable. Here is how to update if:
|
|
363
425
|
|
|
364
426
|
```ts
|
|
365
427
|
// Ajust de FOV, with values from 1 to 50
|
|
366
428
|
map.setVerticalFieldOfView(10);
|
|
367
429
|
```
|
|
368
|
-
|
|
430
|
+
|
|
431
|
+
> ๐ฃ _**Note:**_ with the Mercator projection, it is possible to set a FOV of `0`, which yields a true orthographic projection [_(wikipedia)_](https://en.wikipedia.org/wiki/Orthographic_projection), but the globe projection does not allow this.
|
|
369
432
|
|
|
370
433
|
Here is a table of FOV comparison:
|
|
371
|
-
| 01ยฐ
|
|
434
|
+
| 01ยฐ | 10ยฐ | 20ยฐ | 30ยฐ | 40ยฐ | 50ยฐ |
|
|
372
435
|
| :--------: | :-------: |:-------: |:-------: |:-------: |:-------: |
|
|
373
|
-
|  |  |  |  |  |  |
|
|
436
|
+
|  |  |  |  |  |  |
|
|
374
437
|
|
|
438
|
+
### Globe screenshots
|
|
375
439
|
|
|
376
|
-
## Globe screenshots
|
|
377
440
|

|
|
378
441
|

|
|
379
442
|

|
|
380
443
|

|
|
381
444
|

|
|
382
445
|
|
|
446
|
+
> ๐ฃ _**Note:**_ Terrain is not fully compatible with the globe projection yet so it's better to disable it at low zoom level (from afar) and to choose the Mercator projection at higher zoom level (from up close).
|
|
383
447
|
|
|
384
|
-
|
|
448
|
+
### Centering the map on visitors
|
|
449
|
+
|
|
450
|
+
It is sometimes handy to center the map on the visitor's location, and there are multiple ways of doing it but for the SDK, we have decided to make this extra simple by using the [IP geolocation](#%EF%B8%8F%EF%B8%8F-geolocation) API provided by [MapTiler Geolocation API](https://docs.maptiler.com/cloud/api/geolocation/), directly exposed as a single option of the `Map` constructor. There are two strategies:
|
|
385
451
|
|
|
386
|
-
# Centering the map on visitors
|
|
387
|
-
It is sometimes handy to center the map on the visitor's location, and there are multiple ways of doing it but for the SDK, we have decided to make this extra simple by using the [IP geolocation](#%EF%B8%8F%EF%B8%8F-geolocation) API provided by [MapTiler Cloud](https://docs.maptiler.com/cloud/api/geolocation/), directly exposed as a single option of the `Map` constructor. There are two strategies:
|
|
388
452
|
1. `POINT`: centering the map on the actual visitor location, optionally using the `zoom` option (zoom level `13` if none is provided). As a more precise option, if the user has previously granted access to the browser location (more precise) then this is going to be used.
|
|
389
453
|
2. `COUNTRY`: fitting the map view on the bounding box of the visitor's country. In this case, the `zoom` option, if provided, will be ignored
|
|
390
454
|
|
|
391
455
|
Here is how the map gets centered on the visitor's location:
|
|
456
|
+
|
|
392
457
|
```js
|
|
393
458
|
new maptilersdk.Map({
|
|
394
459
|
// ... other options
|
|
395
460
|
|
|
396
|
-
geolocate: maptilersdk.GeolocationType.POINT
|
|
397
|
-
})
|
|
461
|
+
geolocate: maptilersdk.GeolocationType.POINT,
|
|
462
|
+
});
|
|
398
463
|
```
|
|
399
464
|
|
|
400
465
|
Here is how the map fits the visitor's country bounds:
|
|
466
|
+
|
|
401
467
|
```js
|
|
402
468
|
new maptilersdk.Map({
|
|
403
469
|
// ... other options
|
|
404
470
|
|
|
405
|
-
geolocate: maptilersdk.GeolocationType.COUNTRY
|
|
406
|
-
})
|
|
471
|
+
geolocate: maptilersdk.GeolocationType.COUNTRY,
|
|
472
|
+
});
|
|
407
473
|
```
|
|
408
474
|
|
|
409
475
|
The `geolocation` options will not be taken into consideration in the following cases:
|
|
476
|
+
|
|
410
477
|
- if the `center` option is provided, then it prevails
|
|
411
478
|
- if the `hash` option is provided with the value `true` **AND** a location hash is already part of the URL. If `hash` is `true` but there is not yet a location hash in the URL, then the geolocation will work.
|
|
412
479
|
|
|
413
|
-
> ๐ฃ
|
|
480
|
+
> ๐ฃ _**Note:**_ if none of the options `center` or `hash` is provided to the `Map` constructor, then the map will be centered using the `POINT` strategy, unless the `geolocate` has the value `false`.
|
|
414
481
|
|
|
415
|
-
> ๐ฃ
|
|
482
|
+
> ๐ฃ _**Note 2:**_ the term _IP geolocation_ refers to finding the physical location of a computer using its _IP address_. The _IP address_ is a numerical identifier of a computer within a network, just like the phone number for a telephone. The _IP geolocation_ is **not** using the GPS of a device and usually provides a precision in the order of a few hundred meters. This precision may vary based on many local parameters such as the density of the network grid or the terrain, this is why it is generally better not to use a zoom level higher than `14`.
|
|
483
|
+
|
|
484
|
+
### Easy to add controls
|
|
416
485
|
|
|
417
|
-
# Easy to add controls
|
|
418
486
|
The term "control" is commonly used for all sorts of buttons and information displays that take place in one of the corners of the map area. The most well-known are probably the `[+]` and `[-]` zoom buttons as well as the attribution information. Plenty of others are possible and we have made a few easy to add and directly accessible from the `Map` constructor options:
|
|
419
487
|
|
|
420
488
|
- `navigationControl`
|
|
@@ -434,12 +502,14 @@ The term "control" is commonly used for all sorts of buttons and information dis
|
|
|
434
502
|
- a boolean or a corner position. Hidden by default, showing on top-right if `true`.
|
|
435
503
|
|
|
436
504
|
The corner positions possible are:
|
|
505
|
+
|
|
437
506
|
- `"top-left"`
|
|
438
507
|
- `"top-right"`
|
|
439
508
|
- `"bottom-left"`
|
|
440
509
|
- `"bottom-right"`
|
|
441
510
|
|
|
442
|
-
**Example:**
|
|
511
|
+
**Example:**
|
|
512
|
+
|
|
443
513
|
```ts
|
|
444
514
|
import { Map } from "@maptiler/sdk";
|
|
445
515
|
|
|
@@ -448,31 +518,34 @@ const map = new Map({
|
|
|
448
518
|
terrainControl: false,
|
|
449
519
|
scaleControl: true,
|
|
450
520
|
fullscreenControl: "top-left",
|
|
451
|
-
})
|
|
521
|
+
});
|
|
452
522
|
```
|
|
453
523
|
|
|
454
|
-
|
|
524
|
+
### ๐งฉ Custom Controls
|
|
455
525
|
|
|
456
526
|
MapTiler SDK JS supports two flexible ways to add custom controls to your map interface. Whether you're building a dynamic application or integrating with static HTML, there's a matching approach for both.
|
|
457
527
|
|
|
458
|
-
|
|
528
|
+
#### Programmatic Controls
|
|
459
529
|
|
|
460
530
|
Use `map.addControl()` with `MaptilerExternalControl` to register custom UI elements manually. This approach is ideal for dynamic logic, event-driven behavior, or integration with frameworks like React. The control element can be provided either as a reference to the **element itself**, or as its **CSS selector**. Optionally, two callback functions can be provided:
|
|
461
531
|
|
|
462
|
-
|
|
463
|
-
|
|
532
|
+
- `onClick` function that is called when the element is clicked, and
|
|
533
|
+
- `onRender` function that is called every time the map renders a new state.
|
|
464
534
|
|
|
465
535
|
Both callbacks receive the active `Map` instance, the associated control element itself, and an event object associated with the original event (`PointerEvent` and `MapLibreEvent` respectively).
|
|
466
536
|
|
|
467
|
-
|
|
537
|
+
##### Example
|
|
468
538
|
|
|
469
539
|
```ts
|
|
470
540
|
const panControl = new maptilersdk.MaptilerExternalControl(
|
|
471
541
|
".pan-control",
|
|
472
542
|
(map) => map.panBy([10, 10]), // Move southeast on click
|
|
473
|
-
(map, el) =>
|
|
474
|
-
|
|
475
|
-
|
|
543
|
+
(map, el) =>
|
|
544
|
+
el.classList.toggle(
|
|
545
|
+
// Style based on hemisphere
|
|
546
|
+
"northern-hemisphere",
|
|
547
|
+
map.getCenter().lat > 0,
|
|
548
|
+
),
|
|
476
549
|
);
|
|
477
550
|
map.addControl(panControl);
|
|
478
551
|
|
|
@@ -481,13 +554,13 @@ element.textContent = "Pan NW";
|
|
|
481
554
|
map.addControl(
|
|
482
555
|
new maptilersdk.MaptilerExternalControl(
|
|
483
556
|
element,
|
|
484
|
-
(map) => map.panBy([-10, -10]) // Move northwest
|
|
557
|
+
(map) => map.panBy([-10, -10]), // Move northwest
|
|
485
558
|
),
|
|
486
|
-
"top-left"
|
|
559
|
+
"top-left",
|
|
487
560
|
);
|
|
488
561
|
```
|
|
489
562
|
|
|
490
|
-
|
|
563
|
+
##### Behavior Overview
|
|
491
564
|
|
|
492
565
|
- On add, control element is moved into the map UI
|
|
493
566
|
- `onClick` binds user interaction
|
|
@@ -495,11 +568,11 @@ map.addControl(
|
|
|
495
568
|
- Control maintains its own DOM context
|
|
496
569
|
- On removal, element is returned to its original DOM position (if any) to not interfere with DOM handling of frameworks like React
|
|
497
570
|
|
|
498
|
-
|
|
571
|
+
#### Declarative Controls
|
|
499
572
|
|
|
500
573
|
Add controls using HTML attributes โ no JavaScript required. This is perfect for simple UI setups.
|
|
501
574
|
|
|
502
|
-
|
|
575
|
+
##### Enabling Detection
|
|
503
576
|
|
|
504
577
|
```ts
|
|
505
578
|
const map = new maptilersdk.Map({
|
|
@@ -510,7 +583,7 @@ const map = new maptilersdk.Map({
|
|
|
510
583
|
|
|
511
584
|
You can pass `true` to enable detection globally, or a CSS selector to scope it.
|
|
512
585
|
|
|
513
|
-
|
|
586
|
+
##### Declaring Controls
|
|
514
587
|
|
|
515
588
|
Use `data-maptiler-control` attribute:
|
|
516
589
|
|
|
@@ -521,20 +594,20 @@ Use `data-maptiler-control` attribute:
|
|
|
521
594
|
Supported values:
|
|
522
595
|
|
|
523
596
|
| Value | Description |
|
|
524
|
-
|
|
597
|
+
| ------------------- | ------------------------------------------------ |
|
|
525
598
|
| `zoom-in` | Zooms in |
|
|
526
599
|
| `zoom-out` | Zooms out |
|
|
527
|
-
| `toggle-projection` | Switches Mercator โ Globe
|
|
600
|
+
| `toggle-projection` | Switches Mercator โ Globe |
|
|
528
601
|
| `toggle-terrain` | Toggles terrain layer |
|
|
529
602
|
| `reset-view` | Resets bearing, pitch, and roll |
|
|
530
603
|
| `reset-bearing` | Resets bearing only |
|
|
531
604
|
| `reset-pitch` | Resets pitch only |
|
|
532
605
|
| `reset-roll` | Resets roll only |
|
|
533
|
-
|
|
|
606
|
+
| _(empty)_ | Registers control without built-in functionality |
|
|
534
607
|
|
|
535
608
|
> โ ๏ธ An error is thrown if an unrecognized value is used.
|
|
536
609
|
|
|
537
|
-
|
|
610
|
+
##### Grouping Controls
|
|
538
611
|
|
|
539
612
|
Use `data-maptiler-control-group` to group buttons:
|
|
540
613
|
|
|
@@ -547,7 +620,7 @@ Use `data-maptiler-control-group` to group buttons:
|
|
|
547
620
|
|
|
548
621
|
Groups are styled and positioned together but don't add functionality themselves. Functional behavior is attached to valid descendant elements.
|
|
549
622
|
|
|
550
|
-
|
|
623
|
+
##### Positioning Controls
|
|
551
624
|
|
|
552
625
|
Use `data-maptiler-position` to set placement:
|
|
553
626
|
|
|
@@ -561,12 +634,12 @@ Use `data-maptiler-position` to set placement:
|
|
|
561
634
|
|
|
562
635
|
Valid positions: `'top-left'`, `'top-right'`, `'bottom-left'`, `'bottom-right'`
|
|
563
636
|
|
|
564
|
-
|
|
637
|
+
##### Styling with CSS Variables
|
|
565
638
|
|
|
566
639
|
When declarative controls are enabled, the map container exposes dynamic CSS variables:
|
|
567
640
|
|
|
568
641
|
| Variable | Description | Type |
|
|
569
|
-
|
|
642
|
+
| -------------------------------- | ------------------------------------------------ | --------------- |
|
|
570
643
|
| `--maptiler-center-lng` | Longitude of center | unitless number |
|
|
571
644
|
| `--maptiler-center-lat` | Latitude of center | unitless number |
|
|
572
645
|
| `--maptiler-zoom` | Zoom level | unitless number |
|
|
@@ -576,12 +649,11 @@ When declarative controls are enabled, the map container exposes dynamic CSS var
|
|
|
576
649
|
| `--maptiler-is-globe-projection` | `true` if globe is active<br>`false` otherwise | string |
|
|
577
650
|
| `--maptiler-has-terrain` | `true` if terrain is active<br>`false` otherwise | string |
|
|
578
651
|
|
|
579
|
-
|
|
652
|
+
##### Example
|
|
580
653
|
|
|
581
654
|
```css
|
|
582
655
|
.compass-icon {
|
|
583
|
-
transform: rotateX(calc(var(--maptiler-pitch) * 1deg))
|
|
584
|
-
rotateZ(calc(var(--maptiler-bearing) * -1deg));
|
|
656
|
+
transform: rotateX(calc(var(--maptiler-pitch) * 1deg)) rotateZ(calc(var(--maptiler-bearing) * -1deg));
|
|
585
657
|
}
|
|
586
658
|
|
|
587
659
|
@container style(--maptiler-is-globe-projection: true) {
|
|
@@ -591,14 +663,15 @@ When declarative controls are enabled, the map container exposes dynamic CSS var
|
|
|
591
663
|
}
|
|
592
664
|
```
|
|
593
665
|
|
|
594
|
-
|
|
666
|
+
### 3D terrain in one call
|
|
667
|
+
|
|
595
668
|
<p align="center">
|
|
596
669
|
<img src="images/screenshots/grandcanyon.gif" width="48%"></img>
|
|
597
670
|
<img src="images/screenshots/alps.gif" width="48%"></img>
|
|
598
671
|
</p>
|
|
599
672
|
|
|
600
|
-
|
|
601
673
|
Do you want to enable 3D terrain? That's easy now with a single function call:
|
|
674
|
+
|
|
602
675
|
```ts
|
|
603
676
|
// With the default exaggeration factor of 1
|
|
604
677
|
map.enableTerrain();
|
|
@@ -614,22 +687,24 @@ const map = new Map({
|
|
|
614
687
|
// some options...
|
|
615
688
|
terrain: true,
|
|
616
689
|
terrainExaggeration: 1.5,
|
|
617
|
-
})
|
|
690
|
+
});
|
|
618
691
|
```
|
|
619
692
|
|
|
620
693
|
At any point, you can modify the exaggeration factor:
|
|
694
|
+
|
|
621
695
|
```ts
|
|
622
696
|
map.setTerrainExaggeration(2);
|
|
623
697
|
```
|
|
624
698
|
|
|
625
699
|
Or simply disable it:
|
|
700
|
+
|
|
626
701
|
```ts
|
|
627
|
-
map.disableTerrain()
|
|
702
|
+
map.disableTerrain();
|
|
628
703
|
```
|
|
629
704
|
|
|
630
|
-
> ๐ฃ
|
|
705
|
+
> ๐ฃ _**Note:**_ Keep in mind that setting an exaggeration factor at `0` will result in the same result as disabling the elevation but that terrain RGB tiles will still be fetched in the background.
|
|
631
706
|
|
|
632
|
-
> ๐ฃ
|
|
707
|
+
> ๐ฃ _**Note 2:**_ please be aware that due to the volume and elevation of the map floor in 3D space, the navigation with the terrain enabled is slightly different than without.
|
|
633
708
|
|
|
634
709
|
By default, enabling, disabling or even just updating the terrain exaggeration will result in a 1-second animation. This is possible to modify with the following `Map` method:
|
|
635
710
|
|
|
@@ -638,20 +713,21 @@ By default, enabling, disabling or even just updating the terrain exaggeration w
|
|
|
638
713
|
map.setTerrainAnimationDuration(500);
|
|
639
714
|
```
|
|
640
715
|
|
|
641
|
-
|
|
642
|
-
|
|
716
|
+
#### Terrain events
|
|
717
|
+
|
|
718
|
+
- `"terrain"` event
|
|
643
719
|
|
|
644
720
|
As an extension of Maplibre GL JS, MapTiler SDK is also exposing the terrain event `"terrain"`. This event is triggered when a terrain source is added or removed:
|
|
645
721
|
|
|
646
722
|
```ts
|
|
647
723
|
map.on("terrain", (e) => {
|
|
648
724
|
// your logic here
|
|
649
|
-
})
|
|
725
|
+
});
|
|
650
726
|
```
|
|
651
727
|
|
|
652
728
|
Since MapTiler SDK adds animation and the terrain data is necessary all along, the `"terrain"` event will be called at the very beginning of the terrain animation when enabling and at the very end when disabling.
|
|
653
729
|
|
|
654
|
-
- `"terrainAnimationStart"` and `"terrainAnimationStop"` events
|
|
730
|
+
- `"terrainAnimationStart"` and `"terrainAnimationStop"` events
|
|
655
731
|
|
|
656
732
|
With the animation of the terrain, it can sometimes be convenient to know when the animation starts and ends. These two events are made just for that, here are how they work:
|
|
657
733
|
|
|
@@ -668,6 +744,7 @@ map.on("terrainAnimationStop", (event) => {
|
|
|
668
744
|
The `event` argument is an object that contains (among other things) a `terrain` attribute. In the case of `"terrainAnimationStop"`, this terrain attribute is `null` if the animation was about disabling the terrain, otherwise, this is just a propagation of `map.terrain`.
|
|
669
745
|
|
|
670
746
|
In the following example, we decide to associate the terrain animation with a change of camera, e.g. from clicking on the terrain control:
|
|
747
|
+
|
|
671
748
|
- when the terrain is enabled, it pops up with an animation and only **then** the camera is animated to take a lower point of view
|
|
672
749
|
- when the terrain is disabled, it is flattened with an animation and only **then** the camera is animated to a top view
|
|
673
750
|
|
|
@@ -679,15 +756,19 @@ map.on("terrainAnimationStop", (e) => {
|
|
|
679
756
|
});
|
|
680
757
|
});
|
|
681
758
|
```
|
|
682
|
-
# Halo and Space Options
|
|
683
759
|
|
|
684
|
-
|
|
760
|
+
### Halo and Space Options
|
|
761
|
+
|
|
762
|
+
The `halo` and `space` options allow for enhanced visual customization of the map, especially for globe projections.
|
|
685
763
|
|
|
686
|
-
|
|
687
|
-
|
|
764
|
+
#### `halo` (Atmospheric Glow)
|
|
765
|
+
|
|
766
|
+
The `halo` option adds a gradient-based atmospheric glow around the globe, simulating the visual effect of Earth's atmosphere when viewed from space.
|
|
767
|
+
|
|
768
|
+
##### Usage:
|
|
769
|
+
|
|
770
|
+
You can enable a simple halo by setting it to `true`:
|
|
688
771
|
|
|
689
|
-
### Usage:
|
|
690
|
-
You can enable a simple halo by setting it to `true`:
|
|
691
772
|
```ts
|
|
692
773
|
const map = new maptilersdk.Map({
|
|
693
774
|
container: document.getElementById("map"),
|
|
@@ -695,9 +776,10 @@ const map = new maptilersdk.Map({
|
|
|
695
776
|
halo: true,
|
|
696
777
|
});
|
|
697
778
|
```
|
|
779
|
+
|
|
698
780
|
For more customization, you can define a radial gradient with scale and stops:
|
|
699
|
-
```ts
|
|
700
781
|
|
|
782
|
+
```ts
|
|
701
783
|
const map = new maptilersdk.Map({
|
|
702
784
|
container: document.getElementById("map"),
|
|
703
785
|
style: maptilersdk.MapStyle.OUTDOOR,
|
|
@@ -717,7 +799,9 @@ const map = new maptilersdk.Map({
|
|
|
717
799
|
},
|
|
718
800
|
});
|
|
719
801
|
```
|
|
802
|
+
|
|
720
803
|
You can also set the halo dynamically after the map loads:
|
|
804
|
+
|
|
721
805
|
```ts
|
|
722
806
|
map.on("load", () => {
|
|
723
807
|
map.setHalo({
|
|
@@ -732,17 +816,20 @@ map.on("load", () => {
|
|
|
732
816
|
```
|
|
733
817
|
|
|
734
818
|
To disable state transitions for halo or space:
|
|
819
|
+
|
|
735
820
|
```ts
|
|
736
821
|
map.disableHaloAnimations();
|
|
737
822
|
map.disableSpaceAnimations();
|
|
738
823
|
```
|
|
739
824
|
|
|
740
|
-
|
|
825
|
+
#### `space` (Background Environment)
|
|
741
826
|
|
|
742
827
|
The space option allows customizing the background environment of the globe, simulating deep space or skybox effects.
|
|
743
|
-
|
|
828
|
+
|
|
829
|
+
##### Usage
|
|
744
830
|
|
|
745
831
|
You can enable a simple space background with a solid color:
|
|
832
|
+
|
|
746
833
|
```ts
|
|
747
834
|
const map = new maptilersdk.Map({
|
|
748
835
|
container: document.getElementById("map"),
|
|
@@ -752,16 +839,17 @@ const map = new maptilersdk.Map({
|
|
|
752
839
|
},
|
|
753
840
|
});
|
|
754
841
|
```
|
|
842
|
+
|
|
755
843
|
Alternatively, you can provide a cubemap for a space backround using one of the following methods:
|
|
756
844
|
|
|
757
|
-
|
|
845
|
+
###### Predefined Presets:
|
|
758
846
|
|
|
759
847
|
- `space`: Dark blue hsl(210, 100%, 4%) background and white stars (transparent background image). Space color changes the background color, stars always stay white.
|
|
760
|
-
- `stars` (default): Black background (image mask), space color changes the stars color, background always stays black.
|
|
761
|
-
- `milkyway`: Black half-transparent background with standard milkyway and stars. Space color changes the stars and milkyway color, background always stays black.
|
|
762
|
-
- `milkyway-subtle`: Black half-transparent background with subtle milkyway and less stars.
|
|
763
|
-
- `milkyway-bright`: Black half-transparent background with bright milkyway and more stars.
|
|
764
|
-
- `milkyway-colored`: Full background image with natural space colors.
|
|
848
|
+
- `stars` (default): Black background (image mask), space color changes the stars color, background always stays black.
|
|
849
|
+
- `milkyway`: Black half-transparent background with standard milkyway and stars. Space color changes the stars and milkyway color, background always stays black.
|
|
850
|
+
- `milkyway-subtle`: Black half-transparent background with subtle milkyway and less stars. Space color changes the stars and milkyway color, background always stays black.Black half-transparent background with standard milkyway and stars. Space color changes the stars and milkyway color, background always stays black.
|
|
851
|
+
- `milkyway-bright`: Black half-transparent background with bright milkyway and more stars. Space color changes the stars and milkyway color, background always stays black.
|
|
852
|
+
- `milkyway-colored`: Full background image with natural space colors. Space color doesnโt change anything (non transparent image).
|
|
765
853
|
|
|
766
854
|
```ts
|
|
767
855
|
const map = new maptilersdk.Map({
|
|
@@ -772,39 +860,45 @@ const map = new maptilersdk.Map({
|
|
|
772
860
|
},
|
|
773
861
|
});
|
|
774
862
|
```
|
|
775
|
-
|
|
863
|
+
|
|
864
|
+
###### Cubemap Images (Custom Skybox):
|
|
865
|
+
|
|
776
866
|
```ts
|
|
777
867
|
const map = new maptilersdk.Map({
|
|
778
868
|
container: document.getElementById("map"),
|
|
779
869
|
style: maptilersdk.MapStyle.OUTDOOR,
|
|
780
870
|
space: {
|
|
781
871
|
faces: {
|
|
782
|
-
nX:
|
|
783
|
-
nY:
|
|
784
|
-
nZ:
|
|
785
|
-
pX:
|
|
786
|
-
pY:
|
|
787
|
-
pZ:
|
|
872
|
+
nX: "/path-to-image/nX.png",
|
|
873
|
+
nY: "/path-to-image/nY.png",
|
|
874
|
+
nZ: "/path-to-image/nZ.png",
|
|
875
|
+
pX: "/path-to-image/pX.png",
|
|
876
|
+
pY: "/path-to-image/pY.png",
|
|
877
|
+
pZ: "/path-to-image/pZ.png",
|
|
788
878
|
},
|
|
789
879
|
},
|
|
790
880
|
});
|
|
791
881
|
```
|
|
792
|
-
|
|
882
|
+
|
|
883
|
+
###### Cubemap Path with image format
|
|
793
884
|
|
|
794
885
|
This fetches all images from a path, this assumes all files are named px, nx, py, ny, pz, nz and suffixed with the appropriate extension specified in `format`.
|
|
886
|
+
|
|
795
887
|
```ts
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
888
|
+
const map = new maptilersdk.Map({
|
|
889
|
+
container: document.getElementById("map"),
|
|
890
|
+
style: maptilersdk.MapStyle.OUTDOOR,
|
|
891
|
+
space: {
|
|
892
|
+
path: {
|
|
893
|
+
baseUrl: "spacebox/transparent",
|
|
894
|
+
format: "png", // Defaults to PNG
|
|
895
|
+
},
|
|
896
|
+
},
|
|
897
|
+
});
|
|
806
898
|
```
|
|
807
|
-
|
|
899
|
+
|
|
900
|
+
###### Set the space background dynamically:
|
|
901
|
+
|
|
808
902
|
```ts
|
|
809
903
|
map.on("load", () => {
|
|
810
904
|
map.setSpace({
|
|
@@ -820,7 +914,7 @@ Note: if `space.color` or `space.<faces | path | preset>` are not explicitly set
|
|
|
820
914
|
|
|
821
915
|
Further code examples can be found in `~/demos/`
|
|
822
916
|
|
|
823
|
-
|
|
917
|
+
### `ImageViewer`
|
|
824
918
|
|
|
825
919
|
MapTiler's `ImageViewer` component allows you to display tiled, non-georeferenced images but interact with them in almost the same way you would if you were displaying map. These can be handy for zoomable non-georeferenced, geographically "inaccurate" maps such as hotel maps, golf courses, theme parks etc. Think pixels instead of lattitudes and longtidues.
|
|
826
920
|
|
|
@@ -831,7 +925,7 @@ MapTiler's `ImageViewer` component allows you to display tiled, non-georeference
|
|
|
831
925
|
container: string | HTMLElement // the container element you want to mount the viewer on
|
|
832
926
|
apiKey: string; // your MapTiler API Key
|
|
833
927
|
zoom?: number;
|
|
834
|
-
maxZoom?: number;
|
|
928
|
+
maxZoom?: number;
|
|
835
929
|
minZoom?: number;
|
|
836
930
|
bearing?: number;
|
|
837
931
|
debug?: boolean; // whether you want to debug the tiles
|
|
@@ -851,71 +945,82 @@ MapTiler's `ImageViewer` component allows you to display tiled, non-georeference
|
|
|
851
945
|
imageViewer.on("imageviewerready", () => { console.log('Ready!') })
|
|
852
946
|
```
|
|
853
947
|
|
|
854
|
-
|
|
948
|
+
#### Methods
|
|
949
|
+
|
|
855
950
|
`ImageViewer` provides a subset of methods for interaction with the map. A major caveat is that the `ImageViewer` component works in pixels and not in LngLat. Thus, when using methods such as `setCenter` or `flyTo` the pixel values provided refer to the _absolute pixel position_ on the image, not screen pixel position.
|
|
856
951
|
|
|
857
952
|
Imagine your image is 10,000px x 10,000px, if regardless if your zoom is 2 or 4, calling `.setCenter(500,500)` will always position the viewer over the same part of the image.
|
|
858
953
|
|
|
859
954
|
For full details on supported methods see the type declaration for `ImageViewer` or visit the (docs)[https://docs.maptiler.com/sdk-js/examples/image-viewer/].
|
|
860
955
|
|
|
861
|
-
|
|
956
|
+
#### Events
|
|
957
|
+
|
|
862
958
|
In a similar manner, a subset of map events are fired by the image viewer. All UI interaction events that would normally include a `LngLat` in the event data instead receive an `imageX` and `imageY` field, representing an absolute pixel position of the image. This is same for `flyTo`, `jumpTo`, `panTo` etc.
|
|
863
959
|
|
|
864
960
|
A full list of supported events can be found in the exported type declaration `ImageViewerEventTypes`
|
|
865
961
|
|
|
866
|
-
|
|
962
|
+
#### Markers with `ImageViewerMarker`
|
|
867
963
|
|
|
868
964
|
An `ImageViewerMarker` can also be added and used like the usual `Marker`class, the main difference being it operates in _image pixels_, not LngLat coordinates.
|
|
869
965
|
|
|
870
966
|
```ts
|
|
871
|
-
|
|
967
|
+
const marker = new ImageViewerMarker({ draggable: true });
|
|
872
968
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
969
|
+
marker
|
|
970
|
+
.setPosition([100, 100]) // position in image pixels.
|
|
971
|
+
.addTo(imageViewer)
|
|
972
|
+
.on("dragend", (e) => {
|
|
973
|
+
console.log("e.target.isWithinImageBounds()", e.target.isWithinImageBounds());
|
|
974
|
+
});
|
|
879
975
|
```
|
|
880
976
|
|
|
881
977
|
Full API documentation can be found in the typedocs: `npm run doc`
|
|
882
978
|
|
|
883
|
-
|
|
979
|
+
### Easy language switching
|
|
980
|
+
|
|
884
981
|
The language generally depends on the style but we made it possible to easily set and update from a built-in list of languages.
|
|
885
982
|
|
|
886
983
|
The built-in list of supported languages is accessible from the `Language` object:
|
|
984
|
+
|
|
887
985
|
```ts
|
|
888
986
|
import { Language } from "@maptiler/sdk";
|
|
889
987
|
```
|
|
988
|
+
|
|
890
989
|
In the UMD bundle, it will be directly at `maptilersdk.Language`.
|
|
891
990
|
|
|
892
991
|
There are three distinct ways to set the language of a map:
|
|
893
992
|
|
|
894
993
|
1. **Global way, using the config object:**
|
|
994
|
+
|
|
895
995
|
```ts
|
|
896
996
|
import { config } from "@maptiler/sdk";
|
|
897
997
|
|
|
898
998
|
config.primaryLanguage = Language.ENGLISH;
|
|
899
999
|
```
|
|
900
|
-
|
|
1000
|
+
|
|
1001
|
+
Then, if any further language setting is applied, all the map instances created afterward will use this language.
|
|
901
1002
|
|
|
902
1003
|
2. **Set the language at instantiation time:**
|
|
1004
|
+
|
|
903
1005
|
```ts
|
|
904
1006
|
const map = new Map({
|
|
905
1007
|
// some options...
|
|
906
1008
|
language: Language.ENGLISH, // the ISO codes can also be used (eg. "en")
|
|
907
|
-
})
|
|
1009
|
+
});
|
|
908
1010
|
```
|
|
1011
|
+
|
|
909
1012
|
It will only apply `ENGLISH` as the language of this specific map instance (and will not alter the global `config`).
|
|
910
1013
|
|
|
911
1014
|
3. **Set the language after the map has been instantiated:**
|
|
1015
|
+
|
|
912
1016
|
```ts
|
|
913
1017
|
map.setLanguage(Language.ENGLISH);
|
|
914
1018
|
```
|
|
1019
|
+
|
|
915
1020
|
Again, it will only apply `ENGLISH` as the language of this specific map instance (and will not alter the global `config`).
|
|
916
1021
|
|
|
1022
|
+
The list of supported languages is built-in and can be found [here](src/language.ts). In addition, there are special language _flags_:
|
|
917
1023
|
|
|
918
|
-
The list of supported languages is built-in and can be found [here](src/language.ts). In addition, there are special language *flags*:
|
|
919
1024
|
- `Language.AUTO` **[DEFAULT]** uses the language defined in the web browser
|
|
920
1025
|
- `Language.STYLE_LOCK` to strictly use the language defined in the style. Prevents any further language update
|
|
921
1026
|
- `Language.LOCAL` uses the language local to each country
|
|
@@ -927,7 +1032,8 @@ Whenever a label is not supported in the defined language, it falls back to `Lan
|
|
|
927
1032
|
Here is a sample of some compatible languages:
|
|
928
1033
|

|
|
929
1034
|
|
|
930
|
-
|
|
1035
|
+
#### Built-in support for right-to-left languages
|
|
1036
|
+
|
|
931
1037
|
Languages that are written right-to-left such as Arabic and Hebrew are fully supported by default. No need to install any plugins!
|
|
932
1038
|
|
|
933
1039
|
If you wish to opt of applying the rtl plugin or wish to use a different compatible rtl text plugin, you can pass the `rtlTextPlugin`
|
|
@@ -940,23 +1046,25 @@ constructor option as either `false` (disable the rtl plugin) or a url to load a
|
|
|
940
1046
|
<img src="images/screenshots/lang-hebrew.jpeg" width="48%"></img>
|
|
941
1047
|
</p>
|
|
942
1048
|
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
1049
|
+
#### Visitor language modes
|
|
1050
|
+
|
|
1051
|
+
The _visitor_ language modes are special built-in modes made to display labels in two different languages, concatenated when available:
|
|
1052
|
+
|
|
1053
|
+
- `Language.VISITOR` concatenates labels in the language of your system and the _local_ language
|
|
1054
|
+
- `Language.VISITOR_ENGLISH` concatenates labels in English and the _local_ language
|
|
947
1055
|
|
|
948
1056
|
```ts
|
|
949
1057
|
const map = new Map({
|
|
950
1058
|
// some options...
|
|
951
1059
|
language: Language.VISITOR,
|
|
952
|
-
})
|
|
1060
|
+
});
|
|
953
1061
|
|
|
954
1062
|
// or
|
|
955
1063
|
|
|
956
1064
|
const map = new Map({
|
|
957
1065
|
// some options...
|
|
958
1066
|
language: Language.VISITOR_ENGLISH,
|
|
959
|
-
})
|
|
1067
|
+
});
|
|
960
1068
|
```
|
|
961
1069
|
|
|
962
1070
|
We believe these two modes can be very handy to help the end users identify places, especially when the local labels are not using a latin charset. Here is how it looks like:
|
|
@@ -964,10 +1072,12 @@ We believe these two modes can be very handy to help the end users identify plac
|
|
|
964
1072
|

|
|
965
1073
|

|
|
966
1074
|
|
|
1075
|
+
### Custom Events and Map Lifecycle
|
|
1076
|
+
|
|
1077
|
+
#### Events
|
|
1078
|
+
|
|
1079
|
+
##### The `ready` event
|
|
967
1080
|
|
|
968
|
-
# Custom Events and Map Lifecycle
|
|
969
|
-
## Events
|
|
970
|
-
### The `ready` event
|
|
971
1081
|
The `ready` event happens just after the `load` event but waits until all the controls managed by the `Map` constructor are dealt with, some having an asynchronous logic to set up.
|
|
972
1082
|
Since the `ready` event waits until all the basic controls are nicely positioned, it is **safer** to use `ready` than `load` if you plan to add other custom controls with the `.addControl()` method.
|
|
973
1083
|
|
|
@@ -981,23 +1091,25 @@ const map = new maptilersdk.Map({
|
|
|
981
1091
|
map.on("ready", (evt) => {
|
|
982
1092
|
const terrainControl = new maptilersdk.MaptilerTerrainControl();
|
|
983
1093
|
map.addControl(terrainControl);
|
|
984
|
-
})
|
|
1094
|
+
});
|
|
985
1095
|
```
|
|
986
1096
|
|
|
987
|
-
|
|
988
|
-
|
|
1097
|
+
##### The `loadWithTerrain` event
|
|
1098
|
+
|
|
1099
|
+
The `loadWithTerrain` event is triggered only _once_ in a `Map` instance lifecycle, when both the `ready` event and the `terrain` event **with non-null terrain** are fired.
|
|
989
1100
|
|
|
990
1101
|
**Why a new event?**
|
|
991
1102
|
When a map is instantiated with the option `terrain: true`, then MapTiler terrain is directly added to it and some animation functions such as `.flyTo()` or `.easeTo()` if started straight after the map initialization will actually need to wait a few milliseconds that the terrain is properly initialized before running.
|
|
992
1103
|
Relying on the `ready` or `load` event to run an animation with a map with terrain may fail in some cases for this reason, and this is why waiting for `loadWithTerrain` is safer in this particular situation.
|
|
993
1104
|
|
|
994
|
-
|
|
995
|
-
|
|
1105
|
+
#### Lifecycle Methods
|
|
1106
|
+
|
|
1107
|
+
The events `load`, `ready` and `loadWithTerrain` are both called _at most once_ and require a callback function to add more elements such as markers, layers, popups and data sources. Even though MapTiler SDK fully supports this logic, we have also included a _promise_ logic to provide a more linear and less nested way to wait for a Map instance to be usable. Let's compare the two ways:
|
|
996
1108
|
|
|
997
1109
|
- Classic: with a callback on the `load` event:
|
|
1110
|
+
|
|
998
1111
|
```ts
|
|
999
1112
|
function init() {
|
|
1000
|
-
|
|
1001
1113
|
const map = new Map({
|
|
1002
1114
|
container,
|
|
1003
1115
|
center: [2.34804, 48.85439], // Paris, France
|
|
@@ -1008,18 +1120,18 @@ function init() {
|
|
|
1008
1120
|
// Once triggered, the callback is ran in its own scope.
|
|
1009
1121
|
map.on("load", (evt) => {
|
|
1010
1122
|
// Adding a data source
|
|
1011
|
-
map.addSource(
|
|
1123
|
+
map.addSource("my-gps-track-source", {
|
|
1012
1124
|
type: "geojson",
|
|
1013
1125
|
data: "https://example.com/some-gps-track.geojson",
|
|
1014
1126
|
});
|
|
1015
|
-
})
|
|
1127
|
+
});
|
|
1016
1128
|
}
|
|
1017
1129
|
```
|
|
1018
1130
|
|
|
1019
1131
|
- Modern: with a promise returned by the method `.onLoadAsync()`, used in an `async` function:
|
|
1132
|
+
|
|
1020
1133
|
```ts
|
|
1021
1134
|
async function init() {
|
|
1022
|
-
|
|
1023
1135
|
const map = new Map({
|
|
1024
1136
|
container,
|
|
1025
1137
|
center: [2.34804, 48.85439], // Paris, France
|
|
@@ -1031,7 +1143,7 @@ async function init() {
|
|
|
1031
1143
|
await map.onLoadAsync();
|
|
1032
1144
|
|
|
1033
1145
|
// Adding a data source
|
|
1034
|
-
map.addSource(
|
|
1146
|
+
map.addSource("my-gps-track-source", {
|
|
1035
1147
|
type: "geojson",
|
|
1036
1148
|
data: "https://example.com/some-gps-track.geojson",
|
|
1037
1149
|
});
|
|
@@ -1039,10 +1151,11 @@ async function init() {
|
|
|
1039
1151
|
```
|
|
1040
1152
|
|
|
1041
1153
|
We deployed exactly the same logic for the `loadWithTerrain` event. Let's see how the two ways compare.
|
|
1154
|
+
|
|
1042
1155
|
- Classic: with a callback on the `loadWithTerrain` event:
|
|
1156
|
+
|
|
1043
1157
|
```ts
|
|
1044
1158
|
function init() {
|
|
1045
|
-
|
|
1046
1159
|
const map = new Map({
|
|
1047
1160
|
container,
|
|
1048
1161
|
center: [2.34804, 48.85439], // Paris, France
|
|
@@ -1057,15 +1170,15 @@ function init() {
|
|
|
1057
1170
|
map.flyTo({
|
|
1058
1171
|
center: [-0.09956, 51.50509], // London, UK
|
|
1059
1172
|
zoom: 12.5,
|
|
1060
|
-
})
|
|
1061
|
-
})
|
|
1173
|
+
});
|
|
1174
|
+
});
|
|
1062
1175
|
}
|
|
1063
1176
|
```
|
|
1064
1177
|
|
|
1065
1178
|
- Modern: with a promise returned by the method `.onLoadWithTerrainAsync()`, used in an `async` function:
|
|
1179
|
+
|
|
1066
1180
|
```ts
|
|
1067
1181
|
async function init() {
|
|
1068
|
-
|
|
1069
1182
|
const map = new Map({
|
|
1070
1183
|
container,
|
|
1071
1184
|
center: [2.34804, 48.85439], // Paris, France
|
|
@@ -1081,15 +1194,16 @@ async function init() {
|
|
|
1081
1194
|
map.flyTo({
|
|
1082
1195
|
center: [-0.09956, 51.50509], // London, UK
|
|
1083
1196
|
zoom: 12.5,
|
|
1084
|
-
})
|
|
1197
|
+
});
|
|
1085
1198
|
}
|
|
1086
1199
|
```
|
|
1087
1200
|
|
|
1088
1201
|
And finally, the lifecycle method corresponding to the `ready` event:
|
|
1202
|
+
|
|
1089
1203
|
- Classic: with a callback on the `ready` event:
|
|
1204
|
+
|
|
1090
1205
|
```ts
|
|
1091
1206
|
function init() {
|
|
1092
|
-
|
|
1093
1207
|
const map = new Map({
|
|
1094
1208
|
container,
|
|
1095
1209
|
center: [2.34804, 48.85439], // Paris, France
|
|
@@ -1100,18 +1214,18 @@ function init() {
|
|
|
1100
1214
|
// Once triggered, the callback is ran in its own scope.
|
|
1101
1215
|
map.on("ready", (evt) => {
|
|
1102
1216
|
// Adding a data source
|
|
1103
|
-
map.addSource(
|
|
1217
|
+
map.addSource("my-gps-track-source", {
|
|
1104
1218
|
type: "geojson",
|
|
1105
1219
|
data: "https://example.com/some-gps-track.geojson",
|
|
1106
1220
|
});
|
|
1107
|
-
})
|
|
1221
|
+
});
|
|
1108
1222
|
}
|
|
1109
1223
|
```
|
|
1110
1224
|
|
|
1111
1225
|
- Modern: with a promise returned by the method `.onReadyAsync()`, used in an `async` function:
|
|
1226
|
+
|
|
1112
1227
|
```ts
|
|
1113
1228
|
async function init() {
|
|
1114
|
-
|
|
1115
1229
|
const map = new Map({
|
|
1116
1230
|
container,
|
|
1117
1231
|
center: [2.34804, 48.85439], // Paris, France
|
|
@@ -1123,48 +1237,51 @@ async function init() {
|
|
|
1123
1237
|
await map.onReadyAsync();
|
|
1124
1238
|
|
|
1125
1239
|
// Adding a data source
|
|
1126
|
-
map.addSource(
|
|
1240
|
+
map.addSource("my-gps-track-source", {
|
|
1127
1241
|
type: "geojson",
|
|
1128
1242
|
data: "https://example.com/some-gps-track.geojson",
|
|
1129
1243
|
});
|
|
1130
1244
|
}
|
|
1131
1245
|
```
|
|
1132
1246
|
|
|
1133
|
-
We believe that the
|
|
1247
|
+
We believe that the _promise_ approach is better because it does not nest scopes and will allow for a linear non-nested stream of execution. It also corresponds to more modern development standards.
|
|
1134
1248
|
|
|
1135
|
-
> ๐ฃ
|
|
1249
|
+
> ๐ฃ _**Note:**_ Generally speaking, _promises_ are not a go to replacement for all event+callback and are suitable only for events that are called only once in the lifecycle of a Map instance. This is the reason why we have decided to provide a _promise_ equivalent only for the `load`, `ready` and `loadWithTerrain` events but not for events that may be called multiple time such as interaction events.
|
|
1250
|
+
|
|
1251
|
+
##### The `webglContextLost` event
|
|
1136
1252
|
|
|
1137
|
-
### The `webglContextLost` event
|
|
1138
1253
|
The map is rendered with WebGL, that leverages the GPU to provide high-performance graphics. In some cases, the host machine, operating system or the graphics driver, can decide that continuing to run such high performance graphics is unsustainable, and will abort the process. This is called a "WebGL context loss". Such situation happens when the resources are running low or when multiple browser tabs are competing to access graphics memory.
|
|
1139
1254
|
|
|
1140
1255
|
The best course of action in such situation varies from an app to another. Sometimes a page refresh is the best thing to do, in other cases, instantiating a new Map dynamically at application level is more appropriate because it hides a technical failure to the end user. The event `webglContextLost` is exposed so that the most appropriate scenario can be implemented at application level.
|
|
1141
1256
|
|
|
1142
1257
|
Here is how to respond to a WebGL context loss with a simple page refresh:
|
|
1143
|
-
```ts
|
|
1144
1258
|
|
|
1259
|
+
```ts
|
|
1145
1260
|
// Init the map
|
|
1146
1261
|
const map = new maptilersdk.Map({
|
|
1147
1262
|
container: "map-container",
|
|
1148
1263
|
hash: true,
|
|
1149
|
-
})
|
|
1264
|
+
});
|
|
1150
1265
|
|
|
1151
1266
|
// Refresh the page if context is lost.
|
|
1152
1267
|
// Since `hash` is true, the location will be the same as before
|
|
1153
1268
|
map.on("webglContextLost", (e) => {
|
|
1154
1269
|
location.reload();
|
|
1155
|
-
})
|
|
1270
|
+
});
|
|
1156
1271
|
```
|
|
1157
1272
|
|
|
1158
|
-
|
|
1159
|
-
|
|
1273
|
+
### Color Ramps
|
|
1274
|
+
|
|
1275
|
+
A color ramp is a color gradient defined in a specific interval, for instance in [0, 1], and for any value within this interval will retrieve a color. They are defined by at least a color at each bound and usually additional colors within the range.
|
|
1160
1276
|
|
|
1161
|
-
Color ramps are super useful to represent numerical data in a visual way: the temperature, the population density, the average commute time, etc.
|
|
1277
|
+
Color ramps are super useful to represent numerical data in a visual way: the temperature, the population density, the average commute time, etc.
|
|
1162
1278
|
|
|
1163
1279
|
The SDK includes many built-in ready-to-use color ramps as well as extra logic to manipulate them and create new ones, here is the full list:
|
|
1164
1280
|
|
|
1165
1281
|

|
|
1166
1282
|
|
|
1167
1283
|
To use an already existing color ramp and access some of its values:
|
|
1284
|
+
|
|
1168
1285
|
```ts
|
|
1169
1286
|
import { ColorRampCollection } from "@maptiler/sdk";
|
|
1170
1287
|
|
|
@@ -1182,7 +1299,7 @@ const zeroColorHex = temperatureTurbo.getColorHex(0);
|
|
|
1182
1299
|
// The color is a string: "#2ddabdff"
|
|
1183
1300
|
```
|
|
1184
1301
|
|
|
1185
|
-
Creating a new one consists of defining all the colors for each
|
|
1302
|
+
Creating a new one consists of defining all the colors for each _color stops_. The values can be in the range of interest and _do not_ have to be in [0, 1]. For example, let's recreate a _Viridis_ color ramp but with a range going from 0 to 100:
|
|
1186
1303
|
|
|
1187
1304
|
```ts
|
|
1188
1305
|
import { ColorRamp } from "@maptiler/sdk";
|
|
@@ -1198,55 +1315,60 @@ const myCustomRamp = new ColorRamp({
|
|
|
1198
1315
|
{ value: 75, color: [92, 200, 99] },
|
|
1199
1316
|
{ value: 88, color: [170, 220, 50] },
|
|
1200
1317
|
{ value: 100, color: [253, 231, 37] },
|
|
1201
|
-
]
|
|
1318
|
+
],
|
|
1202
1319
|
});
|
|
1203
1320
|
```
|
|
1204
1321
|
|
|
1205
|
-
When defining a new
|
|
1322
|
+
When defining a new _ramp_, the colors can be an RGB array (`[number, number, number]`) or an RGBA array (`[number, number, number, number]`).
|
|
1206
1323
|
|
|
1207
1324
|
Many methods are available on color ramps, such as getting the `<canvas>` element of it, rescaling it, flipping it or [resampling it in a non-linear way](colorramp.md). Read more on [our reference page](https://docs.maptiler.com/sdk-js/api/color-ramp/) and have a look at our [examples](https://docs.maptiler.com/sdk-js/examples/?q=colorramp) to see how they work.
|
|
1208
1325
|
|
|
1326
|
+
### Vector Layer Helpers
|
|
1209
1327
|
|
|
1210
|
-
# Vector Layer Helpers
|
|
1211
1328
|
**Let's make vector layers easy!** Originally, you'd have to add a source and then proceed to the styling of your layer, which can be tricky because there are a lot of `paint` and `layout` options and they vary a lot from one type of layer to another. **But we have helpers for this!** ๐๏ธ
|
|
1212
1329
|

|
|
1213
1330
|
|
|
1214
|
-
|
|
1331
|
+
#### Shared logic
|
|
1332
|
+
|
|
1215
1333
|
Helpers come with a lot of **built-in defaults** and some fail-proof logic that makes creating vector layers much easier! As a result, a dataset can be displayed in one call, creating both the datasource and the layer(s) in one go!
|
|
1216
1334
|
|
|
1217
1335
|
Depending on the type of feature to add (point, polyline, polygon or heatmap), a different helper function needs to be used, but datasource could contain mixed types of feature and the helper will only display a specific type.
|
|
1218
1336
|
|
|
1219
1337
|
All the helpers are made available under the `helpers` object. If you are using ES Modules, this is how you access them:
|
|
1338
|
+
|
|
1220
1339
|
```ts
|
|
1221
1340
|
import { Map, helpers } from "@maptiler/sdk";
|
|
1222
1341
|
```
|
|
1223
1342
|
|
|
1224
1343
|
If you are using the UMD bundle of the SDK, for example from our CDN, you will find the `helpers` with:
|
|
1344
|
+
|
|
1225
1345
|
```js
|
|
1226
|
-
maptilersdk.helpers
|
|
1346
|
+
maptilersdk.helpers;
|
|
1227
1347
|
```
|
|
1228
1348
|
|
|
1229
|
-
**Example:** we have a
|
|
1349
|
+
**Example:** we have a _geoJSON_ file that contains both _polygons_ and _point_ and we use it as the `data` property on the `helpers.addPoint(map, { options })`, this will only add the _points_.
|
|
1230
1350
|
|
|
1231
1351
|
In addition to easy styling, the helpers' datasource can be:
|
|
1352
|
+
|
|
1232
1353
|
- a URL to a geoJSON file or its string content
|
|
1233
1354
|
- a URL to a GPX or KML file (only for the polyline helper) or its string content
|
|
1234
|
-
- a UUID of a MapTiler
|
|
1355
|
+
- a UUID of a MapTiler dataset
|
|
1356
|
+
|
|
1357
|
+
##### Multiple Layers
|
|
1235
1358
|
|
|
1236
|
-
### Multiple Layers
|
|
1237
1359
|
The key design principle of these vector layer helpers is **it's easy to make what you want**, which is very different from **making MapLibre easier to use**.
|
|
1238
1360
|
|
|
1239
|
-
> For example, to create a road with an outline, one must draw two layers: a wider base layer and a narrower top layer, fueled by the same polyline data. This requires ordering the layers properly and computing not the width of the outline, but rather the width of the polyline underneath so that it outgrows the top road layer of the desired number of pixels.
|
|
1361
|
+
> For example, to create a road with an outline, one must draw two layers: a wider base layer and a narrower top layer, fueled by the same polyline data. This requires ordering the layers properly and computing not the width of the outline, but rather the width of the polyline underneath so that it outgrows the top road layer of the desired number of pixels.
|
|
1240
1362
|
|
|
1241
1363
|
With the polyline helper, you just say if you want an outline and specify its size (or even a zoom-dependent size) and everything is handled for you. As a result, calling the method `helpers.addPolyline` will return an object with **multiple IDs**: the ID of the top/main layer, the ID of the outline layer (could be `null`) and the ID of the data source. This makes further layer and source manipulation possible.
|
|
1242
1364
|
|
|
1243
|
-
|
|
1365
|
+
##### Input
|
|
1244
1366
|
|
|
1245
|
-
The vector layer helper also shares some
|
|
1367
|
+
The vector layer helper also shares some _I/O_ logic: each of them can take many options but a subset of them is common across all the helpers:
|
|
1246
1368
|
|
|
1247
1369
|
```ts
|
|
1248
1370
|
/**
|
|
1249
|
-
* A geojson Feature collection or a URL to a geojson or the UUID of a MapTiler
|
|
1371
|
+
* A geojson Feature collection or a URL to a geojson or the UUID of a MapTiler dataset.
|
|
1250
1372
|
*/
|
|
1251
1373
|
data: FeatureCollection | string;
|
|
1252
1374
|
|
|
@@ -1284,23 +1406,25 @@ minzoom?: number;
|
|
|
1284
1406
|
maxzoom?: number;
|
|
1285
1407
|
```
|
|
1286
1408
|
|
|
1409
|
+
#### Polyline Layer Helper
|
|
1287
1410
|
|
|
1288
|
-
|
|
1289
|
-
## Polyline Layer Helper
|
|
1290
|
-
The method `helpers.addPolyline` is not only compatible with the traditional GeoJSON source but also with **GPX** and **KML** files and the `.data` options can be a MapTiler Cloud dataset UUID and will be resolved automatically.
|
|
1411
|
+
The method `helpers.addPolyline` is not only compatible with the traditional GeoJSON source but also with **GPX** and **KML** files and the `.data` options can be a MapTiler dataset UUID and will be resolved automatically.
|
|
1291
1412
|
|
|
1292
1413
|
here is the minimal usage, with the default line width and a random color (within a selected list):
|
|
1414
|
+
|
|
1293
1415
|
```ts
|
|
1294
|
-
helpers.addPolyline(map, {
|
|
1416
|
+
helpers.addPolyline(map, {
|
|
1295
1417
|
// A URL, relative or absolute
|
|
1296
1418
|
data: "some-trace.geojson",
|
|
1297
1419
|
});
|
|
1298
1420
|
```
|
|
1421
|
+
|
|
1299
1422
|

|
|
1300
1423
|
|
|
1301
|
-
We can add many options, such as specific color, a custom width or a dash pattern, this time sourcing the data from MapTiler
|
|
1424
|
+
We can add many options, such as specific color, a custom width or a dash pattern, this time sourcing the data from MapTiler, using the UUID of a dataset:
|
|
1425
|
+
|
|
1302
1426
|
```ts
|
|
1303
|
-
helpers.addPolyline(map, {
|
|
1427
|
+
helpers.addPolyline(map, {
|
|
1304
1428
|
data: "74003ba7-215a-4b7e-8e26-5bbe3aa70b05",
|
|
1305
1429
|
lineColor: "#FF6666",
|
|
1306
1430
|
lineWidth: 4,
|
|
@@ -1308,20 +1432,24 @@ helpers.addPolyline(map, {
|
|
|
1308
1432
|
lineCap: "butt",
|
|
1309
1433
|
});
|
|
1310
1434
|
```
|
|
1435
|
+
|
|
1311
1436
|

|
|
1312
|
-
As you can see, we've come up with a fun and easy way to create **dash arrays**, just use
|
|
1437
|
+
As you can see, we've come up with a fun and easy way to create **dash arrays**, just use _underscores_ and _white spaces_ and this pattern will repeat!
|
|
1313
1438
|
|
|
1314
1439
|
Adding an outline is also pretty straightforward:
|
|
1440
|
+
|
|
1315
1441
|
```ts
|
|
1316
|
-
helpers.addPolyline(map, {
|
|
1442
|
+
helpers.addPolyline(map, {
|
|
1317
1443
|
data: "74003ba7-215a-4b7e-8e26-5bbe3aa70b05",
|
|
1318
1444
|
lineColor: "#880000",
|
|
1319
1445
|
outline: true,
|
|
1320
1446
|
});
|
|
1321
1447
|
```
|
|
1448
|
+
|
|
1322
1449
|

|
|
1323
1450
|
|
|
1324
1451
|
Endless possibilities, what about a glowing wire?
|
|
1452
|
+
|
|
1325
1453
|
```ts
|
|
1326
1454
|
helpers.addPolyline(map, {
|
|
1327
1455
|
data: "74003ba7-215a-4b7e-8e26-5bbe3aa70b05",
|
|
@@ -1334,12 +1462,13 @@ helpers.addPolyline(map, {
|
|
|
1334
1462
|
outlineOpacity: 0.5,
|
|
1335
1463
|
});
|
|
1336
1464
|
```
|
|
1337
|
-

|
|
1338
1465
|
|
|
1466
|
+

|
|
1339
1467
|
|
|
1340
1468
|
All the other options are documented on [our reference page](https://docs.maptiler.com/sdk-js/api/helpers/#polyline) and more examples are available [here](https://docs.maptiler.com/sdk-js/examples/?q=polyline+helper).
|
|
1341
1469
|
|
|
1342
|
-
|
|
1470
|
+
#### Polygon Layer Helper
|
|
1471
|
+
|
|
1343
1472
|
The polygon helper makes it easy to create vector layers that contain polygons, whether they are *multi*polygons, *holed*polygons or just simple polygons. Whenever it's possible and it makes sense, we use the same terminology across the different helpers.
|
|
1344
1473
|
|
|
1345
1474
|
Here is a minimalist example, with a half-transparent polygon of Switzerland, from a local file:
|
|
@@ -1367,33 +1496,40 @@ helpers.addPolygon(map, {
|
|
|
1367
1496
|
fillOpacity: 0.7,
|
|
1368
1497
|
});
|
|
1369
1498
|
```
|
|
1499
|
+
|
|
1370
1500
|

|
|
1371
1501
|
|
|
1372
1502
|
All the other options are documented on [our reference page](https://docs.maptiler.com/sdk-js/api/helpers/#polygon) and more examples are available [here](https://docs.maptiler.com/sdk-js/examples/?q=polygon+helper).
|
|
1373
1503
|
|
|
1374
|
-
|
|
1504
|
+
#### Point Layer Helper
|
|
1505
|
+
|
|
1375
1506
|
A point visualization may appear like the simplest of all, but we noticed this is where people get the most creative: cluster, data-driven variable radius, but also scaled with zoom, with or without labels, data-driven colors, etc. Our helper supports all of these and will fill-in with built-in default for what's missing.
|
|
1376
1507
|
|
|
1377
1508
|
Here is the simplest example, with a dataset loaded from a local file:
|
|
1509
|
+
|
|
1378
1510
|
```ts
|
|
1379
1511
|
helpers.addPoint(map, {
|
|
1380
1512
|
data: "public-schools.geojson",
|
|
1381
|
-
})
|
|
1513
|
+
});
|
|
1382
1514
|
```
|
|
1515
|
+
|
|
1383
1516
|
if no color is specified, a random color is used and the default radius is ramped over the zoom level:
|
|
1384
1517
|

|
|
1385
1518
|
|
|
1386
|
-
Here is the same dataset, but with
|
|
1519
|
+
Here is the same dataset, but with _point clustering_ enabled:
|
|
1520
|
+
|
|
1387
1521
|
```ts
|
|
1388
1522
|
helpers.addPoint(map, {
|
|
1389
1523
|
data: "public-schools.geojson",
|
|
1390
1524
|
cluster: true,
|
|
1391
1525
|
});
|
|
1392
1526
|
```
|
|
1527
|
+
|
|
1393
1528
|
On the other hand, if clusters are enabled, the default color is fueled by the color ramp `TURBO` scaled from `10` to `10000` non-linearly resampled with the method `"ease-out-square"`. The size also varies from `minPointradius` (default: `10`) to `maxPointRadius` (default: `50`):
|
|
1394
1529
|

|
|
1395
1530
|
|
|
1396
1531
|
With the point helper, it's also possible to adapt the color and the radius based on a property. In the following example, we display a point for each public school, with the scaling factor being the number of students:
|
|
1532
|
+
|
|
1397
1533
|
```ts
|
|
1398
1534
|
helpers.addPoint(map, {
|
|
1399
1535
|
data: "public-schools.geojson",
|
|
@@ -1404,39 +1540,44 @@ helpers.addPoint(map, {
|
|
|
1404
1540
|
maxPointRadius: 30,
|
|
1405
1541
|
showLabel: true,
|
|
1406
1542
|
zoomCompensation: false,
|
|
1407
|
-
})
|
|
1543
|
+
});
|
|
1408
1544
|
```
|
|
1545
|
+
|
|
1409
1546
|

|
|
1410
1547
|
|
|
1411
1548
|
Here, the`PORTLAND` color ramp is going to be used so that schools with `200` students or less will have the colors at the very beginning of the color ramp and schools with `2000` or more will have the color defined at the very end. Schools in between will be attributed a color in a non-linear fashion, following the `"ease-out-sqrt"` method (read **Color Ramps** section above for more info).
|
|
1412
1549
|
|
|
1413
1550
|
All the other options are documented on [our reference page](https://docs.maptiler.com/sdk-js/api/helpers/#point) and more examples are available [here](https://docs.maptiler.com/sdk-js/examples/?q=point+helper).
|
|
1414
1551
|
|
|
1415
|
-
|
|
1552
|
+
#### Heatmap Layer Helper
|
|
1553
|
+
|
|
1416
1554
|
The heatmap layer is a great alternative for visualizing a collection of sparse data, but it can be challenging to use, especially when one has to come up with their own color ramp from scratch. **The helper makes this much easier!**
|
|
1417
1555
|
|
|
1418
1556
|
Here is a minimalist example, using the default built-in `TURBO` color ramp:
|
|
1557
|
+
|
|
1419
1558
|
```ts
|
|
1420
1559
|
helpers.addHeatmap(map, {
|
|
1421
1560
|
data: "public-schools.geojson",
|
|
1422
1561
|
});
|
|
1423
1562
|
```
|
|
1563
|
+
|
|
1424
1564
|

|
|
1425
1565
|
|
|
1426
|
-
Some visualizations are created with a fixed geographic extent or zoom level in mind, whether it's a survey at the scale of a single neighborhood or statistics at a country scale. In this case, we want to tailor the color, radius, weight and intensity of the heatmap blobs exactly for these precise settings. In the following example, we disable the
|
|
1566
|
+
Some visualizations are created with a fixed geographic extent or zoom level in mind, whether it's a survey at the scale of a single neighborhood or statistics at a country scale. In this case, we want to tailor the color, radius, weight and intensity of the heatmap blobs exactly for these precise settings. In the following example, we disable the _zoom compensation_ to make sure radio and intensity are never zoom-dependant:
|
|
1567
|
+
|
|
1427
1568
|
```ts
|
|
1428
1569
|
helpers.addHeatmap(map, {
|
|
1429
1570
|
data: "public-schools.geojson",
|
|
1430
1571
|
property: "students",
|
|
1431
1572
|
// radius: how wide are the blobs
|
|
1432
1573
|
radius: [
|
|
1433
|
-
{propertyValue: 100, value: 15},
|
|
1434
|
-
{propertyValue: 800, value: 50},
|
|
1574
|
+
{ propertyValue: 100, value: 15 },
|
|
1575
|
+
{ propertyValue: 800, value: 50 },
|
|
1435
1576
|
],
|
|
1436
1577
|
// weight: how intense are the blob, as fueled by a property
|
|
1437
1578
|
weight: [
|
|
1438
|
-
{propertyValue: 100, value: 0.1},
|
|
1439
|
-
{propertyValue: 800, value: 1},
|
|
1579
|
+
{ propertyValue: 100, value: 0.1 },
|
|
1580
|
+
{ propertyValue: 800, value: 1 },
|
|
1440
1581
|
],
|
|
1441
1582
|
// A custom color ramp, must be used with its default interval of [0, 1]
|
|
1442
1583
|
colorRamp: ColorRampCollection.MAGMA,
|
|
@@ -1446,13 +1587,16 @@ helpers.addHeatmap(map, {
|
|
|
1446
1587
|
intensity: 1.2,
|
|
1447
1588
|
});
|
|
1448
1589
|
```
|
|
1590
|
+
|
|
1449
1591
|

|
|
1450
|
-
Turning off
|
|
1592
|
+
Turning off _zoom compensation_ allows for more accurate adjustments to the visualization at a specific zoom level, but it may not adapt as smoothly when zooming in or out.
|
|
1451
1593
|
|
|
1452
1594
|
All the other options are documented on [our reference page](https://docs.maptiler.com/sdk-js/api/helpers/#heatmap) and more examples are available [here](https://docs.maptiler.com/sdk-js/examples/?q=heatmap+helper).
|
|
1453
1595
|
|
|
1454
|
-
|
|
1455
|
-
|
|
1596
|
+
### Other helpers
|
|
1597
|
+
|
|
1598
|
+
#### Convert GPX and KML to GeoJSON
|
|
1599
|
+
|
|
1456
1600
|
In the [Polyline helper section](#polyline-layer-helper) above, we have seen that one can feed the helper directly with a path to a GPX or KML file, that is then converted under the hood client-side into a GeoJSON `FeatureCollection` object. This conversion feature is also exposed and can be used as such:
|
|
1457
1601
|
|
|
1458
1602
|
```ts
|
|
@@ -1470,6 +1614,7 @@ const features = maptilersdk.gpx(gpxStr);
|
|
|
1470
1614
|
```
|
|
1471
1615
|
|
|
1472
1616
|
And for KML files:
|
|
1617
|
+
|
|
1473
1618
|
```ts
|
|
1474
1619
|
import { kml } from "@maptiler/sdk";
|
|
1475
1620
|
|
|
@@ -1484,11 +1629,12 @@ const kmlStr = await res.text();
|
|
|
1484
1629
|
const features = maptilersdk.gpx(kmlStr);
|
|
1485
1630
|
```
|
|
1486
1631
|
|
|
1632
|
+
#### Take Screenshots, programmatically
|
|
1487
1633
|
|
|
1488
|
-
|
|
1489
|
-
There are two different ways to create screenshot, corresponding to two very different usecases. Note that screenshots will not contain *DOM elements* such as `Marker` and `Popup`, since those are not part of the rendering context.
|
|
1634
|
+
There are two different ways to create screenshot, corresponding to two very different usecases. Note that screenshots will not contain _DOM elements_ such as `Marker` and `Popup`, since those are not part of the rendering context.
|
|
1490
1635
|
|
|
1491
1636
|
**1. Get a `blob` of a screenshot, PNG encoded:**
|
|
1637
|
+
|
|
1492
1638
|
```ts
|
|
1493
1639
|
import { Map, helpers } from "@maptiler/sdk";
|
|
1494
1640
|
|
|
@@ -1497,9 +1643,11 @@ import { Map, helpers } from "@maptiler/sdk";
|
|
|
1497
1643
|
// Inside an async function, or with using .then()
|
|
1498
1644
|
const blob = await helpers.takeScreenshot(map);
|
|
1499
1645
|
```
|
|
1646
|
+
|
|
1500
1647
|
The returned `Blob` of a PNG image file can be very handy if the goal is to programmatically further manipulate the screenshot, such as sending it to some feedback endpoint with a POST request.
|
|
1501
1648
|
|
|
1502
1649
|
**2. Download a PNG file:**
|
|
1650
|
+
|
|
1503
1651
|
```ts
|
|
1504
1652
|
import { Map, helpers } from "@maptiler/sdk";
|
|
1505
1653
|
|
|
@@ -1507,16 +1655,18 @@ import { Map, helpers } from "@maptiler/sdk";
|
|
|
1507
1655
|
|
|
1508
1656
|
// No need to be inside an async function, the download will be triggered when the file is ready
|
|
1509
1657
|
maptilersdk.helpers.takeScreenshot(map, {
|
|
1510
|
-
download: true,
|
|
1511
|
-
filename: "map_screenshot.png"
|
|
1658
|
+
download: true,
|
|
1659
|
+
filename: "map_screenshot.png",
|
|
1512
1660
|
});
|
|
1513
1661
|
```
|
|
1662
|
+
|
|
1514
1663
|
Getting a file directly is a nice option that can be useful to share some debugging context with colleagues, compare multiple styles, or share your creation on social media.
|
|
1515
1664
|
|
|
1516
|
-
> ๐ฃ
|
|
1665
|
+
> ๐ฃ _**Note:**_ Keep in mind that MapTiler data are copyrighted and their usage is restricted. This include MapTiler built-in styles and tilesets, among others. In case of doubt, do not hesitate to read our [terms](https://www.maptiler.com/terms/) or to ask our [support team](https://www.maptiler.com/contacts/).
|
|
1517
1666
|
|
|
1518
|
-
|
|
1519
|
-
|
|
1667
|
+
### Caching
|
|
1668
|
+
|
|
1669
|
+
Starting from v2, MapTiler SDK introduced the **caching** of tiles and fonts served by MapTiler, which can represent a large chunk of the data being fetched when browsing a map. This caching leverages modern browsers caching API so it's well-managed and there is no risk of bloating! When we update **MapTiler Planet** or our **official styles**, the caching logic will detect it and automatically invalidate older versions of the tiles that were previously cached.
|
|
1520
1670
|
|
|
1521
1671
|
Caching greatly improves the performance at load time and positively impacts the user experience, for this reason, it is **enabled by default**. If for debugging purposes or for a very specific use-case caching needs to be disabled, then it is possible:
|
|
1522
1672
|
|
|
@@ -1526,53 +1676,64 @@ import { config } from "@maptiler/sdk";
|
|
|
1526
1676
|
config.caching = false;
|
|
1527
1677
|
```
|
|
1528
1678
|
|
|
1529
|
-
|
|
1679
|
+
### Easy access to MapTiler API
|
|
1680
|
+
|
|
1530
1681
|
Our map SDK is not only about maps! We also provide plenty of wrappers to our API calls!
|
|
1531
1682
|
|
|
1532
|
-
> ๐ฃ
|
|
1683
|
+
> ๐ฃ _**Note:**_ If you need <ins>only the API Client library</ins> to use in a headless fashion and without any map display, check out out [API Client library](https://docs.maptiler.com/client-js/) for browser and NodeJS. It's exactely what is down below and only that, in a minimalistic [TypeScript package](https://github.com/maptiler/maptiler-client-js) ๐.
|
|
1684
|
+
|
|
1685
|
+
#### ๐ Geocoding
|
|
1533
1686
|
|
|
1687
|
+
> โ
Please, use geocoding functions only from client-side (browser) and do not ๐ซ **store** or **redistribute** MapTiler API data. In case of doubt, consult the [terms](https://www.maptiler.com/cloud/terms/#explicitly-prohibited-use) โ๏ธ
|
|
1534
1688
|
|
|
1535
|
-
|
|
1536
|
-
> โ
Please, use geocoding functions only from client-side (browser) and do not ๐ซ **store** or **redistribute** MapTiler Cloud API data. In case of doubt, consult the [terms](https://www.maptiler.com/cloud/terms/#explicitly-prohibited-use) โ๏ธ
|
|
1689
|
+
##### Forward
|
|
1537
1690
|
|
|
1538
|
-
### Forward
|
|
1539
1691
|
You want to know the longitude and latitude of a specific place, use the forward geocoding:
|
|
1692
|
+
|
|
1540
1693
|
```ts
|
|
1541
1694
|
// in an async function, or as a 'thenable':
|
|
1542
|
-
const result = await maptilersdk.geocoding.forward(
|
|
1695
|
+
const result = await maptilersdk.geocoding.forward("paris");
|
|
1543
1696
|
```
|
|
1697
|
+
|
|
1544
1698
|
You can provide some options such as:
|
|
1699
|
+
|
|
1545
1700
|
- the proximity, given a lon-lat position, to sort the results
|
|
1546
1701
|
- one of more languages to get the results into
|
|
1547
1702
|
- a bounding geo box, to restrict the search to a given window
|
|
1548
1703
|
|
|
1549
1704
|
Read more about forward geocoding on our [official documentation](https://docs.maptiler.com/client-js/geocoding/#forward).
|
|
1550
1705
|
|
|
1551
|
-
|
|
1706
|
+
##### Reverse
|
|
1707
|
+
|
|
1552
1708
|
You want to know the name of a place, given a longitude-latitude? Use the reverse geocoding:
|
|
1709
|
+
|
|
1553
1710
|
```ts
|
|
1554
1711
|
// in an async function, or as a 'thenable':
|
|
1555
1712
|
const result = await maptilersdk.geocoding.reverse([6.249638, 46.402056]);
|
|
1556
1713
|
```
|
|
1714
|
+
|
|
1557
1715
|
The same option object as the forward geocoding can be provided.
|
|
1558
1716
|
|
|
1559
1717
|
Read more about reverse geocoding on our [official documentation](https://docs.maptiler.com/client-js/geocoding/#reverse).
|
|
1560
1718
|
|
|
1561
|
-
|
|
1562
|
-
|
|
1719
|
+
##### Language
|
|
1720
|
+
|
|
1721
|
+
For both _forward_ and _reverse_ geocoding, this library provides a list of supported languages as shorthands to [ISO language codes](https://en.wikipedia.org/wiki/ISO_639-1). The result will be provided in multiple languages if the `language` option is an array:
|
|
1563
1722
|
|
|
1564
1723
|
```ts
|
|
1565
|
-
const result = await maptilersdk.geocoding.forward(
|
|
1724
|
+
const result = await maptilersdk.geocoding.forward("paris", { language: [maptilersdk.geocoding.languages.SPANISH, maptilersdk.geocoding.languages.KOREAN] });
|
|
1566
1725
|
```
|
|
1567
1726
|
|
|
1568
1727
|
The special language `AUTO` will detect the platform/browser preferred language.
|
|
1569
1728
|
|
|
1570
|
-
|
|
1729
|
+
#### ๐ต๏ธโโ๏ธ Geolocation
|
|
1730
|
+
|
|
1571
1731
|
The geolocation service provides location information of a visitor using its IP address.
|
|
1572
1732
|
|
|
1573
1733
|
The geolocation uses the IP address of a visitor to provide information about their location, such as city, region, country, timezone, etc. The precision is lower than GPS but does not require visitors to explicitly enable the location service from their web browser.
|
|
1574
1734
|
|
|
1575
1735
|
There is only a single function:
|
|
1736
|
+
|
|
1576
1737
|
```ts
|
|
1577
1738
|
// in an async function, or as a 'thenable':
|
|
1578
1739
|
const result = await maptilersdk.geolocation.info();
|
|
@@ -1580,11 +1741,14 @@ const result = await maptilersdk.geolocation.info();
|
|
|
1580
1741
|
|
|
1581
1742
|
Read more about geolocation on our [official documentation](https://docs.maptiler.com/client-js/geolocation/).
|
|
1582
1743
|
|
|
1583
|
-
|
|
1744
|
+
#### ๐ Coordinates
|
|
1745
|
+
|
|
1584
1746
|
If you are already familiar with [epsg.io](https://epsg.io/) (created by MapTiler), then you may find it convenient to access the details of more than 10 thousands coordinate reference systems (CRS) programmatically, as well as transform coordinates from one system to another!
|
|
1585
1747
|
|
|
1586
|
-
|
|
1748
|
+
##### Search
|
|
1749
|
+
|
|
1587
1750
|
The `search` lets you perform a query in a free-form fashion. Here are some examples:
|
|
1751
|
+
|
|
1588
1752
|
```ts
|
|
1589
1753
|
// in an async function, or as a 'thenable':
|
|
1590
1754
|
const resultA = await maptilersdk.coordinates.search('mercator');
|
|
@@ -1597,50 +1761,60 @@ The `transformations` options retrieve a lot more details about the CRS that Map
|
|
|
1597
1761
|
|
|
1598
1762
|
Read more about searching coordinate systems on our [official documentation](https://docs.maptiler.com/client-js/coordinates/#search).
|
|
1599
1763
|
|
|
1600
|
-
|
|
1764
|
+
##### Transform
|
|
1765
|
+
|
|
1601
1766
|
Transforming a couple of coordinates from one system to another can be challenging, for example, most countries have their own official system, yet web mapping tools are more often than not exclusive to [WGS84](https://epsg.io/4326).
|
|
1602
1767
|
|
|
1603
|
-
If not provided, both the source (`sourceCrs`) and the destination (`targetCrs) are defaulted to **EPSG:4326
|
|
1768
|
+
If not provided, both the source (`sourceCrs`) and the destination (`targetCrs) are defaulted to **EPSG:4326\*\*** (in other words, [WGS84](https://epsg.io/4326)). Here is how to use this feature:
|
|
1604
1769
|
|
|
1605
1770
|
```ts
|
|
1606
1771
|
// in an async function, or as a 'thenable':
|
|
1607
1772
|
|
|
1608
1773
|
// Providing one coordinate to transform, with a target CRS being EPSG:9793 (RGF93 v2 / Lambert-93, France official CRS)
|
|
1609
|
-
const resultA = await maptilersdk.coordinates.transform([1, 45], {targetCrs: 9793})
|
|
1774
|
+
const resultA = await maptilersdk.coordinates.transform([1, 45], { targetCrs: 9793 });
|
|
1610
1775
|
|
|
1611
1776
|
// Using the same logic, we can pass up to 50 coordinates to be transformed
|
|
1612
|
-
const resultB = await maptilersdk.coordinates.transform(
|
|
1777
|
+
const resultB = await maptilersdk.coordinates.transform(
|
|
1778
|
+
[
|
|
1779
|
+
[10, 48],
|
|
1780
|
+
[1, 45],
|
|
1781
|
+
],
|
|
1782
|
+
{ targetCrs: 9793 },
|
|
1783
|
+
);
|
|
1613
1784
|
```
|
|
1614
1785
|
|
|
1615
1786
|
Read more about transforming coordinates on our [official documentation](https://docs.maptiler.com/client-js/coordinates/#transform).
|
|
1616
1787
|
|
|
1617
|
-
|
|
1618
|
-
|
|
1788
|
+
#### ๐ฝ Data
|
|
1789
|
+
|
|
1790
|
+
MapTiler gives its users the possibility to [upload and create data](https://cloud.maptiler.com/data/), manually with a user interface or by uploading a GPX, GeoJSON, KML or shp file. A unique ID is associated with each dataset so that we can later access it programmatically to retrieve a GeoJSON equivalent of it:
|
|
1619
1791
|
|
|
1620
1792
|
```ts
|
|
1621
1793
|
// in an async function, or as a 'thenable':
|
|
1622
|
-
const result = await maptilersdk.data.get(
|
|
1794
|
+
const result = await maptilersdk.data.get("my-dataset-unique-id");
|
|
1623
1795
|
```
|
|
1624
1796
|
|
|
1625
1797
|
Since the result is a GeoJSON, it can easily be added to a `map` with `.addSource()` and `.addLayer()`.
|
|
1626
1798
|
|
|
1627
1799
|
Read more about fetching your own data on our [official documentation](https://docs.maptiler.com/client-js/data/).
|
|
1628
1800
|
|
|
1629
|
-
|
|
1801
|
+
#### ๐บ๏ธ Static maps
|
|
1802
|
+
|
|
1630
1803
|
> โ
Please, use static maps URLs only from client side `<img>` elements, and do not ๐ซ store or redistribute the static map files. In case of doubt, consult the [terms](https://www.maptiler.com/cloud/terms/#explicitly-prohibited-use) โ๏ธ
|
|
1631
1804
|
|
|
1632
|
-
Maptiler
|
|
1805
|
+
Maptiler provides many possibilities for creating static maps as PNG, JPEG or WebP images. They all offer the possibilities to:
|
|
1806
|
+
|
|
1633
1807
|
- Choose from one of the MapTiler styles or your own
|
|
1634
1808
|
- Add markers with a custom icon (or default icon with a custom color)
|
|
1635
1809
|
- Add a path or polygon, with a parametric line width and color and a parametric filling color
|
|
1636
1810
|
|
|
1637
1811
|
Three modes are available: `centered`, `bounded` and `automatic`.
|
|
1638
1812
|
|
|
1639
|
-
> ๐ฃ
|
|
1640
|
-
> Contrary to the other functions of this library, the static map functions **do not** perform any query to MapTiler
|
|
1813
|
+
> ๐ฃ _**important:**_ <span style="text-decoration: underline">only image **URLs** are returned.</span>
|
|
1814
|
+
> Contrary to the other functions of this library, the static map functions **do not** perform any query to MapTiler API, instead they build the image URL for you to use in `<img>` elements.
|
|
1641
1815
|
|
|
1816
|
+
##### Map Styles
|
|
1642
1817
|
|
|
1643
|
-
### Map Styles
|
|
1644
1818
|
In the following static map functions, the `option` object features a `style` property that can be a string or one of the built-in style shorthand. Here is the full list:
|
|
1645
1819
|
|
|
1646
1820
|
- `MapStyle.STREETS`, reference style for navigation and city exploration
|
|
@@ -1669,7 +1843,7 @@ In the following static map functions, the `option` object features a `style` pr
|
|
|
1669
1843
|
- `MapStyle.VOYAGER.DARK` (variant)
|
|
1670
1844
|
- `MapStyle.VOYAGER.LIGHT` (variant)
|
|
1671
1845
|
- `MapStyle.VOYAGER.VINTAGE` (variant)
|
|
1672
|
-
- `MapStyle.TONER` reference style for very high contrast stylish maps
|
|
1846
|
+
- `MapStyle.TONER` reference style for very high contrast stylish maps
|
|
1673
1847
|
- `MapStyle.TONER.BACKGROUND` (variant)
|
|
1674
1848
|
- `MapStyle.TONER.LITE` (variant)
|
|
1675
1849
|
- `MapStyle.TONER.LINES` (variant)
|
|
@@ -1678,18 +1852,19 @@ In the following static map functions, the `option` object features a `style` pr
|
|
|
1678
1852
|
- `MapStyle.STAGE.DARK` (variant)
|
|
1679
1853
|
- `MapStyle.STAGE.LIGHT` (variant)
|
|
1680
1854
|
|
|
1681
|
-
|
|
1855
|
+
##### Centered static maps
|
|
1856
|
+
|
|
1682
1857
|
This type of map is centered on a longitude-latitude coordinate and the zoom level must also be provided (from `0`: very zoomed out, to `22`: very zoomed in).
|
|
1683
1858
|
Note that if a path or markers are provided, the framing of the map will not automatically adapt to include those (use the `automatic` mode for that).
|
|
1684
1859
|
|
|
1685
1860
|
```ts
|
|
1686
1861
|
const imageLink = maptilersdk.staticMaps.centered(
|
|
1687
1862
|
// center position (Boston)
|
|
1688
|
-
[-71.
|
|
1863
|
+
[-71.0608, 42.362114],
|
|
1689
1864
|
|
|
1690
1865
|
// zoom level
|
|
1691
|
-
12.5,
|
|
1692
|
-
|
|
1866
|
+
12.5,
|
|
1867
|
+
|
|
1693
1868
|
// Options
|
|
1694
1869
|
{
|
|
1695
1870
|
// Request a hiDPI/Retina image
|
|
@@ -1701,23 +1876,24 @@ const imageLink = maptilersdk.staticMaps.centered(
|
|
|
1701
1876
|
|
|
1702
1877
|
// Map style
|
|
1703
1878
|
style: maptilersdk.MapStyle.OUTDOOR,
|
|
1704
|
-
}
|
|
1879
|
+
},
|
|
1880
|
+
);
|
|
1705
1881
|
```
|
|
1706
1882
|
|
|
1707
1883
|
Read more about centered static maps on our official [API documentation](https://docs.maptiler.com/cloud/api/static-maps/#center-based-image).
|
|
1708
1884
|
|
|
1885
|
+
##### Bounded static maps
|
|
1709
1886
|
|
|
1710
|
-
### Bounded static maps
|
|
1711
1887
|
This type of map requires a bounding box made of two points: the south-west bound and the north-east bound. The zoom level cannot be provided and is automatically deduced from the size of the bounding box.
|
|
1712
1888
|
|
|
1713
1889
|
```ts
|
|
1714
1890
|
const imageLink = maptilersdk.staticMaps.bounded(
|
|
1715
1891
|
// The bounding box on Europe
|
|
1716
1892
|
[
|
|
1717
|
-
-24,
|
|
1893
|
+
-24, // west bound (min x)
|
|
1718
1894
|
34.5, // south bound (min y)
|
|
1719
|
-
32,
|
|
1720
|
-
71,
|
|
1895
|
+
32, // east bound (max x)
|
|
1896
|
+
71, // north bound (max y)
|
|
1721
1897
|
],
|
|
1722
1898
|
|
|
1723
1899
|
// Options
|
|
@@ -1729,38 +1905,37 @@ const imageLink = maptilersdk.staticMaps.bounded(
|
|
|
1729
1905
|
|
|
1730
1906
|
// Extra space that will add around the bounding box, in percentage
|
|
1731
1907
|
// (0.1 = 10% is actually the dafault)
|
|
1732
|
-
padding: 0.1
|
|
1733
|
-
}
|
|
1908
|
+
padding: 0.1,
|
|
1909
|
+
},
|
|
1910
|
+
);
|
|
1734
1911
|
```
|
|
1735
1912
|
|
|
1736
1913
|
Since the zoom level cannot be provided, the level of details is dictated by the size of the output image. here is an example:
|
|
1737
1914
|
|
|
1738
|
-
|
|
|
1739
|
-
|
|
|
1740
|
-
| 
|
|
1915
|
+
| `2048 x 2048` | `1024 x 1024` |
|
|
1916
|
+
| :-----------------------------------------------------: | :-----------------------------------------------------: |
|
|
1917
|
+
|  |  |
|
|
1741
1918
|
|
|
1742
1919
|
As you may notice, the geo bounding box could have very different proportions than the output image size. In the following example, we place the very same bounding box around Portugal, which has a this particular strip looking shape. We also add a `path` that repeats exactly the same bounding box to show the difference between the provided bounding box and the final image. We kept the default padding of 10%:
|
|
1743
1920
|
|
|
1744
|
-
|
|
1745
|
-
|
|
|
1746
|
-
|
|
|
1747
|
-
|  |  |
|
|
1748
|
-
|
|
1921
|
+
| `2048 x 2048` | `1024 x 2048` |
|
|
1922
|
+
| :------------------------------------------------------------: | :------------------------------------------------------------: |
|
|
1923
|
+
|  |  |
|
|
1749
1924
|
|
|
1750
1925
|
Read more about bounded static maps on our official [API documentation](https://docs.maptiler.com/cloud/api/static-maps/#bounds-based-image).
|
|
1751
1926
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1927
|
+
##### Automatic static maps
|
|
1928
|
+
|
|
1929
|
+
As we have seen with centered and bounded maps, providing all the parameters is nice but can be cumbersome for the simplest use cases. This is why MapTiler also provides static maps that fit automatically whatever you need to place inside: path or markers.
|
|
1754
1930
|
|
|
1755
1931
|
In the following example, we are going to load a cycling track recorded by one of our team members in Montreal, Canada. The track, originally a GPX file, was pushed to MapTiler Data and is now made available as a GeoJSON:
|
|
1756
1932
|
|
|
1757
1933
|
```ts
|
|
1758
1934
|
// Fetching the GeoJSON
|
|
1759
|
-
const bikeTrack = await maptilersdk.data.get(
|
|
1935
|
+
const bikeTrack = await maptilersdk.data.get("the-id-of-a-bike-track-in-montreal");
|
|
1760
1936
|
|
|
1761
1937
|
// Extracting the track points with the shape [[lng, lat], [lng, lat], ...]
|
|
1762
|
-
const trackPoints = bikeTrack.features[0].geometry.coordinates[0]
|
|
1763
|
-
.map(p => p.slice(0, 2));
|
|
1938
|
+
const trackPoints = bikeTrack.features[0].geometry.coordinates[0].map((p) => p.slice(0, 2));
|
|
1764
1939
|
|
|
1765
1940
|
const imageLink = maptilersdk.staticMaps.automatic({
|
|
1766
1941
|
// hiDPI/Retina precision
|
|
@@ -1768,7 +1943,7 @@ const imageLink = maptilersdk.staticMaps.automatic({
|
|
|
1768
1943
|
|
|
1769
1944
|
// A fairly large output image
|
|
1770
1945
|
width: 2048,
|
|
1771
|
-
height: 1024
|
|
1946
|
+
height: 1024,
|
|
1772
1947
|
|
|
1773
1948
|
// A grey style on which the track will pop!
|
|
1774
1949
|
style: maptilersdk.MapStyle.STREETS.LIGHT,
|
|
@@ -1777,10 +1952,10 @@ const imageLink = maptilersdk.staticMaps.automatic({
|
|
|
1777
1952
|
path: trackPoints,
|
|
1778
1953
|
|
|
1779
1954
|
// Adding a marker for the starting point, with a custom color (array of shape [lng, lat, color])
|
|
1780
|
-
markers: [trackPoints[0][0], trackPoints[0][1],
|
|
1955
|
+
markers: [trackPoints[0][0], trackPoints[0][1], "#0a0"],
|
|
1781
1956
|
|
|
1782
1957
|
// Showing the track in red
|
|
1783
|
-
pathStrokeColor:
|
|
1958
|
+
pathStrokeColor: "red",
|
|
1784
1959
|
});
|
|
1785
1960
|
```
|
|
1786
1961
|
|
|
@@ -1788,20 +1963,22 @@ And voila!
|
|
|
1788
1963
|
|
|
1789
1964
|

|
|
1790
1965
|
|
|
1791
|
-
> ๐ฃ
|
|
1966
|
+
> ๐ฃ _**Note:**_ The GeoJSON for this track contains 9380 couples of coordinates, which is a lot! In order to send the track to MapTiler static maps API, the client simplifies the long paths while keeping a high degree of precision using a very fast [Ramer-Douglas-Peucker algorithm](https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).
|
|
1792
1967
|
|
|
1793
1968
|
Read more about bounded static maps on our official [API documentation](https://docs.maptiler.com/cloud/api/static-maps/#auto-fitted-image).
|
|
1794
1969
|
|
|
1795
|
-
|
|
1970
|
+
#### ๐๏ธ Elevation
|
|
1971
|
+
|
|
1796
1972
|
With the elevation API, it's possible to get the elevation in meters from any location. It's possible to lookup and compute elevation for a single location, to provide a batch of points, from a GeoJSON LineString or a GeoJSON MultiLineString!
|
|
1797
1973
|
|
|
1798
|
-
> โน๏ธ Under the hood, the elevation API is fueled by MapTiler
|
|
1974
|
+
> โน๏ธ Under the hood, the elevation API is fueled by MapTiler **RGB Terrain** raster tileset, which is a composite of many high-resolution DEMs from all over the world, currated and processed by our geodata team! The same dataset is also fueling our SDK's elevation (3D terrain) and the hillshading we use in many of our styles.
|
|
1799
1975
|
|
|
1800
|
-
> ๐ฃ Note for **TypeScript** users: internaly, the elevation feature relies on some
|
|
1976
|
+
> ๐ฃ Note for **TypeScript** users: internaly, the elevation feature relies on some _GeoJSON_ types definitions that can be found in this NPM package: `@types/geojson`. Namely `LineString`, `MultiLineString` and `Position`. It may improve your developer experience to also use these types.
|
|
1801
1977
|
|
|
1802
1978
|
Let's see how to use it:
|
|
1803
1979
|
|
|
1804
|
-
|
|
1980
|
+
##### At a single location
|
|
1981
|
+
|
|
1805
1982
|
```ts
|
|
1806
1983
|
// Not mandatory, but it's to explain where the type comes from:
|
|
1807
1984
|
import { Position } from "geojson";
|
|
@@ -1809,25 +1986,27 @@ import { Position } from "geojson";
|
|
|
1809
1986
|
const montBlancPeak: Position = [6.864884, 45.832743];
|
|
1810
1987
|
const elevatedPosition = await maptilersdk.elevation.at(montBlancPeak);
|
|
1811
1988
|
```
|
|
1812
|
-
|
|
1989
|
+
|
|
1990
|
+
The returned value is also a _GeoJSON_ `Position` array, but with three elements: `[lng, lat, elevation]`.
|
|
1813
1991
|
|
|
1814
1992
|
Read more about elevation lookup for a single location in our [official documentation](https://docs.maptiler.com/client-js/elevation/#at).
|
|
1815
1993
|
|
|
1816
|
-
|
|
1994
|
+
##### Batch mode
|
|
1995
|
+
|
|
1817
1996
|
```ts
|
|
1818
1997
|
// Not mandatory, but it's to explain where the type comes from:
|
|
1819
1998
|
import { Position } from "geojson";
|
|
1820
1999
|
|
|
1821
2000
|
const peaks: Position[] = [
|
|
1822
|
-
[6.864884, 45.832743],
|
|
1823
|
-
[86.
|
|
1824
|
-
[-70.0109, -32.6532],
|
|
1825
|
-
[-151.0064, 63.0695],
|
|
1826
|
-
[37.3556, -3.0674],
|
|
1827
|
-
[42.4453, 43.3499],
|
|
1828
|
-
[137.1595, -4.0784],
|
|
1829
|
-
[-140.4055, 60.5672],
|
|
1830
|
-
[138.73111, 35.358055],
|
|
2001
|
+
[6.864884, 45.832743], // Mont Blanc, Alps
|
|
2002
|
+
[86.925, 27.9881], // Mount Everest, Himalayas
|
|
2003
|
+
[-70.0109, -32.6532], // Aconcagua, Andes
|
|
2004
|
+
[-151.0064, 63.0695], // Denali, Alaska
|
|
2005
|
+
[37.3556, -3.0674], // Mount Kilimanjaro
|
|
2006
|
+
[42.4453, 43.3499], // Mount Elbrus, Caucasus
|
|
2007
|
+
[137.1595, -4.0784], // Puncak Jaya, Sudirman Range
|
|
2008
|
+
[-140.4055, 60.5672], // Mount Logan, Saint Elias Mountains
|
|
2009
|
+
[138.73111, 35.358055], // Mount Fuji
|
|
1831
2010
|
];
|
|
1832
2011
|
|
|
1833
2012
|
const elevatedPeaks = await maptilersdk.elevation.batch(peaks);
|
|
@@ -1835,17 +2014,21 @@ const elevatedPeaks = await maptilersdk.elevation.batch(peaks);
|
|
|
1835
2014
|
|
|
1836
2015
|
Read more about elevation lookup for a batch of locations in our [official documentation](https://docs.maptiler.com/client-js/elevation/#batch).
|
|
1837
2016
|
|
|
1838
|
-
|
|
1839
|
-
|
|
2017
|
+
##### From a GeoJSON LineString
|
|
2018
|
+
|
|
2019
|
+
In the _GeoJSON_ LineString case, it clones the entire structure and the position arrays of the clone will contain three elements: `[lng, lat, elevation]`. The original LineString is not mutated nor pointed at.
|
|
1840
2020
|
|
|
1841
2021
|
```ts
|
|
1842
2022
|
// Not mandatory, but it's to explain where the type comes from:
|
|
1843
2023
|
import { LineString } from "geojson";
|
|
1844
2024
|
|
|
1845
|
-
|
|
1846
2025
|
const someLineString: LineString = {
|
|
1847
2026
|
type: "LineString",
|
|
1848
|
-
coordinates: [
|
|
2027
|
+
coordinates: [
|
|
2028
|
+
[6.864884, 45.832743],
|
|
2029
|
+
[86.925, 27.9881],
|
|
2030
|
+
[-70.0109, -32.6532],
|
|
2031
|
+
],
|
|
1849
2032
|
};
|
|
1850
2033
|
|
|
1851
2034
|
const someElevatedLineString = await maptilersdk.elevation.fromLineString(someLineString);
|
|
@@ -1854,21 +2037,33 @@ const someElevatedLineString = await maptilersdk.elevation.fromLineString(someLi
|
|
|
1854
2037
|
|
|
1855
2038
|
Read more about elevation lookup for a `LineString` in our [official documentation](https://docs.maptiler.com/client-js/elevation/#linestring).
|
|
1856
2039
|
|
|
1857
|
-
|
|
1858
|
-
|
|
2040
|
+
##### From a GeoJSON MultiLineString
|
|
2041
|
+
|
|
2042
|
+
In the _GeoJSON_ MultiLineString case, it clones the entire structure and the position arrays of the clone will contain three elements: `[lng, lat, elevation]`. The original MultiLineString is not mutated nor pointed at.
|
|
1859
2043
|
|
|
1860
2044
|
```ts
|
|
1861
2045
|
// Not mandatory, but it's to explain where the type comes from:
|
|
1862
2046
|
import { MultiLineString } from "geojson";
|
|
1863
2047
|
|
|
1864
|
-
|
|
1865
2048
|
const someMultiLineString: MultiLineString = {
|
|
1866
2049
|
type: "LineString",
|
|
1867
2050
|
coordinates: [
|
|
1868
|
-
[
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
2051
|
+
[
|
|
2052
|
+
[6.864884, 45.832743],
|
|
2053
|
+
[86.925, 27.9881],
|
|
2054
|
+
[-70.0109, -32.6532],
|
|
2055
|
+
],
|
|
2056
|
+
[
|
|
2057
|
+
[-151.0064, 63.0695],
|
|
2058
|
+
[37.3556, -3.0674],
|
|
2059
|
+
[42.4453, 43.3499],
|
|
2060
|
+
],
|
|
2061
|
+
[
|
|
2062
|
+
[137.1595, -4.0784],
|
|
2063
|
+
[-140.4055, 60.5672],
|
|
2064
|
+
[138.73111, 35.358055],
|
|
2065
|
+
],
|
|
2066
|
+
],
|
|
1872
2067
|
};
|
|
1873
2068
|
|
|
1874
2069
|
const someElevatedMultiLineString = await maptilersdk.elevation.fromMultiLineString(someMultiLineString);
|
|
@@ -1877,13 +2072,15 @@ const someElevatedMultiLineString = await maptilersdk.elevation.fromMultiLineStr
|
|
|
1877
2072
|
|
|
1878
2073
|
Read more about elevation lookup for a `MultiLineString` in our [official documentation](https://docs.maptiler.com/client-js/elevation/#multilinestring).
|
|
1879
2074
|
|
|
1880
|
-
|
|
2075
|
+
##### Caching
|
|
2076
|
+
|
|
1881
2077
|
In order to increase performance while reducing unnecessary elevation data fetching, the elevation tiles are cached. This is particularly important for the LineString and MultiLineString lookups because GeoJSON data are likely to come from a recorded or planned route, where position points are very close to one another.
|
|
1882
2078
|
|
|
1883
|
-
|
|
1884
|
-
Some operations can be fairly repetitive: WGS84 to Mercator, WGS84 to *zxy* tile index, the distance between two points with the Haversine formula, etc. As a result, we have decided to expose a `math` package providing the most recurrent feature, so that, just like us at MapTiler, you no longer need to copy-paste the same function from your previous project!
|
|
2079
|
+
#### ๐งฎ Math
|
|
1885
2080
|
|
|
1886
|
-
|
|
2081
|
+
Some operations can be fairly repetitive: WGS84 to Mercator, WGS84 to _zxy_ tile index, the distance between two points with the Haversine formula, etc. As a result, we have decided to expose a `math` package providing the most recurrent feature, so that, just like us at MapTiler, you no longer need to copy-paste the same function from your previous project!
|
|
2082
|
+
|
|
2083
|
+
The `math` package differs from the others in the sense that it does not call the MapTiler API, instead, it operates fully on the machine it's running on.
|
|
1887
2084
|
|
|
1888
2085
|
Here are some examples:
|
|
1889
2086
|
|
|
@@ -1921,10 +2118,12 @@ const tileXY = maptilersdk.math.wgs84ToTileIndex(montBlancPeakWgs84, 14);
|
|
|
1921
2118
|
|
|
1922
2119
|
Please find out more about the math package in our [official documentation](https://docs.maptiler.com/client-js/math):
|
|
1923
2120
|
|
|
1924
|
-
|
|
2121
|
+
### Telemetry
|
|
2122
|
+
|
|
1925
2123
|
The telemetry is very valuable to the team at MapTiler because it shares information about where to add the extra effort. It also helps spotting some incompatibility issues that may arise between the SDK and a specific version of a module.
|
|
1926
2124
|
|
|
1927
2125
|
It consists in sending metrics about usage of the following features:
|
|
2126
|
+
|
|
1928
2127
|
- SDK version [string]
|
|
1929
2128
|
- API key [string]
|
|
1930
2129
|
- MapTiler sesion ID (if opted-in) [string]
|
|
@@ -1938,7 +2137,66 @@ In addition, each official module will be added to a list, alongside its version
|
|
|
1938
2137
|
Telemetry is enabled by default but can be opted-out by setting `telemetry` value of `config` to `false`.
|
|
1939
2138
|
|
|
1940
2139
|
```ts
|
|
1941
|
-
import * as maptilersdk from
|
|
2140
|
+
import * as maptilersdk from "@maptiler/sdk";
|
|
1942
2141
|
|
|
1943
2142
|
maptilersdk.config.telemetry = false;
|
|
1944
2143
|
```
|
|
2144
|
+
|
|
2145
|
+
<br>
|
|
2146
|
+
|
|
2147
|
+
## Migration Guide
|
|
2148
|
+
|
|
2149
|
+
- [How to migrate/switch from Mapbox to MapTiler](https://docs.maptiler.com/sdk-js/examples/switch-from-mapbox/)
|
|
2150
|
+
- [How to migrate/switch from MapLibre to MapTiler](https://docs.maptiler.com/sdk-js/examples/switch-from-maplibre/)
|
|
2151
|
+
|
|
2152
|
+
<br>
|
|
2153
|
+
|
|
2154
|
+
## ๐ฌ Support
|
|
2155
|
+
|
|
2156
|
+
- ๐ [Documentation](https://docs.maptiler.com/sdk-js/) - Comprehensive guides and API reference
|
|
2157
|
+
- โ๏ธ [Contact us](https://maptiler.com/contact) - Get in touch or submit a request
|
|
2158
|
+
- ๐ฆ [Twitter/X](https://twitter.com/maptiler) - Follow us for updates
|
|
2159
|
+
|
|
2160
|
+
<br>
|
|
2161
|
+
|
|
2162
|
+
---
|
|
2163
|
+
|
|
2164
|
+
<br>
|
|
2165
|
+
|
|
2166
|
+
## ๐ค Contributing
|
|
2167
|
+
|
|
2168
|
+
We love contributions from the community! Whether it's bug reports, feature requests, or pull requests, all contributions are welcome:
|
|
2169
|
+
|
|
2170
|
+
- Fork the repository and create your branch fromย `main`
|
|
2171
|
+
- If you've added code, add tests that cover your changes
|
|
2172
|
+
- Ensure your code follows our style guidelines
|
|
2173
|
+
- Give your pull request a clear, descriptive summary
|
|
2174
|
+
- Open a Pull Request with a comprehensive description
|
|
2175
|
+
|
|
2176
|
+
<br>
|
|
2177
|
+
|
|
2178
|
+
## ๐ License
|
|
2179
|
+
|
|
2180
|
+
This project is licensed under the BSD 3-Clause License โ see theย [LICENSE](./LICENSE)ย file for details.
|
|
2181
|
+
|
|
2182
|
+
<br>
|
|
2183
|
+
|
|
2184
|
+
## ๐ Acknowledgements
|
|
2185
|
+
|
|
2186
|
+
This project is built on the shoulders of giants:
|
|
2187
|
+
|
|
2188
|
+
- [MapLibre GL JS](https://maplibre.org/)ย โ The open-source mapping library
|
|
2189
|
+
- [OpenStreetMap](https://openstreetmap.org/)ย โ The free wiki world map
|
|
2190
|
+
|
|
2191
|
+
<br>
|
|
2192
|
+
|
|
2193
|
+
<p align="center" style="margin-top:20px;margin-bottom:20px;"> <a href="https://cloud.maptiler.com/account/keys/" style="display:inline-block;padding:12px 32px;background:#F2F6FF;color:#000;font-weight:bold;border-radius:6px;text-decoration:none;"> Get Your API Key <sup style="background-color:#0000ff;color:#fff;padding:2px 6px;font-size:12px;border-radius:3px;">FREE</sup><br /> <span style="font-size:90%;font-weight:400;">Start building with 100,000 free map loads per month ใป No credit card required.</span> </a> </p>
|
|
2194
|
+
|
|
2195
|
+
<br>
|
|
2196
|
+
|
|
2197
|
+
<p align="center"> ๐ Made with love by the <a href="https://www.maptiler.com/">MapTiler</a> team <br />
|
|
2198
|
+
<p align="center">
|
|
2199
|
+
<a href="https://www.maptiler.com/interactive-maps/">Website</a> โข
|
|
2200
|
+
<a href="https://docs.maptiler.com/sdk-js/">Documentation</a> โข
|
|
2201
|
+
<a href="https://github.com/maptiler/maptiler-sdk-js/">GitHub</a>
|
|
2202
|
+
</p>
|