Dusan
Dusan

Reputation: 3488

Variable line offset in MapBox

I have a MapBox map and I'm drawing some lines on top.

First I create a geojson object. All my features are LineStrings. Some of my lines can have a left/right property, but it is not a mandatory parameter. So a feature looks like this:

const feature = {
    'type': 'Feature',
    'properties': {
        'id': LINE_ID,
        'color': LINE_COLOR,
        'left_right': "LEFT",  // can be "LEFT", "RIGHT", or ""
    },
    "geometry": {
        'type': 'LineString',
        "coordinates": [
            [LINE_POINTS[0].lng, LINE_POINTS[0].lat],
            [LINE_POINTS[1].lng, LINE_POINTS[1].lat],
        ]
    }
}

After my geojson is ready, I add it as a source to the map:

map.addSource('geojson_lines', {type: 'geojson', data: LINE_FEATURES});

Now a need to add a layer to the map, from this source. No problem.
But I need my layer to meet these requirements:

I could make the color and line width work, but can't figure out the offset:

map.addLayer({
    id: 'lines_layer', type: 'line', source: 'geojson_lines',
    layout: {},
    paint: {
        'line-color': ['get', 'color'],
        'line-width': {
            stops: [[8, 4], [18, 10]]
        },
        'line-offset': [] // need help with this
    }
});

The goal is to have an positive offset value for the "RIGHT" lines in the range for example from 2 to 6 for zoom levels 8 to 18 and a negative offset value for the "LEFT" lines.

Is it possible to achieve this with some kind of expression and the stops or interpolate array?

Upvotes: 1

Views: 1378

Answers (1)

Dusan
Dusan

Reputation: 3488

After reading the documentation and trying out some tips found on stackoverflow I was able to solve this on my own

The key here is to first interpolate the values and then determine the direction using a case expression.

map.addLayer({
    id: 'lines_layer', type: 'line', source: 'geojson_lines',
    layout: {},
    paint: {
        'line-color': ['get', 'color'],
        'line-width': {
            stops: [[8, 4], [18, 10]]
        },

        'line-offset': ['interpolate', ['linear'], ['zoom'],
            8
            ['case',
                ["==", ["get", "left_right"], "LEFT"],
                -2,
                ["==", ["get", "left_right"], "RIGHT"],
                2,
                0
            ],
            18,
            ['case',
                ["==", ["get", "left_right"], "LEFT"],
                -6,
                ["==", ["get", "left_right"], "RIGHT"],
                6,
                0
            ],
        ],

    }
});

Upvotes: 2

Related Questions