@geogirafe/lib-geoportal 1.2.0-dev.2800201562 → 1.2.0-dev.2816732111

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 (70) hide show
  1. package/api/apicontext.d.ts +4 -0
  2. package/api/apicontext.js +8 -0
  3. package/api/apigeogirafeapp.js +7 -5
  4. package/api/style.css +18 -1
  5. package/components/drawing/component.d.ts +9 -2
  6. package/components/drawing/component.js +27 -10
  7. package/components/drawing-toolbar/component.js +2 -2
  8. package/components/extlayers/component.d.ts +0 -1
  9. package/components/extlayers/component.js +1 -6
  10. package/components/main.d.ts +3 -1
  11. package/components/main.js +3 -1
  12. package/components/{map → map-2d}/component.d.ts +9 -24
  13. package/components/{map → map-2d}/component.js +28 -260
  14. package/components/map-2d/deprecatedmapcomponent.d.ts +15 -0
  15. package/components/map-2d/deprecatedmapcomponent.js +24 -0
  16. package/components/{map → map-2d}/style.css +0 -30
  17. package/components/{map → map-2d}/tools/swipemanager.d.ts +1 -1
  18. package/components/map-3d/component.d.ts +50 -0
  19. package/components/map-3d/component.js +139 -0
  20. package/components/map-3d/style.css +34 -0
  21. package/components/map-3d/tools/globe.d.ts +42 -0
  22. package/components/map-3d/tools/globe.js +198 -0
  23. package/components/selectiontool/component.d.ts +2 -2
  24. package/components/selectiontool/component.js +2 -2
  25. package/package.json +1 -1
  26. package/styles/iframe.css +18 -1
  27. package/styles/index.css +18 -1
  28. package/styles/mobile.css +18 -1
  29. package/templates/iframe.html +4 -1
  30. package/templates/index.html +4 -1
  31. package/templates/mobile.html +4 -1
  32. package/templates/public/about.json +1 -1
  33. package/templates/vite.config.js +43 -25
  34. package/tools/app/geogirafeapp-mobile.js +7 -2
  35. package/tools/app/geogirafeapp.js +7 -2
  36. package/tools/context/context.d.ts +4 -0
  37. package/tools/context/context.js +8 -0
  38. package/tools/context/icontext.d.ts +5 -0
  39. package/tools/drawing/cesiumDrawing.d.ts +9 -5
  40. package/tools/drawing/cesiumDrawing.js +8 -8
  41. package/tools/drawing/olDrawing.d.ts +2 -2
  42. package/tools/drawing/olDrawing.js +1 -1
  43. package/tools/main.d.ts +2 -0
  44. package/tools/main.js +2 -0
  45. package/tools/selection/selectionmanager.d.ts +19 -0
  46. package/tools/selection/selectionmanager.js +80 -0
  47. package/tools/state/componentManager.d.ts +1 -1
  48. package/tools/tests/mockcontext.d.ts +4 -0
  49. package/tools/tests/mockcontext.js +8 -0
  50. package/{components/map/tools → tools/wmts}/wmtsmanager.d.ts +4 -7
  51. package/{components/map/tools → tools/wmts}/wmtsmanager.js +7 -10
  52. /package/components/{map → map-2d}/tools/cogmanager.d.ts +0 -0
  53. /package/components/{map → map-2d}/tools/cogmanager.js +0 -0
  54. /package/components/{map → map-2d}/tools/contextmenu.d.ts +0 -0
  55. /package/components/{map → map-2d}/tools/contextmenu.js +0 -0
  56. /package/components/{map → map-2d}/tools/drawingmanager.d.ts +0 -0
  57. /package/components/{map → map-2d}/tools/drawingmanager.js +0 -0
  58. /package/components/{map → map-2d}/tools/focusfeature.d.ts +0 -0
  59. /package/components/{map → map-2d}/tools/focusfeature.js +0 -0
  60. /package/components/{map → map-2d}/tools/osmmanager.d.ts +0 -0
  61. /package/components/{map → map-2d}/tools/osmmanager.js +0 -0
  62. /package/components/{map → map-2d}/tools/swipemanager.js +0 -0
  63. /package/components/{map → map-2d}/tools/vectortilesmanager.d.ts +0 -0
  64. /package/components/{map → map-2d}/tools/vectortilesmanager.js +0 -0
  65. /package/components/{map → map-2d}/tools/viewmanager.d.ts +0 -0
  66. /package/components/{map → map-2d}/tools/viewmanager.js +0 -0
  67. /package/components/{map → map-2d}/tools/xyzmanager.d.ts +0 -0
  68. /package/components/{map → map-2d}/tools/xyzmanager.js +0 -0
  69. /package/components/{map → map-3d}/tools/wmsmanager3d.d.ts +0 -0
  70. /package/components/{map → map-3d}/tools/wmsmanager3d.js +0 -0
@@ -8,13 +8,9 @@ import { DragBox } from 'ol/interaction.js';
8
8
  import { ScaleLine } from 'ol/control.js';
9
9
  import { GeometryCollection, Point } from 'ol/geom.js';
10
10
  import { getCenter, getHeight, getWidth } from 'ol/extent.js';
11
- import { Cesium3DTileset } from 'cesium';
12
- import proj4 from 'proj4';
13
11
  import SwipeManager from './tools/swipemanager.js';
