|
1 | | -import { TILE_EXTENT } from "./constants.js"; |
2 | | -import type { PreparedTile, Renderer, Source, Style } from "./types.js"; |
3 | | -import { requestIdleCallback } from "./utils.js"; |
4 | | - |
5 | | -type TileCoordinates = { |
6 | | - x: number; |
7 | | - y: number; |
8 | | - z: number; |
9 | | -}; |
10 | | - |
11 | | -type RenderedTile = { |
12 | | - coordinates: TileCoordinates; |
13 | | - layerElements: Record<string, SVGElement>; |
14 | | -}; |
| 1 | +import { TILE_EXTENT } from "../constants.js"; |
| 2 | +import type { Renderer } from "../types.js"; |
| 3 | +import { requestIdleCallback } from "../utils.js"; |
| 4 | +import { render as renderTile } from "./tile.js"; |
| 5 | +import type { RenderedTile, TileCoordinates } from "./types.js"; |
15 | 6 |
|
16 | 7 | export const renderer = (): Renderer => { |
17 | 8 | const tileCache = new Map< |
@@ -137,7 +128,7 @@ export const renderer = (): Renderer => { |
137 | 128 | const { added, removed } = updateWantedTiles(wantedTiles); |
138 | 129 |
|
139 | 130 | for (const { x, y, z } of added) { |
140 | | - const tile = await renderTileCached({ |
| 131 | + const tile = await renderTile({ |
141 | 132 | tile: { x, y, z }, |
142 | 133 | cache: tileCache, |
143 | 134 | source, |
@@ -276,98 +267,3 @@ const calculateTransformForTile = ({ |
276 | 267 | scale, |
277 | 268 | }; |
278 | 269 | }; |
279 | | - |
280 | | -const renderTileCached = async ({ |
281 | | - tile: { x, y, z }, |
282 | | - cache, |
283 | | - source, |
284 | | - style, |
285 | | -}: { |
286 | | - tile: { x: number; y: number; z: number }; |
287 | | - source: Source; |
288 | | - style: Style; |
289 | | - cache: Map<string, RenderedTile | null>; |
290 | | -}): Promise<RenderedTile | null> => { |
291 | | - const cached = cache.get(`${x}-${y}-${z}`); |
292 | | - if (cached !== undefined) { |
293 | | - return cached; |
294 | | - } |
295 | | - const preparedTile = await style.prepare({ source, tile: { x, y, z } }); |
296 | | - const renderedTile = { |
297 | | - coordinates: { x, y, z }, |
298 | | - layerElements: renderTile(preparedTile), |
299 | | - }; |
300 | | - cache.set(`${x}-${y}-${z}`, renderedTile); |
301 | | - return renderedTile; |
302 | | -}; |
303 | | - |
304 | | -const renderTile = (tile: PreparedTile): Record<string, SVGElement> => { |
305 | | - const layerElements: Record<string, SVGElement> = {}; |
306 | | - |
307 | | - for (const layer of Object.values(tile.layers)) { |
308 | | - if (layer.type === "raster") { |
309 | | - const image = document.createElementNS( |
310 | | - "http://www.w3.org/2000/svg", |
311 | | - "image", |
312 | | - ); |
313 | | - image.setAttribute("x", "-1"); |
314 | | - image.setAttribute("y", "-1"); |
315 | | - image.setAttribute("width", (TILE_EXTENT + 2).toString()); |
316 | | - image.setAttribute("height", (TILE_EXTENT + 2).toString()); |
317 | | - image.setAttribute("href", layer.url); |
318 | | - layerElements[layer.name] = image; |
319 | | - continue; |
320 | | - } |
321 | | - |
322 | | - const element = document.createElementNS("http://www.w3.org/2000/svg", "g"); |
323 | | - |
324 | | - for (const feature of layer.features) { |
325 | | - const path = document.createElementNS( |
326 | | - "http://www.w3.org/2000/svg", |
327 | | - "path", |
328 | | - ); |
329 | | - |
330 | | - path.setAttribute("data-layername", layer.name); |
331 | | - |
332 | | - const d = feature.geometry.commands |
333 | | - .map((command) => { |
334 | | - switch (command.type) { |
335 | | - case "move_to": |
336 | | - return `m${command.x} ${command.y}`; |
337 | | - case "line_to": |
338 | | - return command.points |
339 | | - .map((point) => `l${point.x} ${point.y}`) |
340 | | - .join(""); |
341 | | - case "close_path": |
342 | | - return "z"; |
343 | | - case "reset": |
344 | | - return "M0 0"; |
345 | | - default: |
346 | | - throw new Error("Unknown command type"); |
347 | | - } |
348 | | - }) |
349 | | - .join(""); |
350 | | - path.setAttribute("d", d); |
351 | | - path.setAttribute("fill", feature.static.fill ?? "none"); |
352 | | - path.setAttribute("stroke", feature.static.stroke ?? "none"); |
353 | | - path.setAttribute( |
354 | | - "stroke-width", |
355 | | - feature.static.strokeWidth?.toString() ?? "1", |
356 | | - ); |
357 | | - if (feature.static.opacity) { |
358 | | - path.setAttribute("opacity", feature.static.opacity?.toString() ?? "1"); |
359 | | - } |
360 | | - if (feature.static.fillTranslate) { |
361 | | - path.setAttribute( |
362 | | - "transform", |
363 | | - `translate(${feature.static.fillTranslate.x} ${feature.static.fillTranslate.y})`, |
364 | | - ); |
365 | | - } |
366 | | - element.appendChild(path); |
367 | | - } |
368 | | - |
369 | | - layerElements[layer.name] = element; |
370 | | - } |
371 | | - |
372 | | - return layerElements; |
373 | | -}; |
0 commit comments