@map-colonies/react-components 3.13.1 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +46 -11
  2. package/dist/assets/img/transparent-tile.png +0 -0
  3. package/dist/cesium-map/helpers/customImageryProviders.d.ts +34 -0
  4. package/dist/cesium-map/helpers/customImageryProviders.js +106 -0
  5. package/dist/cesium-map/helpers/utils.d.ts +17 -0
  6. package/dist/cesium-map/helpers/utils.js +142 -0
  7. package/dist/cesium-map/layers/wms.layer.js +7 -1
  8. package/dist/cesium-map/layers/wmts.layer.js +7 -1
  9. package/dist/cesium-map/layers/xyz.layer.js +7 -1
  10. package/dist/cesium-map/layers-manager.d.ts +4 -0
  11. package/dist/cesium-map/layers-manager.js +169 -12
  12. package/dist/cesium-map/map.d.ts +5 -0
  13. package/dist/cesium-map/map.js +40 -12
  14. package/dist/cesium-map/tools/scale-tracker.tool.js +4 -1
  15. package/dist/cesium-map/tools/zoom_level-tracker.tool.css +19 -0
  16. package/dist/cesium-map/tools/zoom_level-tracker.tool.d.ts +8 -0
  17. package/dist/cesium-map/tools/zoom_level-tracker.tool.js +131 -0
  18. package/package.json +2 -2
  19. package/public/assets/img/transparent-tile.png +0 -0
  20. package/src/lib/cesium-map/helpers/customImageryProviders.ts +173 -0
  21. package/src/lib/cesium-map/helpers/utils.ts +135 -0
  22. package/src/lib/cesium-map/layers/optimized-tile-requests.stories.tsx +279 -0
  23. package/src/lib/cesium-map/layers/wms.layer.tsx +10 -4
  24. package/src/lib/cesium-map/layers/wmts.layer.tsx +9 -4
  25. package/src/lib/cesium-map/layers/xyz.layer.tsx +9 -4
  26. package/src/lib/cesium-map/layers-manager.ts +223 -19
  27. package/src/lib/cesium-map/map.stories.tsx +1 -0
  28. package/src/lib/cesium-map/map.tsx +33 -0
  29. package/src/lib/cesium-map/settings/settings.stories.tsx +5 -1
  30. package/src/lib/cesium-map/tools/coordinates-tracker.tool.tsx +6 -1
  31. package/src/lib/cesium-map/tools/scale-tracker.tool.tsx +4 -1
  32. package/src/lib/cesium-map/tools/zoom_level-tracker.tool.css +19 -0
  33. package/src/lib/cesium-map/tools/zoom_level-tracker.tool.tsx +142 -0
  34. package/src/lib/date-range-picker/date-range-picker.spec.tsx +81 -81
  35. package/jest_html_reporters.html +0 -78
@@ -19,8 +19,11 @@ var cesium_1 = require("cesium");
19
19
  var lodash_1 = require("lodash");
20
20
  var boolean_point_in_polygon_1 = __importDefault(require("@turf/boolean-point-in-polygon"));
21
21
  var point_geojson_1 = require("./tools/geojson/point.geojson");
22
+ var customImageryProviders_1 = require("./helpers/customImageryProviders");
23
+ var utils_1 = require("./helpers/utils");
22
24
  var INC = 1;
23
25
  var DEC = -1;
