Skjölun / Grunnatriði / Upplýsingablaðra

Upplýsingablaðra

Blaðra fest við merki, skrifuð í viðmótskóða hvers vettvangs — Compose-composable, SwiftUI-sýn, React-einingar.

ANDROID
com.mapconductor.compose.info
iOS
MapConductorCore
REACT
@mapconductor/js-sdk-react

01 · Hvernig það virkar

Sama form á öllum þremur vettvöngunum: haltu völdu merki í stöðu og teiknaðu blöðruna aðeins á meðan það er valið. Að opna og loka er staða forritsins, ekki SDK-sins.

Haltu valinu

STEP 01

Geymdu valda merkið (eða auðkenni þess) í stöðu — Set þegar fleiri en ein blaðra má vera opin.

Teiknaðu inni í kortinu

STEP 02

Settu Marker og InfoBubble inn í kortaumgjörðina og teiknaðu blöðruna aðeins þegar merkið er valið.

Hreinsaðu við smell á kortið

STEP 03

onMapClick á kortinu hreinsar valið; onClick á merkinu setur það.

Sýnidæmi · blaðra opnuð með því að velja merki hennar

02 · Fjögur mynstur

Síðurnar fjórar undir infobubble í sýnisforritinu samsvara nákvæmlega fjórum útfærslumynstrum. Veldu mynstur og vettvang til að sjá það sýnidæmi.

Vettvangur

Ein lína

Einfaldasta formið: ein lína af texta úr extra á merkinu. Rammi, hali og spássía haldast sjálfgefin, svo það eina sem þú skrifar er innihaldið.

SimpleTextBubblePage.kt
var selectedMarker by remember { mutableStateOf<MarkerState?>(null) }
val markerState = remember {
    MarkerState(
        position = GeoPoint.fromLatLong(37.7749, -122.4194),
        icon = DefaultMarkerIcon(fillColor = Color.Blue, label = "SF"),
        extra = "San Francisco - The Golden Gate City",
        onClick = { selectedMarker = it },
    )
}

MapViewContainer(
    modifier = Modifier.fillMaxSize(),
    state = mapViewState,
    onMapClick = { selectedMarker = null },
    onMapLoaded = { selectedMarker = markerState },
) {
    Marker(markerState)

    selectedMarker?.let { marker ->
        InfoBubble(marker = marker) {
            Text(
                text = marker.extra as? String ?: "No information",
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier.padding(4.dp),
            )
        }
    }
}
Forskoðun
San Francisco - The Golden Gate City
SF

Sjálfgefinn hali situr beint fyrir ofan merkið (tailOffset x:0.5 / y:1.0).

Endurstílað

Breyttu rammanum. Til að stilla liti og hornradíus taka Android og React við stökum viðföngum og iOS við InfoBubbleStyle. Til að teikna rammann og halann sjálf/ur nota allir þrír vettvangarnir InfoBubbleCustom — Canvas í Compose, Shape í SwiftUI, ::before / ::after í CSS.

StyledInfoBubblePage.kt
val markerState1 by remember {
    mutableStateOf(
        MarkerState(
            id = "marker1",
            position = GeoPoint.fromLatLong(37.7749, -122.4194),
            icon = DefaultMarkerIcon(
                fillColor = Color.Blue,
                infoAnchor = Offset(0.5f, 0.25f),
                label = "1",
            ),
            draggable = true,
            onClick = onMarkerClick,
        ),
    )
}

