Docs / Basics / Polyline

Polyline

Build one state object from a list of coordinates and a stroke style, then place it in the map view. How a line curves, how thick it looks and how easily it can be tapped normally differ per provider — MapConductor makes the result identical everywhere.

POINTS
GeoPoint[]
STROKE
color · width
GEODESIC
true / false
EVENT
onClick
Platform

01 · Polyline state

PolylineState represents one line: its coordinates, its stroke and a tap handler. Assigning to a property updates the line in place, so a changing route never needs rebuilding.

PolylinePageViewModel.kt · Jetpack Compose
val polylineState =
    PolylineState(
        points = routePoints,
        strokeColor = Color.Red,
        strokeWidth = 4.dp,
        geodesic = true,
        onClick = { event -> viewModel.onPolylineClick(event) },
    )

// 地図の中に置くだけ
Polyline(polylineState)

// 形の変更は points を書き換えるだけ
polylineState.points = nextPoints
Property
Description
points
The coordinates making up the line; assign to reshape it.
strokeColor
Stroke colour, including partial transparency.
strokeWidth
Stroke width in platform logical units, so it looks the same at any screen density.
geodesic
Whether the points are joined along great circles. Defaults to false.
zIndex
Stacking order relative to other overlays.
extra
Arbitrary payload, handed back on tap.
onClick
Tap handler; receives the line state and the tapped coordinate.

02 · Straight lines and great circles

With geodesic set to true, points are joined along the shortest path across the globe, so a long flight route draws as an arc rather than a straight line. With false you get a straight line in the map projection. The same coordinates can be drawn both ways side by side.

geodesic = false
A straight line in the projection. Barely different over short distances; noticeably off the real shortest path over long ones.
geodesic = true
The shortest path across the globe, drawn as an arc bending polewards.
Two lines from the same points
Polyline(polylineState) // geodesic = true(曲線)
Polyline(
    polylineState.copy(
        id = "${polylineState.id}-straight",
        geodesic = false,
        strokeColor = Color.Blue,
    ),
)

03 · The same result on every provider

Some engines can draw great circles and some cannot; stroke width units differ; lines crossing the date line are handled differently. On the raw SDKs the same coordinates give you different pictures.

MapConductor absorbs those differences internally. You pass one PolylineState and get the same arc, the same thickness and the same tap area on every provider.

GEODESIC

The same arc even without curve support

For engines that cannot draw great circles, the line is converted into a densified list of coordinates before it is handed over, so the displayed arc matches everywhere.

ANTIMERIDIAN

Lines crossing the date line

Passed as-is, some engines route such a line the long way around the globe. Splitting it at the boundary makes every engine take the short side.

STROKE WIDTH

One basis for thickness

Width is given in platform logical units and converted internally for screen density and per-engine unit differences, so the line looks equally thick on real devices.

HIT TEST

Shared tap detection

Tap detection is not left to the engine. A fingertip-sized tolerance is converted into metres for the current zoom, so lines stay equally easy to hit at any scale; geodesic lines are tested along the arc.

Figure · crossing the date line
180°
Passed as-is: some engines draw the line the long way around the globe.
180°
Through MapConductor: split at the boundary, so every engine takes the short side.
Sample video · One SwiftUI implementation on Google Maps and MapLibre

04 · Tapping

onClick receives the line state and the position tapped along the line. That position is snapped to the closest point on the line, so you can drop a marker there or measure from it.

event.state
The tapped line state itself — read its colour or extra payload.
event.clicked
A coordinate on the line: the closest point, not the raw finger position.
Tolerance
A fingertip-sized margin, converted into metres for the current zoom.
PolylineClickPageViewModel.kt
// タップ位置にマーカーを落とす
fun onPolylineClick(event: PolylineEvent) {
    markers = markers + MarkerState(
        position = event.clicked,
        animation = MarkerAnimation.Drop,
        icon = DefaultMarkerIcon(fillColor = event.state.strokeColor),
    )
}

Segments outside the visible region are skipped, so many long routes stay responsive. Where lines overlap, the closest one wins.

Related pages