Search code examples
flutterdartmapboxsymbolslayer

Flutter mapbox_gl how to put polylines below symbols


I am trying to add polylines to a mapbox view in Flutter using the mapbox_gl library. The problem is that I also have markers (called symbols in the library) that need to be on top of the polylines, but it keeps drawing the polylines over the symbols.

This is the function I use to add the symbols:

  _mbController.addSymbol(SymbolOptions(
    geometry:
        LatLng(vehicle['position']['lat'], vehicle['position']['lon']),
    iconImage: 'vehicle'));

Then I use these functions to add the polylines:

  Future<void> updatePolyLines(var geometry) async {
    _fills = {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          "id": 0,
          "properties": <String, dynamic>{},
          "geometry": geometry,
        },
      ],
    };

    await _mbController!.removeLayer("lines");
    await _mbController!.removeSource("fills");

    await _mbController!
        .addSource("fills", GeojsonSourceProperties(data: _fills));
    await _mbController!.addLineLayer(
        "fills",
        "lines",
        const LineLayerProperties(
          lineColor: '#007AFF',
          lineCap: "round",
          lineJoin: "round",
          lineWidth: 4,
        ));
  }

  Future<void> showNavLine(LatLng destination) async {
    LocationTuple l = await getLocation(context);
    if (l.gotPosition) {
      var response = await prepareRoute(l.latLng, destination);
      if (response == null) {
        return;
      } else {
        updatePolyLines(response['routes'][0]['geometry']);
      }
    }
  }

The prepareRoute function uses the mapbox API to get a route, this part is working fine and the line is shown. However, as I said it is draw on top of the symbols.

I read that you can draw the polylines below a certain layer. So I tried adding a separate layer for the symbols and drawing the polylines below that, but I suspect the symbols are not put on that specific layer. I can't even set a specific layer in the addSymbol function of MapboxController.

Please advise. Btw all the examples I found online so far just draw the lines over the symbols. Drawing the lines first and then the symbols doesn't work.


Solution

  • I figured out how to put symbols in layers. Also, I was using [lat, lon] while it should have been [lon, lat]..

    As long as you add the symbolLayer after the polyline layer the symbols will be drawn on top of the lines. Here is a working example (coordinates have been removed for privacy reasons but the working code is there):

    var geometry = {
      "coordinates": [
        [lon, lat],
        [lon, lat],
        [lon, lat],
        [lon, lat],
        [lon, lat],
        [lon, lat],
        [lon, lat]
      ],
      "type": "LineString"
    };
    
    _fills = {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          "id": 0,
          "properties": <String, dynamic>{},
          "geometry": geometry,
        },
      ],
    };
    
    await _mbController!.removeLayer("lines");
    await _mbController!.removeSource("fills");
    
    await _mbController!
        .addSource("fills", GeojsonSourceProperties(data: _fills));
    await _mbController!.addLineLayer(
      "fills",
      "lines",
      const LineLayerProperties(
        lineColor: '#007AFF',
        lineCap: "round",
        lineJoin: "round",
        lineWidth: 4,
      ),
    );
    
    await _mbController!.addSymbolLayer(
      "scooter25_layer",
      "vehicles",
      const SymbolLayerProperties(
        iconImage: "scooter25",
        iconAllowOverlap: true,
      ),
    );
    
    const Map<String, dynamic> featureCollection = {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [lon, lat],
          }
        }
      ]
    };
    
    await _mbController!.addGeoJsonSource("scooter25_layer", featureCollection);