selectedMarker?.let { marker ->
    val text = GeoPoint.from(marker.position).toUrlValue(6)
    InfoBubbleCustom(
        marker = marker,
        tailOffset = Offset(0f, 0.5f), // Tengt á miðri vinstri brún
    ) {
        RightTailInfoBubble(
            bubbleColor = Color.White,
            borderColor = Color.Black,
        ) {
            Text(text = text, color = MaterialTheme.colorScheme.primary)
        }
    }
}
StyledInfoBubblePage.kt · RightTailInfoBubble
@Composable
private fun RightTailInfoBubble(
    bubbleColor: Color,
    borderColor: Color,
    contentPadding: Dp = 8.dp,
    cornerRadius: Dp = 4.dp,
    tailSize: Dp = 8.dp,
    content: @Composable () -> Unit,
) {
    Box(modifier = Modifier.wrapContentSize()) {
        Canvas(modifier = Modifier.matchParentSize()) {
            val path = Path().apply {
                // Teiknaðu ávalan ferhyrning og bættu þríhyrndum hala á miðja vinstri brún
                lineTo(tail, height / 2 + tail / 2)
                lineTo(0f, height / 2)
                lineTo(tail, height / 2 - tail / 2)
                close()
            }
            drawPath(path, color = bubbleColor, style = Fill)
            drawPath(path, color = borderColor, style = Stroke(width = 2f))
        }
        Box(modifier = Modifier.padding(start = contentPadding + tailSize)) {
            content()
        }
    }
}
StyledInfoBubblePage.tsx
const marker1 = createMarkerState({
  id: 'marker1',
  position: createGeoPoint({ latitude: 37.7749, longitude: -122.4194 }),
  icon: new ColorDefaultIcon('#2563eb', {
    label: '1',
    labelTextColor: '#ffffff',
    infoAnchor: { x: 0.5, y: 0.25 },
  }),
  draggable: true,
  onClick: state => setSelectedId(state.id),
});

const activeMarker = markers.find(m => m.id === selectedId);

<Markers states={markers} />
{activeMarker && (
  <InfoBubbleCustom marker={activeMarker} tailOffset={{ x: 0, y: 0.5 }}>
    <div className="right-tail-info-bubble">
      {activeMarker.position.toUrlValue(6)}
    </div>
  </InfoBubbleCustom>
)}
index.css
.right-tail-info-bubble {
  position: relative;
  width: max-content;
  max-width: 220px;
  padding: 8px;
  margin-left: 8px;
  border: 2px solid #000;
  border-radius: 4px;
  background: #fff;
  color: #2563eb;
}
/* Notaðu ::before / ::after til að leggja þríhyrning sem vísar til vinstri yfir hann sem hala */
Forskoðun
1
37.7749,-122.419404

Tengipunkturinn ræðst af tailOffset (bólumegin) og infoAnchor táknsins (merkismegin).

Ríkulegt innihald

Settu hlut í extra og fléttaðu inn heila umbrot — fyrirsögn, lýsingu, einkunn. Stílun rammans helst í bubbleColor / borderColor / contentPadding / cornerRadius svo innihaldskóðinn þinn fjalli aðeins um innihald.

RichContentBubblePage.kt
data class LocationInfo(
    val name: String,
    val description: String,
    val rating: Float,
) : Serializable

selectedMarker?.let { marker ->
    val info = marker.extra as? LocationInfo ?: return@let
    InfoBubble(
        marker = marker,
        bubbleColor = if (isDarkTheme) Color.Black else Color.White,
        borderColor = if (isDarkTheme) Color.Gray else Color.Black,
        contentPadding = 16.dp,
        cornerRadius = 12.dp,
    ) {
        Column(modifier = Modifier.width(200.dp)) {
            Text(info.name, style = MaterialTheme.typography.headlineSmall,
                fontWeight = FontWeight.Bold)
            Spacer(Modifier.height(8.dp))
            Text(info.description, style = MaterialTheme.typography.bodyMedium)
            Spacer(Modifier.height(8.dp))
            Row(verticalAlignment = Alignment.CenterVertically) {
                repeat(5) { index ->
                    Icon(Icons.Default.Star, contentDescription = null,
                        tint = if (index < info.rating.toInt()) Color.Yellow else Color.Gray,
                        modifier = Modifier.size(16.dp))
                }
                Text(" ${info.rating}/5", style = MaterialTheme.typography.bodySmall)
            }
        }
    }
}
Forskoðun
Golden Gate Park

A large urban park with gardens, museums, and recreational areas.

★★★★4.5/5
🌳

