@mapcreator/sdk 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{HighlightManager.d.ts → esm/HighlightManager.d.ts} +2 -2
- package/dist/esm/HighlightManager.js +203 -0
- package/dist/{MCMap.d.ts → esm/MCMap.d.ts} +1 -1
- package/dist/esm/MCMap.js +254 -0
- package/dist/{PopupManager.d.ts → esm/PopupManager.d.ts} +4 -4
- package/dist/esm/PopupManager.js +297 -0
- package/dist/{Registry.d.ts → esm/Registry.d.ts} +3 -3
- package/dist/esm/Registry.js +74 -0
- package/dist/{adornments → esm/adornments}/categoricalLegend.d.ts +1 -1
- package/dist/esm/adornments/categoricalLegend.js +141 -0
- package/dist/{adornments → esm/adornments}/connectedLegend.d.ts +2 -2
- package/dist/esm/adornments/connectedLegend.js +393 -0
- package/dist/{adornments → esm/adornments}/customAdornment.d.ts +1 -1
- package/dist/esm/adornments/customAdornment.js +29 -0
- package/dist/{adornments → esm/adornments}/heading.d.ts +1 -1
- package/dist/esm/adornments/heading.js +71 -0
- package/dist/esm/adornments/insetMap.d.ts +3 -0
- package/dist/esm/adornments/insetMap.js +351 -0
- package/dist/{adornments → esm/adornments}/manualLegend.d.ts +1 -1
- package/dist/esm/adornments/manualLegend.js +15 -0
- package/dist/esm/adornments/northArrow.d.ts +3 -0
- package/dist/esm/adornments/northArrow.js +24 -0
- package/dist/esm/adornments/scalebar.d.ts +3 -0
- package/dist/esm/adornments/scalebar.js +176 -0
- package/dist/{constants → esm/constants}/index.d.ts +2 -2
- package/dist/esm/constants/index.js +53 -0
- package/dist/esm/controls/controls.js +7 -0
- package/dist/{controls → esm/controls}/fullscreenControls.d.ts +1 -1
- package/dist/esm/controls/fullscreenControls.js +29 -0
- package/dist/{controls → esm/controls}/geocoderControl.d.ts +1 -1
- package/dist/esm/controls/geocoderControl.js +202 -0
- package/dist/{controls → esm/controls}/geolocationControls.d.ts +1 -1
- package/dist/esm/controls/geolocationControls.js +65 -0
- package/dist/esm/controls/refreshMapControls.d.ts +3 -0
- package/dist/esm/controls/refreshMapControls.js +26 -0
- package/dist/esm/controls/webControls.d.ts +4 -0
- package/dist/esm/controls/webControls.js +40 -0
- package/dist/{controls → esm/controls}/zoomControls.d.ts +1 -1
- package/dist/esm/controls/zoomControls.js +23 -0
- package/dist/esm/i18n.js +21 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/locales/da_DK/strings.json +7 -0
- package/dist/esm/locales/de_DE/strings.json +7 -0
- package/dist/esm/locales/en_GB/strings.json +7 -0
- package/dist/esm/locales/es_ES/strings.json +7 -0
- package/dist/esm/locales/fr_FR/strings.json +7 -0
- package/dist/esm/locales/it_IT/strings.json +7 -0
- package/dist/esm/locales/nl_NL/strings.json +7 -0
- package/dist/esm/models/area.d.ts +5 -0
- package/dist/esm/models/area.js +165 -0
- package/dist/esm/models/circle.d.ts +5 -0
- package/dist/esm/models/circle.js +110 -0
- package/dist/esm/models/dot.d.ts +3 -0
- package/dist/esm/models/dot.js +42 -0
- package/dist/esm/models/line.d.ts +4 -0
- package/dist/esm/models/line.js +117 -0
- package/dist/esm/models/marker.d.ts +5 -0
- package/dist/esm/models/marker.js +179 -0
- package/dist/esm/models/polygon.d.ts +5 -0
- package/dist/esm/models/polygon.js +80 -0
- package/dist/{renderAdornments.d.ts → esm/renderAdornments.d.ts} +3 -3
- package/dist/esm/renderAdornments.js +129 -0
- package/dist/esm/types/geometry.js +1 -0
- package/dist/{types → esm/types}/index.d.ts +1 -1
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/types/jobObject.js +1 -0
- package/dist/{types → esm/types}/mapstyle.d.ts +6 -2
- package/dist/esm/types/mapstyle.js +1 -0
- package/dist/esm/utils/browser.js +6 -0
- package/dist/{utils → esm/utils}/choropleth.d.ts +3 -3
- package/dist/esm/utils/choropleth.js +110 -0
- package/dist/esm/utils/fullscreen.js +40 -0
- package/dist/{utils → esm/utils}/geolocation.d.ts +1 -1
- package/dist/esm/utils/geolocation.js +93 -0
- package/dist/{utils → esm/utils}/graphhopper.d.ts +1 -1
- package/dist/esm/utils/graphhopper.js +41 -0
- package/dist/{utils → esm/utils}/helpers.d.ts +2 -2
- package/dist/esm/utils/helpers.js +116 -0
- package/dist/{utils → esm/utils}/language.d.ts +1 -1
- package/dist/esm/utils/language.js +170 -0
- package/dist/{utils → esm/utils}/models.d.ts +4 -4
- package/dist/esm/utils/models.js +103 -0
- package/dist/{utils → esm/utils}/overlays.d.ts +1 -1
- package/dist/esm/utils/overlays.js +87 -0
- package/dist/esm/utils/scalebar.js +52 -0
- package/dist/{utils → esm/utils}/svgHelpers.d.ts +4 -3
- package/dist/esm/utils/svgHelpers.js +1512 -0
- package/dist/{utils → esm/utils}/template.d.ts +2 -2
- package/dist/esm/utils/template.js +120 -0
- package/dist/{utils → esm/utils}/youtube.d.ts +1 -1
- package/dist/esm/utils/youtube.js +64 -0
- package/dist/favicon-32x32.png +0 -0
- package/dist/mapcreator-sdk.umd.cjs +3 -3
- package/dist/report.html +4950 -0
- package/package.json +7 -7
- package/dist/adornments/insetMap.d.ts +0 -3
- package/dist/adornments/northArrow.d.ts +0 -3
- package/dist/adornments/scalebar.d.ts +0 -3
- package/dist/controls/refreshMapControls.d.ts +0 -3
- package/dist/controls/webControls.d.ts +0 -4
- package/dist/index.d.ts +0 -3
- package/dist/locales/da_DK/strings.json.d.ts +0 -10
- package/dist/locales/de_DE/strings.json.d.ts +0 -10
- package/dist/locales/en_GB/strings.json.d.ts +0 -10
- package/dist/locales/es_ES/strings.json.d.ts +0 -10
- package/dist/locales/fr_FR/strings.json.d.ts +0 -10
- package/dist/locales/it_IT/strings.json.d.ts +0 -10
- package/dist/locales/nl_NL/strings.json.d.ts +0 -10
- package/dist/mapcreator-sdk.js +0 -39590
- package/dist/models/area.d.ts +0 -5
- package/dist/models/circle.d.ts +0 -5
- package/dist/models/dot.d.ts +0 -3
- package/dist/models/line.d.ts +0 -4
- package/dist/models/marker.d.ts +0 -5
- package/dist/models/polygon.d.ts +0 -5
- /package/dist/{controls → esm/controls}/controls.d.ts +0 -0
- /package/dist/{i18n.d.ts → esm/i18n.d.ts} +0 -0
- /package/dist/{types → esm/types}/geometry.d.ts +0 -0
- /package/dist/{types → esm/types}/jobObject.d.ts +0 -0
- /package/dist/{utils → esm/utils}/browser.d.ts +0 -0
- /package/dist/{utils → esm/utils}/fullscreen.d.ts +0 -0
- /package/dist/{utils → esm/utils}/scalebar.d.ts +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Map } from '@mapcreator/maplibre-gl';
|
|
2
|
-
import { PopupElement } from '
|
|
1
|
+
import { type Map } from '@mapcreator/maplibre-gl';
|
|
2
|
+
import type { PopupElement } from '@/Registry';
|
|
3
3
|
export declare class HighlightManager {
|
|
4
4
|
private map;
|
|
5
5
|
private popupElements;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { LngLatBounds } from '@mapcreator/maplibre-gl';
|
|
2
|
+
import { calculateCircle } from '@/utils/models';
|
|
3
|
+
import { stringToId } from '@/utils/helpers';
|
|
4
|
+
export class HighlightManager {
|
|
5
|
+
map;
|
|
6
|
+
popupElements;
|
|
7
|
+
markerLayerIds;
|
|
8
|
+
resizeObserver;
|
|
9
|
+
constructor(map, popupElements) {
|
|
10
|
+
this.map = map;
|
|
11
|
+
this.popupElements = popupElements;
|
|
12
|
+
this.markerLayerIds = this.map
|
|
13
|
+
.getStyle()
|
|
14
|
+
.layers.filter(layer => layer.id.startsWith('custom-marker'))
|
|
15
|
+
.filter(layer => !layer.id.endsWith('-cluster'))
|
|
16
|
+
.map(layer => layer.id);
|
|
17
|
+
}
|
|
18
|
+
highlight(popupElement) {
|
|
19
|
+
this.deselect();
|
|
20
|
+
if (!popupElement) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const { groupId, modelId } = popupElement;
|
|
24
|
+
const groupedPopups = this.popupElements.filter(item => item.groupId === groupId);
|
|
25
|
+
if (groupedPopups.length > 1 && groupId.startsWith('custom-marker')) {
|
|
26
|
+
this.highlightGroupedMarker(groupId, modelId, groupedPopups);
|
|
27
|
+
}
|
|
28
|
+
if (groupId.startsWith('custom-marker')) {
|
|
29
|
+
this.fadeOtherMarkers(groupId);
|
|
30
|
+
}
|
|
31
|
+
this.repositionMap(popupElement);
|
|
32
|
+
}
|
|
33
|
+
deselect() {
|
|
34
|
+
this.markerLayerIds.forEach(id => {
|
|
35
|
+
this.map.setPaintProperty(id, 'icon-opacity', 1);
|
|
36
|
+
this.map.setPaintProperty(id, 'text-opacity', 1);
|
|
37
|
+
});
|
|
38
|
+
this.resizeObserver?.disconnect();
|
|
39
|
+
}
|
|
40
|
+
highlightGroupedMarker(groupId, modelId, groupedPopups) {
|
|
41
|
+
const groupLayer = this.markerLayerIds.find(id => id.startsWith(groupId));
|
|
42
|
+
if (groupLayer) {
|
|
43
|
+
this.map.setPaintProperty(groupLayer, 'icon-opacity', [
|
|
44
|
+
'case',
|
|
45
|
+
['boolean', ['feature-state', 'highlighted'], false],
|
|
46
|
+
1,
|
|
47
|
+
0.3,
|
|
48
|
+
]);
|
|
49
|
+
this.map.setPaintProperty(groupLayer, 'text-opacity', [
|
|
50
|
+
'case',
|
|
51
|
+
['boolean', ['feature-state', 'highlighted'], false],
|
|
52
|
+
1,
|
|
53
|
+
0.3,
|
|
54
|
+
]);
|
|
55
|
+
groupedPopups.forEach(item => {
|
|
56
|
+
this.map.setFeatureState({ source: groupId, id: stringToId(item.modelId) }, { highlighted: item.modelId === modelId });
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
fadeOtherMarkers(layerId) {
|
|
61
|
+
const otherMarkerIds = this.markerLayerIds.filter(id => !id.startsWith(layerId));
|
|
62
|
+
otherMarkerIds.forEach(id => {
|
|
63
|
+
this.map.setPaintProperty(id, 'icon-opacity', 0.3);
|
|
64
|
+
this.map.setPaintProperty(id, 'text-opacity', 0.3);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
repositionMap(popupElement) {
|
|
68
|
+
let elementBounds;
|
|
69
|
+
let padding = 20;
|
|
70
|
+
if (popupElement.lngLat !== undefined) {
|
|
71
|
+
elementBounds = new LngLatBounds(popupElement.lngLat, popupElement.lngLat);
|
|
72
|
+
padding = 40;
|
|
73
|
+
}
|
|
74
|
+
else if (popupElement.anchorPoints !== undefined) {
|
|
75
|
+
elementBounds = this.getElementBounds(this.flattenCoordinates(popupElement.anchorPoints));
|
|
76
|
+
}
|
|
77
|
+
else if (popupElement.center !== undefined && popupElement.radius !== undefined) {
|
|
78
|
+
elementBounds = this.getElementBounds(calculateCircle(popupElement.center, popupElement.radius));
|
|
79
|
+
}
|
|
80
|
+
const popupEl = document.querySelector('.popup-container');
|
|
81
|
+
if (!popupEl || !elementBounds) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
this.resizeObserver?.disconnect();
|
|
85
|
+
let lastHeight = 0;
|
|
86
|
+
this.resizeObserver = new ResizeObserver(entries => {
|
|
87
|
+
const height = entries[0].contentRect.height;
|
|
88
|
+
if (height > lastHeight) {
|
|
89
|
+
lastHeight = height;
|
|
90
|
+
this.panToElement(elementBounds, padding);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
this.resizeObserver.observe(popupEl);
|
|
94
|
+
}
|
|
95
|
+
getElementBounds(coords) {
|
|
96
|
+
const bounds = new LngLatBounds(coords[0], coords[0]);
|
|
97
|
+
for (const coord of coords) {
|
|
98
|
+
bounds.extend(coord);
|
|
99
|
+
}
|
|
100
|
+
return bounds;
|
|
101
|
+
}
|
|
102
|
+
flattenCoordinates(coords) {
|
|
103
|
+
if (Array.isArray(coords[0][0])) {
|
|
104
|
+
return coords.flat();
|
|
105
|
+
}
|
|
106
|
+
return coords;
|
|
107
|
+
}
|
|
108
|
+
panToElement(elementBounds, padding) {
|
|
109
|
+
const map = this.map;
|
|
110
|
+
const projection = map.getProjection();
|
|
111
|
+
if (projection?.type === 'globe') {
|
|
112
|
+
const testCoords = [
|
|
113
|
+
elementBounds.getSouthWest(),
|
|
114
|
+
elementBounds.getNorthEast(),
|
|
115
|
+
elementBounds.getNorthWest(),
|
|
116
|
+
elementBounds.getSouthEast(),
|
|
117
|
+
];
|
|
118
|
+
const behindGlobe = testCoords.some(c => !this.visibleOnGlobe(c.lng, c.lat));
|
|
119
|
+
if (behindGlobe) {
|
|
120
|
+
map.easeTo({ center: elementBounds.getCenter(), duration: 500 });
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const sw = map.projectWithScaleCorrection(elementBounds.getSouthWest());
|
|
125
|
+
const ne = map.projectWithScaleCorrection(elementBounds.getNorthEast());
|
|
126
|
+
const mapWidth = map.getContainer().clientWidth;
|
|
127
|
+
const mapHeight = map.getContainer().clientHeight;
|
|
128
|
+
const isDesktop = mapWidth > 600;
|
|
129
|
+
const popupRect = document.querySelector('.popup-container')?.getBoundingClientRect();
|
|
130
|
+
const popupWidth = popupRect?.width ?? 0;
|
|
131
|
+
let popupHeight = popupRect?.height ?? 0;
|
|
132
|
+
if (!isDesktop) {
|
|
133
|
+
popupHeight = Math.min(popupHeight, mapHeight / 2);
|
|
134
|
+
}
|
|
135
|
+
const abovePopup = mapHeight - sw.y > popupHeight + padding;
|
|
136
|
+
const leftVisible = sw.x > padding + (isDesktop && !abovePopup ? popupWidth : 0);
|
|
137
|
+
const rightVisible = ne.x < mapWidth - padding;
|
|
138
|
+
const topVisible = ne.y > padding;
|
|
139
|
+
const bottomVisible = isDesktop ? sw.y < mapHeight - padding : abovePopup;
|
|
140
|
+
if (!(leftVisible && rightVisible && topVisible && bottomVisible)) {
|
|
141
|
+
if (ne.x - sw.x + 2 * padding < mapWidth && sw.y - ne.y + 2 * padding < mapHeight) {
|
|
142
|
+
const center = elementBounds.getCenter();
|
|
143
|
+
map.easeTo({ center, duration: 500, offset: isDesktop ? [0, 0] : [0, -30] });
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
map.fitBounds(elementBounds, {
|
|
147
|
+
padding,
|
|
148
|
+
maxZoom: map.getZoom(),
|
|
149
|
+
duration: 500,
|
|
150
|
+
linear: true,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
visibleOnGlobe(lng, lat) {
|
|
156
|
+
const { lng: centerLng, lat: centerLat } = this.map.getCenter();
|
|
157
|
+
const pitch = (this.map.getPitch() * Math.PI) / 180;
|
|
158
|
+
const bearing = (this.map.getBearing() * Math.PI) / 180;
|
|
159
|
+
const centerVector = this.lngLatToUnitVector(centerLng, centerLat);
|
|
160
|
+
const featureVector = this.lngLatToUnitVector(lng, lat);
|
|
161
|
+
const up = [0, 0, 1];
|
|
162
|
+
const east = this.normalize(this.cross(up, centerVector));
|
|
163
|
+
const rotationAxis = this.rotateAroundZ(east, bearing);
|
|
164
|
+
const visibleVector = this.rotateVectorAroundAxis(centerVector, rotationAxis, pitch);
|
|
165
|
+
const dot = visibleVector[0] * featureVector[0] +
|
|
166
|
+
visibleVector[1] * featureVector[1] +
|
|
167
|
+
visibleVector[2] * featureVector[2];
|
|
168
|
+
return dot > 0.3;
|
|
169
|
+
}
|
|
170
|
+
lngLatToUnitVector(lng, lat) {
|
|
171
|
+
const a = (lat * Math.PI) / 180;
|
|
172
|
+
const b = (lng * Math.PI) / 180;
|
|
173
|
+
return [Math.cos(a) * Math.cos(b), Math.cos(a) * Math.sin(b), Math.sin(a)];
|
|
174
|
+
}
|
|
175
|
+
rotateVectorAroundAxis(vector, axis, pitch) {
|
|
176
|
+
const [v0, v1, v2] = vector;
|
|
177
|
+
const [a0, a1, a2] = axis;
|
|
178
|
+
const cos = Math.cos(pitch);
|
|
179
|
+
const sin = Math.sin(pitch);
|
|
180
|
+
const dot = v0 * a0 + v1 * a1 + v2 * a2;
|
|
181
|
+
return [
|
|
182
|
+
v0 * cos + (a1 * v2 - a2 * v1) * sin + a0 * dot * (1 - cos),
|
|
183
|
+
v1 * cos + (a2 * v0 - a0 * v2) * sin + a1 * dot * (1 - cos),
|
|
184
|
+
v2 * cos + (a0 * v1 - a1 * v0) * sin + a2 * dot * (1 - cos),
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
rotateAroundZ(vector, bearing) {
|
|
188
|
+
const [v0, v1, v2] = vector;
|
|
189
|
+
const cos = Math.cos(bearing);
|
|
190
|
+
const sin = Math.sin(bearing);
|
|
191
|
+
return [v0 * cos - v1 * sin, v0 * sin + v1 * cos, v2];
|
|
192
|
+
}
|
|
193
|
+
cross(vectorA, vectorB) {
|
|
194
|
+
const [a0, a1, a2] = vectorA;
|
|
195
|
+
const [b0, b1, b2] = vectorB;
|
|
196
|
+
return [a1 * b2 - a2 * b1, a2 * b0 - a0 * b2, a0 * b1 - a1 * b0];
|
|
197
|
+
}
|
|
198
|
+
normalize(vector) {
|
|
199
|
+
const [v0, v1, v2] = vector;
|
|
200
|
+
const len = Math.hypot(v0, v1, v2);
|
|
201
|
+
return [v0 / len, v1 / len, v2 / len];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { LanguageNotation, setLanguage, transformLanguageCode } from '@/utils/language';
|
|
2
|
+
import { AttributionControl, Map as MapLibre } from '@mapcreator/maplibre-gl';
|
|
3
|
+
import { useRenderAdornments } from '@/renderAdornments';
|
|
4
|
+
import { addPolygonGroup } from '@/models/polygon';
|
|
5
|
+
import { addCircleGroup } from '@/models/circle';
|
|
6
|
+
import { addMarkerGroup } from '@/models/marker';
|
|
7
|
+
import { loadOverlays } from '@/utils/overlays';
|
|
8
|
+
import { PopupManager } from '@/PopupManager';
|
|
9
|
+
import { unitConvert } from '@/utils/helpers';
|
|
10
|
+
import { SvgCache } from '@/utils/svgHelpers';
|
|
11
|
+
import { addLineGroup } from '@/models/line';
|
|
12
|
+
import { addAreaGroup } from '@/models/area';
|
|
13
|
+
import { addDotGroup } from '@/models/dot';
|
|
14
|
+
import { defaultSky } from '@/constants';
|
|
15
|
+
import { t } from '@/i18n';
|
|
16
|
+
export class MCMap {
|
|
17
|
+
map;
|
|
18
|
+
constructor(map) {
|
|
19
|
+
this.map = map;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function initMap(options) {
|
|
23
|
+
const { accessToken, mode = 'sdk', env = 'production' } = options;
|
|
24
|
+
const vapiUrl = env === 'bleeding'
|
|
25
|
+
? 'https://vapi.bleeding.mc-cdn.io'
|
|
26
|
+
: env === 'beta'
|
|
27
|
+
? 'https://vapi.beta.mc-cdn.io'
|
|
28
|
+
: 'https://vapi.mc-cdn.io';
|
|
29
|
+
const cdnUrl = env === 'bleeding'
|
|
30
|
+
? 'https://cdn.bleeding.mapcreator.io'
|
|
31
|
+
: env === 'beta'
|
|
32
|
+
? 'https://cdn.beta.mapcreator.io'
|
|
33
|
+
: 'https://cdn.mapcreator.io';
|
|
34
|
+
const jobObject = typeof options.job === 'string'
|
|
35
|
+
? await loadJobObject(options.job, cdnUrl, accessToken)
|
|
36
|
+
: options.job;
|
|
37
|
+
await nonZeroWindowSize();
|
|
38
|
+
const map = new MapLibre({
|
|
39
|
+
container: options.container,
|
|
40
|
+
attributionControl: false,
|
|
41
|
+
style: null,
|
|
42
|
+
maxBounds: [-Infinity, -90, Infinity, 90],
|
|
43
|
+
maxPitch: 85,
|
|
44
|
+
maxZoom: 22,
|
|
45
|
+
locale: {
|
|
46
|
+
'CooperativeGesturesHandler.WindowsHelpText': t('windowsHelpText'),
|
|
47
|
+
'CooperativeGesturesHandler.MacHelpText': t('macHelpText'),
|
|
48
|
+
'CooperativeGesturesHandler.MobileHelpText': t('mobileHelpText'),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
const container = map.getContainer();
|
|
52
|
+
container.classList.add('mc-map');
|
|
53
|
+
const svgCache = new SvgCache(map);
|
|
54
|
+
const popupManager = new PopupManager(map, mode);
|
|
55
|
+
const { map: { language, zoom, pitch = 0, rotation = 0, center, hideBasemap, layerInfo = [], detailLevel = 0, projection = 'mercator', terrain = false, terrainExaggeration = 1, }, export: exportData, registry = {}, web, positionOffsets, title, } = jobObject;
|
|
56
|
+
const { models = {}, slots = {}, svgs = {} } = registry;
|
|
57
|
+
loadFontFaces(env, vapiUrl, accessToken);
|
|
58
|
+
map.resize();
|
|
59
|
+
if (mode === 'app') {
|
|
60
|
+
document.title = title ? `${title} - Mapcreator` : 'Mapcreator';
|
|
61
|
+
}
|
|
62
|
+
map.setPitch(pitch);
|
|
63
|
+
map.setBearing(rotation);
|
|
64
|
+
const unit = exportData?.unit ?? 'pixel';
|
|
65
|
+
const aspectBoxWidth = unitConvert(unit, 'pixel', exportData?.size?.[0] ?? 600);
|
|
66
|
+
const aspectBoxHeight = unitConvert(unit, 'pixel', exportData?.size?.[1] ?? 400);
|
|
67
|
+
let zoomCorrection = 0;
|
|
68
|
+
// Adjust map's zoom level to preserve viewport regardless of map size
|
|
69
|
+
if (container.clientWidth > 0 && container.clientHeight > 0) {
|
|
70
|
+
const scale = Math.min(container.clientWidth / aspectBoxWidth, container.clientHeight / aspectBoxHeight);
|
|
71
|
+
zoomCorrection = Math.log(scale) / Math.LN2;
|
|
72
|
+
}
|
|
73
|
+
map.setZoom(zoom - detailLevel + zoomCorrection);
|
|
74
|
+
map.setCenter(center);
|
|
75
|
+
map.setDetailLevel(detailLevel);
|
|
76
|
+
map.setMinZoom(detailLevel);
|
|
77
|
+
map.addControl(new AttributionControl({ compact: false }));
|
|
78
|
+
if (mode === 'app') {
|
|
79
|
+
map.cooperativeGestures.enable();
|
|
80
|
+
}
|
|
81
|
+
useRenderAdornments(jobObject, positionOffsets, map, {
|
|
82
|
+
center,
|
|
83
|
+
zoom,
|
|
84
|
+
pitch,
|
|
85
|
+
rotation,
|
|
86
|
+
detailLevel,
|
|
87
|
+
width: aspectBoxWidth,
|
|
88
|
+
height: aspectBoxHeight,
|
|
89
|
+
}, vapiUrl, cdnUrl, accessToken);
|
|
90
|
+
popupManager.setJobObject(jobObject);
|
|
91
|
+
if (web) {
|
|
92
|
+
const { restrictMapMovement, popupPosition } = web;
|
|
93
|
+
if (restrictMapMovement) {
|
|
94
|
+
map.boxZoom.disable();
|
|
95
|
+
map.doubleClickZoom.disable();
|
|
96
|
+
map.dragPan.disable();
|
|
97
|
+
map.dragRotate.disable();
|
|
98
|
+
map.keyboard.disable();
|
|
99
|
+
map.scrollZoom.disable();
|
|
100
|
+
map.touchPitch.disable();
|
|
101
|
+
map.touchZoomRotate.disable();
|
|
102
|
+
}
|
|
103
|
+
popupManager.setParams(popupPosition, transformLanguageCode(language, LanguageNotation.TWO), restrictMapMovement, center);
|
|
104
|
+
}
|
|
105
|
+
const mapstyle = await fetch(`${vapiUrl}/styles/${jobObject.meta.mapstyleSet}.json?access_token=${accessToken}`).then(response => response.json());
|
|
106
|
+
map.setStyle(null);
|
|
107
|
+
map.setStyle(mapstyle);
|
|
108
|
+
await map.once('style.load');
|
|
109
|
+
if (mode === 'app') {
|
|
110
|
+
setCustomStyle(map.getStyle().metadata?.customCssFilePath, accessToken);
|
|
111
|
+
}
|
|
112
|
+
// Don't wait for overlays and models to set the language as maps on slow internet will otherwise not be translated immediately
|
|
113
|
+
setLanguage(language, map);
|
|
114
|
+
await loadOverlays(jobObject.meta.layers ?? [], map, vapiUrl, accessToken, mapstyle.metadata?.styleOverride);
|
|
115
|
+
addModels(map, svgCache, models, slots, svgs, vapiUrl, accessToken);
|
|
116
|
+
// Set the language again to translate the overlays and models
|
|
117
|
+
setLanguage(language, map);
|
|
118
|
+
popupManager.setPublication(mapstyle.metadata?.publication);
|
|
119
|
+
popupManager.setpopupElements();
|
|
120
|
+
popupManager.setHighlightManager();
|
|
121
|
+
map.setProjection({ type: projection === 'globe' ? 'globe' : 'mercator' });
|
|
122
|
+
setSky(map, projection);
|
|
123
|
+
if (terrain) {
|
|
124
|
+
initTerrain(map, vapiUrl, accessToken, terrainExaggeration);
|
|
125
|
+
}
|
|
126
|
+
setLayerVisibility(map, map.getStyle(), layerInfo, !hideBasemap);
|
|
127
|
+
return new MCMap(map);
|
|
128
|
+
}
|
|
129
|
+
function loadJobObject(id, cdnUrl, accessToken) {
|
|
130
|
+
return fetch(`${cdnUrl}/jobs/${id}.json?access_token=${accessToken}`).then(response => response.json());
|
|
131
|
+
}
|
|
132
|
+
function nonZeroWindowSize() {
|
|
133
|
+
return new Promise(resolve => {
|
|
134
|
+
const checkSize = () => {
|
|
135
|
+
if (window.innerWidth > 0 && window.innerHeight > 0) {
|
|
136
|
+
window.removeEventListener('resize', checkSize);
|
|
137
|
+
resolve();
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
window.addEventListener('resize', checkSize);
|
|
141
|
+
checkSize();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function setSky(map, projection) {
|
|
145
|
+
const meta = map.getStyle().metadata ?? {};
|
|
146
|
+
const backgroundColorFlat = meta['mc:background-color'] ?? '#f8f8f8';
|
|
147
|
+
const backgroundColorGlobe = meta['mc:background-color-globe'] ?? '#000000';
|
|
148
|
+
map.getContainer().style.backgroundColor =
|
|
149
|
+
projection === 'globe' ? backgroundColorGlobe : backgroundColorFlat;
|
|
150
|
+
map.setSky(map.getStyle().sky ?? defaultSky);
|
|
151
|
+
map.setLight({ position: [1.15, 210, 45] });
|
|
152
|
+
}
|
|
153
|
+
function initTerrain(map, vapiUrl, accessToken, exaggeration) {
|
|
154
|
+
map.addSource('mc-dem', {
|
|
155
|
+
type: 'raster-dem',
|
|
156
|
+
tiles: [`${vapiUrl}/dataset/jaxa_terrainrgb/{z}/{x}/{y}?access_token=${accessToken}`],
|
|
157
|
+
attribution: '<a href="https://earth.jaxa.jp/en/data/policy" target="_blank">© AW3D30 (JAXA)</a>',
|
|
158
|
+
minzoom: 0,
|
|
159
|
+
maxzoom: 12,
|
|
160
|
+
});
|
|
161
|
+
map.setTerrain({ source: 'mc-dem', exaggeration });
|
|
162
|
+
}
|
|
163
|
+
function loadFontFaces(env, vapiUrl, accessToken) {
|
|
164
|
+
const betaPrefix = env === 'beta' ? 'b-' : '';
|
|
165
|
+
const href = `${vapiUrl}/stylesheets/ff-${betaPrefix}${accessToken}.css?access_token=${accessToken}`;
|
|
166
|
+
const element = document.createElement('link');
|
|
167
|
+
element.setAttribute('rel', 'stylesheet');
|
|
168
|
+
element.setAttribute('href', href);
|
|
169
|
+
element.setAttribute('type', 'text/css');
|
|
170
|
+
// Inserting at the beginning of <head> to avoid redefining existing Roboto fonts
|
|
171
|
+
// See https://mapcreator.atlassian.net/browse/MC-2702
|
|
172
|
+
document.head.insertBefore(element, document.head.firstChild);
|
|
173
|
+
}
|
|
174
|
+
function setCustomStyle(styleOrURL, accessToken) {
|
|
175
|
+
document.getElementById('custom-style')?.remove();
|
|
176
|
+
if (!styleOrURL) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
let element;
|
|
180
|
+
if (styleOrURL.startsWith('http')) {
|
|
181
|
+
styleOrURL = `${styleOrURL}?access_token=${accessToken}`;
|
|
182
|
+
element = document.createElement('link');
|
|
183
|
+
element.setAttribute('rel', 'stylesheet');
|
|
184
|
+
element.setAttribute('href', styleOrURL.replace(/https?:/, ''));
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
element = document.createElement('style');
|
|
188
|
+
element.appendChild(document.createTextNode(styleOrURL));
|
|
189
|
+
}
|
|
190
|
+
element.setAttribute('id', 'custom-style');
|
|
191
|
+
element.setAttribute('type', 'text/css');
|
|
192
|
+
document.head.appendChild(element);
|
|
193
|
+
}
|
|
194
|
+
function setLayerVisibility(map, mapstyle, layers, showBasemap) {
|
|
195
|
+
for (const layer of layers) {
|
|
196
|
+
const existingLayer = mapstyle.layers.find(item => layer.id === item.id || layer.id.endsWith(` | ${item.id}`));
|
|
197
|
+
if (existingLayer) {
|
|
198
|
+
map.setLayoutProperty(existingLayer.id, 'visibility', layer.visibility && showBasemap ? 'visible' : 'none');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function addModels(map, svgCache, models, slots, svgs, vapiUrl, accessToken) {
|
|
203
|
+
const { beforeNone = [], beforeNames = [], beforeBoundaries = [], beforeWaters = [] } = slots;
|
|
204
|
+
beforeNone.forEach(item => {
|
|
205
|
+
addModelsByType(map, svgCache, models, item, svgs, 'mc-before-none', vapiUrl, accessToken);
|
|
206
|
+
});
|
|
207
|
+
beforeNames.forEach(item => {
|
|
208
|
+
addModelsByType(map, svgCache, models, item, svgs, 'mc-before-names', vapiUrl, accessToken);
|
|
209
|
+
});
|
|
210
|
+
beforeBoundaries.forEach(item => {
|
|
211
|
+
addModelsByType(map, svgCache, models, item, svgs, 'mc-before-boundaries', vapiUrl, accessToken);
|
|
212
|
+
});
|
|
213
|
+
beforeWaters.forEach(item => {
|
|
214
|
+
addModelsByType(map, svgCache, models, item, svgs, 'mc-before-waters', vapiUrl, accessToken);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
function addModelsByType(map, svgCache, models, item, svgs, beforeId, vapiUrl, accessToken) {
|
|
218
|
+
if (item.type === 'marker') {
|
|
219
|
+
const group = models.marker?.find(entry => entry.id === item.groupId);
|
|
220
|
+
if (group) {
|
|
221
|
+
addMarkerGroup(map, group, beforeId, svgs, svgCache);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else if (item.type === 'polygon') {
|
|
225
|
+
const group = models.polygon?.find(entry => entry.id === item.groupId);
|
|
226
|
+
if (group) {
|
|
227
|
+
addPolygonGroup(map, group, beforeId, svgs, svgCache);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else if (item.type === 'circle') {
|
|
231
|
+
const group = models.circle?.find(entry => entry.id === item.groupId);
|
|
232
|
+
if (group) {
|
|
233
|
+
addCircleGroup(map, group, beforeId, svgs, svgCache);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else if (item.type === 'line') {
|
|
237
|
+
const group = models.line?.find(entry => entry.id === item.groupId);
|
|
238
|
+
if (group) {
|
|
239
|
+
addLineGroup(map, group, beforeId, svgCache);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else if (item.type === 'dot') {
|
|
243
|
+
const group = models.dot?.find(entry => entry.id === item.groupId);
|
|
244
|
+
if (group) {
|
|
245
|
+
addDotGroup(map, group, beforeId);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else if (item.type === 'area') {
|
|
249
|
+
const group = models.area?.find(entry => entry.id === item.groupId);
|
|
250
|
+
if (group) {
|
|
251
|
+
addAreaGroup(map, group, beforeId, svgs, svgCache, vapiUrl, accessToken);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Map as MapLibre, MapGeoJSONFeature, MapLayerMouseEvent, LngLatLike } from '@mapcreator/maplibre-gl';
|
|
2
|
-
import { JobObject, PopupPosition } from '
|
|
3
|
-
import { PopupElement } from '
|
|
4
|
-
import { Mode } from '
|
|
1
|
+
import { type Map as MapLibre, type MapGeoJSONFeature, type MapLayerMouseEvent, type LngLatLike } from '@mapcreator/maplibre-gl';
|
|
2
|
+
import type { JobObject, PopupPosition } from '@/types/jobObject';
|
|
3
|
+
import { type PopupElement } from '@/Registry';
|
|
4
|
+
import type { Mode } from '@/types';
|
|
5
5
|
export declare class PopupManager {
|
|
6
6
|
private map;
|
|
7
7
|
private popupPosition;
|