ドキュメント / 基本 / GroundImage

GroundImage ― 画像を地図に貼る

南西・北東の2点で範囲を決めて、そこに1枚の画像を敷きます。施設のフロア図、古地図、航空写真、独自に作った塗り分け図など、タイル化されていない画像をそのまま地図に重ねられます。範囲や透明度は後から書き換えられ、画像はカメラ操作に追随して地面に貼り付いたまま表示されます。

BOUNDS
SW / NE
IMAGE
image / url
OPACITY
0.0 – 1.0
TILE SIZE
512 · タイル描画時のみ
プラットフォーム

01 · GroundImage の状態

GroundImageState が1枚の画像を表します。範囲・画像・透明度と、タップハンドラを持ちます。プラットフォームごとに自然な形で画像を渡せます(Android は Drawable、iOS は UIImage、Web は URL)。

GroundImageMapPageViewModel.kt · Jetpack Compose
val groundImageState =
    GroundImageState(
        id = "groundImage",
        bounds =
            GeoRectBounds(
                southWest = southWestPosition,
                northEast = northEastPosition,
            ),
        image = drawable,       // Drawable をそのまま渡す
        opacity = 0.5f,
        onClick = this::onGroundImageClick,
    )

GroundImage(groundImageState)
プロパティ
説明
bounds
画像を敷く矩形範囲。南西と北東の2点で決めます。
image / imageUrl
表示する画像。Android は Drawable、iOS は UIImage、Web は画像URLで渡します。
opacity
不透明度。0.0 で完全に透明、1.0 で不透明。ベースの地図と重ねて見せたいときに下げます。
tileSize
ラスタータイルとして描画する場合の1タイルの辺の長さ。ネイティブの画像オーバーレイで描画されるプロバイダでは使われません。既定の 512 のままで問題ありません。
extra
任意の付随データ。タップ時に受け取れます。
onClick
タップハンドラ。画像の状態とタップされた座標を受け取ります。

02 · 範囲と透明度

範囲は矩形です。画像の縦横比と範囲の縦横比が違う場合は、範囲に合わせて引き伸ばされるため、貼りたい図面の縦横比に合わせた範囲を指定してください。範囲・透明度・画像はすべて後から書き換えられ、書き換えた時点で描画に反映されます。

SW
NE
南西(SW)と北東(NE)の2点で矩形が決まります。図の枠線とマーカーはサンプルアプリ側の実装です。
BOUNDS

ドラッグで範囲を作り直す

2点のマーカーをドラッグしながら bounds を差し替えると、画像が追随します。ただし連続更新の追随性はプロバイダによって差があります。
OPACITY

ベース地図と重ねる

透明度を下げると、下の地図の道路や地名が透けて見えます。エンジンによっては変更のタイミングや効き方に制限があります。
サンプル · 古地図を範囲に合わせて重ねたところ
範囲と透明度を変える
// 四隅のマーカーをドラッグして範囲を作り直す
override fun onMarkerDrag(dragged: MarkerState) {
    when (dragged.id) {
        "south_west" -> southWestPosition = GeoPoint.from(dragged.position)
        "north_east" -> northEastPosition = GeoPoint.from(dragged.position)
    }
    bounds = GeoRectBounds(southWest = southWestPosition, northEast = northEastPosition)
}

// 透明度はそのまま代入するだけ
groundImageState.opacity = sliderOpacity

03 · どのプロバイダでも同じに見える

GroundImage は、各地図SDKドライバーの中でもっとも実装差が大きい機能です。画像オーバーレイの仕組みはエンジンごとに大きく異なり、同等の機能を持たないものもあります。MapConductor は可能な範囲でこの差を吸収しますが、プロバイダによっては動的な変更に制限が残ります。

PLACEMENT

同じ範囲・同じ引き伸ばし

画像は指定した範囲に合わせて配置されます。エンジン側の画像オーバーレイの座標系の違いに関係なく、同じ位置・同じ大きさで表示されます。

NATIVE FIRST

まずネイティブの機能で描く

各ドライバーは、可能な限りその地図SDK固有の画像オーバーレイ機能を使って最適に描画します(ArcGIS なら MediaLayer + ImageElement、Cesium なら Rectangle の画像マテリアルなど)。どうしても同等の機能がないエンジンに限り、画像を切り出してタイルとして供給し、ラスターレイヤーとして重ねます。どちらの経路でもアプリ側のコードは変わりません。

LIMITATIONS

プロバイダによる制限

範囲の作り直し(ドラッグ中の連続更新)や透明度の変更が、エンジン側の制約で限定的になる場合があります。静的な配置はどのプロバイダでも同じですが、動的に変える用途では対象プロバイダでの確認をおすすめします。

HIT TEST

タップ判定も共通

タップ判定は共通ロジックで行うため、エンジンが画像オーバーレイのタップに対応しているかどうかに関係なく onClick が呼ばれます。

04 · タップ

onClick は画像の状態と、タップされた座標を受け取ります。サンプルでは、タップで画像そのものを差し替えて表示を切り替えています。

タップで画像を差し替える
// タップで画像を差し替える
override fun onGroundImageClick(clicked: GroundImageEvent) {
    val isBase = clicked.state.image == imageResources.image
    image = if (isBase) imageResources.clickedImage else imageResources.image
}
event.state
タップされた画像の状態。現在の画像や extra を参照できます。
event.clicked
タップされた地理座標。範囲内のどこが押されたか分かります。

画像の透明な部分もタップ範囲に含まれます。透明部分を無反応にしたい場合は、範囲を画像の実体に合わせるか、ポリゴンを併用してください。

関連ページ