Open chooyan-eng opened 1 month ago
What do you use a style layer with symbols for?
Atm i can only think of a PointAnnotation that can do this.
Future<PointAnnotationManager> createPointManager(
MapboxMap controller, {
required void Function(PointAnnotation) callback,
}) async {
final pointManager = await controller.annotations.createPointAnnotationManager();
pointManager.addOnPointAnnotationClickListener(
AnnotationClickListener(callback: callback),
);
return pointManager;
}
@ThomasAunvik Thanks for your suggestion!
However, its document says this API is not capable of displaying large amount of annotations.
Use style layers. This will require writing more code but is more flexible and provides better performance for the large amount of annotations (e.g. hundreds and thousands of them)
And my app needs to display hundreds of thousands of symbols at the same time. That's why I'd like to know the usage of layer in detail.
You can set the GeoJsonSource data with FeatureCollection and set id for point , then listen map click event and use queryRenderedFeatures function to filter id that is point where you want
@lantah-1 Thanks! I haven't tried queryRenderedFeatures
. I'll try.
This code implements interactive layer tapping:
class _MapScreenState extends State<MapScreen> {
final position = Position.named(lng: 24.9458, lat: 60.17180);
MapboxMap? _mapboxMap;
@override
Widget build(BuildContext context) {
return Scaffold(
body: MapWidget(
cameraOptions: CameraOptions(zoom: 3.0),
styleUri: '[my_style_uri]',
textureView: true,
onMapCreated: (map) => _mapboxMap = map,
onStyleLoadedListener: _onStyleLoadedCallback,
onMapTap: _onMapTap,
),
);
}
Future<void> _onStyleLoadedCallback(StyleLoadedEventData event) async {
final point = Point(coordinates: position);
final features = [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [point.coordinates.lng, point.coordinates.lat],
},
"properties": {
'id': 'test-123',
'anyDataKey': jsonEncode({}) //CUSTOM DATA,
},
},
];
await _mapboxMap?.style.addSource(
GeoJsonSource(
id: 'sourceId',
data: json.encode({"type": "FeatureCollection", "features": features}),
),
);
var modelLayer = SymbolLayer(
id: 'layerId',
sourceId: 'sourceId',
iconImage: '[my_icon_name]',
);
_mapboxMap?.style.addLayer(modelLayer);
}
Future<void> _onMapTap(
MapContentGestureContext mapContentGestureContext,
) async {
if (_mapboxMap == null) return;
final List<QueriedRenderedFeature?> features = await _mapboxMap!.queryRenderedFeatures(
RenderedQueryGeometry.fromScreenCoordinate(mapContentGestureContext.touchPosition),
RenderedQueryOptions(
layerIds: [
///LAYERS IDS YOU WANT TO LISTEN ...[]
'layerId'
],
),
);
final queriedRenderedFeature = features.firstOrNull;
if (queriedRenderedFeature == null || !mounted) return;
_onFeatureTapped(queriedRenderedFeature);
}
void _onFeatureTapped(
QueriedRenderedFeature queriedRenderedFeature,
) {
Point? point;
Map? geometry = queriedRenderedFeature.queriedFeature.feature["geometry"] as Map?;
if (geometry != null && _mapboxMap != null) {
final lon = geometry["coordinates"][0];
final lat = geometry["coordinates"][1];
///YOU CAN EASE TO
///THE POINT CAMERA POSITION
//fitCameraToPosition(lat: lat, lon: lon);
point = Point(coordinates: Position(lon, lat));
}
///GET THE SOURCE PROPERITIES WHERE DEFINED Ids
///OR CUSTOM DATA YOU SET.
final properties = queriedRenderedFeature.queriedFeature.feature["properties"] as Map?;
final id = properties?['id'] as String?;
if (id == null) return;
if (id.startsWith('test-')) {
///CALLBACK CLICK
///YOU HAVE [POINT GEMOETRY,PROPERITIES OF THE POINT],
/// final anyData = jsonDecode(properties?['anyDataKey'] ?? '{}');
}
}
}
How can we tap symbols added with
SymbolLayer
?I have the source code below to show a symbol, but can't find how to make this tappable.
This shows one icon on my map, but that's it.
Do we have any examples or docs for this? Thanks.