Design Proposal: SVG Icons
## Motivation
When designers want to put SVG assets on a map they are currently required to include them either as PNGs or as SDFs. Both methods work to some extent but they have their drawbacks: PNGs are rasterized at a fixed resolution and resampling them on the map after translations, rotations, and scaling leads to degraded visual quality. SDFs are limited to a single fill color and single halo color, gradients are not supported, and detail is lost.
Here we would like to propose changes to the style specification that would allow users to directly reference SVGs from a map stylesheet.
The implementation of SVG support can be discussed separately. The goal here is just to think about how direct SVG referencing and the existing raster sprite mechanism can be brought together.
## Proposed Change / API Modifications
One goal is to support referencing of SVGs in the `icon-image` key of the symbol layer. Usually this key looks for a registered image, either from a spritesheet or from images that have been added by the user dynamically.
MapLibre already has multiple sprite support, i.e., a list of spritesheets can be added. The current form of a spritesheet is `{id: '...', url: '...'}`. We could build this out in the following way to support SVGs:
Add `type: 'svg'` to the spritesheet definition to trigger a different behavior.
Allow a `{name}` wildcard in the url. Like this a folder of SVGs can be easily referenced. The name would be the same as in `icon-image` just with the multisprite id prefix removed.
Add `assets`, a dictionary which can reference individual SVGs by URL and inline them too.
If an icon is not found in the assets dict the engine will try loading it from the url with the wildcard.
Example:
```json
"sprite": [
{
"id": "my_svg_icons",
"assets": {
"airport": "https://example1.com/airport.svg",
"circle": "<svg xmlns=...><circle cx=.../></svg>"
},
"url": "https://example2.com/{name}.svg",
"type": "svg"
},
{
"id": "default",
"url": "https://example3.com/anotherurl"
}
]
```
## Migration Plan and Compatibility
This should be compatible with existing styles.
## Rejected Alternatives
It feels a bit strange to treat SVGs as sprites. One could think of adding a new root style property like this maybe:
```json
"svgs": {
"url": "https://example2.com/{name}.svg",
"assets": {
"airport": "https://example1.com/airport.svg",
"circle": "<svg xmlns=...><circle cx=.../></svg>"
}
}
```
But then how do we make sure that SVG icon names and spritesheet icon names do not collide? And if they collide, how would we prioritize SVGs or normal sprites? Maybe there is a way to work this out like with some convention but keeping it very explicit with the multisprites seems simpler.
1 条评论