Sýnidæmin fyrir Android og iOS skipta líka um ramma- og bakgrunnslit í dökkri stillingu.

Margar blöðrur

Haltu valinu sem Set til að hafa margar blöðrur opnar. Teiknaðu InfoBubble aðeins fyrir opin merki, og settu snertistjóra í innihaldið svo blaðran geti lokað sér sjálf.

MultipleBubblesPage.kt
var selectedMarkers by remember { mutableStateOf(setOf<String>()) }

val onMarkerClick: OnMarkerEventHandler = { markerState ->
    selectedMarkers =
        if (selectedMarkers.contains(markerState.id)) {
            selectedMarkers - markerState.id
        } else {
            selectedMarkers + markerState.id
        }
}

MapViewContainer(
    state = mapViewState,
    onMapClick = { selectedMarkers = emptySet() },
) {
    markerStates.forEach { markerState ->
        Marker(markerState)

        if (selectedMarkers.contains(markerState.id)) {
            InfoBubble(
                marker = markerState,
                bubbleColor = Color.White,
                borderColor = Color.Black,
            ) {
                Column(modifier = Modifier.clickable(true, onClick = {
                    selectedMarkers = selectedMarkers - markerState.id
                })) {
                    Text(markerState.extra as String, fontWeight = FontWeight.Bold)
                    Text("Tap to close", color = Color.Gray)
                }
            }
        }
    }
}
Forskoðun
Restaurant ATap to close
1
Hotel BTap to close
2
Shop CTap to close
3

Í öllum sýnidæmum lokar smellur á kortið þeim öllum (aftur í tómt Set).

03 · API

InfoBubble teiknar rammann með halanum fyrir þig; InfoBubbleCustom sér aðeins um staðsetninguna. Á iOS eru stílviðföngin tekin saman í InfoBubbleStyle.

PARAM
ANDROID
REACT
Lýsing
marker
nauðsynlegt
nauðsynlegt
Merkið sem blaðran er fest við; staðsetning þess og táknstærð ákvarða tengipunktinn.
bubbleColor
Color.White
'#ffffff'
Bakgrunnslitur blöðrunnar.
borderColor
Color.Black
'#000000'
Litur rammans.
contentPadding
8.dp
8
Innri spássía.
cornerRadius
4.dp
4
Hornradíus.
tailSize
8.dp
8
Stærð halans.
content / children
nauðsynlegt
nauðsynlegt
Innihald blöðrunnar — venjulegur viðmótskóði vettvangsins.
InfoBubbleStyle · iOS

iOS tekur stílviðföngin saman í þessa strúktúru og sendir hana sem style.

InfoBubbleStyle(
  bubbleColor: Color,
  borderColor: Color,
  contentPadding: CGFloat,
  cornerRadius: CGFloat,
  tailSize: CGFloat
)
InfoBubbleCustom

Teiknaðu rammann og halann sjálf/ur; SDK-ið sér aðeins um að stilla eininguna af.

marker: MarkerState
tailOffset: Offset   // ios: CGPoint
content / children
InfoBubble (position)

Festir blöðru við hnit í stað merkis. Allir þrír vettvangarnir nota InfoBubble með position — yfirhleðsluna InfoBubble(position:) á Compose og iOS.

position: GeoPoint
// react: <InfoBubble position=… />
// compose / ios: InfoBubble(position:)

04 · Athugasemdir

Engin skörun án tákns

Merki án tákns er meðhöndlað sem sjálfgefna 48 px nælan með festipunkt í oddinum, svo blaðran hliðrast um raunverulega stærð nælunnar í stað þess að falla ofan á merkið.

Hliðraðu með infoAnchor

Tengipunkturinn merkismegin kemur úr infoAnchor (Offset í Compose, x/y í React). Blaðran heldur áfram að fylgja meðan merkið er dregið.

Innihald blöðrunnar tekur við atburðum

clickable í Compose, bendingar í SwiftUI og onClick í React virka öll inni í blöðrunni, óháð onMapClick á kortinu — svo lokunaraðgerðin getur búið í innihaldinu.

Tengdar síður