【问题标题】:How to handle multiple markers on Google Maps with same location?如何处理谷歌地图上具有相同位置的多个标记?
【发布时间】:2013-11-11 07:37:20
【问题描述】:

我在一个应用程序中使用 Google 地图,很可能多个标记附加到同一位置,每个标记代表一个人。在这种情况下,用户不会知道这个特定标记后面还有其他标记/人。

我环顾四周以处理这种情况,关于 SO 的一个问题表明我可以显示一个标记并将所有人与该单个标记相关联。当用户点击该标记时,我应该显示与该标记关联的所有用户的列表。这是一个很好的解决方法,但我想避免显示大部分隐藏 Google 地图的视图。

有没有人在类似情况下使用过任何解决方法?

【问题讨论】:

  • 如果您不想显示列表视图,我不知道您要找什么,它真的是您唯一的选择
  • @tyczj 如果其他人正在使用其他解决方法,例如显示稍微向左/向右倾斜的标记图标以说明同一点上的多个标记,请寻找其他解决方法。或者其他人可能有的任何其他工作。
  • 嗨,我想显示列表视图或展开地图上相同位置的标记。有什么方法可以实现吗?我想这样实现:jawj.github.io/OverlappingMarkerSpiderfier/demo.html

标签: android ios objective-c google-maps google-maps-markers


【解决方案1】:

我使用的解决方法是在地图上显示相同位置的标记,以便用户稍微了解多个标记。

我会跟踪地图上的标记及其在地图上的位置,每当我想在地图上添加标记时,我都会确保没有其他标记显示在同一位置。如果是,那么我在要添加的新标记的位置添加一个偏移量。

static final float COORDINATE_OFFSET = 0.00002f; // You can change this value according to your need

以下方法返回必须用于新标记的位置。此方法将新标记的当前纬度和经度作为参数。

// Check if any marker is displayed on given coordinate. If yes then decide
// another appropriate coordinate to display this marker. It returns an
// array with latitude(at index 0) and longitude(at index 1).
private String[] coordinateForMarker(float latitude, float longitude) {

    String[] location = new String[2];

    for (int i = 0; i <= MAX_NUMBER_OF_MARKERS; i++) {

        if (mapAlreadyHasMarkerForLocation((latitude + i
                * COORDINATE_OFFSET)
                + "," + (longitude + i * COORDINATE_OFFSET))) {

            // If i = 0 then below if condition is same as upper one. Hence, no need to execute below if condition.
            if (i == 0)
                continue;

            if (mapAlreadyHasMarkerForLocation((latitude - i
                    * COORDINATE_OFFSET)
                    + "," + (longitude - i * COORDINATE_OFFSET))) {

                continue;

            } else {
                location[0] = latitude - (i * COORDINATE_OFFSET) + "";
                location[1] = longitude - (i * COORDINATE_OFFSET) + "";
                break;
            }

        } else {
            location[0] = latitude + (i * COORDINATE_OFFSET) + "";
            location[1] = longitude + (i * COORDINATE_OFFSET) + "";
            break;
        }
    }

    return location;
}

// Return whether marker with same location is already on map
private boolean mapAlreadyHasMarkerForLocation(String location) {
    return (markerLocation.containsValue(location));
}

在上面的代码中,markerLocation 是一个 HashMap。

HashMap<String, String> markerLocation;    // HashMap of marker identifier and its location as a string

此答案包含适用于 android 的代码,但同样的逻辑适用于 iOS。

【讨论】:

  • MAX_NUMBER_OF_MARKERS 是多少? lat lng 的总数?
  • 不错。但是您在哪里将项目添加到 markerLocation hashMap ?您在 coordinateForMarker() 方法中错过了这个变量
  • 我真的很喜欢这个答案,这就是我采用的解决方案。但我认为使用更少的代码也可以实现相同的目标,因此我发布了我的变体以防有人感兴趣。
【解决方案2】:

也许你应该看看标记聚类。这是在同一个地方显示大量标记的常见解决方案。 关于它的谷歌文章:https://developers.google.com/maps/articles/toomanymarkers

