@maptiler/sdk 3.10.2-rc.2 β†’ 3.11.0-rc.1

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.
Files changed (112) hide show
  1. package/README.md +233 -66
  2. package/dist/eslint.mjs +8 -0
  3. package/dist/maptiler-sdk.mjs +3512 -2464
  4. package/dist/maptiler-sdk.mjs.map +1 -1
  5. package/dist/src/ImageViewer/ImageViewer.d.ts +2 -2
  6. package/dist/src/Map.d.ts +42 -2
  7. package/dist/src/MaptilerAnimation/AnimationManager.d.ts +41 -0
  8. package/dist/src/MaptilerAnimation/MaptilerAnimation.d.ts +238 -0
  9. package/dist/src/MaptilerAnimation/animation-helpers.d.ts +183 -0
  10. package/dist/src/MaptilerAnimation/easing.d.ts +3 -0
  11. package/dist/src/MaptilerAnimation/index.d.ts +7 -0
  12. package/dist/src/MaptilerAnimation/types.d.ts +26 -0
  13. package/dist/src/custom-layers/AnimatedRouteLayer/AnimatedRouteLayer.d.ts +293 -0
  14. package/dist/src/custom-layers/AnimatedRouteLayer/index.d.ts +1 -0
  15. package/dist/src/custom-layers/CubemapLayer/CubemapLayer.d.ts +1 -1
  16. package/dist/src/index.d.ts +2 -0
  17. package/dist/src/utils/array.d.ts +1 -0
  18. package/dist/src/utils/json.d.ts +1 -0
  19. package/dist/src/utils/string.d.ts +1 -0
  20. package/e2e/global.d.ts +14 -1
  21. package/e2e/public/animated-route.geojson +82 -0
  22. package/e2e/public/animatedRouteLayer.html +24 -0
  23. package/e2e/public/haloSpace.html +25 -0
  24. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-0-chromium-linux.png +0 -0
  25. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-1-chromium-linux.png +0 -0
  26. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-10-chromium-linux.png +0 -0
  27. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-11-chromium-linux.png +0 -0
  28. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-12-chromium-linux.png +0 -0
  29. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-13-chromium-linux.png +0 -0
  30. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-14-chromium-linux.png +0 -0
  31. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-15-chromium-linux.png +0 -0
  32. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-16-chromium-linux.png +0 -0
  33. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-17-chromium-linux.png +0 -0
  34. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-18-chromium-linux.png +0 -0
  35. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-19-chromium-linux.png +0 -0
  36. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-2-chromium-linux.png +0 -0
  37. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-3-chromium-linux.png +0 -0
  38. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-4-chromium-linux.png +0 -0
  39. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-5-chromium-linux.png +0 -0
  40. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-6-chromium-linux.png +0 -0
  41. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-7-chromium-linux.png +0 -0
  42. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-8-chromium-linux.png +0 -0
  43. package/e2e/snapshots/tests/AnimatedRouteLayer.test.ts-snapshots/animated-route-9-chromium-linux.png +0 -0
  44. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-catalogue-style-halo-constructor-override-chromium-linux.png +0 -0
  45. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-json-style-config-halo-constructor-override-chromium-linux.png +0 -0
  46. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-json-style-config-halo-rendered-chromium-linux.png +0 -0
  47. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-json-style-config-halo-rendered-chromium.png +0 -0
  48. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-json-style-config-halo-true-chromium-linux.png +0 -0
  49. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-no-style-config-halo-true-chromium-linux.png +0 -0
  50. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-remote-style-config-halo-constructor-override-chromium-linux.png +0 -0
  51. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-remote-style-config-halo-false-chromium-linux.png +0 -0
  52. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-remote-style-config-halo-true-chromium-linux.png +0 -0
  53. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-style-config-halo-json-default-chromium-linux.png +0 -0
  54. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-style-config-halo-json-default-chromium.png +0 -0
  55. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-style-config-halo-json-false-chromium-linux.png +0 -0
  56. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-style-config-halo-json-false-chromium.png +0 -0
  57. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-style-config-halo-json-valid-chromium-linux.png +0 -0
  58. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-style-config-halo-json-valid-chromium.png +0 -0
  59. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/halo-halo-style-config-halo-remote-valid-chromium-linux.png +0 -0
  60. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-catalogue-style-config-space-true-chromium-linux.png +0 -0
  61. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-catalogue-style-config-space-undefined-chromium-linux.png +0 -0
  62. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-json-style-config-space-true-chromium-linux.png +0 -0
  63. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-json-style-config-space-true-chromium.png +0 -0
  64. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-json-style-config-space-true-default-chromium-linux.png +0 -0
  65. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-json-style-config-space-true-default-chromium.png +0 -0
  66. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-style-config-constructor-undefined-with-json-style-config-chromium-linux.png +0 -0
  67. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-style-config-space-constructor-with-catalogue-style-config-chromium-linux.png +0 -0
  68. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-style-config-space-constructor-with-json-space-config-chromium-linux.png +0 -0
  69. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-style-config-space-constructor-with-json-space-config-chromium.png +0 -0
  70. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-style-config-space-false-with-json-style-config-chromium-linux.png +0 -0
  71. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-style-config-space-false-with-json-style-config-chromium.png +0 -0
  72. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-style-config-space-false-with-style-config-chromium-linux.png +0 -0
  73. package/e2e/snapshots/tests/haloSpace.test.ts-snapshots/space-space-style-config-space-true-no-style-config-chromium-linux.png +0 -0
  74. package/e2e/snapshots/tests/map-load.test.ts-snapshots/halo-halo-json-style-config-halo-rendered-chromium-linux.png +0 -0
  75. package/e2e/snapshots/tests/map-load.test.ts-snapshots/halo-halo-json-style-config-halo-true-chromium-linux.png +0 -0
  76. package/e2e/snapshots/tests/map-load.test.ts-snapshots/halo-halo-style-config-halo-json-default-chromium-linux.png +0 -0
  77. package/e2e/snapshots/tests/map-load.test.ts-snapshots/halo-halo-style-config-halo-json-false-chromium-linux.png +0 -0
  78. package/e2e/snapshots/tests/map-load.test.ts-snapshots/halo-halo-style-config-halo-json-valid-chromium-linux.png +0 -0
  79. package/e2e/snapshots/tests/map-load.test.ts-snapshots/space-space-json-style-config-space-true-chromium-linux.png +0 -0
  80. package/e2e/snapshots/tests/map-load.test.ts-snapshots/space-space-json-style-config-space-true-chromium.png +0 -0
  81. package/e2e/snapshots/tests/map-load.test.ts-snapshots/space-space-json-style-config-space-true-default-chromium-linux.png +0 -0
  82. package/e2e/snapshots/tests/map-load.test.ts-snapshots/space-space-style-config-space-constructor-with-json-space-config-chromium-linux.png +0 -0
  83. package/e2e/snapshots/tests/map-load.test.ts-snapshots/space-space-style-config-space-false-with-json-style-config-chromium-linux.png +0 -0
  84. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/halo-halo-json-style-config-halo-rendered-chromium-linux.png +0 -0
  85. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/halo-halo-json-style-config-halo-true-chromium-linux.png +0 -0
  86. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/halo-halo-style-config-halo-json-default-chromium-linux.png +0 -0
  87. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/halo-halo-style-config-halo-json-false-chromium-linux.png +0 -0
  88. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/halo-halo-style-config-halo-json-valid-chromium-linux.png +0 -0
  89. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/space-space-json-style-config-space-true-chromium-linux.png +0 -0
  90. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/space-space-json-style-config-space-true-default-chromium-linux.png +0 -0
  91. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/space-space-style-config-space-constructor-with-json-space-config-chromium-linux.png +0 -0
  92. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/space-space-style-config-space-false-with-json-style-config-chromium-linux.png +0 -0
  93. package/e2e/tests/AnimatedRouteLayer.test.ts +45 -0
  94. package/e2e/tests/consts.ts +0 -0
  95. package/e2e/tests/expected-results/animatedRouteLayer-1.json +202 -0
  96. package/e2e/tests/haloSpace.test.ts +809 -0
  97. package/e2e/tests/helpers/fetchGeojson.ts +21 -0
  98. package/e2e/tests/helpers/getMapInstanceForFixture.ts +87 -0
  99. package/e2e/tests/helpers/injectGlobalVariables.ts +13 -0
  100. package/e2e/tests/helpers/loadFixtureAndGetMapHandle.ts +46 -36
  101. package/e2e/tests/mocks/maptiler-style-space-halo-invalid.json +38 -0
  102. package/e2e/tests/mocks/maptiler-style-space-halo.json +41 -0
  103. package/e2e/tests/mocks/maptiler-style.json +1 -0
  104. package/e2e/tests/rtlTextPlugin.test.ts +3 -12
  105. package/e2e/tsconfig.json +1 -1
  106. package/eslint.config.mjs +8 -0
  107. package/package.json +11 -4
  108. package/playwright.config.ts +7 -2
  109. package/tsconfig.json +1 -1
  110. package/vitest-setup-tests.ts +16 -0
  111. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/rtlTextPlugin-active-chromium-linux.png +0 -0
  112. package/e2e/snapshots/tests/rtlTextPlugin.test.ts-snapshots/rtlTextPlugin-disabled-chromium-linux.png +0 -0
