Mapbox-gl-js: Outline for lines (styling)

Created on 21 Dec 2016  路  6Comments  路  Source: mapbox/mapbox-gl-js

It would be nice to have a style property for lines like:

line-outline-opacity

This removes the need for having to create a separate layer in order to give my geojson geometries a white outline. Guess that improves performance as you only have one geometry instead of two.

feature

Most helpful comment

This is how I solved this issue, it seems to do the job most of the time:

https://codepen.io/joedazza/pen/QWwKRKP

All 6 comments

Hi @dannybloe thanks for submitting this feature request!

Have you tried using the line-gap-width property to accomplish this? Its not exactly what you're suggesting because you still need an extra layer for the line casings, but it does prevent you from having to generate additional geometries.

Of course but indeed you need an extra layer. Of course you share the same data source but still. An extra style would be a lot easier/faster.

We may introduce this for fill layers (https://github.com/mapbox/mapbox-gl-style-spec/issues/223), but don't have plans to do so for line layers. Using two layers is a reasonable balance between efficiency and keeping the style specification simple.

I want to be able to click on a line and visually "select" it using a border

Approach 1: Use id to set the feature-state, and create a new layer where the selected line is filtered

The idea here is to use line-gap-width and a different color with some opacity to represent the outline/border.

// separate layer for drawing the borders (using the same source)
{ ..., filter: ['boolean', ['feature-state', 'selected'], false] }

// => Error: layers[1].filter: "feature-state" data expressions are not supported with filters.

Approach 2: Create a new source, and make sure it contains only the selected feature, but with different styling

map.addSource('selected', { type: 'geojson', data: feature })

// => Uncaught Error: There is already a source with this ID

Okay, so what if I clone the feature but omit the id then?

import { omit } from 'ramda'
// ...
const clonedFeature = omit(['id'], feature)
map.addSource('selected', { type: 'geojson', data: clonedFeature })

// => Error: The feature id parameter must be provided and non-negative.

Approach 3: Manually set the filter of the highlight-layer

// This is the approach that actually works:
map.setFilter('lines-highlighted-layer', ['==', 'someUniqueProperty', selectedFeature.properties.someUniqueProperty])

Although approach 3 works, it is a lot slower [O(n)] than adding a border/stroke to a circle [O(1)].

It also requires that your feature properties contain some kind of unique identifier property, since you can't filter on the feature style id.

In my usecase where am rendering hurricane segments, loading a whole new vector layer to highlight selected storm is pretty expensive. Essentially when if we had line-outline-color and
line-outline-opacity I can get away with just rendering all segments, and then showing a highlight around the entire track. Without that, I now have to maintain and load a whole new tracks layer.

This is how I solved this issue, it seems to do the job most of the time:

https://codepen.io/joedazza/pen/QWwKRKP

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jfirebaugh picture jfirebaugh  路  3Comments

samanpwbb picture samanpwbb  路  3Comments

PBrockmann picture PBrockmann  路  3Comments

yoursweater picture yoursweater  路  3Comments

BernhardRode picture BernhardRode  路  3Comments