We’ve been working on a label placement strategy in Mapbox GL tailored specifically for navigation.

Left: current basemap labelling in Mapbox GL. Right: prototype of navigation labelling in Mapbox GL.

To accomplish this we’ve had to bend some of our own rules for placing labels on maps.

How basemap label placement works

Basemap label placement

Placement logic for roads is currently quite efficient for basemaps: per tile, we iterate through features calculating the first possible anchor based on beginning of line geometry and the style’s desired spacing of labels along a line. After checking a variety of factors like max angle, desired padding, and text shaping, the label is placed. If it fails one of those checks, it’s skipped.

This approach distributes labels evenly. But it starts to break down on small screens with a perspective viewpoint because it’s 100% camera agnostic. Basemap label placement is optimized for many possible perspectives because it anticipates a user’s interactions causing panning and zooming, rather than the user’s current perspective.

How navigation label placement works

Viewport label placement

We can optimize label placement for the user’s current perspective by making the following assumptions about how users will interact with a navigation map:

  1. The map camera will primarily move forward.
  2. When changing direction, the camera will rotate gradually.

In short: drivers, bikers and runners don’t move side to side and don’t turn recklessly.

By taking this into account we can define a modified label placement algorithm that focuses on roads the user will cross as landmarks in their path of travel. The new approach:

  • Places labels close to the viewport center: we calculate the perceptual vertical centerline on-screen and sort labels to place those closest to this centerline first.
  • Dedupe text labels: we show a label at most 1x per tile on screen. Labels are deduped in this mode based on text — so between two labels for the same text, the first instance of Main St will win.
  • Filtering lines by 45° threshold: lines that are > 45° from the camera baseline are filtered out. This portion selects cross streets for labelling.
  • Label stabilizer: all of the camera-specific logic causes popping of labels for small shifts. The algorithm implements a stabilizing threshold to prevent jarring between frames.

Comparison of selected labels

Differences in labels selected between basemap and viewport labelling.

Integrating into Mapbox GL

We’re continuing to add Mapbox GL features specifically for building custom navigation experiences. Get in touch with our team if you’re interested in learning more.