package/README.md CHANGED
@@ -10,7 +10,7 @@ In addition, the MapTiler SDK JS provides well-documented and easy-to-use wrappe
10
10
 
11
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
12
 
13
- [![](https://img.shields.io/npm/v/@maptiler/sdk?style=for-the-badge&labelColor=D3DBEC&color=f2f6ff&logo=npm&logoColor=333359)](https://www.npmjs.com/package/@maptiler/sdk) ![](https://img.shields.io/badge/-white?style=for-the-badge&logo=javascript)![](https://img.shields.io/badge/-white?style=for-the-badge&logo=typescript)
13
+ [![npm](https://img.shields.io/npm/v/@maptiler/sdk?style=for-the-badge&labelColor=D3DBEC&color=f2f6ff&logo=npm&logoColor=333359)](https://www.npmjs.com/package/@maptiler/sdk) ![](https://img.shields.io/badge/-white?style=for-the-badge&logo=javascript)![](https://img.shields.io/badge/-white?style=for-the-badge&logo=typescript)
14
14
 
15
15
  ---
16
16
 
@@ -333,91 +333,105 @@ The **globe projection**, available starting from MapTiler SDK v3, does not suff
333
333
 
334
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**.
335
335
 
336
- - In the style, using the `projection` top-level property.
337
- For globe:
336
+ - In the style, using the `projection` top-level property.
337
+ This projection is used when the style loads unless it has been overriden by one of the options below.
338
338
 
339
- ```js
340
- {
341
- "version": ...,
342
- "id": ...,
343
- "name": ...,
344
- "sources": ...,
345
- "layers": ...,
346
-
347
- // Make the style use the globe projection at load time
348
- "projection": {
349
- "type": "globe"
339
+ ```js
340
+ {
341
+ "version": ...,
342
+ "id": ...,
343
+ "name": ...,
344
+ "sources": ...,
345
+ "layers": ...,
346
+
347
+ // Make the style use the globe projection at load time
348
+ "projection": {
349
+ "type": "globe"
350
+ }
351
+
352
+ // ...
350
353
  }
351
354
 
352
- // ...
353
- }
354
- ```
355
+ // or
355
356
 
356
- or for Mercator:
357
+ {
358
+ "version": ...,
359
+ "id": ...,
360
+ "name": ...,
361
+ "sources": ...,
362
+ "layers": ...,
357
363
 
358
- ```js
359
- {
360
- "version": ...,
361
- "id": ...,
362
- "name": ...,
363
- "sources": ...,
364
- "layers": ...,
365
-
366
- // Make the style use the mercator projection at load time
367
- "projection": {
368
- "type": "mercator"
364
+ // Make the style use the mercator projection at load time
365
+ "projection": {
366
+ "type": "mercator"
367
+ }
368
+
369
+ // ...
369
370
  }
371
+ ```
370
372
 
371
- // ...
372
- }
373
- ```
373
+ - In the constructor of the `Map` class, using the `projection` option.
374
+ This overrides the `projection` property from the style (if any) and will persist it if the map style changes later, even if the style contains its own projection.
374
375
 
375
- - In the constructor of the `Map` class, using the `projection` option. For globe:
376
+ ```ts
377
+ const map = new maptilersdk.Map({
378
+ container: "map",
379
+ projection: "globe", // Force a globe projection
380
+ });
376
381
 
377
- ```ts
378
- const map = new maptilersdk.Map({
379
- container: "map",
380
- projection: "globe", // Force a globe projection
381
- });
382
- ```
382
+ // or
383
383
 
384
- or for Mercator:
384
+ const map = new maptilersdk.Map({
385
+ container: "map",
386
+ projection: "mercator", // Force a mercator projection
387
+ });
388
+ ```
385
389
 
386
- ```ts
387
- const map = new maptilersdk.Map({
388
- container: "map",
389
- projection: "mercator", // Force a mercator projection
390
- });
391
- ```
390
+ - Using the built-in methods.
391
+ This changes the projection for the current style and optionally also persists it if the map style changes later.
392
392
 
393
- This will overwrite the `projection` property from the style (if any) and will persist it later if the map style was to change.
393
+ ```ts
394
+ map.setProjection("mercator", { persist: true });
395
+ // or
396
+ map.setProjection("globe", { persist: true });
397
+ ```
394
398
 
395
- - Use the built-in methods:
399
+ > ℹ️ Deprecated methods `enableGlobeProjection()` and `enableMercatorProjection()` also persist the projection.
396
400
 
397
- ```ts
398
- map.enableGlobeProjection();
399
- // or
400
- map.enableMercatorProjection();
401
- ```
401
+ Without persistance, when the style next changes, the projection is reset to a previously persisted projection, or a projection specified in the `Map` options, or a projection specified in `projection` property of the style itself, or the default (Mercator) projection.
402
+
403
+ ```ts
404
+ map.setProjection("mercator");
405
+ // or
406
+ map.setProjection("globe");
407
+ ```
402
408
 
403
- The projection setter built in Maplibre GL JS is also usable:
409
+ The signature built in Maplibre GL JS is also usable, however a style specification other than `"mercator"` or `"globe"` can't be persisted.
404
410
 
405
- ```ts
406
- map.setProjection({ type: "mercator" });
407
- // or
408
- map.setProjection({ type: "globe" });
409
- ```
411
+ ```ts
412
+ map.setProjection({ type: "mercator" });
413
+ // or
414
+ map.setProjection({ type: "globe" });
415
+ // or
416
+ map.setProjection({ type: ["step", ["zoom"], "vertical-perspective", 3, "mercator"] });
417
+ ```
410
418
 
411
419
  - Using the `MaptilerProjectionControl`. Not mounted by default, it can easily be added with a single option in the `Map` constructor:
412
420
 
413
- ```ts
414
- const map = new maptilersdk.Map({
415
- container: "map",
416
- projectionControl: true, // or the position such as "top-left", "top-right",
417
- }); // "bottom-right" or "bottom-left"
418
- ```
421
+ ```ts
422
+ const map = new maptilersdk.Map({
423
+ container: "map",
424
+ projectionControl: true, // or the position such as "top-left", "top-right",
425
+ }); // "bottom-right" or "bottom-left"
426
+ ```
419
427
 
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.
428
+ 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.
429
+
430
+ - You can also forget the persisted projection. This is the only way how to make projection specified inside style itself work again if `Map` constructor `projection` option was specified, or `map.setProjection(..., { persist: true })` was called, or `MaptilerProjectionControl` was used, starting from the next style change.
431
+
432
+ ```ts
433
+ map.forgetPersistedProjection();
434
+ ```
421
435
 
422
436
  #### Field of view (FOV)
423
437
 
@@ -1323,6 +1337,159 @@ When defining a new _ramp_, the colors can be an RGB array (`[number, number, nu
1323
1337
 
1324
1338
  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.
1325
1339
 
1340
+ ### Camera routes and animations
1341
+
1342
+ The SDK comes with several classes to help with animations, particularly route animations.
1343
+
1344
+ See `demos/11-animated-routes.html` for examples.
1345
+ See `demos/12-maptiler-animation.html` for examples.
1346
+
1347
+ #### 🧩 `MaptilerAnimation`
1348
+
1349
+ MaptilerAnimation is a utility class for smoothly animating between keyframes using custom easing and playback control. It supports event-based hooks for frame updates and completion, and works well within rendering loops or UI transitions.
1350
+
1351
+ ##### πŸš€ Usage
1352
+
1353
+ ```ts
1354
+ // linearly animated between values
1355
+ const animation = new MaptilerAnimation({
1356
+ keyframes: [
1357
+ // `props` are interpolated across the duration
1358
+ { delta: 0, props: { lon: -7.445, } },
1359
+ // `userData` can hold any type of custom data to pass with the keyframe
1360
+ { delta: 0.5, userData: { mydata: "whoa!" } },
1361
+ { delta: 1, props: { lon: -7.473 } }
1362
+ ],
1363
+ duration: 1000, // 1 second
1364
+ iterations: Infinity // loop forever
1365
+ });
1366
+
1367
+ const marker = new Marker().setLngLat(
1368
+ new LngLat(
1369
+ -7.449346225791231,
1370
+ 39.399728941536836,
1371
+ )
1372
+ ).addTo(map);
1373
+
1374
+ // TimeUpdate is fired every frame
1375
+ animation.addEventListener(AnimationEventTypes.TimeUpdate, (e) => {
1376
+ marker.setLngLat(
1377
+ new LngLat(
1378
+ e.props.lon,
1379
+ 39.399728941536836,
1380
+ )
1381
+ )
1382
+ })
1383
+ // fired when the keyframe changes
1384
+ animation.addEventListener(AnimationEventTypes.Keyframe, ({ userData }) => {
1385
+ console.log(userData.mydata) // "whoa!"
1386
+ });
1387
+
1388
+ animation.play();
1389
+ ```
1390
+ ![](images/animate-linear-trimmed.gif)
1391
+
1392
+ ```ts
1393
+ // eased between values
1394
+ const animation = new MaptilerAnimation({
1395
+ keyframes: [
1396
+ // `props` are interpolated across the duration
1397
+ { delta: 0, easing: EasingFunctionName.ElasticInOut, props: { lon: -7.445, } },
1398
+ { delta: 1, props: { lon: -7.455 } }
1399
+ ],
1400
+ duration: 1000, // 1 second
1401
+ iterations: Infinity // loop forever
1402
+ });
1403
+ ```
1404
+ ![](images/animate-elastic-trimmed.gif)
1405
+
1406
+ #### Β πŸ—ΊοΈ `AnimatedRouteLayer`
1407
+
1408
+ `AnimatedRouteLayer` is custom layer that animates a path or route on the map based on keyframes or GeoJSON data. It supports animated line styling and camera following, making it ideal for visualizing routes, playback tracks, or timeline-based geographic events.
1409
+
1410
+ Note: At present, to avoid problems arising from the camera being manipulated by two animations at any one time, there can only ever be one instance of `AnimatedRouteLayer` on the map at any time. This API may change in the future, but at present you must remove each instance of `AnimatedRouteLayer` from the map before adding another.
1411
+
1412
+ ##### ✨ Features
1413
+ - Animate a path using keyframes or GeoJSON data
1414
+ - Optional animated stroke styles to indicate progress
1415
+ - Camera movement smoothing, following along the route
1416
+ - Configurable duration, easing, delay, and iterations via geojson properties
1417
+ - Event-based lifecycle hooks for adaptability.
1418
+ - Optional manual frame advancement (e.g., for scrubbing or syncing with map events, scroll etc etc)
1419
+
1420
+ ##### πŸš€ Basic Usage
1421
+ ```ts
1422
+ const myGeoJSONSource = {
1423
+ "type": "FeatureCollection",
1424
+ "features": [
1425
+ {
1426
+ "type": "Feature",
1427
+ "geometry": {
1428
+ "type": "LineString",
1429
+ "coordinates": [
1430
+ [-74.0060, 40.7128],
1431
+ [-73.9352, 40.7306],
1432
+ [-73.9851, 40.7580]
1433
+ ]
1434
+ },
1435
+ "properties": {
1436
+ "@duration": 5000, // animation params are prepended with '@'
1437
+ "@iterations": 3,
1438
+ "@delay": 1000,
1439
+ "@autoplay": true,
1440
+ "bearing": [
1441
+ 40,
1442
+ 30,
1443
+ 10,
1444
+ 10,
1445
+ 20,
1446
+ 40,
1447
+ ]
1448
+ }
1449
+ }
1450
+ ]
1451
+ }
1452
+
1453
+ map.addSource("my-geojson-source", {
1454
+ type: "geojson",
1455
+ data: myGeoJSONSource,
1456
+ });
1457
+
1458
+ const animatedRoute = new AnimatedRouteLayer({
1459
+ source: {
1460
+ // assumes that the source is already added to the map with the given layer ID
1461
+ id: "my-geojson-source", // the name of the source
1462
+ layerID: "route-layer", // the name of the layer
1463
+ },
1464
+ // OR
1465
+ keyframes: [], // an array of keyframes
1466
+
1467
+ duration: 5000,
1468
+ pathStrokeAnimation: {
1469
+ // will only be applied to LineString GeoJSON types
1470
+ activeColor: [0, 128, 0, 1], // color of the line that has already been traversed
1471
+ inactiveColor: [128, 128, 128, 0.5],
1472
+ },
1473
+ cameraAnimation: {
1474
+ follow: true, // should the camera follow the route?
1475
+ pathSmoothing: {
1476
+ resolution: 20, // the resolution of the smoothness
1477
+ epsilon: 10, // how much the path is simplified before smoothing
1478
+ },
1479
+ },
1480
+ autoplay: true,
1481
+ });
1482
+
1483
+ // Add to map
1484
+ map.addLayer(animatedRoute);
1485
+
1486
+ // Playback controls
1487
+ animatedRoute.play();
1488
+ animatedRoute.pause();
1489
+ ```
1490
+
1491
+ For a full example of how to use this, look at [the example](./demos/11-animated-routes.html)
1492
+
1326
1493
  ### Vector Layer Helpers
1327
1494
 
1328
1495
  **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!** πŸ–‹οΈ
package/dist/eslint.mjs CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import tseslint from "typescript-eslint";
4
4
  import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
5
+ import eslintPluginCompat from "eslint-plugin-compat";
5
6
 
6
7
  export default tseslint.config(
7
8
  // https://typescript-eslint.io/getting-started/typed-linting/
@@ -11,6 +12,7 @@ export default tseslint.config(
11
12
  {
12
13
  // forked from https://www.npmjs.com/package/eslint-plugin-restrict-imports
13
14
  plugins: {
15
+ compat: eslintPluginCompat,
14
16
  import: {
15
17
  rules: {
16
18
  "default-imports-only": {
@@ -67,7 +69,12 @@ export default tseslint.config(
67
69
  },
68
70
  },
69
71
  },
72
+ settings: {
73
+ // eslint-plugin-compat polyfill
74
+ polyfills: ["requestIdleCallback"],
75
+ },
70
76
  rules: {
77
+ "compat/compat": "error",
71
78
  "import/default-imports-only": [
72
79
  "error",
73
80
  {
@@ -127,6 +134,7 @@ export default tseslint.config(
127
134
  "@typescript-eslint/related-getter-setter-pairs": "off",
128
135
  "@typescript-eslint/unbound-method": "warn",
129
136
  "@typescript-eslint/use-unknown-in-catch-callback-variable": "warn",
137
+ "@typescript-eslint/unified-signatures": ["error", { ignoreOverloadsWithDifferentJSDoc: true }],
130
138
  },
131
139
  },
132
140
  //