はじめに
※この記事はLIFULL Advent Calendar 2021の15日目の記事となります。
※2日目に投稿したけど、まだ空いていたのでまた投稿しちゃいます。
MapKitでピンを立てたりルートを表示したりすることはあったけど、MKTileOverlay
を使ってタイルを表示させることはなかったので、大きく二種類の方法があったので今回やってみたという記事です。
サーバ上にあるタイル情報を用いる場合
使用する情報
今回はよく検索にもヒットする**国土地理院**のデータを利用します。
注意点としては以下があります。
地理院タイルをウェブサイトやソフトウェア、アプリケーション上でリアルタイムに読み込んで利用する場合、地理院タイルは出典の明示のみで申請不要でご利用いただけます。
アプリ開発で使う場合は出典を明示しておきましょう。
実装
StoryBoard上にMKMapView
が既に配置されている前提とします。
// 国土地理院のデータから、今回は「淡色地図」タイルを利用する
let overlay = MKTileOverlay.init(urlTemplate:"https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png")
// MKMapView にオーバーレイを追加する
mapView.addOverlay(overlay)
これだけだとマップに変化はありません。
MKMapViewDelegateのrendererForメソッドを実装する必要があります。
extension HogeViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
return MKTileOverlayRenderer.init(overlay: overlay)
}
}
##結果
オーバーレイを追加したことで右画像のように淡色地図が表示されます。
他にも国土地理院のデータでは航空写真や活断層図等、さまざまなデータが用意されています。
標準地図 | 淡色地図 |
---|---|
カスタムのタイル情報を用いる場合
タイルを表示する方法は先ほど実現した、国土地理院や他のサイトで公開されているデータを用いるか、自作のAPIからタイル情報を受けとってその情報をもとにカスタムな表示をする
のどちらかに分かれるかと思います。
後者ではMKTileOverlay
のloadTile()
メソッドを用いて実現します。
今回は、タイルの座標によって赤、青、緑のいずれかのタイルを重ねるようにしてみます。
実装
まずはMKTileOverlay
を継承したカスタムクラスを定義します。
このクラスでloadTile()
メソッドをオーバーライドします。
import UIKit
import MapKit
class CustomTileOverlay: MKTileOverlay {
override func loadTile(at path:MKTileOverlayPath, result:@escaping (Data?, Error?) -> Void) {
UIGraphicsBeginImageContext(CGSize(width: 256,height: 256))
guard let context = UIGraphicsGetCurrentContext() else {
return
}
let r: CGFloat = ((path.x + path.y) % 3) == 0 ? 1 : 0
let g: CGFloat = ((path.x + path.y + 1) % 3) == 0 ? 1 : 0
let b: CGFloat = ((path.x + path.y + 2) % 3) == 0 ? 1 : 0
let alpha: CGFloat = 0.5;
let fill = CGColor(red: r, green: g, blue: b, alpha: alpha)
context.setFillColor(fill)
context.fill(CGRect(x: 0, y: 0, width: 256,height: 256))
let tileImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
result(tileImage?.pngData(), nil)
}
}
国土地理院のデータを扱っていた箇所を今回のオーバーレイを使うように書き換えてみましょう。
一行変更するだけで問題ありません。
// 国土地理院のデータを扱う場合
// let overlay = MKTileOverlay.init(urlTemplate:"https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png")
// 今回作成したOverlayを呼び出す
let overlay = CustomTileOverlay()
// そのまま
mapView.addOverlay(overlay)
##結果
見事チェック模様にタイルが表示されるようになりましたね。
おまけ:特定の位置だけタイルを表示してみる
上記の例から、ある特定の場所だけにタイルを表示するような処理に書き換えてみます。
loadTile
メソッドの引数にあるpath: MKTileOverlay
はx、y、z
というプロパティを持っています。
xとyはタイルを表示するためのx座標とy座標を表し、zは地図のズームレベルを表します。
今回は直撃ちで、x=116397、y=51624、z=17
を指定してみます。
override func loadTile(at path:MKTileOverlayPath, result:@escaping (Data?, Error?) -> Void) {
UIGraphicsBeginImageContext(CGSize(width: 256,height: 256))
guard
let context = UIGraphicsGetCurrentContext(),
path.x == 116397,
path.y == 51624,
path.z == 17 else {
return
}
// 以降は同じ
}
これで実行すると、渋谷付近にタイルが表示されるのを確認できました。
ちなみにズームレベルが17で指定しているので、このズームレベルよりも大きくても小さくても表示されません。
終わりに
普段触らないタイル表示は数行で実現はできるものでした。
後者のカスタムな表示方法は、独自のAPIを用意できると、より個人開発で活用できそうだなと思いました。
API開発のスキルは現在磨き中なので、自前でできるようにして色々遊べるようになりたい。。