我在应用程序中使用谷歌地图,很可能多个标记附加到每个标记代表一个人的同一位置。在这种情况下,用户将不知道该特定标记后面还有其他标记/人。
我环顾四周以处理这种情况,关于 SO 的一个问题表明我可以显示一个标记并将所有人与该单个标记相关联。当用户点击该标记时,我应该显示与该标记关联的所有用户的列表。这是一个很好的解决方法,但我想避免显示主要隐藏 Google 地图的视图。
有没有人在类似情况下使用过任何解决方法?
我在应用程序中使用谷歌地图,很可能多个标记附加到每个标记代表一个人的同一位置。在这种情况下,用户将不知道该特定标记后面还有其他标记/人。
我环顾四周以处理这种情况,关于 SO 的一个问题表明我可以显示一个标记并将所有人与该单个标记相关联。当用户点击该标记时,我应该显示与该标记关联的所有用户的列表。这是一个很好的解决方法,但我想避免显示主要隐藏 Google 地图的视图。
有没有人在类似情况下使用过任何解决方法?
我使用的解决方法是在地图上显示具有相同位置的标记,以便用户稍微了解多个标记。
我跟踪地图上的标记及其在地图上的位置,每当我想在地图上添加标记时,我确保没有其他标记显示在同一位置。如果是,那么我将偏移量添加到要添加的新标记的位置。
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。
也许你应该看看标记聚类。这是在同一个地方显示大量标记的常见解决方案。关于它的谷歌文章:https ://developers.google.com/maps/articles/toomanymarkers
也有现有的库可以做到这一点,例如:
您可以处理(单个)标记的单击事件,并使用它来更新位于 Google 地图画布之外的元素,其中包含有关该标记处人员的详细信息。
当用户放大到最大时,给予偏移将使标记远离。所以我找到了实现这一目标的方法。这可能不是正确的方法,但效果很好。
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 将标记置于顶部。
受极客回答的启发,我创建了一个函数。此函数返回一个新的经纬度对,靠近原始值,几乎以圆形方式。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;
}
我真的很喜欢接受的答案,但我相信它使用了很多代码。这是 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);