Mapbox の ピンのタップで、一番近いピンを選びたい
悩み
- ピンが密集しているので見づらい
- → ピンの表示サイズを小さくした (max 15px)
- 小さいとタップで拾いづらい
- → タップ用の透明レイヤを用意 (30 px)
- 見えないレイヤが隣のピンを隠してしまうことに (裏目)
- → これは、細かく操作したいユーザに相当ストレス (のはず)
- → 「手前」ではなく、「一番近い」ピンを選択したい
やりたいこと
- タップ位置で拾われたピンをすべて取得し、一番近いものを選択する
変更前のコード(手前のピンを 1 個取得)
swift
.onLayerTapGesture("parksTouchArea") { queriedFeature, context in
let feature = queriedFeature.feature
print(feature) // ★
}
変更後のコード(タップ範囲のピンをすべて取得)
swift
.onLayerTapGesture("parksTouchArea") { _, context in
mapReader.map?.queryRenderedFeatures(with: context.point) { result in
guard case .success(let queriedRenderedFeatures) = result else {
print("Failed to query features: \(result)")
return
}
// for feature in queriedRenderedFeatures {
// print("=====================================")
// print(feature.queriedFeature.feature)
// }
let tapPoint = context.point
let featureAndDistance = queriedRenderedFeatures.compactMap { queriedRenderedFeature -> (Feature, CGFloat)? in
let feature = queriedRenderedFeature.queriedFeature.feature
guard let pinPoint = feature.geometry?.point else { return nil }
guard let screenPoint = mapReader.map?.point(for: pinPoint.coordinates) else { return nil }
let distance = hypot(screenPoint.x - tapPoint.x, screenPoint.y - tapPoint.y)
return (feature, distance)
}
.min(by: { $0.1 < $1.1 })
if let nearestFeature = featureAndDistance?.0 {
print(nearestFeature) // ★
}
}