1

I'm working on a Flutter application that utilizes Mapbox Maps, and I'm facing challenges in displaying feature IDs when users click on specific map layers. So basically, i have a Mapbox map in my Flutter app, where I've loaded GeoJSON data with various features and assigned different layers based on their status using mapbox_maps_flutter: ^0.5.1,

This is how it looks currently

When a user clicks on a feature within a specific layer (those grids), I want to display its feature ID in a popup, Snackbar, or any other user-friendly way. As there is no clear documentation or instruction about how click or tap event works, i'm unable to fulfill my requirements

/*view page code */
SizedBox(
  height: Get.height,
  child: Obx(() => MapWidget(
        key: const ValueKey("mapWidget"),
        onMapCreated: controller.onMapCreated,
        cameraOptions: CameraOptions(
            center: Point(
                    coordinates:
                        Position(-107.882000467, 47.616100673))
                .toJson(),
            zoom: controller.zoom.value),
        resourceOptions: ResourceOptions(
          accessToken: "<MAPBOX ACCESSS TOKEN>",
        ),
      )),
)
/* view page code */

/* controller page code */
Rx<MapboxMap?> mapboxMap = Rx<MapboxMap?>(null);

Future<void> onMapCreated(MapboxMap mapboxMap) async {
    this.mapboxMap.value = mapboxMap;

    // Load GeoJSON data
    var data = await rootBundle.loadString('assets/geo.geojson');
    var geoJson = json.decode(data);
    var geoJsonFeatures = geoJson['features'];

    // Create a Map to store colors based on status
    Map<int, Color> statusColors = {
      1: Color.fromARGB(128, 247, 247, 0), // 50% opacity
      2: Color.fromARGB(128, 24, 225, 31), // 50% opacity
      3: Color.fromARGB(128, 13, 104, 185), // 50% opacity
      4: const Color.fromARGB(0, 229, 210, 210), // Custom color for status 4
    };

    // Filter GeoJSON features based on status and create separate sources
    for (var status in statusColors.keys) {
      var filteredFeatures = geoJsonFeatures
          .where((feature) =>
              feature['properties'] != null &&
              feature['properties']['status'] == status)
          .toList();

      var filteredGeoJson = {
        'type': 'FeatureCollection',
        'features': filteredFeatures,
      };

      await mapboxMap.style.addSource(GeoJsonSource(
        id: 'fill_source_$status',
        data: json.encode(filteredGeoJson), // Ensure GeoJSON is a string
      ));

      await mapboxMap.style.addLayer(FillLayer(
        id: 'fill_layer_$status',
        sourceId: 'fill_source_$status',
        fillColor: statusColors[status]?.value ?? Colors.transparent.value,
        fillOutlineColor: Colors.black.value,
        fillOpacity: .5,
      ));
    }
  }
/* controller page code*/

This is my sample geojson data,

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -107.900000467,
              47.598100673
            ],
            [
              -107.891000467,
              47.598100673
            ],
            [
              -107.891000467,
              47.589100673
            ],
            [
              -107.900000467,
              47.589100673
            ],
            [
              -107.900000467,
              47.598100673
            ]
          ]
        ]
      },
      "properties": {
        "dbId": "5",
        "status": 4,
        "uid": null,
        "isBlocked": 0,
        "id": "5",
        "left": -107.900000467,
        "top": 47.598100673,
        "right": -107.891000467,
        "bottom": 47.589100673
      }
    },...    
  ]
}

I've reviewed the Mapbox Maps documentation, but I couldn't find a clear example for achieving this specific functionality. Any assistance or code snippets would be highly appreciated. Thank you!

1 Answer 1

1

Since their documentation only lists a small number of ingredients (mapbox_maps_flutter: ~0.5.1), I used a different package, mapbox_gl: ~0.16.0, to meet my needs.

/* view code */
MapboxMap(
    onMapCreated: controller.onMapCreated,
    zoomGesturesEnabled: true,
    accessToken:"<MAPBOX ACCESS TOKEN>",
    initialCameraPosition: const CameraPosition(
        target: LatLng(47.60498923803516, -107.06846142289754),
        zoom: 12),
)
/* view code */
* controller code */
void onMapCreated(MapboxMapController mapboxMap) async {
    // await getJson();

    //Create a Map to store colors based on status
    Map<int, String> statusColors = {
      1: convertColorToRgba(const Color.fromARGB(128, 221, 143, 137), 1),
      2: convertColorToRgba(const Color.fromARGB(128, 68, 235, 73), 1),
      3: convertColorToRgba(const Color.fromARGB(128, 14, 125, 215), 1),
      4: 'rgba(0, 0, 255, 0.0)', // Transparent color for status 4
    };

   //Add the GeoJSON source to the map
    await mapboxMap.addSource("fills", GeojsonSourceProperties(data: geojson));

   //Add the fill layer with the specified color and filter
    await mapboxMap.addFillLayer(
      "fills",
      "fills",
      FillLayerProperties(
        fillColor: [
          "step", ["get", "status"],
          statusColors[1], 1,
          statusColors[2], 2,
          statusColors[3], 3,
          statusColors[4], 4,
          'rgba(0, 0, 255, 0.0)' // Default color
        ],
        fillOpacity: 0.4,
        fillOutlineColor: 'rgba(0, 0, 0, 1)',
      ),
      filter: [
        "has",
        "status"
      ], // Add filter to only render features with a "status" property
      enableInteraction: true,
    );
    
    update();
  }
* controller code */

This code works fine; additionally, this package has some dedicated functions to achieve a specific functionality, such as onFeatureTap, and they have a sufficient community resource, for example. For any further reference, you can check out this GitHub document: https://github.com/flutter-mapbox-gl/maps/tree/b2bfef669e42397704b6f43d55b5df67b18c0fa8/example/lib

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.