@maptrip/map-tiles 1.3.2 → 1.4.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.
- package/README.md +9 -2
- package/dist/core/VectorTileFactory.d.ts +2 -0
- package/dist/core/constants.d.ts +5 -0
- package/dist/map-tiles.js +126 -58
- package/dist/map-tiles.js.map +1 -1
- package/dist/util/MapReleaseFetcher.d.ts +2 -1
- package/lib/api-extensions/leaflet/MapTripLeafletGridLayer.ts +3 -1
- package/lib/core/VectorTileFactory.ts +52 -7
- package/lib/core/VectorTileRenderer.ts +66 -101
- package/lib/core/constants.ts +12 -1
- package/lib/util/MapReleaseFetcher.ts +15 -5
- package/package.json +3 -2
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export declare class MapReleaseFetcher {
|
|
2
2
|
private _token;
|
|
3
3
|
private _tomtom;
|
|
4
|
+
private _orbis;
|
|
4
5
|
private _osm;
|
|
5
6
|
private _here;
|
|
6
7
|
constructor(token: string);
|
|
7
8
|
getRelease(provider: string): Promise<string | null | undefined>;
|
|
8
|
-
fetchAndExtractRelease(url: string): Promise<string | null>;
|
|
9
|
+
fetchAndExtractRelease(provider: string, url: string): Promise<string | null>;
|
|
9
10
|
private extractTargetString;
|
|
10
11
|
}
|
|
@@ -119,10 +119,12 @@ class MapTripLeafletGridLayer extends L.GridLayer {
|
|
|
119
119
|
const eventProvider = event.layer.options.provider;
|
|
120
120
|
let newProvider: string;
|
|
121
121
|
if (eventProvider) {
|
|
122
|
-
if (eventProvider.toLowerCase() === "
|
|
122
|
+
if (eventProvider.toLowerCase() === "openstreetmap") {
|
|
123
123
|
newProvider = "openstreetmap";
|
|
124
124
|
} else if (eventProvider.toLowerCase() === "tomtom") {
|
|
125
125
|
newProvider = "tomtom";
|
|
126
|
+
} else if (eventProvider.toLowerCase() === "orbis") {
|
|
127
|
+
newProvider = "orbis";
|
|
126
128
|
} else if (eventProvider.toLowerCase() === "here") {
|
|
127
129
|
newProvider = "here";
|
|
128
130
|
} else {
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
URL_TEMPLATE,
|
|
7
7
|
PROVIDER_PROJECTS,
|
|
8
8
|
PROVIDER_TRAFFIC,
|
|
9
|
+
VECTOR_TILE_SIZE,
|
|
10
|
+
VECTOR_TILE_RENDER_PADDING
|
|
9
11
|
} from "./constants.js";
|
|
10
12
|
|
|
11
13
|
import WebFont from "webfontloader";
|
|
@@ -163,6 +165,49 @@ class VectorTileFactory {
|
|
|
163
165
|
}
|
|
164
166
|
}
|
|
165
167
|
|
|
168
|
+
private createCanvas(size: number, padding: number): HTMLCanvasElement {
|
|
169
|
+
let canvas = document.createElement("canvas");
|
|
170
|
+
|
|
171
|
+
const paddedTileSize = size + 2 * padding;
|
|
172
|
+
|
|
173
|
+
canvas.width = paddedTileSize;
|
|
174
|
+
canvas.height = paddedTileSize;
|
|
175
|
+
canvas.style.width = paddedTileSize + 'px';
|
|
176
|
+
canvas.style.height = paddedTileSize + 'px';
|
|
177
|
+
canvas.style.maxWidth = paddedTileSize + 'px';
|
|
178
|
+
canvas.style.maxHeight = paddedTileSize + 'px';
|
|
179
|
+
canvas.style.left = -padding + 'px';
|
|
180
|
+
canvas.style.top = -padding + 'px';
|
|
181
|
+
|
|
182
|
+
const context = canvas.getContext('2d');
|
|
183
|
+
if (!context) {
|
|
184
|
+
throw new Error("Failed to create canvas");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (typeof context.setTransform === 'function') {
|
|
188
|
+
context.setTransform(1, 0, 0, 1, padding, padding);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
context.translate(padding, padding);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return canvas;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private cropCanvas(source: HTMLCanvasElement, target: HTMLCanvasElement): void {
|
|
198
|
+
const ctx = target.getContext("2d");
|
|
199
|
+
|
|
200
|
+
if (ctx) {
|
|
201
|
+
ctx.drawImage(
|
|
202
|
+
source,
|
|
203
|
+
VECTOR_TILE_RENDER_PADDING, VECTOR_TILE_RENDER_PADDING, // position in source
|
|
204
|
+
VECTOR_TILE_SIZE, VECTOR_TILE_SIZE, // size in source
|
|
205
|
+
0, 0, // position in target
|
|
206
|
+
VECTOR_TILE_SIZE, VECTOR_TILE_SIZE // size in target
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
166
211
|
public getJsonTile(
|
|
167
212
|
z: number,
|
|
168
213
|
x: number,
|
|
@@ -174,9 +219,8 @@ class VectorTileFactory {
|
|
|
174
219
|
x = (x + 16 * maximumIndex) % maximumIndex;
|
|
175
220
|
y = (y + 16 * maximumIndex) % maximumIndex;
|
|
176
221
|
|
|
177
|
-
let
|
|
178
|
-
|
|
179
|
-
canvas.height = 256;
|
|
222
|
+
let resultCanvas = this.createCanvas(VECTOR_TILE_SIZE, 0);
|
|
223
|
+
let tempCanvas = this.createCanvas(VECTOR_TILE_SIZE, VECTOR_TILE_RENDER_PADDING);
|
|
180
224
|
|
|
181
225
|
let baseMapUrl = this.resolveTileUrl(z, x, y);
|
|
182
226
|
let urls = baseMapUrl ? [baseMapUrl] : [];
|
|
@@ -192,15 +236,16 @@ class VectorTileFactory {
|
|
|
192
236
|
});
|
|
193
237
|
|
|
194
238
|
let tileLoadedSuccessfullyCallback = (json: GeoJSON.Feature) => {
|
|
195
|
-
this.drawTile(json, z, x, y,
|
|
239
|
+
this.drawTile(json, z, x, y, tempCanvas);
|
|
240
|
+
this.cropCanvas(tempCanvas, resultCanvas);
|
|
196
241
|
|
|
197
242
|
if (callback) {
|
|
198
|
-
callback(
|
|
243
|
+
callback(resultCanvas);
|
|
199
244
|
}
|
|
200
245
|
};
|
|
201
246
|
|
|
202
247
|
let tile_FailedCallback = () => {
|
|
203
|
-
this.drawErroredTile(
|
|
248
|
+
this.drawErroredTile(resultCanvas);
|
|
204
249
|
|
|
205
250
|
if (callback) {
|
|
206
251
|
callback(null);
|
|
@@ -217,7 +262,7 @@ class VectorTileFactory {
|
|
|
217
262
|
this._tileLoader.loadNext();
|
|
218
263
|
}
|
|
219
264
|
|
|
220
|
-
return
|
|
265
|
+
return resultCanvas;
|
|
221
266
|
}
|
|
222
267
|
|
|
223
268
|
/**
|
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
MultiPolygon,
|
|
7
7
|
GeoJsonProperties,
|
|
8
8
|
} from "geojson";
|
|
9
|
+
|
|
9
10
|
import { CollisionDetector } from "./CollisionDetector.js";
|
|
11
|
+
|
|
10
12
|
import {
|
|
11
13
|
Boundaries,
|
|
12
14
|
ImageStyle,
|
|
@@ -19,7 +21,11 @@ import {
|
|
|
19
21
|
Vertex,
|
|
20
22
|
} from "../types/interfaces.js";
|
|
21
23
|
|
|
22
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
VECTOR_TILE_SIZE
|
|
26
|
+
} from "./constants.js"
|
|
27
|
+
|
|
28
|
+
import { RENDERING_CONFIG } from "../types/interfaces.js"
|
|
23
29
|
|
|
24
30
|
class VectorTileRenderer {
|
|
25
31
|
private _styles: RENDERING_CONFIG;
|
|
@@ -38,7 +44,7 @@ class VectorTileRenderer {
|
|
|
38
44
|
context: CanvasRenderingContext2D
|
|
39
45
|
): void {
|
|
40
46
|
context.fillStyle = this.getBackgroundColor(z);
|
|
41
|
-
context.fillRect(0, 0,
|
|
47
|
+
context.fillRect(0, 0, VECTOR_TILE_SIZE, VECTOR_TILE_SIZE);
|
|
42
48
|
|
|
43
49
|
var collisions = new CollisionDetector();
|
|
44
50
|
let polygons = layer
|
|
@@ -128,7 +134,7 @@ class VectorTileRenderer {
|
|
|
128
134
|
var context = canvas.getContext("2d");
|
|
129
135
|
if (context != null) {
|
|
130
136
|
context.fillStyle = "#C8C8C8";
|
|
131
|
-
context.fillRect(0, 0,
|
|
137
|
+
context.fillRect(0, 0, VECTOR_TILE_SIZE, VECTOR_TILE_SIZE);
|
|
132
138
|
context.fillStyle = "#AAA";
|
|
133
139
|
context.font = "15px Arial";
|
|
134
140
|
context.textAlign = "center";
|
|
@@ -164,7 +170,7 @@ class VectorTileRenderer {
|
|
|
164
170
|
const rendererName = this._styles.layers[kind];
|
|
165
171
|
const renderer = rendererName
|
|
166
172
|
? //@ts-ignore
|
|
167
|
-
|
|
173
|
+
this._styles?.renderers[rendererName]
|
|
168
174
|
: undefined;
|
|
169
175
|
|
|
170
176
|
if (renderer) {
|
|
@@ -179,10 +185,7 @@ class VectorTileRenderer {
|
|
|
179
185
|
if (geometry.type === "Polygon") {
|
|
180
186
|
const polygonGeometry = geometry as Polygon;
|
|
181
187
|
const coordinates = polygonGeometry.coordinates;
|
|
182
|
-
if (
|
|
183
|
-
(phase === "areasOutline" || phase === "areas") &&
|
|
184
|
-
renderer[j].polygon
|
|
185
|
-
) {
|
|
188
|
+
if ((phase === "areasOutline" || phase === "areas") && renderer[j].polygon) {
|
|
186
189
|
this.drawPolygon(
|
|
187
190
|
coordinates,
|
|
188
191
|
layer[i].properties,
|
|
@@ -192,10 +195,7 @@ class VectorTileRenderer {
|
|
|
192
195
|
context,
|
|
193
196
|
phase
|
|
194
197
|
);
|
|
195
|
-
} else if (
|
|
196
|
-
phase === "areaTexts" &&
|
|
197
|
-
renderer[j].text !== undefined
|
|
198
|
-
) {
|
|
198
|
+
} else if (phase === "areaTexts" && renderer[j].text !== undefined) {
|
|
199
199
|
this.drawPolygon(
|
|
200
200
|
coordinates,
|
|
201
201
|
layer[i].properties,
|
|
@@ -211,10 +211,7 @@ class VectorTileRenderer {
|
|
|
211
211
|
} else if (geometry.type === "MultiPolygon") {
|
|
212
212
|
const multiPolygonGeometry = geometry as MultiPolygon;
|
|
213
213
|
const coordinates = multiPolygonGeometry.coordinates;
|
|
214
|
-
if (
|
|
215
|
-
(phase === "areasOutline" || phase === "areas") &&
|
|
216
|
-
renderer[j].polygon
|
|
217
|
-
) {
|
|
214
|
+
if ((phase === "areasOutline" || phase === "areas") && renderer[j].polygon) {
|
|
218
215
|
for (let k = 0; k < coordinates.length; k++) {
|
|
219
216
|
this.drawPolygon(
|
|
220
217
|
coordinates[k],
|
|
@@ -244,10 +241,7 @@ class VectorTileRenderer {
|
|
|
244
241
|
} else if (geometry.type === "LineString") {
|
|
245
242
|
const lineStringGeometry = geometry as LineString;
|
|
246
243
|
const coordinates = lineStringGeometry.coordinates;
|
|
247
|
-
if (
|
|
248
|
-
(phase === "linesOutline" || phase === "lines") &&
|
|
249
|
-
renderer[j].line
|
|
250
|
-
) {
|
|
244
|
+
if ((phase === "linesOutline" || phase === "lines") && renderer[j].line) {
|
|
251
245
|
this.drawPolyline(
|
|
252
246
|
coordinates,
|
|
253
247
|
layer[i].properties,
|
|
@@ -270,10 +264,7 @@ class VectorTileRenderer {
|
|
|
270
264
|
} else if (geometry.type === "MultiLineString") {
|
|
271
265
|
const multiLineStringGeometry = geometry as MultiLineString;
|
|
272
266
|
const coordinates = multiLineStringGeometry.coordinates;
|
|
273
|
-
if (
|
|
274
|
-
(phase === "linesOutline" || phase === "lines") &&
|
|
275
|
-
renderer[j].line
|
|
276
|
-
) {
|
|
267
|
+
if ((phase === "linesOutline" || phase === "lines") && renderer[j].line) {
|
|
277
268
|
for (let k = 0; k < coordinates.length; k++) {
|
|
278
269
|
this.drawPolyline(
|
|
279
270
|
coordinates[k],
|
|
@@ -360,6 +351,9 @@ class VectorTileRenderer {
|
|
|
360
351
|
}
|
|
361
352
|
}
|
|
362
353
|
}
|
|
354
|
+
else {
|
|
355
|
+
console.log("no renderer for kind " + kind);
|
|
356
|
+
}
|
|
363
357
|
}
|
|
364
358
|
}
|
|
365
359
|
|
|
@@ -435,17 +429,25 @@ class VectorTileRenderer {
|
|
|
435
429
|
var part = coordinates[j];
|
|
436
430
|
|
|
437
431
|
context.globalAlpha = merged.opacity;
|
|
438
|
-
context.beginPath();
|
|
439
432
|
|
|
433
|
+
/// XXX edit here
|
|
434
|
+
if ('areas' !== phase || j === 0) {
|
|
435
|
+
// when rendering areas, only the first part of a polygon should begin a path
|
|
436
|
+
// (otherwise especially islands are clipped on some zoom levels)
|
|
437
|
+
context.beginPath();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const width = boundaries.max.lon - boundaries.min.lon;
|
|
441
|
+
const height = boundaries.max.lat - boundaries.min.lat;
|
|
442
|
+
if (width === 0 || height === 0) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
|
|
440
446
|
var points: { x: number; y: number }[] = [];
|
|
441
447
|
|
|
442
448
|
for (let k = 0; k < part.length; k++) {
|
|
443
|
-
let x =
|
|
444
|
-
|
|
445
|
-
(boundaries.max.lon! - boundaries.min.lon!);
|
|
446
|
-
let y =
|
|
447
|
-
(256 * (part[k][1] - boundaries.min.lat!)) /
|
|
448
|
-
(boundaries.max.lat! - boundaries.min.lat!);
|
|
449
|
+
let x = (VECTOR_TILE_SIZE * (part[k][0] - boundaries.min.lon!)) / width;
|
|
450
|
+
let y = (VECTOR_TILE_SIZE * (part[k][1] - boundaries.min.lat!)) / height;
|
|
449
451
|
|
|
450
452
|
points.push({ x: x, y: y });
|
|
451
453
|
|
|
@@ -466,7 +468,7 @@ class VectorTileRenderer {
|
|
|
466
468
|
}
|
|
467
469
|
|
|
468
470
|
return;
|
|
469
|
-
} else if ("areas" === phase) {
|
|
471
|
+
} else if ("areas" === phase && j === coordinates.length - 1) {
|
|
470
472
|
if (merged.url) {
|
|
471
473
|
if (this._images[merged.url]) {
|
|
472
474
|
var pattern = context.createPattern(
|
|
@@ -486,7 +488,7 @@ class VectorTileRenderer {
|
|
|
486
488
|
context.fillStyle = merged.color;
|
|
487
489
|
}
|
|
488
490
|
|
|
489
|
-
context.fill();
|
|
491
|
+
context.fill('evenodd');
|
|
490
492
|
} else if ("areaTexts" === phase) {
|
|
491
493
|
if (geoJsonProperties && geoJsonProperties.NAME) {
|
|
492
494
|
// skip texts which already are in this tile
|
|
@@ -497,14 +499,8 @@ class VectorTileRenderer {
|
|
|
497
499
|
let merged = { ...VectorTileRenderer.DEFAULT_STYLE.TEXT, ...style };
|
|
498
500
|
|
|
499
501
|
context.globalAlpha = merged.opacity;
|
|
500
|
-
context.font =
|
|
501
|
-
|
|
502
|
-
" " +
|
|
503
|
-
merged.fontWeight +
|
|
504
|
-
" " +
|
|
505
|
-
merged.size +
|
|
506
|
-
"px " +
|
|
507
|
-
merged.font;
|
|
502
|
+
context.font = `${merged.fontStyle} ${merged.fontWeight} ${merged.size}px ${merged.font}`;
|
|
503
|
+
|
|
508
504
|
context.textAlign = "left";
|
|
509
505
|
context.textBaseline = "top";
|
|
510
506
|
|
|
@@ -518,7 +514,7 @@ class VectorTileRenderer {
|
|
|
518
514
|
let h = merged.size!;
|
|
519
515
|
|
|
520
516
|
// skip texts outside a tile
|
|
521
|
-
if (x < 0 || x + w >
|
|
517
|
+
if (x < 0 || x + w > VECTOR_TILE_SIZE || y < 0 || y + h > VECTOR_TILE_SIZE) {
|
|
522
518
|
return;
|
|
523
519
|
}
|
|
524
520
|
|
|
@@ -622,15 +618,12 @@ class VectorTileRenderer {
|
|
|
622
618
|
var lastX, lastY;
|
|
623
619
|
var points = [];
|
|
624
620
|
|
|
621
|
+
const width = boundaries.max.lon - boundaries.min.lon;
|
|
622
|
+
const height = boundaries.max.lat - boundaries.min.lat;
|
|
623
|
+
|
|
625
624
|
for (var j = 0; j < coordinates.length; j++) {
|
|
626
|
-
var x = Math.round(
|
|
627
|
-
|
|
628
|
-
(boundaries.max.lon! - boundaries.min.lon!)
|
|
629
|
-
);
|
|
630
|
-
var y = Math.round(
|
|
631
|
-
(256 * (coordinates[j][1] - boundaries.min.lat!)) /
|
|
632
|
-
(boundaries.max.lat! - boundaries.min.lat!)
|
|
633
|
-
);
|
|
625
|
+
var x = Math.round((VECTOR_TILE_SIZE * (coordinates[j][0] - boundaries.min.lon!)) / width);
|
|
626
|
+
var y = Math.round((VECTOR_TILE_SIZE * (coordinates[j][1] - boundaries.min.lat!)) / height);
|
|
634
627
|
|
|
635
628
|
if (x != lastX || y != lastY) {
|
|
636
629
|
points.push({ x: x, y: y });
|
|
@@ -755,14 +748,7 @@ class VectorTileRenderer {
|
|
|
755
748
|
var merged = { ...VectorTileRenderer.DEFAULT_STYLE.TEXT, ...style };
|
|
756
749
|
|
|
757
750
|
context.globalAlpha = merged.opacity;
|
|
758
|
-
context.font =
|
|
759
|
-
merged.fontStyle +
|
|
760
|
-
" " +
|
|
761
|
-
merged.fontWeight +
|
|
762
|
-
" " +
|
|
763
|
-
merged.size +
|
|
764
|
-
"px " +
|
|
765
|
-
merged.font;
|
|
751
|
+
context.font = `${merged.fontStyle} ${merged.fontWeight} ${merged.size}px ${merged.font}`;
|
|
766
752
|
|
|
767
753
|
var points = this.projectCoordinates(coordinates, boundaries);
|
|
768
754
|
if (points.length < 2) {
|
|
@@ -909,8 +895,8 @@ class VectorTileRenderer {
|
|
|
909
895
|
positions.length == 0
|
|
910
896
|
? 0
|
|
911
897
|
: Math.abs(
|
|
912
|
-
|
|
913
|
-
|
|
898
|
+
positions[positions.length - 1].angle - position.angle
|
|
899
|
+
);
|
|
914
900
|
|
|
915
901
|
if (!collision && deltaAngle < Math.PI / 6) {
|
|
916
902
|
widthUsed += letterWidth;
|
|
@@ -1010,12 +996,12 @@ class VectorTileRenderer {
|
|
|
1010
996
|
if (merged.url) {
|
|
1011
997
|
if (this._images[merged.url]) {
|
|
1012
998
|
var x = Math.round(
|
|
1013
|
-
(
|
|
1014
|
-
|
|
999
|
+
(VECTOR_TILE_SIZE * (coordinate[0] - boundaries.min.lon!)) /
|
|
1000
|
+
(boundaries.max.lon! - boundaries.min.lon!)
|
|
1015
1001
|
);
|
|
1016
1002
|
var y = Math.round(
|
|
1017
|
-
(
|
|
1018
|
-
|
|
1003
|
+
(VECTOR_TILE_SIZE * (coordinate[1] - boundaries.min.lat!)) /
|
|
1004
|
+
(boundaries.max.lat! - boundaries.min.lat!)
|
|
1019
1005
|
);
|
|
1020
1006
|
if (merged.width && merged.height) {
|
|
1021
1007
|
merged.width = Number(merged.width);
|
|
@@ -1045,26 +1031,19 @@ class VectorTileRenderer {
|
|
|
1045
1031
|
): boolean {
|
|
1046
1032
|
var merged = { ...VectorTileRenderer.DEFAULT_STYLE.TEXT, ...style };
|
|
1047
1033
|
|
|
1048
|
-
|
|
1049
|
-
(
|
|
1050
|
-
|
|
1034
|
+
let x = Math.round(
|
|
1035
|
+
(VECTOR_TILE_SIZE * (coordinate[0] - boundaries.min.lon)) /
|
|
1036
|
+
(boundaries.max.lon - boundaries.min.lon)
|
|
1051
1037
|
);
|
|
1052
|
-
|
|
1053
|
-
(
|
|
1054
|
-
|
|
1038
|
+
let y = Math.round(
|
|
1039
|
+
(VECTOR_TILE_SIZE * (coordinate[1] - boundaries.min.lat)) /
|
|
1040
|
+
(boundaries.max.lat - boundaries.min.lat)
|
|
1055
1041
|
);
|
|
1056
1042
|
|
|
1057
|
-
context.font =
|
|
1058
|
-
merged.fontStyle +
|
|
1059
|
-
" " +
|
|
1060
|
-
merged.fontWeight +
|
|
1061
|
-
" " +
|
|
1062
|
-
merged.size +
|
|
1063
|
-
"px " +
|
|
1064
|
-
merged.font;
|
|
1043
|
+
context.font = `${merged.fontStyle} ${merged.fontWeight} ${merged.size}px ${merged.font}`;
|
|
1065
1044
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1045
|
+
const w = context.measureText(name).width;
|
|
1046
|
+
const h = merged.size; // XXX ???
|
|
1068
1047
|
|
|
1069
1048
|
x = x - w / 2; // center on x
|
|
1070
1049
|
|
|
@@ -1085,23 +1064,16 @@ class VectorTileRenderer {
|
|
|
1085
1064
|
var merged = { ...VectorTileRenderer.DEFAULT_STYLE.TEXT, ...style };
|
|
1086
1065
|
|
|
1087
1066
|
var x = Math.round(
|
|
1088
|
-
(
|
|
1089
|
-
|
|
1067
|
+
(VECTOR_TILE_SIZE * (coordinate[0] - boundaries.min.lon)) /
|
|
1068
|
+
(boundaries.max.lon - boundaries.min.lon)
|
|
1090
1069
|
);
|
|
1091
1070
|
var y = Math.round(
|
|
1092
|
-
(
|
|
1093
|
-
|
|
1071
|
+
(VECTOR_TILE_SIZE * (coordinate[1] - boundaries.min.lat)) /
|
|
1072
|
+
(boundaries.max.lat - boundaries.min.lat)
|
|
1094
1073
|
);
|
|
1095
1074
|
|
|
1096
1075
|
context.globalAlpha = merged.opacity;
|
|
1097
|
-
context.font =
|
|
1098
|
-
merged.fontStyle +
|
|
1099
|
-
" " +
|
|
1100
|
-
merged.fontWeight +
|
|
1101
|
-
" " +
|
|
1102
|
-
merged.size +
|
|
1103
|
-
"px " +
|
|
1104
|
-
merged.font;
|
|
1076
|
+
context.font = `${merged.fontStyle} ${merged.fontWeight} ${merged.size}px ${merged.font}`;
|
|
1105
1077
|
|
|
1106
1078
|
var w = context.measureText(name).width;
|
|
1107
1079
|
var h = merged.size; // XXX ???
|
|
@@ -1158,15 +1130,8 @@ class VectorTileRenderer {
|
|
|
1158
1130
|
let text = this._styles.renderers[renderer][i].text;
|
|
1159
1131
|
if (text) {
|
|
1160
1132
|
let merged = { ...VectorTileRenderer.DEFAULT_STYLE.TEXT, ...text };
|
|
1161
|
-
let font = (
|
|
1162
|
-
|
|
1163
|
-
" " +
|
|
1164
|
-
merged.fontWeight +
|
|
1165
|
-
" " +
|
|
1166
|
-
merged.size +
|
|
1167
|
-
"px " +
|
|
1168
|
-
merged.font
|
|
1169
|
-
).trim();
|
|
1133
|
+
let font = `${merged.fontStyle} ${merged.fontWeight} ${merged.size}px ${merged.font}`.trim();
|
|
1134
|
+
|
|
1170
1135
|
result.push(font);
|
|
1171
1136
|
}
|
|
1172
1137
|
}
|
package/lib/core/constants.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
export const URL_TEMPLATE =
|
|
2
2
|
"https://v${index}.maptrip.de/?tilex=${x}&tiley=${y}&acao=true&context=tomtom${z}&project=${project}&projection=wgs84";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
export const PROVIDER_PROJECTS: { [key: string]: string } = {
|
|
6
6
|
tomtom: "TomTom_latest",
|
|
7
|
+
orbis: "Orbis_latest",
|
|
7
8
|
here: "HERE_latest",
|
|
8
9
|
openstreetmap: "OSM_latest",
|
|
9
10
|
};
|
|
10
11
|
|
|
12
|
+
export const PROVIDER_NAMES: { [key: string]: string } = {
|
|
13
|
+
tomtom: "TomTom",
|
|
14
|
+
orbis: "TomTom Orbis",
|
|
15
|
+
here: "HERE",
|
|
16
|
+
openstreetmap: "OpenStreetMap",
|
|
17
|
+
};
|
|
18
|
+
|
|
11
19
|
export const PROVIDER_TRAFFIC: { [key: string]: string | null } = {
|
|
12
20
|
tomtom:
|
|
13
21
|
"https://v0.maptrip.de/tiles?project=TrafficMobileTomTom_EUROPE&tilex=${x}&tiley=${y}&acao=true&context=traffic${z}&projection=wgs84",
|
|
@@ -20,3 +28,6 @@ export const MAX_ZOOM = 18;
|
|
|
20
28
|
|
|
21
29
|
export const ATTRIBUTION =
|
|
22
30
|
'© <a href="https://maptrip.de/" target="_blank">infoware GmbH</a>';
|
|
31
|
+
|
|
32
|
+
export const VECTOR_TILE_SIZE = 256;
|
|
33
|
+
export const VECTOR_TILE_RENDER_PADDING = 32;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { PROVIDER_NAMES } from "../core/constants.js"
|
|
2
|
+
|
|
1
3
|
export class MapReleaseFetcher {
|
|
2
4
|
private _token: string;
|
|
3
5
|
|
|
4
6
|
private _tomtom: Promise<string | null> | null = null;
|
|
7
|
+
private _orbis: Promise<string | null> | null = null;
|
|
5
8
|
private _osm: Promise<string | null> | null = null;
|
|
6
9
|
private _here: Promise<string | null> | null = null;
|
|
7
10
|
|
|
@@ -14,27 +17,34 @@ export class MapReleaseFetcher {
|
|
|
14
17
|
if (!this._tomtom) {
|
|
15
18
|
const url =
|
|
16
19
|
"https://v1.maptrip.de/?CMD=GETFILE&PROJECT=TomTom_latest&RELATIVEPATH=/data/mapset/data/routing_geocoder/admin.bin&acao=true";
|
|
17
|
-
this._tomtom = this.fetchAndExtractRelease(url);
|
|
20
|
+
this._tomtom = this.fetchAndExtractRelease(provider, url);
|
|
18
21
|
}
|
|
19
22
|
return this._tomtom;
|
|
23
|
+
} if (provider === "orbis") {
|
|
24
|
+
if (!this._orbis) {
|
|
25
|
+
const url =
|
|
26
|
+
"https://v1.maptrip.de/?CMD=GETFILE&PROJECT=Orbis_latest&RELATIVEPATH=/data/mapset/data/routing_geocoder/admin.bin&acao=true";
|
|
27
|
+
this._orbis = this.fetchAndExtractRelease(provider, url);
|
|
28
|
+
}
|
|
29
|
+
return this._orbis;
|
|
20
30
|
} else if (provider === "here") {
|
|
21
31
|
if (!this._here) {
|
|
22
32
|
const url =
|
|
23
33
|
"https://v1.maptrip.de/?CMD=GETFILE&PROJECT=HERE_latest&RELATIVEPATH=/data/mapset/data/routing_geocoder/admin.bin&acao=true";
|
|
24
|
-
this._here = this.fetchAndExtractRelease(url);
|
|
34
|
+
this._here = this.fetchAndExtractRelease(provider, url);
|
|
25
35
|
}
|
|
26
36
|
return this._here;
|
|
27
37
|
} else if (provider === "openstreetmap") {
|
|
28
38
|
if (!this._osm) {
|
|
29
39
|
const url =
|
|
30
40
|
"https://v1.maptrip.de/?CMD=GETFILE&PROJECT=OSM_latest&RELATIVEPATH=/data/mapset/data/routing_geocoder/admin.bin&acao=true";
|
|
31
|
-
this._osm = this.fetchAndExtractRelease(url);
|
|
41
|
+
this._osm = this.fetchAndExtractRelease(provider, url);
|
|
32
42
|
}
|
|
33
43
|
return this._osm;
|
|
34
44
|
}
|
|
35
45
|
}
|
|
36
46
|
|
|
37
|
-
async fetchAndExtractRelease(url: string): Promise<string | null> {
|
|
47
|
+
async fetchAndExtractRelease(provider: string, url: string): Promise<string | null> {
|
|
38
48
|
return new Promise((resolve, reject) => {
|
|
39
49
|
var xhr = new XMLHttpRequest();
|
|
40
50
|
xhr.onreadystatechange = () => {
|
|
@@ -44,7 +54,7 @@ export class MapReleaseFetcher {
|
|
|
44
54
|
const text = new TextDecoder("latin1").decode(xhr.response);
|
|
45
55
|
const textString = this.extractTargetString(text);
|
|
46
56
|
const formattedString = textString!.split("Q").join(" Q");
|
|
47
|
-
const release = ` ${formattedString}`;
|
|
57
|
+
const release = ` ${PROVIDER_NAMES[provider]} ${formattedString}`;
|
|
48
58
|
|
|
49
59
|
resolve(release);
|
|
50
60
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maptrip/map-tiles",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "API to use MapTrip map tiles in other map APIs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"map",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"dev": "vite src",
|
|
22
22
|
"prepublish": "tsc",
|
|
23
23
|
"build": "tsc && vite build",
|
|
24
|
-
"
|
|
24
|
+
"check-updates": "npm outdated || echo 'All dependencies are up to date'",
|
|
25
|
+
"publish": "npm run check-updates && vite build && npm login --scope=@maptrip && npm publish"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@googlemaps/js-api-loader": "^1.16.2",
|