Renders vector maps as SVG.
Supported layer types: background, fill, line, circle, symbol, and raster.
npm install @versatiles/svg-rendererimport { renderToSVG } from '@versatiles/svg-renderer';
import { styles } from '@versatiles/style';
import { writeFileSync } from 'node:fs';
const svg = await renderToSVG({
style: styles.colorful(),
width: 800,
height: 600,
lon: 13.4,
lat: 52.5,
zoom: 10,
});
writeFileSync('map.svg', svg);import { renderToSVG } from '@versatiles/svg-renderer';
const svg = await renderToSVG({
style: await fetch('https://tiles.versatiles.org/assets/styles/colorful/style.json').then((r) =>
r.json(),
),
width: 800,
height: 600,
lon: 13.4,
lat: 52.5,
zoom: 10,
});
document.body.innerHTML = svg;The package includes an SVGExportControl that adds an export button to any MapLibre GL JS map.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@5/dist/maplibre-gl.css" />
<script src="https://unpkg.com/maplibre-gl@5/dist/maplibre-gl.js"></script>
<script src="https://unpkg.com/@versatiles/svg-renderer/dist/maplibre.umd.js"></script>
</head>
<body>
<div id="map"></div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://tiles.versatiles.org/assets/styles/colorful/style.json',
center: [13.4, 52.5],
zoom: 10,
});
map.addControl(new VersaTilesSVG.SVGExportControl(), 'top-right');
</script>
</body>
</html>The control opens a panel where the user can set width, height, and scale, preview the SVG, download it, or open it in a new tab. Map interactions are disabled while the panel is open.
Options:
new SVGExportControl({
defaultWidth: 1024, // default: 1024
defaultHeight: 1024, // default: 1024
defaultScale: 1, // default: 1
});| Option | Type | Default | Description |
|---|---|---|---|
style |
StyleSpecification |
(required) | MapLibre style specification |
width |
number |
1024 |
Output width in pixels |
height |
number |
1024 |
Output height in pixels |
lon |
number |
0 |
Center longitude |
lat |
number |
0 |
Center latitude |
zoom |
number |
2 |
Zoom level |
renderLabels |
boolean |
false |
Enable rendering of text labels and icons |
When renderLabels is set to true, symbol layers are rendered, including text labels and sprite-based icons. By default, this option is disabled.
Warning
The rendering of labels and icons is experimental and may produce imperfect results. Since we cannot use the original layouting engine of MapLibre GL JS, there are known limitations:
- No collision detection: Text labels are rendered without collision detection, so labels may overlap.
- Simplified text placement: Labels can not be positioned along lines.
A visual comparison report between the SVG renderer and MapLibre GL JS is published to GitHub Pages:
---
config:
layout: elk
---
flowchart TB
subgraph 0["src"]
1["demo.ts"]
2["index.ts"]
subgraph 3["pipeline"]
4["render.ts"]
E["style_layer.ts"]
end
subgraph 5["sources"]
6["index.ts"]
7["geojson.ts"]
9["merge.ts"]
A["raster.ts"]
B["tiles.ts"]
C["sprite.ts"]
D["vector.ts"]
end
8["geometry.ts"]
subgraph F["renderer"]
G["svg.ts"]
H["color.ts"]
I["svg_path.ts"]
N["types.ts"]
end
subgraph J["maplibre"]
K["control.ts"]
L["panel_css.ts"]
M["index.ts"]
end
end
1-->2
2-->4
2-->G
4-->6
4-->C
4-->E
6-->7
6-->9
6-->A
6-->C
6-->D
7-->8
9-->8
A-->B
B-->8
D-->8
D-->B
G-->H
G-->I
K-->2
K-->L
M-->2
M-->K
class 0,3,5,F,J subgraphs;
classDef subgraphs fill-opacity:0.1, fill:#888, color:#888, stroke:#888;