14
- import WmsManager3d from './tools/wmsmanager3d.js';
15
12
  import OsmManager from './tools/osmmanager.js';
16
13
  import VectorTilesManager from './tools/vectortilesmanager.js';
17
- import WmtsManager from './tools/wmtsmanager.js';
18
14
  import ViewManager from './tools/viewmanager.js';
19
15
  import CogManager from './tools/cogmanager.js';
20
16
  import DrawingManager from './tools/drawingmanager.js';
@@ -40,11 +36,10 @@ import { parseCoordinates } from '../../tools/geometrytools.js';
40
36
  import CircleGeom from 'ol/geom/Circle.js';
41
37
  import WfsFilter from '../../tools/wfs/wfsfilter.js';
42
38
  import WfsFilterCondition from '../../tools/wfs/wfsfiltercondition.js';
43
- import { applyFeaturesToSelection, applyOpacityToLayers } from '../../tools/utils/utils.js';
44
- import { SelectionMode } from '../../models/selection.js';
39
+ import { applyOpacityToLayers } from '../../tools/utils/utils.js';
45
40
  import { platformModifierKeyOnly } from 'ol/events/condition.js';
46
41
  import { HighlightMode } from '../../tools/configuration/girafeconfig.js';
47
- export default class MapComponent extends GirafeHTMLElement {
42
+ export default class Map2dComponent extends GirafeHTMLElement {
48
43
  templateUrl = null;
49
44
  styleUrls = null;
50
45
  template = () => {
@@ -53,25 +48,17 @@ export default class MapComponent extends GirafeHTMLElement {
53
48
  </style><style>
54
49
  .hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}button,input,select,textarea{font:inherit}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height) / 1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad1);background-color:var(--bkg-color-grad2)}.gg-button:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed;border:none}.gg-button:disabled img{filter:opacity(.6)}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height) / 1.2);min-height:calc(var(--app-standard-height) / 1.2);max-height:calc(var(--app-standard-height) / 1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height) / 2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height) / 2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height) / 2);min-height:calc(var(--app-standard-height) / 2);max-height:calc(var(--app-standard-height) / 2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height) / 3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height) / 3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover:not(:disabled),.gg-select:hover:not(:disabled),.gg-input:hover:not(:disabled),.gg-textarea:hover:not(:disabled),.gg-icon-button:hover:not(:disabled){background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height) / 2);height:calc(var(--app-standard-height) / 2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}.tippy-box{background-color:var(--bkg-color)!important;border:var(--app-standard-border)!important}.tippy-content{color:var(--text-color)!important}.tippy-arrow{color:var(--bkg-color)!important}.tippy-box[data-theme~=error]{background-color:var(--error-color);white-space:pre-line}div.tippy-box[data-theme=image-popup]{border:var(--app-standard-border)!important;& div.tippy-content{background-color:var(--bkg-color)!important;& img{max-width:20rem;max-height:20rem}}& div.tippy-arrow{color:var(--bkg-color)!important}}
55
50
  </style><style>