26
+ var TRANSPARENT_LAYER_ID = 'TRANSPARENT_BASE_LAYER';
24
27
  var LayerManager = /** @class */ (function () {
25
28
  function LayerManager(mapViewer, legendsExtractor, onLayersUpdate) {
26
29
  var _this = this;
@@ -33,18 +36,44 @@ var LayerManager = /** @class */ (function () {
33
36
  if (onLayersUpdate) {
34
37
  this.layerUpdated.addEventListener(onLayersUpdate, this);
35
38
  }
36
- this.mapViewer.imageryLayers.layerRemoved.addEventListener(function () {
37
- _this.setLegends();
38
- _this.layerUpdated.raiseEvent();
39
- });
39
+ // Binding layer's relevancy check to cesium lifecycle if optimized tile requests enabled.
40
+ if (this.mapViewer.shouldOptimizedTileRequests) {
41
+ this.layerUpdated.addEventListener(function (meta) {
42
+ var newMetaKeys = Object.keys(meta);
43
+ var shouldTriggerRelevancyCheck = newMetaKeys.length === 1 &&
44
+ newMetaKeys[0] === customImageryProviders_1.HAS_TRANSPARENCY_META_PROP;
45
+ if (shouldTriggerRelevancyCheck) {
46
+ _this.markRelevantLayersForExtent();
47
+ _this.hideNonRelevantLayers();
48
+ }
49
+ });
50
+ this.mapViewer.imageryLayers.layerRemoved.addEventListener(function () {
51
+ _this.setLegends();
52
+ _this.markRelevantLayersForExtent();
53
+ _this.hideNonRelevantLayers();
54
+ });
55
+ this.mapViewer.imageryLayers.layerMoved.addEventListener(function () {
56
+ _this.markRelevantLayersForExtent();
57
+ _this.hideNonRelevantLayers();
58
+ });
59
+ this.mapViewer.imageryLayers.layerAdded.addEventListener(function () {
60
+ _this.markRelevantLayersForExtent();
61
+ _this.hideNonRelevantLayers();
62
+ });
63
+ this.mapViewer.camera.moveEnd.addEventListener(function () {
64
+ _this.markRelevantLayersForExtent();
65
+ _this.hideNonRelevantLayers();
66
+ });
67
+ }
40
68
  }
41
69
  /* eslint-disable */
42
70
  LayerManager.prototype.addMetaToLayer = function (meta, layerPredicate) {
71
+ var _a;
43
72
  var layer = this.layers.find(layerPredicate);
44
73
  if (layer) {
45
- layer.meta = meta;
74
+ layer.meta = __assign(__assign({}, ((_a = layer.meta) !== null && _a !== void 0 ? _a : {})), meta);
46
75
  this.setLegends();
47
- this.layerUpdated.raiseEvent();
76
+ this.layerUpdated.raiseEvent(meta);
48
77
  }
49
78
  };
50
79
  /* eslint-enable */
@@ -54,19 +83,50 @@ var LayerManager = /** @class */ (function () {
54
83
  sortedBaseMapLayers.forEach(function (layer, idx) {
55
84
  _this.addRasterLayer(layer, idx, baseMap.id);
56
85
  });
86
+ /**
87
+ * Set transparent layer as the first layer. if using optimized tile requests.
88
+ *
89
+ * Apparently, cesium layer's rectangle is not affective when:
90
+ * - There is only one active layer && The layer's rectangle contains the extent rectangle.
91
+ *
92
+ * As a result, when using optimized tile requesting and we zoom in a discrete layer,
93
+ * there are some visual artifacts due to tiles requesting outside of the layer's rectangle boundary.
94
+ *
95
+ * A simple workaround would be adding a transparent layer as the very first layer at all times,
96
+ * so that we ensure the rectangle will always be affective.
97
+ */
98
+ if (this.mapViewer.shouldOptimizedTileRequests) {
99
+ this.removeLayer(TRANSPARENT_LAYER_ID);
100
+ this.addTransparentImageryProvider();
101
+ }
57
102
  };
58
103
  LayerManager.prototype.addRasterLayer = function (layer, index, parentId) {
59
104
  var cesiumLayer;
60
105
  switch (layer.type) {
61
- case 'XYZ_LAYER':
62
- cesiumLayer = this.mapViewer.imageryLayers.addImageryProvider(new cesium_1.UrlTemplateImageryProvider(layer.options), index);
106
+ case 'XYZ_LAYER': {
107
+ var options = layer.options;
108
+ var providerInstance = this.mapViewer.shouldOptimizedTileRequests
109
+ ? new customImageryProviders_1.CustomUrlTemplateImageryProvider(options, this.mapViewer)
110
+ : new cesium_1.UrlTemplateImageryProvider(options);
111
+ cesiumLayer = this.mapViewer.imageryLayers.addImageryProvider(providerInstance, index);
63
112
  break;
64
- case 'WMS_LAYER':
65
- cesiumLayer = this.mapViewer.imageryLayers.addImageryProvider(new cesium_1.WebMapServiceImageryProvider(layer.options), index);
113
+ }
114
+ case 'WMS_LAYER': {
115
+ var options = layer.options;
116
+ var providerInstance = this.mapViewer.shouldOptimizedTileRequests
117
+ ? new customImageryProviders_1.CustomWebMapServiceImageryProvider(options, this.mapViewer)
118
+ : new cesium_1.WebMapServiceImageryProvider(options);
119
+ cesiumLayer = this.mapViewer.imageryLayers.addImageryProvider(providerInstance, index);
66
120
  break;
67
- case 'WMTS_LAYER':
68
- cesiumLayer = this.mapViewer.imageryLayers.addImageryProvider(new cesium_1.WebMapTileServiceImageryProvider(layer.options), index);
121
+ }
122
+ case 'WMTS_LAYER': {
123
+ var options = layer.options;
124
+ var providerInstance = this.mapViewer.shouldOptimizedTileRequests
125
+ ? new customImageryProviders_1.CustomWebMapTileServiceImageryProvider(options, this.mapViewer)
126
+ : new cesium_1.WebMapTileServiceImageryProvider(options);
127
+ cesiumLayer = this.mapViewer.imageryLayers.addImageryProvider(providerInstance, index);
69
128
  break;
129
+ }
70
130
  case 'OSM_LAYER':
71
131
  break;
72
132
  }
@@ -205,6 +265,19 @@ var LayerManager = /** @class */ (function () {
205
265
  return ((_a = layer2.meta) === null || _a === void 0 ? void 0 : _a.zIndex) - ((_b = layer1.meta) === null || _b === void 0 ? void 0 : _b.zIndex);
206
266
  });
207
267
  };
268
+ LayerManager.prototype.addTransparentImageryProvider = function () {
269
+ // Worldwide transparent layer
270
+ var transparentLayer = this.mapViewer.imageryLayers.addImageryProvider(new cesium_1.SingleTileImageryProvider({
271
+ url: './assets/img/transparent-tile.png',
272
+ /* eslint-disable @typescript-eslint/no-magic-numbers */
273
+ rectangle: new cesium_1.Rectangle(-3.141592653589793, -1.5707963267948966, 3.141592653589793, 1.5707963267948966),
274
+ /* eslint-enable @typescript-eslint/no-magic-numbers */
275
+ }), 0);
276
+ transparentLayer.meta = {
277
+ id: TRANSPARENT_LAYER_ID,
278
+ skipRelevancyCheck: true,
279
+ };
280
+ };
208
281
  LayerManager.prototype.setLegends = function () {
209
282
  if (typeof this.legendsExtractor !== 'undefined') {
210
283
  this.legendsList = this.legendsExtractor(this.layers);
@@ -241,6 +314,90 @@ var LayerManager = /** @class */ (function () {
241
314
  }
242
315
  });
243
316
  };
317
+ LayerManager.prototype.hideNonRelevantLayers = function () {
318
+ var _a, _b, _c;
319
+ for (var _i = 0, _d = this.layers; _i < _d.length; _i++) {
320
+ var layer = _d[_i];
321
+ if (((_a = layer.meta) === null || _a === void 0 ? void 0 : _a.relevantToExtent) !== layer.show &&
322
+ layer.imageryProvider.ready) {
323
+ //@ts-ignore
324
+ layer.show = (_c = (_b = layer.meta) === null || _b === void 0 ? void 0 : _b.relevantToExtent) !== null && _c !== void 0 ? _c : true;
325
+ }
326
+ }
327
+ };
328
+ LayerManager.prototype.markRelevantLayersForExtent = function () {
329
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
330
+ try {
331
+ var extent = this.mapViewer.camera.computeViewRectangle();
332
+ // Iterating in reverse order so that top layer is first.
333
+ for (var i = this.layers.length - 1; i >= 0; i--) {
334
+ var layer = this.layers[i];
335
+ var intersectsExtent = !lodash_1.isEmpty(extent) &&
336
+ !lodash_1.isEmpty(layer.rectangle) &&
337
+ cesium_1.Rectangle.intersection(extent, layer.rectangle);
338
+ // Iterating from top layer until the current. (inclusive)
339
+ for (var j = this.layers.length - 1; j >= i; j--) {
340
+ if (((_a = layer.meta) === null || _a === void 0 ? void 0 : _a.skipRelevancyCheck) === true) {
341
+ layer.meta = __assign(__assign({}, layer.meta), { relevantToExtent: true });
342
+ continue;
343
+ }
344
+ var layerAbove = this.layers[j];
345
+ var layerAboveHasTransparency = ((_b = layerAbove.meta) === null || _b === void 0 ? void 0 : _b[customImageryProviders_1.HAS_TRANSPARENCY_META_PROP]) === true;
346
+ if (layer !== layerAbove) {
347
+ // Layer is relevant if in extent and there is no layer above it which is opaque and contains it.
348
+ if (intersectsExtent instanceof cesium_1.Rectangle) {
349
+ if (utils_1.cesiumRectangleContained(extent, layer.rectangle)) {
350
+ // Layer contains the extent.
351
+ if (utils_1.cesiumRectangleContained(extent, layerAbove.rectangle) &&
352
+ !layerAboveHasTransparency) {
353
+ layer.meta = __assign(__assign({}, ((_c = layer.meta) !== null && _c !== void 0 ? _c : {})), { relevantToExtent: false });
354
+ break;
355
+ }
356
+ else {
357
+ layer.meta = __assign(__assign({}, ((_d = layer.meta) !== null && _d !== void 0 ? _d : {})), { relevantToExtent: true });
358
+ }
359
+ }
360
+ if (utils_1.cesiumRectangleContained(extent, layerAbove.rectangle) &&
361
+ !layerAboveHasTransparency) {
362
+ layer.meta = __assign(__assign({}, ((_e = layer.meta) !== null && _e !== void 0 ? _e : {})), { relevantToExtent: false });
363
+ break;
364
+ }
365
+ if (utils_1.cesiumRectangleContained(layer.rectangle, layerAbove.rectangle)) {
366
+ layer.meta = __assign(__assign({}, ((_f = layer.meta) !== null && _f !== void 0 ? _f : {})), { relevantToExtent: layerAboveHasTransparency });
367
+ // Once there is layer above that hides it, no need to continue to check.
368
+ if (!layerAboveHasTransparency) {
369
+ break;
370
+ }
371
+ }
372
+ else {
373
+ // Not contained by layer above it, and inside the extent.
374
+ layer.meta = __assign(__assign({}, ((_g = layer.meta) !== null && _g !== void 0 ? _g : {})), { relevantToExtent: true });
375
+ }
376
+ }
377
+ else {
378
+ layer.meta = __assign(__assign({}, ((_h = layer.meta) !== null && _h !== void 0 ? _h : {})), { relevantToExtent: false });
379
+ }
380
+ }
381
+ else {
382
+ // Handle top layer
383
+ if (i === this.layers.length - 1) {
384
+ layer.meta = __assign(__assign({}, ((_j = layer.meta) !== null && _j !== void 0 ? _j : {})), { relevantToExtent: intersectsExtent instanceof cesium_1.Rectangle });
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
390
+ catch (e) {
391
+ console.error(e);
392
+ }
393
+ };
394
+ Object.defineProperty(LayerManager.prototype, "layerList", {
395
+ get: function () {
396
+ return this.layers;
397
+ },
398
+ enumerable: false,
399
+ configurable: true
400
+ });
244
401
  return LayerManager;
245
402
  }());
246
403
  exports.default = LayerManager;
@@ -9,7 +9,10 @@ import { CesiumSceneModeEnum } from './map.types';
9
9
  import './map.css';
10
10
  export declare class CesiumViewer extends CesiumViewerCls {
11
11
  layersManager?: LayerManager;
12
+ private useOptimizedTileRequests?;
12
13
  constructor(container: string | Element, options?: CesiumViewerCls.ConstructorOptions);
14
+ get shouldOptimizedTileRequests(): boolean;
15
+ set shouldOptimizedTileRequests(useOptimizedTileRequests: boolean);
13
16
  }
14
17
  export interface IContextMenuData {
15
18
  data: Record<string, unknown>[];
@@ -40,6 +43,7 @@ interface ILegends {
40
43
  }
41
44
  export interface CesiumMapProps extends ViewerProps {
42
45
  showMousePosition?: boolean;
46
+ showZoomLevel?: boolean;
43
47
  showScale?: boolean;
44
48
  projection?: Proj;
45
49
  center?: [number, number];
@@ -49,6 +53,7 @@ export interface CesiumMapProps extends ViewerProps {
49
53
  };
50
54
  sceneModes?: CesiumSceneModeEnum[];
51
55
  baseMaps?: IBaseMaps;
56
+ useOptimizedTileRequests?: boolean;
52
57
  terrainProvider?: TerrainProvider;
53
58
  imageryContextMenu?: React.ReactElement<IContextMenuData>;
54
59
  imageryContextMenuSize?: {
@@ -59,6 +59,7 @@ var box_1 = require("../box");
59
59
  var projections_1 = require("../utils/projections");
60
60
  var coordinates_tracker_tool_1 = require("./tools/coordinates-tracker.tool");
61
61
  var scale_tracker_tool_1 = require("./tools/scale-tracker.tool");
62
+ var zoom_level_tracker_tool_1 = require("./tools/zoom_level-tracker.tool");
62
63
  var settings_1 = require("./settings/settings");
63
64
  var map_legend_1 = require("./map-legend");
64
65
  var layers_manager_1 = __importDefault(require("./layers-manager"));
@@ -73,6 +74,17 @@ var CesiumViewer = /** @class */ (function (_super) {
73
74
  function CesiumViewer(container, options) {
74
75
  return _super.call(this, container, options) || this;
75
76
  }
77
+ Object.defineProperty(CesiumViewer.prototype, "shouldOptimizedTileRequests", {
78
+ get: function () {
79
+ var _a;
80
+ return (_a = this.useOptimizedTileRequests) !== null && _a !== void 0 ? _a : false;
81
+ },
82
+ set: function (useOptimizedTileRequests) {
83
+ this.useOptimizedTileRequests = useOptimizedTileRequests;
84
+ },
85
+ enumerable: false,
86
+ configurable: true
87
+ });
76
88
  return CesiumViewer;
77
89
  }(cesium_1.Viewer));
78
90
  exports.CesiumViewer = CesiumViewer;
@@ -93,16 +105,17 @@ var CesiumMap = function (props) {
93
105
  var _p = react_1.useState(), mapViewRef = _p[0], setMapViewRef = _p[1];
94
106
  var _q = react_1.useState(), projection = _q[0], setProjection = _q[1];
95
107
  var _r = react_1.useState(), showMousePosition = _r[0], setShowMousePosition = _r[1];
96
- var _s = react_1.useState(), showScale = _s[0], setShowScale = _s[1];
97
- var _t = react_1.useState(), locale = _t[0], setLocale = _t[1];
98
- var _u = react_1.useState(), cameraState = _u[0], setCameraState = _u[1];
99
- var _v = react_1.useState(), sceneModes = _v[0], setSceneModes = _v[1];
100
- var _w = react_1.useState([]), legendsList = _w[0], setLegendsList = _w[1];
101
- var _x = react_1.useState(), baseMaps = _x[0], setBaseMaps = _x[1];
102
- var _y = react_1.useState(false), showImageryMenu = _y[0], setShowImageryMenu = _y[1];
103
- var _z = react_1.useState(undefined), imageryMenuPosition = _z[0], setImageryMenuPosition = _z[1];
104
- var _0 = react_1.useState(false), isLegendsSidebarOpen = _0[0], setIsLegendsSidebarOpen = _0[1];
105
- var _1 = react_1.useState(), rightClickCoordinates = _1[0], setRightClickCoordinates = _1[1];
108
+ var _s = react_1.useState(), showZoomLevel = _s[0], setShowZoomLevel = _s[1];
109
+ var _t = react_1.useState(), showScale = _t[0], setShowScale = _t[1];
110
+ var _u = react_1.useState(), locale = _u[0], setLocale = _u[1];
111
+ var _v = react_1.useState(), cameraState = _v[0], setCameraState = _v[1];
112
+ var _w = react_1.useState(), sceneModes = _w[0], setSceneModes = _w[1];
113
+ var _x = react_1.useState([]), legendsList = _x[0], setLegendsList = _x[1];
114
+ var _y = react_1.useState(), baseMaps = _y[0], setBaseMaps = _y[1];
115
+ var _z = react_1.useState(false), showImageryMenu = _z[0], setShowImageryMenu = _z[1];
116
+ var _0 = react_1.useState(undefined), imageryMenuPosition = _0[0], setImageryMenuPosition = _0[1];
117
+ var _1 = react_1.useState(false), isLegendsSidebarOpen = _1[0], setIsLegendsSidebarOpen = _1[1];
118
+ var _2 = react_1.useState(), rightClickCoordinates = _2[0], setRightClickCoordinates = _2[1];
106
119
  var viewerProps = __assign({ fullscreenButton: true, timeline: false, animation: false, baseLayerPicker: false, geocoder: false, navigationHelpButton: false, homeButton: false, sceneModePicker: false }, props);
107
120
  var getImageryMenuStyle = function (x, y, menuWidth, menuHeight, menuDynamicHeightIncrement) {
108
121
  var container = mapViewRef.container;
@@ -134,14 +147,24 @@ var CesiumMap = function (props) {
134
147
  setMapViewRef((_a = ref.current) === null || _a === void 0 ? void 0 : _a.cesiumElement);
135
148
  }, [ref, props.imageryContextMenu]);
136
149
  react_1.useEffect(function () {
137
- var _a;
150
+ var _a, _b;
138
151
  if (mapViewRef) {
139
- mapViewRef.layersManager = new layers_manager_1.default(mapViewRef, (_a = props.legends) === null || _a === void 0 ? void 0 : _a.mapLegendsExtractor, function () {
152
+ mapViewRef.shouldOptimizedTileRequests =
153
+ (_a = props.useOptimizedTileRequests) !== null && _a !== void 0 ? _a : false;
154
+ mapViewRef.layersManager = new layers_manager_1.default(mapViewRef, (_b = props.legends) === null || _b === void 0 ? void 0 : _b.mapLegendsExtractor, function () {
140
155
  var _a;
141
156
  setLegendsList((_a = mapViewRef === null || mapViewRef === void 0 ? void 0 : mapViewRef.layersManager) === null || _a === void 0 ? void 0 : _a.legendsList);
142
157
  });
143
158
  }
159
+ // eslint-disable-next-line react-hooks/exhaustive-deps
144
160
  }, [mapViewRef]);
161
+ react_1.useEffect(function () {
162
+ var _a;
163
+ if (mapViewRef) {
164
+ mapViewRef.shouldOptimizedTileRequests =
165
+ (_a = props.useOptimizedTileRequests) !== null && _a !== void 0 ? _a : false;
166
+ }
167
+ }, [props.useOptimizedTileRequests, mapViewRef]);
145
168
  react_1.useEffect(function () {
146
169
  var _a;
147
170
  setSceneModes((_a = props.sceneModes) !== null && _a !== void 0 ? _a : [
@@ -169,6 +192,10 @@ var CesiumMap = function (props) {
169
192
  var _a;
170
193
  setShowMousePosition((_a = props.showMousePosition) !== null && _a !== void 0 ? _a : true);
171
194
  }, [props.showMousePosition]);
195
+ react_1.useEffect(function () {
196
+ var _a;
197
+ setShowZoomLevel((_a = props.showZoomLevel) !== null && _a !== void 0 ? _a : true);
198
+ }, [props.showZoomLevel]);
172
199
  react_1.useEffect(function () {
173
200
  var _a;
174
201
  setShowScale((_a = props.showScale) !== null && _a !== void 0 ? _a : true);
@@ -269,6 +296,7 @@ var CesiumMap = function (props) {
269
296
  } })),
270
297
  react_1.default.createElement(box_1.Box, { className: "toolsContainer" },
271
298
  showMousePosition === true ? (react_1.default.createElement(coordinates_tracker_tool_1.CoordinatesTrackerTool, { projection: projection })) : (react_1.default.createElement(react_1.default.Fragment, null)),
299
+ showZoomLevel === true ? (react_1.default.createElement(zoom_level_tracker_tool_1.ZoomLevelTrackerTool, { locale: locale })) : (react_1.default.createElement(react_1.default.Fragment, null)),
272
300
  showScale === true ? react_1.default.createElement(scale_tracker_tool_1.ScaleTrackerTool, { locale: locale }) : react_1.default.createElement(react_1.default.Fragment, null))), document.querySelector('.cesium-viewer')));
273
301
  }, [
274
302
  baseMaps,
@@ -136,7 +136,10 @@ var ScaleTrackerTool = function (props) {
136
136
  mapViewer.camera.moveEnd.addEventListener(setFromEvent);
137
137
  return function () {
138
138
  try {
139
- mapViewer.camera.moveEnd.removeEventListener(setFromEvent);
139
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition*/
140
+ if (lodash_1.get(mapViewer, '_cesiumWidget') != undefined) {
141
+ mapViewer.camera.moveEnd.removeEventListener(setFromEvent);
142
+ }
140
143
  }
141
144
  catch (e) {
142
145
  console.log('CESIUM camera "moveEnd" remove listener failed', e);
@@ -0,0 +1,19 @@
1
+ .zoomLevel {
2
+ z-index: 2000;
3
+ background-color: var(--mdc-theme-surface);
4
+ border-radius: 2px;
5
+ padding: 2px;
6
+ height: 24px;
7
+ }
8
+
9
+ .zoomLevelValue {
10
+ margin: 2px;
11
+ font-size: 14px;
12
+ line-height: 10px;
13
+ text-align: center;
14
+ }
15
+
16
+ .zoomLevelLabel {
17
+ font-size: 8px;
18
+ line-height: 8px;
19
+ }
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import './zoom_level-tracker.tool.css';
3
+ export interface RZoomLevelTrackerToolProps {
4
+ locale?: {
5
+ [key: string]: string;
6
+ };
7
+ }
8
+ export declare const ZoomLevelTrackerTool: React.FC<RZoomLevelTrackerToolProps>;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.ZoomLevelTrackerTool = void 0;
23
+ var react_1 = __importStar(require("react"));
24
+ var lodash_1 = require("lodash");
25
+ var map_1 = require("../map");
26
+ var map_types_1 = require("../map.types");
27
+ require("./zoom_level-tracker.tool.css");
28
+ /* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/naming-convention, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call */
29
+ var detectZoomLevel = function (distance, viewer) {
30
+ var MAX_ZOOM_LEVEL = 19;
31
+ var tileProvider = lodash_1.get(viewer.scene.globe, '_surface.tileProvider');
32
+ var quadtree = tileProvider._quadtree;
33
+ var drawingBufferHeight = viewer.canvas.height;
34
+ var sseDenominator = lodash_1.get(viewer.camera.frustum, 'sseDenominator');
35
+ for (var level = 0; level <= MAX_ZOOM_LEVEL; level++) {
36
+ var maxGeometricError = tileProvider.getLevelMaximumGeometricError(level);
37
+ var error = (maxGeometricError * drawingBufferHeight) / (distance * sseDenominator);
38
+ if (error < quadtree.maximumScreenSpaceError) {
39
+ return level;
40
+ }
41
+ }
42
+ return null;
43
+ };
44
+ var getZoomLevelHeights = function (precision, viewer) {
45
+ precision = precision || 10;
46
+ var result = [];
47
+ var step = 100000.0;
48
+ var currentZoomLevel = 0;
49
+ for (var height = 100000000.0; height > step; height = height - step) {
50
+ var level = detectZoomLevel(height, viewer);
51
+ if (level === null) {
52
+ break;
53
+ }
54
+ if (level !== currentZoomLevel) {
55
+ var minHeight = height;
56
+ var maxHeight = height + step;
57
+ while (maxHeight - minHeight > precision) {
58
+ height = minHeight + (maxHeight - minHeight) / 2;
59
+ if (detectZoomLevel(height, viewer) === level) {
60
+ minHeight = height;
61
+ }
62
+ else {
63
+ maxHeight = height;
64
+ }
65
+ }
66
+ result.push({
67
+ level: level,
68
+ height: Math.round(height),
69
+ });
70
+ currentZoomLevel = level;
71
+ if (result.length >= 2) {
72
+ step = (result[result.length - 2].height - height) / 1000.0;
73
+ }
74
+ }
75
+ }
76
+ return result;
77
+ };
78
+ /* eslint-enable @typescript-eslint/no-magic-numbers */
79
+ var ZoomLevelTrackerTool = function (props) {
80
+ var _a;
81
+ var mapViewer = map_1.useCesiumMap();
82
+ var _b = react_1.useState(1), zoomLevel = _b[0], setZoomLevel = _b[1];
83
+ var zoomLevelHeights = getZoomLevelHeights(1, mapViewer);
84
+ react_1.useEffect(function () {
85
+ var calculateZoomLevel = function () {
86
+ var camera = mapViewer.camera;
87
+ var ORTHOPHOTO_HEIGHT_FRUSTRUM_FACTOR = 0.5;
88
+ var cameraHeight = 0;
89
+ switch (mapViewer.scene.mode) {
90
+ case map_types_1.CesiumSceneMode.SCENE3D:
91
+ cameraHeight = mapViewer.scene.mapProjection.ellipsoid.cartesianToCartographic(camera.positionWC).height;
92
+ break;
93
+ case map_types_1.CesiumSceneMode.SCENE2D:
94
+ cameraHeight =
95
+ (camera.frustum.right -
96
+ camera.frustum.left) *
97
+ ORTHOPHOTO_HEIGHT_FRUSTRUM_FACTOR;
98
+ break;
99
+ case map_types_1.CesiumSceneMode.COLUMBUS_VIEW:
100
+ cameraHeight = camera.position.z;
101
+ break;
102
+ default:
103
+ cameraHeight = 0;
104
+ break;
105
+ }
106
+ var closestZoom = zoomLevelHeights.reduce(function (a, b) {
107
+ return Math.abs(b.height - cameraHeight) <
108
+ Math.abs(a.height - cameraHeight)
109
+ ? b
110
+ : a;
111
+ });
112
+ setZoomLevel(closestZoom.level);
113
+ };
114
+ mapViewer.camera.moveEnd.addEventListener(calculateZoomLevel);
115
+ return function () {
116
+ try {
117
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition*/
118
+ if (lodash_1.get(mapViewer, '_cesiumWidget') != undefined) {
119
+ mapViewer.camera.moveEnd.removeEventListener(calculateZoomLevel);
120
+ }
121
+ }
122
+ catch (e) {
123
+ console.log('CESIUM camera "moveEnd"(from zoom tracker) remove listener failed', e);
124
+ }
125
+ };
126
+ }, [mapViewer]);
127
+ return (react_1.default.createElement("div", { className: "zoomLevel" },
128
+ react_1.default.createElement("div", { className: "zoomLevelValue" }, zoomLevel),
129
+ react_1.default.createElement("div", { className: "zoomLevelLabel" }, (_a = lodash_1.get(props.locale, 'ZOOM_LABEL')) !== null && _a !== void 0 ? _a : 'zoom')));
130
+ };
131
+ exports.ZoomLevelTrackerTool = ZoomLevelTrackerTool;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@map-colonies/react-components",
3
- "version": "3.13.1",
3
+ "version": "3.15.0",
4
4
  "module": "dist/index.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -93,7 +93,7 @@
93
93
  "jest-enzyme": "^7.1.2",
94
94
  "react-test-renderer": "^16.13.1"
95
95
  },
96
- "gitHead": "2b22c0f4e5e2b632bd656ec88b29a4d02d339af0",
96
+ "gitHead": "6b136929ab3c4ba3489825ee9be301eb0b968a1e",
97
97
  "jest": {
98
98
  "coverageReporters": [
99
99
  "text",