LoginSignup
2
1

More than 3 years have passed since last update.

Google Maps iOS Utils でマーカーをまとめて表示する

Last updated at Posted at 2020-03-01

Google Maps SDK を使用していてマップ上にマーカーを立てることはよくあると思います
ただ、マップ上にマーカーをたてすぎると、広域表示にした際にマーカーが密集しちゃって見辛くなってしまうってこともよくあると思います

そんな時マーカーを1つにまとめたいなーと思ったので、その実装方法を残しておきたいと追います

GrWyuKwR.gif

開発環境

Xcode:11.1(11A1027)
Swift 5
iOS:13.1
CocoaPods: 1.8.0

実装

ライブラリのインストール

Google Maps iOS Utils をインストールするために CocoaPods を使用します
以下のように Podfile を編集し、 pod install を実行してください

target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
  use_frameworks!

  pod 'GoogleMaps'
  pod 'Google-Maps-iOS-Utils'
end

こちらのセットアップガイドにも記載されていますが、
CocoaPods のバージョンが 1.8.1 以上はサポート対象外のようです

1.6.1 が推奨されているようですが、Xcode11 では 1.6.1 を使用した場合にビルドが通らなかったため、今回は 1.8.0 を使用しています

CocoaPods のバージョンを下げるにはこちらを参考にしてください

マーカーをまとめて表示する用の class を作成

普段は GMSMarker class を使用してマーカーを表示していますが、
マーカーをまとめて表示するには GMUClusterItem protocol に準拠した class を作成し、その class を使用してマーカーを表示する必要があります

import GoogleMapsUtils

class POIItem: NSObject, GMUClusterItem {

    var position: CLLocationCoordinate2D

    init(position: CLLocationCoordinate2D) {
        self.position = position
    }
}

Map 上にマーカーを配置

先ほど作成した独自 class POIItem を使用してマーカーを Google Map 上に表示していきます

import UIKit
import GoogleMaps
import GoogleMapsUtils

class ViewController: UIViewController {

  // デフォルトの位置情報(仮で東京駅付近にしています)
    let defaultPositionLat = 35.681223
    let defaultPositionLng = 139.767059
    private var mapView: GMSMapView!
    /// Map 上に表示するマーカーを管理するためのプロパティ
    private var clusterManager: GMUClusterManager!

    override func viewDidLoad() {
        super.viewDidLoad()

        // GoogleMapの初期位置
        let camera = GMSCameraPosition.camera(withLatitude: defaultPositionLat, longitude: defaultPositionLng, zoom: 17.0)
        mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
        view = mapView

        let iconGenerator = GMUDefaultClusterIconGenerator()
        let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
        let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
        clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)

        // マーカーをランダムに生成して Map 上に表示
        generateClusterItems()
    }

    private func generateClusterItems() {
        let extent = 0.01
        for _ in 1...100 {
            let lat = defaultPositionLat + extent * randomScale()
            let lng = defaultPositionLng + extent * randomScale()
            let item = POIItem(position: CLLocationCoordinate2DMake(lat, lng))
            clusterManager.add(item)
        }
        // Map にマーカーを描画
        clusterManager.cluster()
    }

    /// ランダムな位置にマーカーを表示するための乱数を生成
    private func randomScale() -> Double {
        return Double(arc4random()) / Double(UINT32_MAX) * 2.0 - 1.0
    }
}

上記のコードを実行すると、最初に載せた gif のような挙動になるかと思います

Delegate とか

マーカーをタップした際のアクションを設定したい場合、以下のように GMUClusterManagerDelegateGMSMapViewDelegate を設定してあげるとタップ時のアクションが設定可能なようです

class ViewController: UIViewController, GMUClusterManagerDelegate, GMSMapViewDelegate {

    private var mapView: GMSMapView!
    private var clusterManager: GMUClusterManager!

    override func viewDidLoad() {
        super.viewDidLoad()

        // ... Rest of code omitted for easy reading.

        // Register self to listen to both GMUClusterManagerDelegate and
        // GMSMapViewDelegate events.
        clusterManager.setDelegate(self, mapDelegate: self)
    }

    // MARK: - GMUClusterManagerDelegate
    func clusterManager(clusterManager: GMUClusterManager, didTapCluster cluster: GMUCluster) {
        let newCamera = GMSCameraPosition.cameraWithTarget(cluster.position,
      zoom: mapView.camera.zoom + 1)
        let update = GMSCameraUpdate.setCamera(newCamera)
        mapView.moveCamera(update)
    }

    // MARK: - GMUMapViewDelegate
    func mapView(mapView: GMSMapView, didTapMarker marker: GMSMarker) -> Bool {
        if let poiItem = marker.userData as? POIItem {
            NSLog("Did tap marker for cluster item \(poiItem.name)")
        } else {
            NSLog("Did tap a normal marker")
        }
        return false
    }
}

終わりに

Google Maps iOS Utils というライブラリはマーカーをまとめるだけでなく、
マーカーの画像をカスタマイズしたり KML や GeoJSON をレンダリングできたりと他にも色々な機能が使用できるようなので、機会があれば触ってみようかと思います

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1