I'm building a simple Flutter application using the mapbox_gl: ^0.16.0 plugin. 1: https://i.sstatic.net/vh4Mp.png So basically i have a GeoJSON data, which i need to add in rendered map as source and apply a Fill Layer based on source (GeoJSON) property. Currently feature with fill layer is showing properly, but when try to get the feature or any feature details when user click on feature layer,it shows the "id" blank.
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
Here is my code snippets,
/* view code */
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
import '../controllers/home_controller.dart';
class HomeView extends GetView<HomeController> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: SizedBox(
height: Get.height,
child: MapboxMap(
onMapCreated: (mapcontroller) {
controller.onMapCreated(mapcontroller);
},
zoomGesturesEnabled: true,
accessToken:
"<MAPBOX ACCESS TOKEN>",
initialCameraPosition: const CameraPosition(
target: LatLng(47.616100673, -107.882000467), zoom: 10),
),
),
),
);
}
}
/* view code */
/* controller code */
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:get/get.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
class HomeController extends GetxController {
String geojsonString = "";
// Create a Map to store colors based on status
Map<int, Color> statusColors = {
1: const Color.fromARGB(128, 221, 143, 137), // 50% opacity
2: const Color.fromARGB(128, 68, 235, 73), // 50% opacity
3: const Color.fromARGB(128, 14, 125, 215), // 50% opacity
4: Colors.transparent, // Custom color for status 4
};
@override
void onInit() {
super.onInit();
}
@override
void onReady() {
super.onReady();
}
@override
void onClose() {}
Future<void> loadGeoJSON() async {
geojsonString = await rootBundle.loadString('assets/geo.geojson');
}
void onMapCreated(MapboxMapController mapboxMap) async {
// Create a Map to store colors based on status
Map<int, Color> statusColors = {
1: const Color.fromARGB(128, 221, 143, 137), // 50% opacity
2: const Color.fromARGB(128, 68, 235, 73), // 50% opacity
3: const Color.fromARGB(128, 14, 125, 215), // 50% opacity
4: Colors.transparent, // Custom 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",
const FillLayerProperties(
fillColor: 'rgba(0, 0, 255, 0.4)', // Use a valid color string
fillOpacity: 0.4,
),
filter: [
'==',
['get', 'status'],
1 // Note: Removed quotes around 1 to compare with a number
],
);
mapboxMap.onFeatureTapped.add((id, point, coordinates) {
// Check if the tapped feature is part of the "fills" layer
if (id != null && id is String && id.startsWith('fills')) {
// Extract the original feature ID
String originalFeatureId = id.replaceAll('fills.', '');
print(
'Tapped feature with original ID - $originalFeatureId, Point - $point, Coordinates - $coordinates');
}
});
}
}
/* controller code*/
/* sample GeoJSON */
{
"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
}
},...
]
}
/* sample GeoJSON code */
This block of code works fine for me!
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();
}