この Codelab について
1. 始める前に
概要
このコードラボでは、Objective-C での iOS アプリの作成に Google Maps Platform を使用するための基本事項について説明します。事前の設定、Maps SDK for iOS の読み込み、最初の地図の表示、マーカーとマーカー クラスタリングの操作、地図上での図形の描画、ユーザー操作の処理など、あらゆる基本事項を習得できます。
作成するアプリの概要
この Codelab では、以下の機能を備えた iOS アプリを作成します。
- Maps SDK for iOS と Maps SDK for iOS ユーティリティ ライブラリを読み込む
- オーストラリアのシドニーが中央に配置された地図を表示する
- シドニー周辺の 100 個のポイントを示すカスタム マーカーを表示する
- マーカー クラスタリングを実装する
- マーカーがクリックされた際、地図上にそのマーカーを中心とする円を描画する
学習する内容
- Google Maps Platform スタートガイド
- Maps SDK for iOS と Google Maps SDK for iOS ユーティリティ ライブラリを読み込む
- 地図を読み込む
- マーカー、カスタム マーカー、マーカー クラスタリングを使用する
- Maps SDK for iOS のイベント システムを使用してユーザー操作を処理する
- 地図をプログラムで制御する
- 地図上に図形を描画する
要件
この Codelab を実行するには、以下の内容を理解しておく必要があります。Google Maps Platform の操作に慣れている場合は、すぐに Codelab に進んでください。
必要な Google Maps Platform サービス
この Codelab では次の Google Maps Platform サービスを使用します。
- Maps SDK for iOS
- Google Maps SDK for iOS ユーティリティ ライブラリ
Google Maps Platform を初めて使用する場合
Google Maps Platform を初めて使用する場合は、Google Maps Platform スタートガイドを参照するか、再生リスト「Getting Started with Google Maps Platform」を視聴して、以下の手順を行ってください。
- 請求先アカウントを作成します。
- プロジェクトを作成します。
- Google Maps Platform の API と SDK(前セクションに記載のもの)を有効化します。
- API キーを生成します。
この Codelab のその他の要件
この Codelab を実行するには、次のアカウント、サービス、ツールが必要です。
- 課金が有効になっている Google Cloud Platform アカウント
- Maps SDK for iOS を有効にした Google Maps Platform API キー
- Objective-C に関する基本的な知識
- ターゲット SDK が 12.0 以降の Xcode 12.0
2. 準備
以下の有効化の手順では、Maps SDK for iOS を有効にする必要があります。
Google Maps Platform を設定する
課金を有効にした Google Cloud Platform アカウントとプロジェクトをまだ作成していない場合は、Google Maps Platform スタートガイドに沿って請求先アカウントとプロジェクトを作成してください。
- Cloud Console で、プロジェクトのプルダウン メニューをクリックし、この Codelab に使用するプロジェクトを選択します。
- Google Cloud Marketplace で、この Codelab に必要な Google Maps Platform API と SDK を有効にします。詳しい手順については、こちらの動画またはドキュメントをご覧ください。
- Cloud Console の [認証情報] ページで API キーを生成します。詳しい手順については、こちらの動画またはドキュメントをご覧ください。Google Maps Platform へのすべてのリクエストで API キーが必要になります。
プロジェクトのスターター テンプレートの設定
この Codelab を開始する前に、次の手順に沿って、スターター プロジェクト テンプレートと完全なソリューション コードをダウンロードしてください。
- https://github.com/googlecodelabs/maps-platform-101-objc で、この Codelab 用の GitHub リポジトリをダウンロードまたはフォークします。
StarterApp プロジェクトは /starter
ディレクトリに置かれており、この Codelab の実行に必要な基本的なファイル構造が含まれています。作業対象のすべてのコンポーネントは /starter/StarterApp
ディレクトリにあります。
ソリューション コード全体の動作を確認する場合は、上述の設定手順を実行し、/solution/SolutionApp
ディレクトリでソリューションをご確認ください。
3. Maps SDK for iOS をインストールする
Maps SDK for iOS を使用する最初の手順は、必要な依存関係のインストールで、このプロセスには 2 つの手順があります。それは、CocoaPods 依存関係マネージャーから Maps SDK for iOS と Maps SDK for iOS ユーティリティ ライブラリをインストールし、SDK に API キーを提供することです。
- Maps SDK for iOS と Maps SDK for iOS ユーティリティ ライブラリを
Podfile
に追加します。
この Codelab では、Google マップのすべての主要な機能を提供する Maps SDK for iOS と、地図を強化するためのさまざまなユーティリティ(マーカー クラスタリングなど)を提供する Maps iOS ユーティリティ ライブラリの両方を使用します。
まずは、Xcode(または任意のテキスト エディタ)で Pods > Podfile
を開き、ファイルを更新して、Maps SDK for iOS とユーティリティ ライブラリの依存関係を use_frameworks!
に含めます。
pod 'GoogleMaps'
pod 'Google-Maps-iOS-Utils'
- Maps SDK for iOS と Maps SDK for iOS ユーティリティ ライブラリの pod をインストールします。
依存関係をインストールするには、コマンドラインから /starter
ディレクトリで pod install
を実行します。CocoaPods では、依存関係のダウンロードに加えて、StarterApp.xcworkspace
の作成も自動的に行われます。3. 依存関係がインストールされたら、Xcode で StarterApp.xcworkspace
を開き、Command+R
を押して iPhone シミュレータでアプリを実行します。すべてが正しく設定されると、シミュレータが起動し、画面が黒く表示されますが、まだ何も作成されていないため、これは予期されたエラーです。4. SDK を AppDelegate.h
にインポートします。
これで依存関係のインストールが完了しました。次に API キーを SDK に提供します。最初の手順として、#import "AppDelegate.h"
インポート文の下に以下のコードを挿入して、Maps SDK for iOS を依存関係としてインポートします。
@import GoogleMaps;
- iOS SDK インポート文の下で、値を API キーに設定して
NSString
定数を宣言します。
static NSString *const kMapsAPIKey = @"YOUR API KEY";
application: didFinishLaunchingWithOptions:
のGMSServices
でprovideAPIKey
を呼び出して、API キーを iOS SDK に渡します。
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GMSServices provideAPIKey:kMapsAPIKey];
return YES;
}
更新された AppDelegate.m
ファイルは以下のようになります。
#import "AppDelegate.h"
@import GoogleMaps;
static NSString *const kMapsAPIKey = @"YOUR API KEY";
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GMSServices provideAPIKey:kMapsAPIKey];
return YES;
}
@end
Podfile
は以下のようになります。
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '11.0'
target 'StarterApp' do
use_frameworks!
pod 'GoogleMaps', '5.1.0.0'
pod 'Google-Maps-iOS-Utils', '3.4.0'
end
これで、依存関係のインストールと、API キーの提供が完了しました。次は、Maps SDK for iOS の呼び出しを開始します。
4. 地図を表示する
ではいよいよ地図を表示してみましょう。
Maps SDK for iOS で最も頻繁に使用されるのは GMSMapView
クラスで、地図インスタンスの作成と操作を可能にする多くのメソッドが用意されています。その方法を以下に示します。
ViewController.m
を開きます。
ここで、この Codelab の残りの作業をすべて行います。ビュー コントローラの loadView
および viewDidLoad
のライフサイクル イベントは、すでにスタブアウトされています。2. ファイルの先頭に以下のコードを追加して、Maps SDK for iOS をインポートします。
@import GoogleMaps;
ViewController
インスタンス変数を宣言してGMSMapView
を格納します。
GMSMapView
のインスタンスは、この Codelab 全体をとおして主に使用するオブジェクトで、ビュー コントローラのさまざまなライフサイクル メソッドから参照や操作を行う対象となります。それを使用できるようにするには、ViewController
の実装を更新してインスタンス変数を宣言し、格納します。
@implementation ViewController {
GMSMapView *_mapView;
}
loadView
で、GMSCameraPosition
のインスタンスを作成します。
GMSCameraPosition
は、地図の中心に配置される場所と、表示されるズームレベルを定義します。このコードで cameraWithLatitude:longitude:zoom:
のメソッドを呼び出して、オーストラリアのシドニー(緯度 -33.86、経度 151.20)を地図の中心に配置し、ズームレベルを 12 に設定します。
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86 longitude:151.20 zoom:12];
loadView
でGMSMapView
のインスタンスを作成して、地図をインスタンス化します。
新しい地図インスタンスを作成するには、mapWithFrame:camera:
を呼び出します。フレームは CGRectZero
に設定されます。これは iOS CGGeometry
ライブラリのグローバル変数で、幅 0、高さ 0 のフレームを指定し、ビュー コントローラ内の「0,0」の位置に配置されます。カメラは、先ほど作成したカメラ位置に設定されます。
地図を実際に表示するには、次に、ビュー コントローラのルートビューを _mapview
に設定します。これにより、地図が全画面表示になります。
_mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
self.view = _mapView;
GMSMapViewDelegate
をビュー コントローラに設定します。
実装すると、マップビュー デリゲートにより、GMSMapView
インスタンスでのユーザー操作からのイベントを処理できるようになります。これは後の手順で必要になります。
まず、GMSMapViewDelegate:
のプロトコルに準拠するように ViewController
のインターフェースを更新します。
@interface ViewController ()<GMSMapViewDelegate>
次に、以下のコードを追加して GMSMapViewDelegate
を ViewController
に設定します。
_mapView.delegate = self;
これで、iOS シミュレータ(Command+R
)でアプリを再読み込みすると、地図が表示されるようになりました。
この手順では、オーストラリアのシドニーを中心に配置した地図を表示する GMSMapView
のインスタンスを作成しました。
ViewController.m
ファイルは以下のようになります。
#import "ViewController.h"
#import "LocationGenerator.h"
@import GoogleMaps;
@interface ViewController ()<GMSMapViewDelegate>
@end
@implementation ViewController {
GMSMapView *_mapView;
}
- (void)loadView {
[super loadView];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86 longitude:151.20 zoom:12];
_mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
self.view = _mapView;
_mapView.delegate = self;
}
5. Cloud ベースのマップのスタイル設定(任意)
Cloud ベースのマップのスタイル設定によって地図のスタイルをカスタマイズすることも可能です。
マップ ID を作成する
地図スタイルを関連付けたマップ ID の作成が済んでいない場合は、マップ ID のガイドを参照して、以下を行いましょう。
- マップ ID を作成します。
- マップ ID を地図スタイルに関連付けます。
マップ ID をアプリに追加する
前のステップで作成したマップ ID を使用するには、ViewController.m
ファイルを開き、loadView
メソッド内に GMSMapID
オブジェクトを作成してマップ ID を指定します。次に、GMSMapID
オブジェクトをパラメータとして指定して GMSMapView
のインスタンス化を変更します。
ViewController.m
- (void)loadView {
GMSMapID *mapID = [[GMSMapID alloc] initWithIdentifier:@"YOUR_MAP_ID"];
_mapView = [GMSMapView mapWithFrame:CGRectZero mapID:mapID camera:camera];
// ...
}
以上が完了したら、アプリを実行してみましょう。指定したスタイルで地図が表示されるはずです。
6. 地図にマーカーを追加する
Maps SDK for iOS で実行できる操作は多数ありますが、最も頻繁に使用するのは地図上にマーカーを配置する操作です。地図上の特定の地点を示すマーカーは、ユーザー操作を処理するための一般的な UI 要素です。Google マップを利用したことがあれば、以下のようなデフォルトのマーカーを見たことがあるかもしれません。
この手順では、GMSMarker
クラスを使って地図上にマーカーを配置する方法を学習します。
なお、ビュー コントローラの loadView
ライフサイクル イベントの前の手順から地図が読み込まれるまではマーカーを地図に配置できないため、これらの手順は、ビュー(と地図)の読み込み後に呼び出される viewDidLoad
ライフサイクル イベントで完了することになります。
CLLocationCoordinate2D
オブジェクトを定義します。
CLLocationCoordinate2D
は、iOS の CoreLocation ライブラリによって使用可能になる構造体で、設定された緯度と経度でエリアを定義します。最初のマーカーの作成を開始するには、CLLocationCoordinate2D
オブジェクトを定義し、緯度と経度を地図の中心に設定します。camera.target.latitude
プロパティと camera.target.longitude
プロパティを使用すると、地図表示から地図の中心の座標にアクセスできます。
CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude, _mapView.camera.target.longitude);
GMSMarker
のインスタンスを作成します。
Maps SDK for iOS には、GMSMarker
クラスが用意されています。GMSMarker
の各インスタンスは、地図上で個々のマーカーを示し、markerWithPosition:
を呼び出してそれに CLLocationCoordinate2D
オブジェクトを渡すことで作成され、地図上のどこにマーカーを配置するかを SDK に伝えます.
GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
- カスタム マーカー アイコンを設定します。
Google マップのデフォルトの赤いピンでも機能に不足はありませんが、地図をカスタマイズするのも効果的です。Maps SDK for iOS では、カスタム マーカーをとても簡単に使用できます。StarterApp プロジェクトには ‘custom_pin.png' という画像が含まれていますが、任意の画像を使用できます。
カスタム マーカーを設定するには、マーカーの icon
プロパティを UIImage
インスタンスに設定します。
marker.icon = [UIImage imageNamed:@"custom_pin.png"];
- 地図にマーカーをレンダリングします。
マーカーは作成されたものの、地図上にはまだ表示されていません。これを行うには、GMSMarker
インスタンスの map
プロパティを GMSMapView
のインスタンスに設定します。
marker.map = _mapView;
アプリを再読み込みして、マーカーが配置された最初の地図を確認してみましょう。
このセクションでは GMSMarker クラスのインスタンスを作成し、地図表示に適用して、地図上にマーカーを表示しました。ViewController.m
内の更新された viewDidLoad ライフサイクル イベントは、以下のようになります。
- (void)viewDidLoad {
[super viewDidLoad];
CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude, _mapView.camera.target.longitude);
GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
marker.icon = [UIImage imageNamed:@"custom_pin.png"];
marker.map = _mapView;
}
7. マーカー クラスタリングを有効にする
マーカーの数が多くて密集している場合、複数のマーカーが重なって表示され、ユーザーの利便性が低下します。たとえば、2 個のマーカーが近接している場合、以下のように表示される可能性があります。
このような場合に効果を発揮するのがマーカー クラスタリングです。マーカー クラスタリングも広く利用されている機能で、以下のように、近接する複数のマーカーをズームレベルに応じて 1 つのアイコンにグループ化できます。
マーカー クラスタリングのアルゴリズムは、地図の表示可能領域をグリッドに分割し、同じセル内にあるアイコンをクラスタ化します。この処理は、Google Maps Platform チームが作成した Google Maps SDK for iOS ユーティリティ ライブラリと呼ばれる、オープンソースの便利なユーティリティ ライブラリによってすべて自動的に行われます。このライブラリでは、特にマーカー クラスタリングを自動的に処理します。マーカー クラスタリングについて詳しくは、Google Maps Platform のドキュメントをご覧いただくか、GitHub で iOS ユーティリティ ライブラリのソースをご確認ください。
- さらに多くのマーカーを地図に追加します。
マーカー クラスタリングの動作を確認するには、地図上に多数のマーカーを配置する必要があります。これを簡単に行えるように、スターター プロジェクトの LocationGenerator.m
には便利なマーカー生成ツールが用意されています。
必要な数のマーカーを地図に追加するには、前の手順のコードの下にあるビュー コントローラの viewDidLoad
ライフサイクルで generateMarkersNear:count:
を呼び出します。このメソッドは、CLLocationCoordinate2D
オブジェクトで指定された座標周辺の無作為な位置に、count
オブジェクトで指定された数のマーカーを作成します。今回の場合は、先ほど作成した mapCenter
変数を渡すだけで済みます。マーカーは NSArray
で返されます。
NSArray<GMSMarker *> *markerArray = [LocationGenerator generateMarkersNear:mapCenter count:100];
- Google Maps SDK for iOS ユーティリティ ライブラリをインポートします。
Maps iOS ユーティリティ ライブラリを依存関係としてプロジェクトに追加するには、ViewController.m
の先頭の依存関係リストに以下のコードを追加します。
@import GoogleMapsUtils;
- Marker Clusterer を設定します。
Marker Clusterer を使用するには、その仕組みを設定するために、クラスタリング アルゴリズム、アイコン生成ツール、レンダラの 3 つを指定する必要があります。アルゴリズムは、同じクラスタに含めるマーカー間の距離など、マーカーをクラスタ化する仕組みの動作を決定します。アイコン生成ツールは、異なるズームレベルで使用されるクラスタ アイコンを提供します。レンダラは、地図上にあるクラスタ アイコンに対して行う実際のレンダリングを処理します。
これらはすべて、ゼロから作成することもできますが、Maps iOS ユーティリティ ライブラリには、このプロセスを簡単に行うためにデフォルトの実装が用意されており、以下のコードを追加するだけで済みます。
id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];
id<GMUClusterIconGenerator> clusterIconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];
id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:clusterIconGenerator];
GMUClusterManager
のインスタンスを作成します。
GMUClusterManager
は、指定されたアルゴリズム、アイコン生成ツール、レンダラを使ってマーカー クラスタリングを実装するクラスです。レンダラを作成して地図表示で使用できるようにするには、まず ViewController
の実装にインスタンス変数を追加して、クラスタ マネージャー インスタンスを格納します。
@implementation ViewController {
GMSMapView *_mapView;
GMUClusterManager *_clusterManager;
}
次に、viewDidLoad
ライフサイクル イベントで GMUClusterManager
のインスタンスを作成します。
_clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer];
- マーカーを追加して Marker Clusterer を実行します。
Marker Clusterer インスタンスの構成が完了したら、addItems:
を呼び出してクラスタ化するマーカーの配列をクラスタ マネージャーに渡してから、cluster
を呼び出して Marker Clusterer を実行します。
[_clusterManager addItems:markerArray];
[_clusterManager cluster];
アプリを再読み込みすると、多数のマーカーがすべて適切にクラスタ化された状態で表示されます。ピンチ操作で地図をズームしてさまざまなズームレベルを試し、マーカーのズームインとズームアウトに合わせてマーカー クラスタが変化するのを確認してみましょう。
この手順では、Google Maps SDK for iOS ユーティリティ ライブラリの Marker Clusterer のインスタンスを設定し、それを使って地図上で 100 個のマーカーをクラスタ化しました。ViewController.m
の viewDidLoad
ライフサイクル イベントは以下のようになります。
- (void)viewDidLoad {
[super viewDidLoad];
CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude,
_mapView.camera.target.longitude);
GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
marker.icon = [UIImage imageNamed:@"custom_pin.png"];
marker.map = _mapView;
NSArray<GMSMarker *> *markerArray = [LocationGenerator generateMarkersNear:mapCenter count:100];
id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];
id<GMUClusterIconGenerator> clusterIconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];
id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:clusterIconGenerator];
_clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer];
[_clusterManager addItems:markerArray];
[_clusterManager cluster];
}
8. ユーザー操作を追加する
これで、マーカーを表示し、マーカー クラスタリングを使用する地図が完成しました。この手順では、先ほどビュー コントローラに設定した GMSMapViewDelegate
を使ってさらに多くのユーザー操作を処理し、地図の利便性を高めます。
Maps SDK for iOS には、マップビュー デリゲートを介して実装される包括的なイベント システムが用意されており、さまざまなユーザー操作が発生した際にコードを実行できるようにするイベント ハンドラが含まれています。たとえば、mapview デリゲートには、地図やマーカーのクリック、地図表示のパン、ズームインやズームアウトなど、ユーザーがなんらかの操作を行った際にコードの実行をトリガーできるようにするメソッドが含まれています。
この手順では、ユーザーがタップした任意のマーカーが中央に表示されるように、プログラムで地図をパンします。
- マーカー タップ リスナーを実装します。
mapView:didTapMarker
は、以前に作成したマーカーのいずれか、およびマーカー クラスタ(マーカー クラスタは GMSMarker
のインスタンスとして内部で実装されます)をユーザーがタップするたびに呼び出されます。
イベント リスナーを実装するには、まず end
ステートメントの前の ViewController.m
でイベント リスナーをスタブアウトします。
メソッドからは NO
が返されます。これにより、iOS SDK はデフォルトの GMSMarker
機能を引き続き実行するように伝えられます。たとえば、情報ウィンドウが設定されている場合は、イベント ハンドラ コードの実行後、情報ウィンドウが表示されます。
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
return NO;
}
- タップイベントを処理し、カメラの動きにアニメーションを付けて、マーカーまたはマーカー クラスタがタップされた際に地図をセンタリングし直します。
mapView:didTapMarker
を呼び出すと、タップされた GMSMarker
のインスタンスが渡され、コードでそれを処理できるようになります。このインスタンスを使って、イベント ハンドラ内から地図表示で animateToLocation:
を呼び出し、position
プロパティで使用可能なマーカー インスタンスの位置を渡すことにより、地図をセンタリングし直すことができます。
[_mapView animateToLocation:marker.position];
- タップされたマーカー クラスタにズームインします。
一般的な UX パターンでは、タップされたマーカー クラスタにズームインします。クラスタはより低いズームレベルで展開されるため、ユーザーはクラスタ化されたマーカーを表示できるようになります。
前述のように、マーカー クラスタ アイコンは、実際には、カスタム アイコンを使用した GMSMarker
の実装に過ぎません。では、マーカーやマーカー クラスタがタップされたかどうかを判別するには、どうすればよいでしょうか。Marker Clusterer マネージャーで新しいクラスタ アイコンが作成されると、GMUCluster.
というプロトコルに準拠するように GMSMarker
のインスタンスが実装されます。イベント ハンドラに渡されるマーカーがこのプロトコルに準拠しているかどうかは、条件を使って確認できます。
クラスタがタップされていることをプログラムで把握したら、地図表示インスタンスで animateToZoom:
を呼び出して、現在のズームレベルに 1 を足した値にズームを設定できます。現在のズームレベルは、camera.zoom
プロパティの地図表示インスタンスで確認できます。
また、以下のコードでは YES
が返されます。これにより、イベントの処理を完了したことと、ハンドラで追加のコードを実行してはならないことがイベント ハンドラに伝えられます。これを行う理由の 1 つは、基盤となる GMSMarker
オブジェクトが、その他のデフォルト動作(クラスタ アイコンがタップされた場合にそれほど意味を持たない情報ウィンドウの表示など)を実行するのを防ぐことです。
if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
[_mapView animateToZoom:_mapView.camera.zoom +1];
return YES;
}
アプリを再読み込みし、いくつかのマーカーとマーカー クラスターをタップしてみましょう。どちらかをタップすると、タップされた要素が地図の中央にセンタリングし直されます。マーカー クラスタをタップすると、地図も 1 つ上のレベルにズームインされ、マーカー クラスタが展開されて、そこにクラスタ化されているマーカーが表示されます。
この手順では、マーカー タップ リスナーを実装し、イベントを処理して、タップされた要素が中央に表示されるようにし、その要素がマーカー クラスタ アイコンの場合はズームインされるようにしました。
mapView:didTapMarker
メソッドは以下のようになります。
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
[_mapView animateToLocation:marker.position];
if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
[_mapView animateToZoom:_mapView.camera.zoom +1];
return YES;
}
return NO;
}
9. 地図上に図形を描画する
ここまでの手順により、無作為の 100 個のポイントにマーカーを表示し、ユーザーの操作を処理できるシドニーの地図が完成しました。この Codelab の最後のステップでは、Maps SDK for iOS の描画機能を使用して、地図を操作するうえで有用な機能を追加します。
この地図は、シドニー市内を探索する観光客が使用することを想定しています。クリックされたマーカーを中心とする半径を地図上に描画し、その地点から歩いて行ける範囲が一目でわかるようにしましょう。
iOS SDK には、正方形、ポリゴン、ライン、円などの図形を地図上に描画する関数が用意されています。次に、クリックされたマーカーを中心に、半径 800 メートル(約 0.5 マイル)の円を描画します。
- ViewController の実装に
_circ
インスタンス変数を追加します。
このインスタンス変数は、最後に描画された円を保存するために使用されます。これにより、最後に描画された円は別の円が描画される前に破棄されるようになります。タップされたすべてのマーカーの周囲に円が表示された場合、ユーザーの操作性が落ち、見た目も悪くなるため、避ける必要があります。
これを行うには、ViewController
の実装を以下のように更新します。
@implementation ViewController {
GMSMapView *_mapView;
GMUClusterManager *_clusterManager;
GMSCircle *_circ;
}
- マーカーがタップされた際に円を描画します。
mapView:didTapMarker
メソッドの下部に以下のコードを追加して、iOS SDK の GMSCircle
クラスのインスタンスを作成し、上記で地図をセンタリングし直した際と同じように circleWithPosition:radius:
を呼び出して、マーカーがタップされた位置を渡し、半径 800 m の新しい円を描画します。
_circ = [GMSCircle circleWithPosition:marker.position radius:800];
- 円のスタイルを設定します。
デフォルトでは、GMSCircle
は黒いストロークと透明の塗りつぶしで円を描画します。これは、半径を表示するうえでは問題ありませんが、見た目が悪く、視認性にも少々劣ります。UIColor
を円の fillColor
プロパティに割り当てて円に塗りつぶし色を加え、スタイルを改善してみましょう。以下のコードでは、透明度 50%のグレーの塗りつぶし色を追加します。
_circ.fillColor = [UIColor colorWithRed: 0.67 green: 0.67 blue: 0.67 alpha: 0.5];
- 地図上に円をレンダリングします。
前の手順でマーカーを作成した際と同様、GMSCircle
のインスタンスを作成しただけでは、地図上に表示されません。これを行うには、地図表示インスタンスを円の map
プロパティに割り当てます。
_circ.map = _mapView;
- 以前にレンダリングした円をすべて削除します。
前述のとおり、単に地図に円を追加し続けても、優れたユーザー エクスペリエンスはもたらされません。以前のタップイベントによってレンダリングされた円を削除するには、mapView:didTapMarker
の上部にある _circ
の map
プロパティを nil
に設定します。
_circ.map = nil;
アプリを再読み込みしてマーカーをタップしてみましょう。マーカーがタップされ、以前にレンダリングされた円が削除されるたびに、新しく描画された円が表示されます。
この手順では、GMSCircle
クラスを使って、マーカーがタップされるたびに円をレンダリングしました。
mapView:didTapMarker
メソッドは以下のようになります。
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
_circ.map = nil;
[_mapView animateToLocation:marker.position];
if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
[_mapView animateToZoom:_mapView.camera.zoom +1];
return YES;
}
_circ = [GMSCircle circleWithPosition:marker.position radius:800];
_circ.fillColor = [UIColor colorWithRed: 0.67 green: 0.67 blue: 0.67 alpha: 0.5];
_circ.map = _mapView;
return NO;
}
10. 完了
この Codelab では、Google Maps Platform を使って初めての iOS アプリを作成し、Maps SDK for iOS の読み込み、地図の読み込み、マーカーの操作、地図上での操作と図形の描画、ユーザー操作の追加について学習しました。
最終的なコードは、/solution
ディレクトリにある完了プロジェクトでご確認いただけます。
次のステップ
この Codelab では、Maps SDK for iOS の基本的な機能についてのみ学習しました。次は、以下の機能を地図に追加してみましょう。
- 地図の種類を変更し、航空写真、ハイブリッド地図、地形地図を表示する
- 地図のズームやコントロールなど、その他のユーザー操作をカスタマイズする
- マーカーがクリックされたときに情報を表示する情報ウィンドウを追加する
- 場所に関する Google Maps Platform の豊富な機能やデータをアプリに追加するには、Places SDK for iOS をご覧ください。
Google Maps Platform をウェブで利用するその他の方法については、次のリンクをご覧ください。