Mapbox で 公園の表示サンプル
やりたいこと
Google マイマップで登録したピンを「公園の訪問済/未訪問」などで色分けしたい
前提
- Google マイマップから Download した KML ファイルをパースして、geojson ファイルを作成
- 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()
}
}