Sharing my SVG research

For a while I have been wondering about the benefits of SVG tiles compared to PNG.

Here is why:

  • Most of the map tiles consist of shapes and very few colours which is ideal for vector graphics
  • Multiple zoom levels can be packed because it scales better.
  • Smaller file size (I thought)
  • Style can be implemented in client (CSS)
  • Text and other layers can to toggled on and off in the client or be served as separate file.

Down sides:

  • Rendering has to be done in the client. but mobile phones have become faster. and an optimized SVG would also render faster.
  • Shapes would need to be clipped anyway (for instance a giant lake)
  • Compatibility, although every major browser supports it now.

So I though I would look into it and got a bit disappointed with my findings. I wanted to share my progress to see if anyone got insights.

I started by rendering an SVG using Mapnik and Carto to look at the current stage:

  • A file of my home town (5.35, 51.67, 5.4, 51.7, 1000x1000pt) = 6,8MB
  • Coordinates are about 6 decimals
  • Glymps are base64 encoded PNGs and there are many doubles
  • Text renders each character as a shape and it’s line as another.
  • Styles are in the SVG and inline on each element

This had potential for optimization. so I continued…

I grabbed a single PNG tile 256x256px which was 21kB

First I needed to know if this could be optimized. Since there aren’t many different colours in the PNG I’ve set the colour index to 13 colors
This would get the filesize to 11kB

But it would lose some colour depth and anti-aliasing so this optimization might not be worth it.

Getting this image as an SVG smaller/equal to 11kB would be a challenge
Here is a list of optimization I had in mind.

  • Background rectangle for the colour that occurs most.
  • Style borders with SVG stoke attribute. (not in file)
  • Text as or attribute
  • Add all shaped with the same colour into a group with an ID and style on the client with CSS
  • Reduce the amount of decimals for each point

To get a proof of concept I needed an estimate of the amount of vector point the above image would at least need.

Using Illustrator I path traced the image and toyed with the sliders until a got a vector with 65 paths and 600 points.
It looks all wiggly but getting a good looking map tile wasn’t the target.

Having 0 decimals per vector would mean this doesn’t scale. However with 1 decimal it would scale 10x (I think)

Writing the code that would generate a high performant minimalistic SVG from the OSM data would take a lot of work. Specially because I am new to all of this.

What do you think? Is my vector count estimate close to correct or are there other downsides of using SVG that I missed?

I think SVG can be styled with CSS, would it make resulting files smaller by (sort of) decoupling styling from data?

Edit: oops, I have now read the first paragraph :smiley:

Have you read about Vector tiles ? It seems to me that while SVG gives some improvements over PNG regarding the size, it does not give the flexibility to render only certain types of objects in the style the client wants that vector tiles offer.

Thanks for the link. I have seen the Vector tiles wiki page and found the GeoJSON specification. I assume this is the most common transport format for vector tiles. I think the data in GeoJSON would also fit in SVG format.

Until now I was under the impression that SVG is offering at least the same flexibility as other vector tiles.
Could you think of a use case that is not possible using SVG?

No, MVT is the most common format for vector tiles.

SVG is a vector graphics format, but most people probably think of vector data when talking about vector tiles. The boundary can be blurry at times, but essentially it’s the difference between “draw a thick yellow line with gray casing, and write ‘Foo Road’ in black letters on top of it” and “over there is a tertiary asphalt road called ‘Foo Road’ that has 4 lanes”.

One of the potential benefits of tiles containing geographic data is to leave the largest possible freedom to the client-side application in terms of styling. Should roads be coloured based on importance or surface? Which language should labels be displayed in – maybe even more than one? Should buildings be rendered in 3D? SVG can also leave certain styling decisions to the client with CSS, but it’s still not quite as flexible as raw geographic data.

Of course, due to practical performance limitations, real world vector tile formats such as Mapbox Vector Tiles still have to bake some assumptions/limitations into their tiles.

Thanks for sharing the results of your experiments by the way! :slight_smile:

Thank you for clarifying. This makes a lot of sense and yes SVG is basically a set of drawing instructions to the renderer.

However when separating structure from style like one does with HTML and CSS, an SVG could look like this:

<svg>...<g id="tertiary-asphalt"><path name="Foo road" d="over there"></g>...</svg>

Then on the client there is a style sheet with

#teriary-asphalt path {fill: yellow; stroke:gray; }

I’ve created a script that generated an svg like this and was very satisfied with the results:

  • 3 to 4 zoom levels can be packed into 1
  • file size of 30kb covers about 12 PNG files.
  • didn’t need a 5th of the vector points I had estimated.

I also found that some assumptions need to be made on the server. For instance which languages should be included. (Maybe in a separate file or concatenate on request based on http request lang)

I am on vacation right now, I will share the result when I get back.

As promised here is the result of my SVG generation script.

http://www.cloudengineering.nl/osmsvg/
(use ctrl +/- to zoom in/out)

I generated a single tile it contains, house numbers, street names and symbols for supermarket
It far is from finished, street names repeat for every part and are not in the middle of the road. text renders over other text that happens to be in the same place and it doesn’t wrap.

Other than that it gives me a good idea of what would be possible. I think an SVG should be seen as a graphic format not as vector tile data format. render times are very acceptable. I opened the SVG on my 3 year old OnePlus 3 and it shows instantly.

A down side from using CSS with SVG is that it has to be inline. It does not work with an tag. so I injected it into the HTML with javascript.

My main goal was to learn about OSM data and how maps can be drawn from it.
It has been a lot of fun playing around with the tool chain.