maplibre / flutter-maplibre-gl

Customizable, performant and vendor-free vector and raster maps, flutter wrapper for maplibre-native and maplibre-gl-js (fork of flutter-mapbox-gl/maps)
https://pub.dev/packages/maplibre_gl
Other
228 stars 125 forks source link

[BUG] onMapClick not fired when tapping SymbolLayer #506

Open nijs9 opened 2 months ago

nijs9 commented 2 months ago

Platforms

Android en iOS

Version of flutter maplibre_gl

0.20

Bug Description

I am adding a vector source to the map. After that, I add a SymbolLayer. Then, in the onMapClick event, I use the queryRenderedFeaturesInRect function to query all features that I click on. This function works fine when I click on the base map, but when I click on a symbol from my self-added vector layer, the onMapClick event is not triggered. When I retrieve the style IDs for the current style, it’s clear that my own SymbolLayer has been correctly added and exists.

Steps to Reproduce

  1. Add a vector source.
  2. Add a symbol layer based on this vector source.
  3. Implement queryRenderedFeaturesInRect in onMapClick.
  4. Click on map.
  5. When clicking outside the self added layer, onMapClick is fired.
  6. When clicking on a feature of the custom vector source, onMapClick is not fired.

Expected Results

Getting my own added features after onMapClick and queryRenderedFeaturesInRect.

Actual Results

Only features from basemap are triggering onMapClick. When clicking on a feature of the custom vector source, onMapClick is not fired.

Code Sample

Adding vector source:

await mapController.addSource(
      'custom-nodes',
      VectorSourceProperties(
        tiles: [
          'https://xxxx.com/$flavor/nodes/{z}/{x}/{y}.pbf'
        ],
        maxzoom: 18,
      ),
    );

Add layer:

await mapController.addSymbolLayer(
        'custom-nodes',
        'custom-nodes-signed',
        SymbolLayerProperties(
          iconImage: 'node-image-signed',
          iconSize: [
            Expressions.interpolate,
            ["linear"],
            [Expressions.zoom],
            10,
            0.52,
            12,
            0.64,
            13,
            0.70,
            15,
            0.72
          ],
          textAllowOverlap: false,
          iconAllowOverlap: true,
          iconIgnorePlacement: true,
          textField: ['get', 'label'],
          textColor: RPColors.colorNodes,
          textOpacity: 1.0,
          textSize: [
            Expressions.interpolate,
            ["linear"],
            [Expressions.zoom],
            10,
            8,
            12,
            9,
            13,
            10,
            15,
            11
          ],
          textAnchor: 'center',
          textJustify: 'center',
          visibility: 'visible',
          textFont: ['Noto Sans Bold', 'Open Sans Bold'],
        ),
        sourceLayer: 'nodes_data_$flavor',
        minzoom: 11,
        filter: [
          'all',
          ['!=', 'label', 'SP'],
          ['!=', 'label', 'TP'],
          ['!=', 'onlylf', 1],
          ['==', 'signed', 1]
        ]);

onMapClick:

void _onMapClick(Point<double> point, LatLng coordinates) async {

    final features = await mapController.queryRenderedFeaturesInRect(
      Rect.fromCenter(
        center: Offset(point.x, point.y), 
        width: 50, 
        height: 50,
      ),
      [
        'custom-nodes-signed',
      ],
      null,
    );

    if (features.isNotEmpty) {
      for (final feature in features) {
        print("Feature found: ${feature.id}");
      }
    } else {
      print("No Features Found");
    }
  }
Samriddhi98 commented 1 month ago

I am facing a similar issue. I have simply added a marker using the .addSymbol() function to the map. When tapping on the added marker on the map I would like to obtain the information of the newly added marker, but the onMapClick callback isnt seem to be triggering. However, the onMapClick callback works when tapping on other areas of the base map.

My code implementation looks something like this:

Future<void> _addSymbol(LatLng latlng, String title) async {
    try {
      var symbol = SymbolOptions().zIndex;
      await mapController?.addSymbol(
        SymbolOptions(
          geometry: latlng,
          iconImage:
              'custom-marker', // Icon image from the Mapbox Style// Size of the icon
          iconColor: "#FF0000",
          textField: title,
          textSize: 12.5,
          textOffset: const Offset(0, 0.8),
          textAnchor: 'top',
          textColor: '#000000',
          textHaloBlur: 1,
          textHaloColor: '#ffffff',
          textHaloWidth: 0.8,
          iconSize: 3.0,
        ),
      );
      setState(() {});
    } catch (e) {
      log(' errro while adding symbol ${e.toString()}');
    }
  } 
@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _mapStyle == null
          ? const Center(child: CircularProgressIndicator())
          : MapLibreMap(
                  styleString: _mapStyle!,
                  onMapCreated: _onMapCreated,
                  onStyleLoadedCallback: _onStyleLoadedCallback,
                  initialCameraPosition: _kInitialPosition,
                  cameraTargetBounds: _cameraTargetBounds,
                  trackCameraPosition: true,
                  scrollGesturesEnabled: true,
                  zoomGesturesEnabled: true, 
                  rotateGesturesEnabled: false, 
                  tiltGesturesEnabled: false,
                  annotationOrder: const [
                    AnnotationType.symbol,
                    AnnotationType.line,
                    AnnotationType.circle,
                    AnnotationType.fill,
                  ],
                  onMapClick: (points, latlong) async {
                    log("Map click: ${points.x},${points.y}   ${latlong.latitude}/${latlong.longitude}");
                    var list = await mapController?.queryRenderedFeatures(
                        points, [...layerIds, 'custom-symbol-layer'], null);
                    log('on map click function return $list');
                  },
                ),
      floatingActionButton:   FloatingActionButton(
            heroTag: 'btn2',
            onPressed: () {
              _addSymbol(const LatLng(27.7103, 85.3222),
                  'KTM'); // Add symbol in San Francisco
            },
            child: Icon(Icons.add_location),
          ),
    );
  }

Is there some other way of doing this? or what am I doing wrong?