56
- #container,#ol-map{background-color:var(--bkg-color);width:100%;height:100%;position:relative}#ol-map.darkmap canvas{filter:invert()hue-rotate(180deg)}.hidden{display:none}.center{text-align:center;margin:10px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.loading span{color:var(--text-color);margin-top:1rem;font-weight:600;display:block}.loading span.quote{font-style:italic;font-weight:300}#cs-map{background-color:var(--bkg-color);border-left:3px solid #444;height:100%;display:none;position:absolute;overflow:hidden}.ol-control{background-color:#0000;border:none;box-shadow:0 1px 4px #0000004d;right:2rem!important;left:unset!important}.ol-zoom{top:2rem!important}.mobile-map .ol-zoom{display:none!important}.ol-rotate{top:11.6rem!important}.ol-fullscreen{top:7rem!important}.ol-location{top:9.3rem!important}.img-location,.img-disable-location,.img-fullscreen{width:55%;height:auto}.ol-zoom-in,.ol-zoom-out,.btn-location,.btn-disable-location,.btn-fullscreen,.btn-exit-fullscreen,.ol-rotate-reset{cursor:pointer;background-color:var(--bkg-color)!important;width:2rem!important;height:2rem!important;color:var(--text-color)!important;font-size:1.2rem!important}.ol-scale-line{bottom:.5rem!important;right:1rem!important;left:unset!important}#swiper{width:100%;height:0;margin:0;display:none;position:absolute;top:50%}input[type=range]{-webkit-appearance:none;width:100%}input[type=range]::-webkit-slider-runnable-track{height:0}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background:var(--bkg-color);cursor:ew-resize;border:2px solid #444;width:6px;height:0;margin-top:-1000px;padding-top:1000px;padding-bottom:1000px}input[type=range]::-moz-range-thumb{background:var(--bkg-color);cursor:ew-resize;border:2px solid #444;width:3px;height:0;padding-top:1000px;padding-bottom:1000px}.close-swiper{--button-size:2rem;transform:translateX(calc(-1 * var(--button-size) / 2));width:var(--button-size);height:var(--button-size);background-color:var(--bkg-color);color:var(--text-color);cursor:pointer;border-width:1px;border-radius:4px;display:none;position:absolute;top:0}.close-swiper:hover,.close-swiper:focus{outline:1px solid var(--text-color);color:var(--text-color-grad1)}.ol-viewport .tooltip{color:#fff;opacity:.7;white-space:nowrap;background:#00000080;border-radius:0;padding:.32rem .62rem;position:relative}@media screen and (hover:none){.ol-zoom,.ol-rotate,.ol-location,.ol-fullscreen{display:none!important}}.contextmenu{background-color:var(--bkg-color);color:var(--text-color);border:1px solid #ccc;box-shadow:1px 3px 4px #0006;& .hidden{display:none}& .menu-entry{cursor:pointer;padding:10px}& .menu-entry:hover{background-color:var(--bkg-color-grad1)}& .menu-entry[aria-disabled=true]{pointer-events:none;color:var(--text-color-grad1)}}
51
+ #container,#ol-map{background-color:var(--bkg-color);width:100%;height:100%;position:relative}#ol-map.darkmap canvas{filter:invert()hue-rotate(180deg)}.hidden{display:none}.ol-control{background-color:#0000;border:none;box-shadow:0 1px 4px #0000004d;right:2rem!important;left:unset!important}.ol-zoom{top:2rem!important}.mobile-map .ol-zoom{display:none!important}.ol-rotate{top:11.6rem!important}.ol-fullscreen{top:7rem!important}.ol-location{top:9.3rem!important}.img-location,.img-disable-location,.img-fullscreen{width:55%;height:auto}.ol-zoom-in,.ol-zoom-out,.btn-location,.btn-disable-location,.btn-fullscreen,.btn-exit-fullscreen,.ol-rotate-reset{cursor:pointer;background-color:var(--bkg-color)!important;width:2rem!important;height:2rem!important;color:var(--text-color)!important;font-size:1.2rem!important}.ol-scale-line{bottom:.5rem!important;right:1rem!important;left:unset!important}#swiper{width:100%;height:0;margin:0;display:none;position:absolute;top:50%}input[type=range]{-webkit-appearance:none;width:100%}input[type=range]::-webkit-slider-runnable-track{height:0}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background:var(--bkg-color);cursor:ew-resize;border:2px solid #444;width:6px;height:0;margin-top:-1000px;padding-top:1000px;padding-bottom:1000px}input[type=range]::-moz-range-thumb{background:var(--bkg-color);cursor:ew-resize;border:2px solid #444;width:3px;height:0;padding-top:1000px;padding-bottom:1000px}.close-swiper{--button-size:2rem;transform:translateX(calc(-1 * var(--button-size) / 2));width:var(--button-size);height:var(--button-size);background-color:var(--bkg-color);color:var(--text-color);cursor:pointer;border-width:1px;border-radius:4px;display:none;position:absolute;top:0}.close-swiper:hover,.close-swiper:focus{outline:1px solid var(--text-color);color:var(--text-color-grad1)}.ol-viewport .tooltip{color:#fff;opacity:.7;white-space:nowrap;background:#00000080;border-radius:0;padding:.32rem .62rem;position:relative}@media screen and (hover:none){.ol-zoom,.ol-rotate,.ol-location,.ol-fullscreen{display:none!important}}.contextmenu{background-color:var(--bkg-color);color:var(--text-color);border:1px solid #ccc;box-shadow:1px 3px 4px #0006;& .hidden{display:none}& .menu-entry{cursor:pointer;padding:10px}& .menu-entry:hover{background-color:var(--bkg-color-grad1)}& .menu-entry[aria-disabled=true]{pointer-events:none;color:var(--text-color-grad1)}}
57
52
  </style>
58
53
  <style>${this.customStyle}</style>
59
- <div id="container"><div id="ol-map" class="${this.onMobile ? 'mobile-map' : ''}"></div><div class="${this.onMobile ? 'hidden' : 'ol-fullscreen ol-unselectable ol-control'}"><button id="fullscreen-enter-button" onclick="${() => this.toggleFullscreen()}" tip="fullscreen-on" class="btn-fullscreen"><img class="img-fullscreen" alt="fullscreen-icon" src="icons/fullscreen.svg"></button> <button id="fullscreen-exit-button" onclick="${() => this.toggleFullscreen()}" tip="fullscreen-off" class="btn-exit-fullscreen hidden"><img class="img-fullscreen" alt="fullscreen-exit-icon" src="icons/fullscreen-exit.svg"></button></div><div class="${this.onMobile ? 'hidden' : 'ol-location ol-unselectable ol-control'}"><button onclick="${() => this.locateUser()}" class="btn-location" tip="Locate user"><img class="img-location" alt="location-icon" src="icons/adjust.svg"></button> <button id="disable-location" onclick="${() => this.disableLocateUser()}" tip="Disable locate user" class="btn-disable-location hidden"><img class="img-disable-location" alt="disable-location-icon" src="icons/adjust-disable.svg"></button></div><div id="cs-map"><div class="${this.loading ? 'loading center' : 'loading hidden'}"><img alt="loading-icon" src="icons/loading.svg" class="gg-spin"> <span i18n="Loading cesium...">Loading cesium...</span> <span class="quote" i18n="cesium-loading-quote">Please be patient, like a giraffe reaching for the tastiest leaves.</span></div></div><input id="swiper" type="range" min="0" max="1000" step="1"> <button tip="Hide Swiper" id="close-swiper" class="close-swiper">×</button></div>
54
+ <div id="container"><div id="ol-map" class="${this.onMobile ? 'mobile-map' : ''}"></div><div class="${this.onMobile ? 'hidden' : 'ol-fullscreen ol-unselectable ol-control'}"><button id="fullscreen-enter-button" onclick="${() => this.toggleFullscreen()}" tip="fullscreen-on" class="btn-fullscreen"><img class="img-fullscreen" alt="fullscreen-icon" src="icons/fullscreen.svg"></button> <button id="fullscreen-exit-button" onclick="${() => this.toggleFullscreen()}" tip="fullscreen-off" class="btn-exit-fullscreen hidden"><img class="img-fullscreen" alt="fullscreen-exit-icon" src="icons/fullscreen-exit.svg"></button></div><div class="${this.onMobile ? 'hidden' : 'ol-location ol-unselectable ol-control'}"><button onclick="${() => this.locateUser()}" class="btn-location" tip="Locate user"><img class="img-location" alt="location-icon" src="icons/adjust.svg"></button> <button id="disable-location" onclick="${() => this.disableLocateUser()}" tip="Disable locate user" class="btn-disable-location hidden"><img class="img-disable-location" alt="disable-location-icon" src="icons/adjust-disable.svg"></button></div><input id="swiper" type="range" min="0" max="1000" step="1"> <button tip="Hide Swiper" id="close-swiper" class="close-swiper">×</button></div>
60
55
  ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
