LoginSignup
eri1208
@eri1208

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

地図上の複数のアノテーションのテキストを被らせないよう表示する

解決したいこと

iOS17.0~のswiftUI、Mapkitを使って、
地図上に置いてある複数のアノテーションのテキストを被らせないよう表示したいです。
最悪アイコンは問題ないので、テキストだけでもどんなスケールでも重ならずに表示する方法はないでしょうか。

<前提条件>
・アノテーションは最大3つ
・アノテーションの位置情報は固定ではなく、別で処理させた結果で変わる想定
 (別処理の例:現在位置から近い駅を検索、近い順に3つの位置情報を取得)
・アノテーションのテキストをタップするとappleのナビアプリへ飛ぶ想定
・最低限、現在地と3つのアノテーションすべてが表示されるカメラスケールで、極力テキストが被らない

発生している問題・エラー

下図のように、アノテーション同士が近い場所だとかなり拡大しないテキストが重なってしまう。
スクリーンショット 2024-06-21 14.04.17.png

該当するソースコード

こんな感じで書いてます。

struct ContentView: View {
    var body: some View {
        VStack{
            Map(interactionModes: .all) {
                Annotation("", coordinate: CLLocationCoordinate2D(latitude: 35.68137823015221, longitude: 139.76709089598975)) {
                    Text("テスト1\n表示を被らせたくない")
                        .bold()
                        .foregroundColor(.yellow)
                        .padding([.top, .horizontal], 5)
                        .background(Color.black.opacity(0.7))
                        .cornerRadius(5)
                        .font(.system(size: 20))
                    Image(systemName: "car").font(.system(size: 20, weight: .bold)).foregroundColor(.red)
                }.annotationTitles(.hidden)
                Annotation("", coordinate: CLLocationCoordinate2D(latitude: 35.68122136457911, longitude: 139.76655445438064)) {
                    Text("テスト2\n表示を被らせたくない")
                        .bold()
                        .foregroundColor(.yellow)
                        .padding([.top, .horizontal], 5)
                        .background(Color.black.opacity(0.7))
                        .cornerRadius(5)
                        .font(.system(size: 20))
                    Image(systemName: "car").font(.system(size: 20, weight: .bold)).foregroundColor(.red)
                }.annotationTitles(.hidden)
            }
            .mapControls {
                MapUserLocationButton()
            }
        }
    }
}

0

2Answer

経度緯度情報に基づいて配置されているので、表示スケールに応じた近い距離の2つのアノテーションが重なることは必然ですね。
アノテーションが最大2つに限定できるなら、画面の上部と下部に分けて配置することはできるかもしれません。

scr1.png
struct ContentView: View {
    var body: some View {
        VStack{
            Map(interactionModes: .all) {
                Annotation("", coordinate: CLLocationCoordinate2D(latitude: 35.68137823015221, longitude: 139.76709089598975)) {
                    Text("テスト1\n表示を被らせたくない")
                        .bold()
                        .foregroundColor(.yellow)
                        .padding([.top, .horizontal], 5)
                        .background(Color.black.opacity(0.7))
                        .cornerRadius(5)
                        .font(.system(size: 20))
                        .offset(x: 0, y: -30)
                    Image(systemName: "car").font(.system(size: 20, weight: .bold)).foregroundColor(.red)
                }.annotationTitles(.hidden)
                Annotation("", coordinate: CLLocationCoordinate2D(latitude: 35.68122136457911, longitude: 139.76655445438064)) {
                    Text("テスト2\n表示を被らせたくない")
                        .bold()
                        .foregroundColor(.yellow)
                        .padding([.top, .horizontal], 5)
                        .background(Color.black.opacity(0.7))
                        .cornerRadius(5)
                        .font(.system(size: 20))
                        .offset(x: 0, y: +30)
                    Image(systemName: "car").font(.system(size: 20, weight: .bold)).foregroundColor(.red)
                }.annotationTitles(.hidden)
            }
            .mapControls {
                MapUserLocationButton()
            }
        }
    }
}

offsetを使って上下に離しましたが、positionを使えば、もっと明確に位置を離すことができるかもしれません。

1Like

Comments

  1. @eri1208

    Questioner

    ご回答ありがとうございます。
    下段midoribiさんコメントにもあります通り、前提条件が足りておりませんでしたので追記させていただきました。
    2つのアノテーション位置が近いとわかっていれば、回答いただいた通りの方法で解決できそうなのですが、今回位置情報は別処理での結果に応じて変わりますので、その結果に応じて自動的にテキストが被らないような手段はないのかなーと思っておりました。
    情報が不足しており誠に申し訳ありませんでした。

  2. アノテーションが最大3つなら、また、位置関係が近くないとしても、
    offsetやpositionを使って位置を調整する処理は、変わらないと思います。

    scr.png scr2.png

こういうのってさ、前提によって方針が結構変わるからさ、しっかりと前提を共有しないとさ、適切なアドバイスが難しいんだよね。

たとえば「複数」っていうのがさ、東京駅周辺に1000個ラベルを付ける必要があるっていうのと3個ぐらいでいいだっていうのではさ、全然異なる解決策になると思うんだ。
前者だったらさ、マップのスケールに合わせてラベルの大きさ変更するみたいな仕組みとか、ラベルごとに重要度が設定されていて重なる場合は重要度がより高いほうのみ表示するとかが考えられるんだ。
後者だったらさ、ぶつかった場合にちょっとだけ上下にずらす仕組みで十分なんだ。

他にも「どんなスケールでも重ならずに表示する」ってあるけど、それは地球規模でも重なっちゃいけないの?とか思っちゃうわけさ。

何が言いたいかっていうとさ、適切な回答がほしいなら適切な情報提供を心掛けたほうがいいよっていうこと。

1Like

Comments

  1. @eri1208

    Questioner

    ご回答・アドバイス、ありがとうございます。
    おっしゃる通りですね、申し訳なかったです。
    前提条件が足りておりませんでしたので追記させていただきました。

Your answer might help someone💌