rorystephenson / flutter_map_marker_popup

Popups for flutter_map markers
BSD 3-Clause "New" or "Revised" License
103 stars 84 forks source link

min/max zoom #11

Closed berkayoruc closed 3 years ago

berkayoruc commented 3 years ago

Is there any implementation of min/max zoom for PopupMarkerLayerOptions? For massive data, this option should be good.

I want to use popup and cluster in same time.

berkayoruc commented 3 years ago

I don't know is it true way, but I coded something and work in your package;

Firstly, added minZoom option to popup_marker_layer_options.dart

class PopupMarkerLayerOptions extends LayerOptions {
  final List<Marker> markers;
  final PopupBuilder popupBuilder;
  final PopupController popupController;
  final PopupSnap popupSnap;
  final int minZoom;

  /// Show the list of markers on the map with a popup that is shown when a
  /// marker is tapped or via the popupController.
  ///
  /// popupSnap:       To which edge of the marker the popup should snap to.
  /// popupBuilder:    A function that builds the popup for the given context
  ///                  and for the given Marker.
  /// popupController: Optional. Provide a PopupController instance to control
  ///                  popup functionality programmatically.
  PopupMarkerLayerOptions({
    this.minZoom = 0,
    this.markers = const [],
    this.popupSnap = PopupSnap.top,
    @required this.popupBuilder,
    popupController,
    rebuild,
  })  : this.popupController = popupController ?? PopupController(),
        super(rebuild: rebuild);
}

After that, I added if condition in widget build to popup_marker_layer.dart

@override
  Widget build(BuildContext context) {
    if (map.zoom >= layerOpts.minZoom) {
      return StreamBuilder<int>(
        stream: stream, // a Stream<int> or null
        builder: (BuildContext _, AsyncSnapshot<int> __) {
          var markers = <Widget>[];

          for (var markerOpt in layerOpts.markers) {
            var pos = map.project(markerOpt.point);
            pos = pos.multiplyBy(map.getZoomScale(map.zoom, map.zoom)) -
                map.getPixelOrigin();

            var pixelPosX =
                (pos.x - (markerOpt.width - markerOpt.anchor.left)).toDouble();
            var pixelPosY =
                (pos.y - (markerOpt.height - markerOpt.anchor.top)).toDouble();

            if (!_boundsContainsMarker(markerOpt)) {
              continue;
            }

            var bottomPos = map.pixelBounds.max;
            bottomPos =
                bottomPos.multiplyBy(map.getZoomScale(map.zoom, map.zoom)) -
                    map.getPixelOrigin();

            markers.add(
              Positioned(
                width: markerOpt.width,
                height: markerOpt.height,
                left: pixelPosX,
                top: pixelPosY,
                child: GestureDetector(
                  onTap: () => layerOpts.popupController.togglePopup(markerOpt),
                  child: markerOpt.builder(context),
                ),
              ),
            );
          }

          markers.add(
            MarkerPopup(
              mapState: map,
              popupController: layerOpts.popupController,
              snap: layerOpts.popupSnap,
              popupBuilder: layerOpts.popupBuilder,
            ),
          );

          return Container(
            child: Stack(
              children: markers,
            ),
          );
        },
      );
    } else {
      return Container();
    }
  }
Swepilot commented 3 years ago

So with your solution @berkayoruc at a lower zoom one would see the layer with clustered markers and at higher than minZoom one would see the MarkerPopupLayer. I'm I understanding this correctly? That is a feature I would like to use too as my map can get thousands of markers displayed and that's not really working at the moment due to performance lagging issues...

rorystephenson commented 3 years ago

Sorry for the slow response @berkayoruc and @Swepilot !

Have you tried this plugin: https://github.com/lpongetti/flutter_map_marker_cluster

I use it for clustering and I contributed to that plugin to integrate the popup functionality (it actually uses the code in this repository) so you can use both together.

Is that what you're looking for?

rorystephenson commented 3 years ago

I'm closing this now but please feel free to comment and @ tag me if my answer is not satisfactory.