@versatiles/svg-renderer 2.0.0 → 2.2.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 +95 -47
- package/dist/index.d.ts +689 -50
- package/dist/index.js +15289 -11315
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -29,81 +29,129 @@ No native code. The only dependency is `@types/geojson` (types only). The packag
|
|
|
29
29
|
|
|
30
30
|
## Usage
|
|
31
31
|
|
|
32
|
-
### Node.js
|
|
33
|
-
|
|
34
32
|
```typescript
|
|
35
33
|
import { renderToSVG } from '@versatiles/svg-renderer';
|
|
36
|
-
import { inlineSources, osm } from '@versatiles/style';
|
|
37
|
-
import { writeFile } from 'node:fs/promises';
|
|
38
|
-
|
|
39
|
-
// inlineSources() resolves the style's TileJSON sources into tile URLs, which the
|
|
40
|
-
// renderer needs. Without it, the map comes out empty.
|
|
41
|
-
const style = await inlineSources(osm({ theme: 'colorful' }));
|
|
42
34
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
width: 800,
|
|
46
|
-
height: 600,
|
|
47
|
-
lon: 13.4,
|
|
48
|
-
lat: 52.5,
|
|
49
|
-
zoom: 10,
|
|
50
|
-
});
|
|
35
|
+
const url = 'https://tiles.versatiles.org/assets/styles/colorful/style.json';
|
|
36
|
+
const style = await (await fetch(url)).json();
|
|
51
37
|
|
|
52
|
-
await
|
|
38
|
+
const svg = await renderToSVG({ style, lon: 13.4, lat: 52.5, zoom: 10 });
|
|
53
39
|
```
|
|
54
40
|
|
|
55
|
-
|
|
56
|
-
> The style's sources must list their tile URLs directly (`"tiles": [...]`). A source that only points at a TileJSON document (`"url": ".../tiles.json"`) is **not fetched, and the map comes out empty without an error**. Styles built with `@versatiles/style` are in that form, so pass them through its `inlineSources()` as above. Hosted style files usually list their tiles already.
|
|
41
|
+
The result is an SVG document as a string: write it to a file, or put it into a web page. This works the same in Node.js and in the browser. Without `width` and `height`, the image is 1024 × 1024 pixels.
|
|
57
42
|
|
|
58
|
-
|
|
43
|
+
A source may list its tile URLs (`"tiles": [...]`) or point at a TileJSON document (`"url": "…/tiles.json"`). The renderer fetches a TileJSON document once per `SVGMapRenderer` and takes `tiles`, `minzoom`, `maxzoom` and the like from it, unless the style sets them, as MapLibre GL JS does.
|
|
44
|
+
|
|
45
|
+
### Many views of one style
|
|
46
|
+
|
|
47
|
+
`renderToSVG` starts from scratch on every call. To render many views of one style, create an `SVGMapRenderer` once: it parses the style once and keeps the tiles it has fetched.
|
|
59
48
|
|
|
60
49
|
```typescript
|
|
61
|
-
import {
|
|
50
|
+
import { SVGMapRenderer } from '@versatiles/svg-renderer';
|
|
62
51
|
|
|
63
|
-
const
|
|
64
|
-
(r) => r.json(),
|
|
65
|
-
);
|
|
52
|
+
const map = new SVGMapRenderer({ style });
|
|
66
53
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
width: 800,
|
|
70
|
-
height: 600,
|
|
71
|
-
lon: 13.4,
|
|
72
|
-
lat: 52.5,
|
|
73
|
-
zoom: 10,
|
|
74
|
-
});
|
|
54
|
+
const berlin = await map.renderSVG({ lon: 13.4, lat: 52.52, zoom: 12 });
|
|
55
|
+
const potsdam = await map.renderSVG({ lon: 13.06, lat: 52.4, zoom: 12 });
|
|
75
56
|
```
|
|
76
57
|
|
|
77
58
|
## API
|
|
78
59
|
|
|
79
60
|
### `renderToSVG(options): Promise<string>`
|
|
80
61
|
|
|
81
|
-
| Option
|
|
82
|
-
|
|
|
83
|
-
| `style`
|
|
84
|
-
| `width`
|
|
85
|
-
| `height`
|
|
86
|
-
| `lon`
|
|
87
|
-
| `lat`
|
|
88
|
-
| `zoom`
|
|
89
|
-
| `
|
|
62
|
+
| Option | Type | Default | Description |
|
|
63
|
+
| ------------- | ----------------------------------------------- | --------------------------- | -------------------------------------------------------------------------------------- |
|
|
64
|
+
| `style` | `StyleSpecification` | _(required)_ | MapLibre style specification |
|
|
65
|
+
| `width` | `number` | `1024` | Output width in pixels |
|
|
66
|
+
| `height` | `number` | `1024` | Output height in pixels |
|
|
67
|
+
| `lon` | `number` | style's `center`, else `0` | Center longitude |
|
|
68
|
+
| `lat` | `number` | style's `center`, else `0` | Center latitude |
|
|
69
|
+
| `zoom` | `number` | style's `zoom`, else `2` | Zoom level |
|
|
70
|
+
| `bearing` | `number` | style's `bearing`, else `0` | Compass direction that is up, in degrees (`90`: east is up) |
|
|
71
|
+
| `padding` | `number \| Padding` | `0` | Space around the center, in pixels: it sits in the middle of the area inside |
|
|
72
|
+
| `labels` | `'none' \| 'text' \| 'glyphs' \| 'glyphs-text'` | `'none'` | Whether and how to draw labels and icons; see [About labels](#about-labels) |
|
|
73
|
+
| `fetch` | `FetchFunction` | global `fetch` | Loads tiles and sprites; see [Loading tiles your own way](#loading-tiles-your-own-way) |
|
|
74
|
+
| `onWarning` | `(message) => void` | `console.warn` | Reports parts of the style that are not drawn; see [Warnings](#warnings) |
|
|
75
|
+
| `globalState` | `GlobalState` | style's `state` | Values for `global-state` expressions, over the style's defaults |
|
|
76
|
+
|
|
77
|
+
### `new SVGMapRenderer(options)`
|
|
78
|
+
|
|
79
|
+
Renders many views of one style. The options stay the same for every view:
|
|
80
|
+
|
|
81
|
+
| Option | Type | Default | Description |
|
|
82
|
+
| --------------- | ----------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------- |
|
|
83
|
+
| `style` | `StyleSpecification` | _(required)_ | MapLibre style specification. Read once: to render a changed style, create a new instance |
|
|
84
|
+
| `labels` | `'none' \| 'text' \| 'glyphs' \| 'glyphs-text'` | `'none'` | Whether and how to draw labels and icons; see [About labels](#about-labels) |
|
|
85
|
+
| `tileCacheSize` | `number` | `134217728` (128 MB) | How much memory fetched tiles may take, in bytes. `0` keeps none |
|
|
86
|
+
| `fetch` | `FetchFunction` | global `fetch` | Loads tiles and sprites; see [Loading tiles your own way](#loading-tiles-your-own-way) |
|
|
87
|
+
| `onWarning` | `(message) => void` | `console.warn` | Reports parts of the style that are not drawn; see [Warnings](#warnings) |
|
|
88
|
+
| `globalState` | `GlobalState` | style's `state` | Values for `global-state` expressions, over the style's defaults |
|
|
89
|
+
|
|
90
|
+
- **`renderSVG(view?): Promise<string>`** renders one view. `view` takes `width`, `height`, `lon`, `lat`, `zoom`, `bearing` and `padding`, with the same defaults as `renderToSVG`. Renders may run concurrently.
|
|
91
|
+
- **`project(view, [lon, lat]): [x, y] | undefined`** tells where a coordinate lands in the image of `view`, in the units of `width` and `height`, to place your own drawing on the map. On the globe, a point on the far side gives `undefined`.
|
|
92
|
+
- **`unproject(view, [x, y]): [lon, lat] | undefined`** is the opposite: the coordinate shown at a position in the image, e.g. where a user clicked. It gives `undefined` where the image shows no map: next to the globe, or beyond the poles of the mercator map (about ±85°).
|
|
93
|
+
- **`clearCache()`** forgets the fetched tiles and sprite, e.g. after they were updated on the server.
|
|
94
|
+
|
|
95
|
+
Tiles are kept for the lifetime of the instance, regardless of their HTTP caching headers; beyond `tileCacheSize`, the least recently used ones are dropped. A tile the server does not have (404) is remembered as missing; a failed request (network error, server error) is not, so the next render tries again.
|
|
96
|
+
|
|
97
|
+
### Loading tiles your own way
|
|
98
|
+
|
|
99
|
+
Tiles and sprites are loaded with the global `fetch`, unless you pass your own function as `fetch`: `(url: string) => Promise<Response>`. Use it to send headers (an API key, say), go through a proxy, or keep tiles on disk between runs — see [Caching tiles on disk](https://github.com/versatiles-org/versatiles-svg-renderer/blob/main/packages/png-renderer/README.md#caching-tiles-on-disk) for an example in Node.js.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const map = new SVGMapRenderer({
|
|
103
|
+
style,
|
|
104
|
+
fetch: (url) => fetch(url, { headers: { Authorization: `Bearer ${token}` } }),
|
|
105
|
+
});
|
|
106
|
+
```
|
|
90
107
|
|
|
91
|
-
|
|
108
|
+
It must return a real `Response`, and the status counts: a 404 or 204 means the server has no such tile, and the renderer remembers that; any other error status, or a rejected promise, counts as failed, so the next render tries again. The renderer asks it for tiles, sprites, and the TileJSON documents and GeoJSON data of the style's sources.
|
|
92
109
|
|
|
93
|
-
|
|
110
|
+
### About labels
|
|
94
111
|
|
|
95
|
-
|
|
112
|
+
Labels and icons (the style's symbol layers) are drawn with `labels`:
|
|
113
|
+
|
|
114
|
+
| `labels` | Labels drawn as |
|
|
115
|
+
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
116
|
+
| `'none'` | nothing: no labels and no icons (the default) |
|
|
117
|
+
| `'text'` | `<text>` naming the style's fonts (`text-font`), which whatever displays the SVG resolves: the intended typeface only where it is installed |
|
|
118
|
+
| `'glyphs'` | the style's own glyphs (`glyphs`), the letter shapes MapLibre GL JS draws, traced into outlines: exact in every viewer and editor, but not text |
|
|
119
|
+
| `'glyphs-text'` | as `'glyphs'`, with the text laid invisibly over the outlines, so labels stay selectable and searchable |
|
|
120
|
+
|
|
121
|
+
With glyphs, each glyph is defined once in the SVG's `<defs>` and placed with `<use>`, and labels are laid out with MapLibre's own metrics. A style without `glyphs`, or a label whose glyphs cannot be loaded, is drawn as `'text'`, and reported through `onWarning`.
|
|
122
|
+
|
|
123
|
+
Labels are placed as in MapLibre GL JS: at points, inside each polygon at the point farthest from its edges, and along lines, glyph by glyph; labels and icons that would overlap one placed before are left out, from the top layer down; point labels break into lines of at most `text-max-width` ems.
|
|
124
|
+
|
|
125
|
+
The option `renderLabels: true` of earlier versions still works, as `labels: 'glyphs-text'`, but is deprecated.
|
|
96
126
|
|
|
97
127
|
> [!WARNING]
|
|
98
|
-
>
|
|
128
|
+
> Labels are drawn without MapLibre GL JS's own layout engine, so there are known differences:
|
|
99
129
|
>
|
|
100
|
-
> - **
|
|
101
|
-
> - **
|
|
130
|
+
> - **Text measured with Noto Sans:** With `labels: 'text'`, text is measured with the widths of Noto Sans (the font of the VersaTiles styles). In other fonts, labels keep a little too much or too little distance.
|
|
131
|
+
> - **Placement:** Labels along lines are placed from the lines on screen, not from the tiles as in MapLibre, so a few labels differ.
|
|
132
|
+
>
|
|
133
|
+
> Which MapLibre GL JS features are covered, and which are not yet: [MapLibre GL JS Coverage](https://github.com/versatiles-org/versatiles-svg-renderer#maplibre-gl-js-coverage).
|
|
134
|
+
|
|
135
|
+
### Warnings
|
|
136
|
+
|
|
137
|
+
Parts of a style the renderer does not draw are reported, not skipped silently: layer types such as `fill-extrusion` or `heatmap`, properties such as `fill-pattern`, unsupported sources, and TileJSON documents or GeoJSON data that could not be loaded. Each message goes to `onWarning`, once per renderer, by default to `console.warn`:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
const map = new SVGMapRenderer({ style, onWarning: (message) => warnings.push(message) });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Pass `onWarning: () => {}` to silence them. Properties that make no difference to a flat, north-up map (e.g. `*-pitch-alignment`) are not reported, nor are symbol layers unless `renderLabels` is set. The [MapLibre GL JS coverage table](https://github.com/versatiles-org/versatiles-svg-renderer#maplibre-gl-js-coverage) lists what is supported.
|
|
102
144
|
|
|
103
145
|
### Projections
|
|
104
146
|
|
|
105
147
|
The renderer follows the style's [`projection`](https://maplibre.org/maplibre-style-spec/projection/): `mercator` (the default), `vertical-perspective` and `globe`, which — like in MapLibre GL JS — shows the globe up to zoom 11 and blends into mercator between zoom 11 and 12. Zoom-dependent `step`/`interpolate` expressions are supported as well. On the globe, geometry is clipped at the horizon and the map is clipped to the globe's outline; everything outside of it stays transparent. Raster tiles are drawn as a mesh of small triangles, each mapped exactly onto the globe by its own affine transform.
|
|
106
148
|
|
|
149
|
+
## Dependency Graph
|
|
150
|
+
|
|
151
|
+
<!--- This chapter is generated automatically --->
|
|
152
|
+
|
|
153
|
+
[](https://raw.githubusercontent.com/versatiles-org/versatiles-svg-renderer/main/packages/svg-renderer/docs/dependency-graph.svg)
|
|
154
|
+
|
|
107
155
|
## License
|
|
108
156
|
|
|
109
157
|
MIT. Part of [VersaTiles](https://github.com/versatiles-org/versatiles-svg-renderer): source code, issues and the changelog are on GitHub.
|