Skip to main content

Mapbox で タップ位置の情報取得+ポップアップ表示

やりたいこと

  • タップ時にポップアップを出したい
  • ピンのタップの場合はピンの情報を取得

今後用

  • iPad, iPhone 両方で使うことを考えると、詳細情報表示/操作は inspector か sheet でやるのが良いか
  • ということで 座標と ピン情報が取得できるところまでで完了とする
  • queriedFeature からの情報取得は 煩雑で可読性も悪いので、 utility 関数的なのを用意しておいたほうが楽そうだ
  • @State var selectedFeature のように選択したもの保持しといて、ハイライトに使うのも良さそう
  • onLayerTapGesture は 15pt だとタップするには狭い。でもピンのサイズは大きくしたくない
    • opacity 薄めか透明で、広めに取った CircleLayer を重ねておけば良いはず(試してない)
    • もしかすると shadow も、この方式で作れば良い? (circleBlur)

サンプル

swift
import SwiftUI
import MapboxMaps

struct MapboxView: View {
@State private var popupCoordinate: CLLocationCoordinate2D?

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)

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

CircleLayer(id: "parksPoint", source: "parks")
.sourceLayer("parks-9qd2dk")
.circleRadius(10)
.circleColor(UIColor.red)

if let coord = popupCoordinate {
MapViewAnnotation(coordinate: coord) {
VStack(spacing: 4) {
Text("ポップアップ")
.font(.caption)
.padding(6)
.background(Color.white)
.cornerRadius(8)
.shadow(radius: 3)
}
}
}
}
// ★ onTapGesture, onLayerTapGesture は Deprecated らしいが、公式ドキュメントが追いつくまでそのままにしておこう
.onMapTapGesture { context in
// ★ タップ位置の座標をセット (でポップアップ表示)
print("####### onTapGesture | \(context.coordinate)") // 地図上の座標
print("####### onTapGesture | \(context.point)") // 画面上の座標
popupCoordinate = context.coordinate
}
.onLayerTapGesture("parksPoint") { queriedFeature, context in
// ★ 例: ズームアウトしたときは反応しないようにする
guard let zoom = mapReader.map?.cameraState.zoom else {
return false
}
if zoom > 13 {
return false
}

// ★ ピンの情報取得 (公園名を取得)
print("####### onLayerTapGesture | \(queriedFeature) | \(context)")
if let name = (queriedFeature.feature.properties?["name"] as? JSONValue)?.rawValue {
print(name)
}

return true
}
}

.ignoresSafeArea()
}
}