web-dev-qa-db-ja.com

同じ場所にあるGoogleマップで複数のマーカーを処理するにはどうすればよいですか?

アプリでGoogleマップを使用していますが、各マーカーが1人を表す同じ場所に複数のマーカーが付けられている可能性があります。この状況では、ユーザーはこの特定のマーカーの後ろに他のマーカー/人物がいることを知りません。

私はこの状況に対処するために周りを見回し、SOに関する1つの質問は、単一のマーカーを表示してすべての人をその単一のマーカーに関連付けることができることを示唆しています。ユーザーがそのマーカーをタップすると、すべてのリストを表示する必要がありますそのマーカーに関連付けられているユーザー。これは適切な回避策ですが、Googleマップをほとんど非表示にするビューを表示しないようにします。

誰かが同様の状況で回避策を使用しましたか?

19
Geek

私が使用した回避策は、ユーザーが複数のマーカーについてわずかに理解できるように、同じ位置にマーカーを少し離れて地図上に表示することです。

私はマップ上のマーカーとマップ上のそれらの位置を追跡し、マップ上にマーカーを追加したいときはいつでも、他のマーカーが同じ位置に表示されないことを確認します。はいの場合、追加する新しいマーカーの位置にオフセットを追加します。

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でも同じロジックが適用されます。

17
Geek

多分あなたはマーカーのクラスタリングを見てみるべきです。同じ場所に多くのマーカーを表示するための一般的なソリューションです。それに関するGoogleの記事: https://developers.google.com/maps/articles/toomanymarkers

これを行うための既存のライブラリもあります。例:

1
hunyadym

オタクの 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;
}

オフセットを与えると、ユーザーが最大にズームインしたときにマーカーが遠くなります。だから私はそれを達成する方法を見つけました。これは適切な方法ではないかもしれませんが、非常にうまくいきました。

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 Swapを使用してzIndexハンドルを上に移動してマーカーを配置します。

0
Satheesh G

(単一の)マーカーのクリックイベントを処理し、それを使用して、Google Mapキャンバスの外側にある要素を、そのマーカーにいる人の詳細で更新します。

0
Tim Ebenezer