読者です 読者をやめる 読者になる 読者になる

A Day In The Life

とあるプログラマの備忘録

iPhone の地図上に簡単に図形を書く方法

以前は MKMapView 上に線を引いたり四角形を書いたりするのに自前で View を作成しないといけませんでしたが iOS4 になって地図上に図形を書くためのクラスが追加されました。使い方がわりと簡単なので紹介したいと思います。

地図に線を引く

地図に線を引くには MKPolyline クラスと MKPolylineView クラスを使います。山手線の渋谷駅から新宿駅に線を引く例をもとに説明します。
サンプルコードの画面イメージ
手順は以下の通りです。

  1. プロジェクトに MapKit.framework を追加
  2. UIViewController のサブクラスを作成し MKMapViewDelegate プロトコルの実装を宣言する
  3. viewDidLoad メソッドで MKPolyline オブジェクトを生成し MKMapView の addOverlay メソッドを使ってオーバーレイを追加する
  4. mapView:viewForOverlay: メソッドで MKPolylineView オブジェクトを生成する

まずはヘッダのコードから。

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

@interface MapOverlaySampleViewController : UIViewController
    <MKMapViewDelegate> {・・・2
  MKMapView *mapView_;
}

@property (nonatomic, retain) IBOutlet MKMapView *mapView;

@end

次に実装部分のコードです。
注意点は MKMapView の addOverlay メソッドを呼ぶだけでは線は表示されないことです。必ずmapView:viewForOverlay: メソッドの実装をしてください。MKPolyline と MKPolylineView 二つのクラスがあってなんか少しややこしいですがこの辺の手順は地図にアノテーションを表示するのと同じやり方です。

#import "MapOverlaySampleViewController.h"

@implementation MapOverlaySampleViewController

@synthesize mapView = mapView_;

- (void)viewDidLoad {
  [super viewDidLoad];
  CLLocationCoordinate2D coors[4];
  // 渋谷、原宿、代々木、新宿
  coors[0] = CLLocationCoordinate2DMake(35.658517, 139.701334);
  coors[1] = CLLocationCoordinate2DMake(35.670168, 139.702687);
  coors[2] = CLLocationCoordinate2DMake(35.683061, 139.702042);
  coors[3] = CLLocationCoordinate2DMake(35.690921, 139.700258);
  MKPolyline *line = [MKPolyline polylineWithCoordinates:coors
                                                   count:4];
  [mapView_ addOverlay:line];・・・3
  // 地図の設定
  mapView_.delegate = self;
  MKCoordinateRegion region = mapView_.region;
  region.span.latitudeDelta = 0.05; // 地図の表示倍率
  region.span.longitudeDelta = 0.05;
  region.center = coors[1]; // 原宿を画面中央に表示
  [mapView_ setRegion:region animated:YES];
}

- (void)dealloc {
  [mapView_ release];
  [super dealloc];
}

#pragma mark MKMapViewDelegate methods
- (MKOverlayView *)mapView:(MKMapView *)mapView
    viewForOverlay:(id<MKOverlay>)overlay {
  MKPolylineView *view = [[[MKPolylineView alloc] initWithOverlay:overlay]
      autorelease];・・・4
  view.strokeColor = [UIColor blueColor];
  view.lineWidth = 5.0;
  return view;
}

@end

プログラムの流れをシーケンス図で表すと以下のようになります。
MapOverlayを表示するまでの流れ シーケンス図
mapView:viewForOverlay: メソッドは MKMapView の addOverlay メソッドが呼ばれた後に地図に図形を表示する必要があれば呼び出されます。

地図に多角形を描く

MKPolygon と MKPolygonView クラスを使います。地図に線を引くのとほぼ同じです。
サンプルコードの画面イメージ

#import "MapOverlaySampleViewController.h"

@implementation MapOverlaySampleViewController

@synthesize mapView = mapView_;

- (void)viewDidLoad {
  [super viewDidLoad];
  CLLocationCoordinate2D coors[4];
  // 渋谷、原宿、東京、新宿
  coors[0] = CLLocationCoordinate2DMake(35.658517, 139.701334);
  coors[1] = CLLocationCoordinate2DMake(35.670168, 139.702687);
  coors[2] = CLLocationCoordinate2DMake(35.681382, 139.766084);
  coors[3] = CLLocationCoordinate2DMake(35.690921, 139.700258);
  MKPolygon *polygon = [MKPolygon polygonWithCoordinates:coors count:4];
  [mapView_ addOverlay:polygon];
  // 地図の設定
  ・・・省略・・・
}

#pragma mark MKMapViewDelegate methods
- (MKOverlayView *)mapView:(MKMapView *)mapView
    viewForOverlay:(id<MKOverlay>)overlay {
  MKPolygonView *view = [[[MKPolygonView alloc] initWithOverlay:overlay]
      autorelease];
  // 塗りつぶしの色を指定
  view.fillColor = [UIColor greenColor];
  return view;
}

地図に円を描く

MKCircle と MKCircleView クラスを使います。円の中心の位置と半径(メートル)を指定します。
サンプルコードの画面イメージ

#import "MapOverlaySampleViewController.h"

@implementation MapOverlaySampleViewController

@synthesize mapView = mapView_;

- (void)viewDidLoad {
  [super viewDidLoad];
  // 原宿
  CLLocationCoordinate2D coor = CLLocationCoordinate2DMake(35.670168, 139.702687);
  MKCircle *circle = [MKCircle circleWithCenterCoordinate:coor radius:500];
  [mapView_ addOverlay:circle];
  // 地図の設定
  ・・・省略・・・
}

#pragma mark MKMapViewDelegate methods
- (MKOverlayView *)mapView:(MKMapView *)mapView
    viewForOverlay:(id<MKOverlay>)overlay {
  MKCircleView *view = [[[MKCircleView alloc] initWithCircle:overlay]
      autorelease];
  view.strokeColor = [UIColor greenColor];
  view.fillColor = [UIColor redColor];
  return view;
}

MKOverlay,MKOverlayView 関連のクラスの関係

地図描画系のクラスの関連をまとめると以下のようになります。
MKOverlay関連のクラス図 プラス MKAnnotaion
MKOverlayView関連のクラス図 プラス MKAnnotaionView

まとめ

MKMapView に図形やアノテーションを表示する方法をまとめると

  1. MKMapView に図形またはアノテーションの情報を追加する
  2. 地図の描画範囲に表示したい図形やアノテーションがあれば MKMapViewDelegate の該当メソッドが呼ばれる(今回の例だと mapView:viewForOverlay: メソッドです)。
  3. デリゲートメソッド内で表示したい図形なりアノテーションの View をインスタンス化する

となります。この流れさえ覚えておけば独自画像を地図上に表示したい場合なんかもわりと迷わずに実装できるのではないでしょうか。

サンプルコード

今回作成したサンプルコードを github に置いておきました。ご自由にお使いください。

関連アプリ

COMPASS des COMPASS は経路表示に MKOverlay, MKOverlayView クラスを使っています。