也有现有的库可以做到这一点,例如:

【讨论】:

  • 您提供的链接很有用,但在我的情况下,我将在地图上最多有 12 个标记。我的问题是如果他们有same exact 位置怎么办。
【解决方案3】:

您可以处理(单个)标记的点击事件,并使用它来更新位于 Google 地图画布之外的元素,其中包含该标记处人员的详细信息。

【讨论】:

【解决方案4】:

当用户放大到最大时,给予偏移将使标记远离。所以我找到了实现这一目标的方法。这可能不是正确的方法,但效果很好。

for loop markers
{
 //create marker
 let mapMarker = GMSMarker()
 mapMarker.groundAnchor = CGPosition(0.5, 0.5)
 mapMarker.position = //set the CLLocation
 //instead of setting marker.icon set the iconView
 let image:UIIMage = UIIMage:init(named:"filename")
 let imageView:UIImageView = UIImageView.init(frame:rect(0,0, ((image.width/2 * markerIndex) + image.width), image.height))
 imageView.contentMode = .Right
 imageView.image = image
 mapMarker.iconView = imageView
 mapMarker.map = mapView
}

设置标记的 zIndex 以便您可以在顶部看到您想要看到的标记图标,否则它将像自动交换一样为标记设置动画。 当用户点击标记时,处理 zIndex 以使用 zIndex Swap 将标记置于顶部。

【讨论】:

    【解决方案5】:

    受极客answer 的启发,我创建了一个函数。此函数返回一个新的经纬度对,靠近原始值,几乎以圆形方式。 COORINDATE_OFFSET 可根据需要进行调整。

    private static final float COORDINATE_OFFSET = 0.000085f;
    private ArrayList<LatLng> markerCoordinates = new ArrayList<>();
    private int offsetType = 0;
    
    private LatLng getLatLng(LatLng latLng) {
    
        LatLng updatedLatLng;
    
        if (markerCoordinates.contains(latLng)) {
            double latitude = 0;
            double longitude = 0;
            if (offsetType == 0) {
                latitude = latLng.latitude + COORDINATE_OFFSET;
                longitude = latLng.longitude;
            } else if (offsetType == 1) {
                latitude = latLng.latitude - COORDINATE_OFFSET;
                longitude = latLng.longitude;
            } else if (offsetType == 2) {
                latitude = latLng.latitude;
                longitude = latLng.longitude + COORDINATE_OFFSET;
            } else if (offsetType == 3) {
                latitude = latLng.latitude;
                longitude = latLng.longitude - COORDINATE_OFFSET;
            } else if (offsetType == 4) {
                latitude = latLng.latitude + COORDINATE_OFFSET;
                longitude = latLng.longitude + COORDINATE_OFFSET;
            }
            offsetType++;
            if (offsetType == 5) {
                offsetType = 0;
            }
    
    
            updatedLatLng = getLatLng(new LatLng(latitude, longitude));
    
        } else {
            markerCoordinates.add(latLng);
            updatedLatLng = latLng;
        }
        return updatedLatLng;
    }
    

    【讨论】:

      【解决方案6】:

      我真的很喜欢接受的答案,但我相信它使用了很多代码。这是 JavaScript 的一个变体,您可以在浏览器的控制台中尝试:

      var positions = Array([46,-2],[46,-2],[46,-2],[46.3,-2.1]);
      
      var used_locations = [];
      for (let position of positions) {
          while (used_locations.includes(position[0].toString() + position[1].toString())) {
              let lat = position[0];
              let lng = position[1] * 1.001;
              position = [lat, lng];
          }
          used_locations.push(position[0].toString() + position[1].toString());
          //add_marker(position);
      }
      
      console.log(used_locations);
      

      【讨论】:

        猜你喜欢
        • 2012-01-27
        • 1970-01-01
        • 1970-01-01
        • 2013-07-16
        • 1970-01-01
        • 2011-04-02
        • 1970-01-01
        • 2015-09-01
        相关资源
        最近更新 更多