61
56
  };
62
57
  olMap;
63
58
  mapTarget;
64
- // TODO REG : Howto use the right type here without importing the whole library (it needs to be imported only on demand) ?
65
- // This works but needs the library: type OLCesiumType = typeof OLCesium;
66
- map3d;
67
- map3dTarget;
68
- map3dShadowsTimestamp;
69
- loading = false;
70
59
  swiper;
71
60
  closeSwiperButton;
72
61
  swipeManager;
73
- wmtsManager;
74
- wmsManager3d = null;
75
62
  osmManager;
76
63
  cogManager;
77
64
  xyzManager;
@@ -125,8 +112,11 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
125
112
  dragbox;
126
113
  focusFeature;
127
114
  mapTargetResizeObserver;
128
- constructor() {
129
- super('map');
115
+ get wmtsManager() {
116
+ return this.context.wmtsManager;
117
+ }
118
+ constructor(name = 'map-2d') {
119
+ super(name);
130
120
  }
131
121
  /**
132
122
  * The Map needs to be displayed in Fullscreen Mode.
@@ -158,7 +148,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
158
148
  this.subscribe('projection', (oldProjection, newProjection) => this.onChangeProjection(oldProjection, newProjection));
159
149
  this.subscribe('interface.darkMapMode', () => this.onChangeDarkMode());
160
150
  this.subscribe('interface.fullscreenMode', (_oldValue, newValue) => this.updateFullscreenButton(newValue));
161
- this.subscribe('selection.selectionParameters', (_, newParams) => this.onSelectFeatures(newParams));
162
151
  this.subscribe('selection.selectedFeatures', (_oldFeatures, newFeatures) => this.onFeaturesSelected(newFeatures));
163
152
  this.subscribe('selection.selectedFeaturesType', (_oldFeaturesType, newFeaturesType) => this.onFeaturesTypeChanged(newFeaturesType));
164
153
  this.subscribe('selection.highlightedFeatures', (_oldFeatures, newFeatures) => this.onFeatureHighlighted(newFeatures));
@@ -169,16 +158,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
169
158
  this.addMarker(marker);
170
159
  }
171
160
  });
172
- this.subscribe('globe.display', async () => {
173
- await this.onGlobeToggled();
174
- this.onCameraChanged(this.state.globe.camera);
175
- });
176
- this.subscribe('globe.shadows', (_oldShadows, newShadows) => this.onShadowsToggled(newShadows));
177
- this.subscribe('globe.shadowsTimestamp', (_oldTimestamp, newTimestamp) => this.onShadowsTimestampChanged(newTimestamp));
178
- this.subscribe('globe.camera', async (_oldCamera, newCamera) => {
179
- await this.onGlobeToggled();
180
- this.onCameraChanged(newCamera);
181
- });
161
+ this.subscribe('globe.display', (_oldDisplay, newDisplay) => this.onGlobeDisplayChanged(newDisplay));
182
162
  this.subscribe(/layers\.layersList\..*\.activeState/, async (_oldActive, _newActive, layer) => {
183
163
  await this.onLayerToggled(layer);
184
164
  if (layer.active) {
@@ -195,7 +175,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
195
175
  // The map component may not be fully ready when other part of the application will be initialized
196
176
  // And some operations that need a fuly loaded map need to be first done when the application is ready
197
177
  // For example, Permalink needs resolution,
198
- this.onCameraChanged(this.state.globe.camera);
199
178
  // If the app is opened from a permalink, prioritize this data over settings in the shared state
200
179
  if (this.context.permalinkManager.hasFeatureSelectionQuery()) {
201
180
  this.applyFeatureSelectionFromPermalink();
@@ -297,7 +276,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
297
276
  this.defaultSrid = this.context.configManager.getDefaultConfigValue('map.srid');
298
277
  // Initialize the map element
299
278
  this.mapTarget = this.shadow.getElementById('ol-map');
300
- this.map3dTarget = this.shadow.getElementById('cs-map');
301
279
  this.olMap.setTarget(this.mapTarget);
302
280
  // Initialize managers
303
281
  this.osmManager = new OsmManager(this.olMap);
@@ -306,7 +284,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
306
284
  this.drawingManager = new DrawingManager(this.olMap);
307
285
  this.viewManager = new ViewManager(this.olMap, this.context.configManager, this.context.stateManager);
308
286
  this.vectorTilesManager = new VectorTilesManager(this.olMap);
309
- this.wmtsManager = new WmtsManager(this.olMap, this.context.stateManager);
310
287
  this.swiper = this.shadow.getElementById('swiper');
311
288
  this.closeSwiperButton = this.shadow.getElementById('close-swiper');
312
289
  this.swipeManager = new SwipeManager(this.olMap, this.swiper, this.closeSwiperButton, this.wmtsManager, this.context.wmsManager, this.context.localFileManager);
@@ -492,58 +469,10 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
492
469
  this.select(extent);
493
470
  }
494
471
  select(extent) {
495
- // Reset current selection if SelectionMode is Replace
496
- if (this.state.selection.selectionMode === SelectionMode.Replace) {
497
- this.selectNone();
498
- }
499
- else if (this.state.selection.selectionMode === SelectionMode.Add) {
500
- this.state.selection.selectionParameters = [];
501
- }
502
- // Layers selectable today are WMS, WMTS (with wms layer) and Local files
503
- // Use batch for changes to prevent multiple selection of objects
504
- this.context.stateManager.batchChanges(() => {
505
- this.context.wmsManager.selectFeatures(extent);
506
- this.wmtsManager.selectFeatures(extent);
507
- this.context.localFileManager.selectFeatures(extent);
508
- });
472
+ this.context.selectionManager.select(extent);
509
473
  }
510
474
  selectNone() {
511
- this.state.selection.selectedFeatures = [];
512
- this.state.selection.selectionParameters = [];
513
- this.state.selection.highlightedFeatures = [];
514
- }
515
- async onSelectFeatures(selectionParams) {
516
- if (selectionParams.length === 0) {
517
- return;
518
- }
519
- this.state.loading = true;
520
- try {
521
- // WMS GetFeatureInfo
522
- const wmsPromises = selectionParams.map((param) => {
523
- const wmsGetFeatureInfoSelectionParam = param.clone((l) => l.queryable && l.wmsQueryableOnly);
524
- const client = this.context.wmsManager.getClient(wmsGetFeatureInfoSelectionParam.ogcServer);
525
- return client.getFeatureInfo(wmsGetFeatureInfoSelectionParam);
526
- });
527
- // WFS GetFeature
528
- const wfsPromises = selectionParams.map((param) => {
529
- const wfsGetFeatureInfoSelectionParam = param.clone((l) => l.wfsQueryable);
530
- const client = this.context.wfsManager.getClient(wfsGetFeatureInfoSelectionParam.ogcServer);
531
- const features = client.getFeature(wfsGetFeatureInfoSelectionParam);
532
- return features;
533
- });
534
- const wmsGmlFeatures = (await Promise.all(wmsPromises)).flat();
535
- const wfsGmlFeatures = (await Promise.all(wfsPromises)).flat();
536
- const gmlFeatures = [...wmsGmlFeatures, ...wfsGmlFeatures];
537
- if (gmlFeatures.length === 0 && this.state.selection.selectedFeatures.length === 0) {
538
- this.state.interface.selectionComponentVisible = false;
539
- }
540
- else {
541
- applyFeaturesToSelection(gmlFeatures, this.state);
542
- }
543
- }
544
- finally {
545
- this.state.loading = false;
546
- }
475
+ this.context.selectionManager.selectNone();
547
476
  }
548
477
  connectedCallback() {
549
478
  super.connectedCallback();
@@ -552,7 +481,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
552
481
  this.render();
553
482
  this.listenOpenLayersEvents();
554
483
  this.registerEvents();
555
- this.onGlobeToggled();
484
+ this.onGlobeDisplayChanged(this.state.globe.display);
556
485
  }
557
486
  onCustomGirafeEvent(details) {
558
487
  if (details.action === GeoEvents.zoomToExtent) {
@@ -620,159 +549,24 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
620
549
  })
621
550
  }));
622
551
  }
623
- async create3dMap() {
624
- if (!this.map3d && this.config.map3d) {
625
- this.loading = true;
626
- super.render();
627
- // First : Lazy loading of Cesium and olcs
628
- const Cesium = await import('cesium');
629
- window.Cesium = Cesium;
630
- const olcs = await import('olcs');
631
- // Initialize the 3D Map
632
- this.map3d = new olcs.default({
633
- map: this.olMap,
634
- target: this.map3dTarget,
635
- time: () => {
636
- const date = new Date(this.map3dShadowsTimestamp);
637
- return Number.isNaN(date.getTime()) ? Cesium.JulianDate.now() : Cesium.JulianDate.fromDate(date);
638
- }
639
- });
640
- const scene = this.map3d.getCesiumScene();
641
- const config = this.config.map3d;
642
- scene.screenSpaceCameraController.maximumZoomDistance = config.maximumZoomDistance ?? 30000;
643
- // Add terrain
644
- if (config.terrainUrl) {
645
- scene.terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl(config.terrainUrl);
646
- }
647
- // Add terrain imagery
648
- let coverage = Cesium.Rectangle.MAX_VALUE;
649
- if (config.terrainImagery) {
650
- if (config.terrainImagery.coverageArea) {
651
- coverage = Cesium.Rectangle.fromDegrees(...config.terrainImagery.coverageArea);
652
- }
653
- scene.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
654
- url: config.terrainImagery.url,
655
- minimumLevel: config.terrainImagery.minLoD ?? 0,
656
- maximumLevel: config.terrainImagery.maxLoD,
657
- tilingScheme: config.terrainImagery.srid === 3857
658
- ? new Cesium.WebMercatorTilingScheme()
659
- : new Cesium.GeographicTilingScheme(),
660
- rectangle: coverage
661
- }));
662
- }
663
- // Add 3D-Tiles layers
664
- const tilesetOptions = {
665
- // If the error of the model is higher than this, we increase the resolution
666
- maximumScreenSpaceError: 0.5,
667
- // Enable different level of details based on the distance from the camera
668
- dynamicScreenSpaceError: true,
669
- // Model error at the max distance from the camera (higher = distant models are of lower quality)
670
- dynamicScreenSpaceErrorFactor: config.tilesetsMaxError ?? 7
671
- };
672
- config.tilesetsUrls.forEach((tilesetUrl) => {
673
- Cesium3DTileset.fromUrl(tilesetUrl, tilesetOptions).then((t) => scene.primitives.add(t));
674
- });
675
- // REG: ambientOcclusion was temporary deactivated because of performance impact and horizontal lines artefacts
676
- // const ambientOcclusion = scene.postProcessStages.ambientOcclusion;
677
- // ambientOcclusion.enabled = true;
678
- // ambientOcclusion.uniforms.bias = 0.5;
679
- // ambientOcclusion.uniforms.stepSize = 1;
680
- // ambientOcclusion.uniforms.blurStepSize = 1;
681
- // REG: Adding the following line solves the problem, but it remains a log less performatn with ambiant occlusion.
682
- // So I don't know what we want to do with it.
683
- // See https://github.com/CesiumGS/cesium/issues/13039#issuecomment-3583233494
684
- // viewer.camera.frustum.near = 1.0;
685
- this.loading = false;
686
- this.state.globe.loaded = true;
687
- super.render();
688
- const cesiumScreenToLocalCoord = (position) => {
689
- const cart = Cesium.Cartographic.fromCartesian(pickOnGlobe(position));
690
- const longLat = [Cesium.Math.toDegrees(cart.longitude), Cesium.Math.toDegrees(cart.latitude)];
691
- return proj4('EPSG:4326', this.config.map.srid, longLat);
692
- };
693
- const pickOnGlobe = (position) => {
694
- const ray = scene.camera.getPickRay(position);
695
- return ray == undefined ? undefined : scene.globe.pick(ray, scene);
696
- };
697
- this.registerInteractionListener('globe.select', true);
698
- const eventHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
699
- eventHandler.setInputAction((event) => {
700
- // If the click is on the map and selection is allowed
701
- if (Cesium.defined(event.position) && this.canExecute('globe.select')) {
702
- const topLeftScreen = event.position.clone();
703
- topLeftScreen.x -= this.pixelTolerance;
704
- topLeftScreen.y -= this.pixelTolerance;
705
- const bottomRightScreen = event.position.clone();
706
- bottomRightScreen.x += this.pixelTolerance;
707
- bottomRightScreen.y += this.pixelTolerance;
708
- const topLeft = cesiumScreenToLocalCoord(topLeftScreen);
709
- const bottomRight = cesiumScreenToLocalCoord(bottomRightScreen);
710
- this.select([topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]]);
711
- }
712
- }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
713
- this.wmsManager3d = new WmsManager3d(scene, this.context);
714
- this.state.layers.layersList.forEach((l) => this.addAllActiveLayers3dMap(l));
715
- const camera = scene.camera;
716
- camera.changed.addEventListener(() => {
717
- console.debug('Cesium camera moved');
718
- this.state.globe.camera = {
719
- heading: camera.heading,
720
- pitch: camera.pitch,
721
- roll: camera.roll
722
- };
723
- }, 1);
724
- }
725
- }
726
- addAllActiveLayers3dMap(layer) {
727
- if (layer instanceof LayerWms) {
728
- if (layer.active) {
729
- this.wmsManager3d?.addLayer(layer);
730
- }
731
- }
732
- else if (layer instanceof GroupLayer) {
733
- layer.children.forEach((l) => this.addAllActiveLayers3dMap(l));
734
- }
735
- }
736
- async onGlobeToggled() {
737
- if (this.state.globe.display === '3D') {
738
- // Full screen globe has been enabled
739
- this.mapTarget.style.display = 'none';
740
- this.map3dTarget.style.display = 'block';
741
- this.map3dTarget.style.left = '0';
742
- this.map3dTarget.style.width = '100%';
743
- await this.create3dMap();
744
- this.map3d.setEnabled(true);
552
+ /**
553
+ * Resizes the 2D Map depending on the current globe display mode.
554
+ * In side-by-side mode the 2D Map only takes the left part of the available space,
555
+ * in full 3D mode it is hidden. The 3D Map takes care of its own sizing.
556
+ */
557
+ onGlobeDisplayChanged(display) {
558
+ if (display === '3D') {
559
+ this.style.display = 'none';
745
560
  }
746
- else if (this.state.globe.display === '2D/3D') {
747
- // Side by side has been enabled
748
- this.mapTarget.style.display = 'inline-block';
749
- this.mapTarget.style.width = '45%';
750
- this.map3dTarget.style.display = 'inline-block';
751
- this.map3dTarget.style.left = '45%';
752
- this.map3dTarget.style.width = '55%';
753
- await this.create3dMap();
754
- this.map3d.setEnabled(true);
561
+ else if (display === '2D/3D') {
562
+ this.style.display = 'block';
563
+ this.style.width = '45%';
564
+ this.olMap.updateSize();
755
565
  }
756
566
  else {
757
- // 3d map is not visible
758
- if (this.map3d) {
759
- this.map3d.setEnabled(false);
760
- }
761
- this.mapTarget.style.display = 'block';
762
- this.mapTarget.style.width = '100%';
763
- this.map3dTarget.style.display = 'none';
764
- this.unregisterInteractionListeners('globe.select');
765
- }
766
- }
767
- onShadowsToggled(shadows) {
768
- if (this.map3d) {
769
- const scene = this.map3d.getCesiumScene();
770
- scene.shadowMap.enabled = scene.globe.enableLighting = shadows;
771
- }
772
- }
773
- onShadowsTimestampChanged(shadowsTimestamp) {
774
- if (this.map3d) {
775
- this.map3dShadowsTimestamp = shadowsTimestamp;
567
+ this.style.display = 'block';
568
+ this.style.width = '100%';
569
+ this.olMap.updateSize();
776
570
  }
777
571
  }
778
572
  onFeaturesSelected(features) {
@@ -793,19 +587,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
793
587
  // Recreate the style in case user preferences have changed in the meantime
794
588
  this.setHighlightLayerStyle();
795
589
  }
796
- onCameraChanged(camera) {
797
- if (this.map3d && camera) {
798
- const scene = this.map3d.getCesiumScene();
799
- scene.camera.setView({
800
- destination: scene.camera.position, // Keep current position
801
- orientation: {
802
- heading: camera.heading,
803
- pitch: camera.pitch,
804
- roll: camera.roll
805
- }
806
- });
807
- }
808
- }
809
590
  zoomToExtent(extent) {
810
591
  this.olMap.getView().fit(extent);
811
592
  }
@@ -835,8 +616,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
835
616
  for (const l of layerInfos) {
836
617
  if (l instanceof LayerWms) {
837
618
  this.context.wmsManager.getClient(l).addLayer(l);
838
- if (this.wmsManager3d != null)
839
- this.wmsManager3d.addLayer(l);
840
619
  }
841
620
  else if (l instanceof LayerWmts) {
842
621
  await this.wmtsManager.addLayer(l);
@@ -859,9 +638,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
859
638
  for (const l of layerInfos) {
860
639
  if (l instanceof LayerWms) {
861
640
  this.context.wmsManager.getClient(l).removeLayer(l);
862
- if (this.wmsManager3d != null) {
863
- this.wmsManager3d.removeLayer(l);
864
- }
865
641
  }
866
642
  else if (l instanceof LayerWmts) {
867
643
  this.wmtsManager.removeLayer(l);
@@ -888,8 +664,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
888
664
  onChangeLayerOpacity(layerInfos) {
889
665
  if (layerInfos instanceof LayerWms) {
890
666
  this.context.wmsManager.getClient(layerInfos).changeOpacity(layerInfos);
891
- if (this.wmsManager3d != null)
892
- this.wmsManager3d.changeOpacity(layerInfos);
893
667
  }
894
668
  else if (layerInfos instanceof LayerWmts) {
895
669
  if (this.wmtsManager.layerExists(layerInfos)) {
@@ -917,8 +691,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
917
691
  */
918
692
  onChangeFilter(layerInfos) {
919
693
  this.context.wmsManager.getClient(layerInfos).changeFilter(layerInfos);
920
- if (this.wmsManager3d != null)
921
- this.wmsManager3d.changeFilter(layerInfos);
922
694
  }
923
695
  /**
924
696
  * Change time configuration on layer (only LayerWMS are affected)
@@ -947,8 +719,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
947
719
  removeAllBasemapLayers() {
948
720
  this.wmtsManager.removeAllBasemapLayers();
949
721
  this.context.wmsManager.removeAllBasemapLayers();
950
- if (this.wmsManager3d != null)
951
- this.wmsManager3d.removeAllBasemapLayers();
952
722
  this.osmManager.removeAllBasemapLayers();
953
723
  this.cogManager.removeAllBasemapLayers();
954
724
  this.xyzManager.removeAllBasemapLayers();
@@ -974,8 +744,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
974
744
  }
975
745
  else if (layer instanceof LayerWms) {
976
746
  this.context.wmsManager.getClient(layer).addBasemapLayer(layer);
977
- if (this.wmsManager3d != null)
978
- this.wmsManager3d.addBasemapLayer(layer);
979
747
  }
980
748
  else {
981
749
  throw new TypeError('Unknown basemap type');
@@ -0,0 +1,15 @@
1
+ import Map2dComponent from './component.js';
2
+ /**
3
+ * The `<girafe-map>` Element of the previous versions, kept as a deprecated alias of
4
+ * `<girafe-map-2d>` to give the applications using GeoGirafe time to migrate.
5
+ *
6
+ * It keeps the component name `map`, so that the custom styles and the feedback configuration
7
+ * that were written for `<girafe-map>` keep working. It only displays the 2D Map: an application
8
+ * that needs the 3D Map has to add a `<girafe-map-3d>` Element next to it.
9
+ *
10
+ * @deprecated Use `<girafe-map-2d>` (and `<girafe-map-3d>` for the 3D Map) instead.
11
+ */
12
+ export default class DeprecatedMapComponent extends Map2dComponent {
13
+ constructor();
14
+ protected connectedCallback(): void;
15
+ }
@@ -0,0 +1,24 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import Map2dComponent from './component.js';
3
+ /**
4
+ * The `<girafe-map>` Element of the previous versions, kept as a deprecated alias of
5
+ * `<girafe-map-2d>` to give the applications using GeoGirafe time to migrate.
6
+ *
7
+ * It keeps the component name `map`, so that the custom styles and the feedback configuration
8
+ * that were written for `<girafe-map>` keep working. It only displays the 2D Map: an application
9
+ * that needs the 3D Map has to add a `<girafe-map-3d>` Element next to it.
10
+ *
11
+ * @deprecated Use `<girafe-map-2d>` (and `<girafe-map-3d>` for the 3D Map) instead.
12
+ */
13
+ export default class DeprecatedMapComponent extends Map2dComponent {
14
+ constructor() {
15
+ super('map');
16
+ }
17
+ connectedCallback() {
18
+ console.warn('<girafe-map> is deprecated and will be removed in a future version. ' +
19
+ 'Please replace it with <girafe-map-2d>. ' +
20
+ 'If your application uses the 3D Map, add a <girafe-map-3d> Element next to it, ' +
21
+ 'otherwise the 3D Map will not be displayed anymore.');
22
+ super.connectedCallback();
23
+ }
24
+ }
@@ -15,36 +15,6 @@
15
15
  display: none;
16
16
  }
17
17
 
18
- .center {
19
- position: absolute;
20
- top: 50%;
21
- left: 50%;
22
- transform: translate(-50%, -50%);
23
- margin: 10px;
24
- text-align: center;
25
- }
26
-
27
- .loading span {
28
- color: var(--text-color);
29
- display: block;
30
- margin-top: 1rem;
31
- font-weight: 600;
32
- }
33
-
34
- .loading span.quote {
35
- font-style: italic;
36
- font-weight: 300;
37
- }
38
-
39
- #cs-map {
40
- background-color: var(--bkg-color);
41
- position: absolute;
42
- height: 100%;
43
- overflow: hidden;
44
- display: none;
45
- border-left: solid 3px #444;
46
- }
47
-
48
18
  .ol-control {
49
19
  right: 2rem !important;
50
20
  left: unset !important;
@@ -1,5 +1,5 @@
1
1
  import { Map } from 'ol';
2
- import WmtsManager from './wmtsmanager.js';
2
+ import WmtsManager from '../../../tools/wmts/wmtsmanager.js';
3
3
  import WmsManager from '../../../tools/wms/wmsmanager.js';
4
4
  import { Layer as OLayer } from 'ol/layer.js';
5
5
  import { Listener } from 'ol/events.js';
@@ -0,0 +1,50 @@
1
+ import GirafeHTMLElement from '../../base/GirafeHTMLElement.js';
2
+ import { Callback } from '../../tools/state/statemanager.js';
3
+ import type Globe from './tools/globe.js';
4
+ /**
5
+ * The 3D Map.
6
+ *
7
+ * The Component itself stays lightweight: Cesium and OLCesium are only imported when the 3D Map
8
+ * is displayed for the first time. Everything that needs those libraries lives in ./tools/globe.
9
+ * The synchronization with the 2D Map is done by OLCesium, through the OpenLayers map of the
10
+ * MapManager. There is therefore no direct dependency to the map-2d Component.
11
+ */
12
+ export default class Map3dComponent extends GirafeHTMLElement {
13
+ protected templateUrl: string | null;
14
+ protected styleUrls: string[] | null;
15
+ template: () => import("uhtml").Hole;
16
+ globe: Globe | null;
17
+ map3dTarget: HTMLDivElement;
18
+ loading: boolean;
19
+ pixelTolerance: number;
20
+ /** Promise of the currently running globe creation, to prevent creating it twice. */
21
+ private globeCreation;
22
+ /** The OLCesium instance, once the globe has been created. */
23
+ get map3d(): any;
24
+ private get config();
25
+ constructor();
26
+ /**
27
+ *
28
+ * @param path Overridden to make those methods public for this component
29
+ * @param callback
30
+ */
31
+ subscribe(path: string, callback: Callback): Callback;
32
+ subscribe(path: RegExp, callback: Callback): Callback;
33
+ /**
34
+ * The Map needs to be displayed in Fullscreen Mode.
35
+ */
36
+ protected get isFullscreenComponent(): boolean;
37
+ protected connectedCallback(): void;
38
+ render(): void;
39
+ private registerEvents;
40
+ /**
41
+ * Lazily loads Cesium/OLCesium and creates the globe. Does nothing if no 3D configuration
42
+ * is available or if the globe has already been created.
43
+ */
44
+ private createGlobe;
45
+ /**
46
+ * Shows or hides the 3D Map and sizes it depending on the current display mode.
47
+ * The 2D Map takes care of its own sizing.
48
+ */
49
+ onGlobeToggled(): Promise<void>;
50
+ }