Skip to main content

Mapbox で 公園の表示サンプル

やりたいこと

Google マイマップで登録したピンを「公園の訪問済/未訪問」などで色分けしたい

前提

  1. Google マイマップから Download した KML ファイルをパースして、geojson ファイルを作成
  2. Mapbox Studio で geojson ファイルを Tileset として読み込んでおく

メモ

  • これで 11,000 のピンを表示したが、サクサク動く
  • MapKit の Annotation でピンを作っていたときは そうはいかなかったので 驚きの結果

サンプル

swift
import SwiftUI
import MapboxMaps

struct MapboxView: View {
var body: some View {
let center = CLLocationCoordinate2D(latitude: 35.6598, longitude: 139.702389)
let camera = Viewport.camera(center: center, zoom: 13, bearing: 0, pitch: 0)

Map(initialViewport: camera) {
VectorSource(id: "parks")
.url("mapbox://takaaki024.99uywdyx")

CircleLayer(id: "parksPoint", source: "parks")
.sourceLayer("parks-9qd2dk")
.circleRadius(
// ★ ズームアウトに合わせてサイズを小さくする
Exp(.interpolate) {
Exp(.linear)
Exp(.zoom)
// _/ ̄ こうなる
// zoom level 6 以下は 3 pt 固定
6 ; 2 // zoom level 6 で 2 pt
// この間が線形補間
22 ; 15 // zoom level 22 で 15 pt
// zoom level 22 以上は 15 pt 固定
}
)
.circleColor( // TODO: 遊具など、別の基準で
Exp(.switchCase) {
Exp(.get) { "isVisited" }
Exp(.literal) { UIColor.red }

Exp(.get) { "hasUserPhoto" }
Exp(.literal) { UIColor.orange }

Exp(.not) {
Exp(.get) { "isAvailable" }
}
Exp(.literal) { UIColor.gray }

// Default
Exp(.literal) { UIColor.blue }
}
)

// TODO: SymbolLayer にして、遊具の種類のアイコンなどにするのも良さそうだ

SymbolLayer(id: "parksText", source: "parks")
.sourceLayer("parks-9qd2dk")
.textField(
Exp(.concat) {
Exp(.get) { "name" }
Exp(.literal) { " (" }
Exp(.get) { "city" }
Exp(.literal) { ")" }
}
)
.textSize(12)
.textAnchor(.top)
.textOffset(x: 0, y: 0.5)
.textOpacity(
// ★ サイズに応じて非表示
// TODO: ユーザが「非表示」選択で非表示
Exp(.interpolate) {
Exp(.linear)
Exp(.zoom)
5.999 ; 0 // zoom level 6 未満は 非表示 (opacity = 0)
6.000 ; 1 // zoom level 6 以上は 表示 (opacity = 1)
}
)

}
.ignoresSafeArea()
}
}