[Talk-us] Client-side SVG shield rendering in JavaScript using relations

Chris Lawrence lordsutch at gmail.com
Fri Aug 8 00:23:23 UTC 2014

I've been working on a long-term project off-and-on to build a
specialized OpenStreetMap editor for connected windshield or
pedestrian surveying (which occasionally shows up in OSM changesets as
edits from "HandOSMFix"); in the course of rewriting it to be
client-side JavaScript as much as possible, I fell down the rabbit
hole of trying to get decent-looking shields suitable for map overlays
and the like - even if not pattern-accurate - produced in client-side
HTML5 technologies rather than having to cache a bunch of pre-rendered
stuff on the server.

So while I'm not making much headway on the bigger project for now, I
did want to throw this code over my wall in the event that those of
you trying to make a prettier default US map would find it useful. The
two files are at:


shield-shapes.js just holds JSON representations of the shield
outlines for things too complex to manually draw in JavaScript,
converted from slightly modified versions of the shields in Phil!
Gold's repository at https://launchpad.net/osm-shields (which I
presume were adapted from the shields at Wikimedia); I mainly stripped
out the thin outlines and the text, since that's either added later in
my process or too small to be legible anyway (for example the word
"Interstate" in the blue part of the shield).

svg-shields.js is the actual meat of the code. It assumes that you
have the tags from an OSM relation object in GeoJSON format (like one
converted using osmtogeojson.js at
https://github.com/tyrasd/osmtogeojson) built from some OSM data; in
my code it's using data retrieved from the Overpass API, but you could
also use any other OSM data source. It also assumes the end user has
Roboto and Roboto Condensed fonts available somehow (in my app,
presumably on the device or as a web font); of course you could use
Roadgeek 2014 or some alternative instead by hacking the code.

There's a live debugging demo at
http://www.signifying-nothing.com/test.html - click somewhere on the
map and you'll see an overlay of nearby ways retrieved from the
Overpass API and get info for some number of close-by roads, with a
rendered shield (or multiple shields) next to it if applicable. You
can also search and change layers. The code only does shields for
relations, and only if they are reasonably well-formed; it catches a
few common mistakes/tagging discrepancies for bannered routes that the
experimental shield rendering layer doesn't, but not others, and does
a few more things the rendering layer doesn't, like handling the
tagged county roads in Florida. (If you open the Javascript console
you'll see an error message if it can't render a shield for something
it should at least give you some guidance why - most likely because it
didn't understand the network tag the relation has.)

(The edit link is there for my use and won't really do anything for
you, since it goes to the server-side code that is behind a login and
which I plan to retire once the client-side code is done and
authenticates against OSM directly via OAuth2 the same way iD does, as
documented here:

It also only does fairly generic stuff like you'd see on a commercial
map of the U.S.; you're not going to see state outlines and the like,
but rather circles, lozenges, and rectangles/squares, although it does
distinguish between the various types of roads in Texas by rendering
something not unlike what you'd see on a freeway guide sign in Texas.
The only exceptions are Interstate, US, Mexico, and Quebec autoroute
shields. Bannered routes are rendered either as green Interstate
shields or with the banner inside the shield (like the print Michelin
road atlas does/did, unlike the Google Maps rendering of a separate
banner). It's basically designed to reflect my tastes in
cartography... so you probably will disagree with my choices. :)

Anyway hope someone finds this useful while I fiddle more with the
project it is part of.


More information about the Talk-us mailing list