Mapbox как растворить кластер по щелчку мыши

#ios #xcode #map #mapbox #markerclusterer

#iOS #xcode #словарь #mapbox #markerclusterer

Вопрос:

Я использую Mapbox sdk в своем проекте. https://www.mapbox.com/mapbox-ios-sdk /

У меня работает базовая кластеризация, но мой вопрос в том, как мне дальше растворять кластер по щелчку мыши.

например. У меня есть кластер с 8 маркерами. По щелчку он должен увеличивать масштаб не только на один уровень, но и до точки, где все 8 маркеров отображаются на экране с максимально возможным увеличением.(некоторые маркеры из этих 8 могут быть сгруппированы)

Я попробовал [масштабирование карты с широтой и длиной юго-запада: CLLocationCoordinate2DMake (юг, запад) Северо-восток: CLLocationCoordinate2DMake (север, восток) анимированный: ДА]; но безуспешно.

Ответ №1:

Вот как это получилось:

 - (void)tapOnAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map {

    if (annotation.isClusterAnnotation) {

        CLLocationCoordinate2D southwestCoordinate = annotation.coordinate;
        CLLocationCoordinate2D northeastCoordinate = annotation.coordinate;

        for (RMAnnotation *plot in annotation.clusteredAnnotations) {

            CGFloat latititude = plot.coordinate.latitude;
            CGFloat longitude = plot.coordinate.longitude;

            if (southwestCoordinate.latitude > fabsf(latititude)) southwestCoordinate.latitude = latititude;
            if (southwestCoordinate.longitude > fabsf(longitude)) southwestCoordinate.longitude = longitude;

            if (northeastCoordinate.latitude < fabsf(latititude)) northeastCoordinate.latitude = latititude;
            if (northeastCoordinate.longitude < fabsf(longitude)) northeastCoordinate.longitude = longitude;

        }

        [self.mapView zoomWithLatitudeLongitudeBoundsSouthWest:southwestCoordinate northEast:northeastCoordinate animated:YES];

   }
}
  

По сути, здесь происходит то, что я сохраняю ограничивающие координаты самой удаленной области southwestCoordinate и northeastCoordinate аннотацию к ней (в данном случае, кластер). Затем для каждой аннотации внутри кластера мы проверяем, является ли абсолютное расстояние от этой «центральной» координаты наибольшим в группе.

Кажется, для меня это работает довольно хорошо.

Комментарии:

1. Я начал с аналогичного подхода, но я считаю, что мой ответ является улучшением по сравнению с этим.

Ответ №2:

Следующий фрагмент будет лучше масштабировать точки вашего кластера, расширяясь до уровня, на котором некоторые или все точки не кластеризованы:

     // 1. Start with a maximum (world-wide) bounding box
    CLLocationCoordinate2D topRight = CLLocationCoordinate2DMake(180, -90);
    CLLocationCoordinate2D bottomLeft = CLLocationCoordinate2DMake(-180, 90);

    // 2. Derive the minimum bounding box coordinates that contains all cluster points, by "squeezing in" on their coordinates
    for (RMAnnotation *a in annotation.clusteredAnnotations) {

        if (a.coordinate.latitude < topRight.latitude) {
            topRight.latitude = a.coordinate.latitude;
        }
        if (a.coordinate.longitude > topRight.longitude) {
            topRight.longitude = a.coordinate.longitude;
        }

        if (a.coordinate.latitude > bottomLeft.latitude) {
            bottomLeft.latitude = a.coordinate.latitude;
        }
        if (a.coordinate.longitude < bottomLeft.longitude) {
            bottomLeft.longitude = a.coordinate.longitude;
        }
    }

    CLLocation *sw = [[CLLocation alloc] initWithLatitude:topRight.latitude longitude:topRight.longitude];
    CLLocation *ne = [[CLLocation alloc] initWithLatitude:bottomLeft.latitude longitude:bottomLeft.longitude];

    // 3. Calculate the distance in meters across the calculated bounding box
    CLLocationDistance distanceInMeters = [ne distanceFromLocation:sw];
    // 4. Adjust the map view's meters per pixel setting so that the bounding box fits nicely within the map views bounds (which is equivalent to zooming)
    [self.mapView setMetersPerPixel:(distanceInMeters / (self.mapView.frame.size.width * 0.7)) animated:YES];
    // 5. Center on the midpoint of the bounding box
    [self.mapView setCenterCoordinate:[self midPointBetween:topRight and:bottomLeft] animated:YES];
  

Ответ №3:

GoogleMaps

Используется: https://github.com/googlemaps/google-maps-ios-utils для кластеризации

«Кластер без кластера»: D

Swift 3

 if let cluster = marker.userData as? GMUCluster {
let boxConstant = 0.01
    var southwestCoordinate = cluster.position
    var northeastCoordinate = cluster.position

    for clusterItem in cluster.items {

      let latitude = clusterItem.position.latitude
      let longitude = clusterItem.position.longitude

      if southwestCoordinate.latitude > latitude {
        southwestCoordinate.latitude = latitude
      }
      if southwestCoordinate.longitude > longitude {
        southwestCoordinate.longitude = longitude
      }
      if northeastCoordinate.latitude < latitude {
        northeastCoordinate.latitude = latitude
      }
      if northeastCoordinate.longitude < longitude {
        northeastCoordinate.longitude = longitude
      }

    }

    // Create Box
    southwestCoordinate.longitude  = boxConstant
    southwestCoordinate.latitude -= boxConstant
    northeastCoordinate.longitude -= boxConstant
    northeastCoordinate.latitude  = boxConstant
    let bounds = GMSCoordinateBounds(coordinate: southwestCoordinate, coordinate: northeastCoordinate)
    self.mapView.moveCamera(GMSCameraUpdate.fit(bounds))
}
  

Ответ №4:

я бы добавил это в качестве комментария к метатеорическому ответу, но у меня недостаточно репутации.

Я думаю, что с этим fasbf он плохо вычисляет отрицательные координаты и работает лучше без него. Я прав?

 - (void)tapOnAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map {
    if (annotation.isClusterAnnotation) {

        CLLocationCoordinate2D southwestCoordinate = annotation.coordinate;
        CLLocationCoordinate2D northeastCoordinate = annotation.coordinate;

        for (RMAnnotation *plot in annotation.clusteredAnnotations) {

            CGFloat latitude = plot.coordinate.latitude;
            CGFloat longitude = plot.coordinate.longitude;

            if (southwestCoordinate.latitude > latitude) southwestCoordinate.latitude = latitude;
            if (southwestCoordinate.longitude > longitude) southwestCoordinate.longitude = longitude;

            if (northeastCoordinate.latitude < latitude) northeastCoordinate.latitude = latitude;
            if (northeastCoordinate.longitude < longitude) northeastCoordinate.longitude = longitude;

        }

        [map zoomWithLatitudeLongitudeBoundsSouthWest:southwestCoordinate northEast:northeastCoordinate animated:YES];    
    }
}