Skip to content

Commit 94e9ed3

Browse files
committed
Implement loading style from URL
1 parent c47c417 commit 94e9ed3

11 files changed

Lines changed: 190 additions & 8824 deletions

File tree

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353

5454
const map = mewmap({
5555
svg: document.getElementById("mewmap"),
56+
style: "https://tiles.versatiles.org/assets/styles/colorful/style.json",
5657
longitude: 24.9384,
5758
latitude: 60.1699,
5859
zoom: 14,

src/index.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { camera } from "./camera.js";
22
import { renderer } from "./renderer.js";
3-
import { source } from "./source.js";
3+
import { dummy as dummySource } from "./source/dummy.js";
4+
import { vector } from "./source/vector.js";
5+
import { dummy as dummyStyle } from "./style/dummy.js";
46
import { style } from "./style/index.js";
7+
import { style as styleSchema } from "./style/schema.js";
58
import type { MewMap, MewMapOptions } from "./types.js";
69
import { ui } from "./ui.js";
710

@@ -10,7 +13,7 @@ export const mewmap = (options: MewMapOptions): MewMap => {
1013
throw new Error("svg option must be an svg element");
1114
}
1215

13-
const map: MewMap = {
16+
const map = {
1417
camera: camera({
1518
...options,
1619
screen: {
@@ -21,15 +24,33 @@ export const mewmap = (options: MewMapOptions): MewMap => {
2124
move(params) {
2225
this.camera.move(params);
2326
},
24-
source: source(),
25-
style: style(),
27+
source: dummySource(),
28+
style: dummyStyle(),
2629
svg: options.svg as SVGSVGElement,
2730
renderer: renderer(),
2831
ui: ui(),
32+
loaded: Promise.resolve(false),
33+
} satisfies MewMap;
34+
35+
const init = async (): Promise<boolean> => {
36+
if (typeof options.style === "string") {
37+
const response = await fetch(options.style);
38+
const json = await response.json();
39+
const parsed = styleSchema.parse(json);
40+
41+
map.style = style(parsed);
42+
map.source = vector({ name: "versatiles-shortbread" });
43+
44+
map.renderer.init(map);
45+
map.ui.init(map);
46+
47+
return true;
48+
}
49+
50+
return false;
2951
};
3052

31-
map.renderer.init(map);
32-
map.ui.init(map);
53+
map.loaded = init();
3354

3455
return map;
3556
};

src/renderer.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ type RenderedTile = {
1414
};
1515

1616
export const renderer = (): Renderer => {
17-
const tileCache = new Map<`${number}-${number}-${number}`, RenderedTile>();
17+
const tileCache = new Map<
18+
`${number}-${number}-${number}`,
19+
RenderedTile | null
20+
>();
1821
const visibleTiles = new Set<RenderedTile>();
1922

2023
let wantedTiles: TileCoordinates[] = [];
@@ -132,6 +135,10 @@ export const renderer = (): Renderer => {
132135
style,
133136
});
134137

138+
if (!tile) {
139+
continue;
140+
}
141+
135142
const transform = calculateTransformForTile({
136143
camera,
137144
tile: { x, y, z },
@@ -263,13 +270,20 @@ const renderTileCached = async ({
263270
tile: { x: number; y: number; z: number };
264271
source: Source;
265272
style: Style;
266-
cache: Map<string, RenderedTile>;
267-
}): Promise<RenderedTile> => {
273+
cache: Map<string, RenderedTile | null>;
274+
}): Promise<RenderedTile | null> => {
268275
const cached = cache.get(`${x}-${y}-${z}`);
269-
if (cached) {
276+
if (cached !== undefined) {
270277
return cached;
271278
}
272-
const tile = await source.fetch(x, y, z);
279+
const tile = await source.fetch({
280+
name: "versatiles-shortbread",
281+
tile: { x, y, z },
282+
});
283+
if (!tile || tile.type === "raster") {
284+
cache.set(`${x}-${y}-${z}`, null);
285+
return null;
286+
}
273287
const preparedTile = style.prepare({ ...tile, x, y, z });
274288
const renderedTile = {
275289
coordinates: { x, y, z },

src/source/composite.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { Source } from "../types.js";
2+
3+
export const composite = (...sources: Source[]): Source => {
4+
return {
5+
get name() {
6+
return null;
7+
},
8+
async fetch({ name, tile: { x, y, z } }) {
9+
return (
10+
sources
11+
.find((source) => source.name === name)
12+
?.fetch({ name, tile: { x, y, z } }) ?? null
13+
);
14+
},
15+
};
16+
};

src/source/dummy.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { Source } from "../types.js";
2+
3+
export const dummy = (): Source => {
4+
return {
5+
get name() {
6+
return null;
7+
},
8+
async fetch() {
9+
return null;
10+
},
11+
};
12+
};

src/source.ts renamed to src/source/vector.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
import { fromBinary } from "@bufbuild/protobuf";
2-
import { type Tile, TileSchema } from "./gen/vector_tile_pb.js";
3-
import type { Source } from "./types.js";
2+
import { type Tile, TileSchema } from "../gen/vector_tile_pb.js";
3+
import type { Source } from "../types.js";
44

55
const TILES_URL = "https://tiles.versatiles.org/tiles/osm/{z}/{x}/{y}";
66

7-
export const fetchTile = async (
8-
tilesUrl: string,
9-
x: number,
10-
y: number,
11-
z: number,
12-
) => {
7+
const fetchTile = async (tilesUrl: string, x: number, y: number, z: number) => {
138
const url = tilesUrl
149
.replace("{x}", x.toString())
1510
.replace("{y}", y.toString())
@@ -19,21 +14,26 @@ export const fetchTile = async (
1914
return bytes;
2015
};
2116

22-
export const parseTile = (bytes: Uint8Array) => {
17+
const parseTile = (bytes: Uint8Array) => {
2318
const tile = fromBinary(TileSchema, bytes);
2419
return tile;
2520
};
2621

27-
export const source = (): Source => {
28-
const tileCache = new Map<string, Tile>();
22+
export const vector = ({ name: sourceName }: { name: string }): Source => {
23+
const tileCache = new Map<string, { type: "vector" } & Tile>();
2924

3025
return {
31-
async fetch(x, y, z) {
26+
get name() {
27+
return sourceName;
28+
},
29+
async fetch({ name, tile: { x, y, z } }) {
30+
if (name !== sourceName) return null;
31+
3232
const cached = tileCache.get(`${x}-${y}-${z}`);
3333
if (cached) return cached;
3434

3535
const bytes = await fetchTile(TILES_URL, x, y, z);
36-
const tile = parseTile(bytes);
36+
const tile = { type: "vector" as const, ...parseTile(bytes) };
3737

3838
tileCache.set(`${x}-${y}-${z}`, tile);
3939

0 commit comments

Comments
 (0)