MapCameraPositionInterface (posición de cámara)
MapCameraPositionInterface representa la posición de vista de la cámara, su orientación y la región visible en el mapa. Define hacia dónde mira la cámara, qué parte del mapa se muestra y el punto de vista usado para mostrar el mapa.
Interfaz e implementación
Interfaz MapCameraPositionInterface
interface MapCameraPositionInterface { val position: GeoPointInterface val zoom: Double val bearing: Double val tilt: Double val paddings: MapPaddingsInterface? val visibleRegion: VisibleRegion?}MapCameraPosition
La implementación principal proporciona datos inmutables de posición de cámara:
data class MapCameraPosition( override val position: GeoPoint, override val zoom: Double = 0.0, override val bearing: Double = 0.0, override val tilt: Double = 0.0, override val paddings: MapPaddingsInterface? = MapPaddings.Zeros, override val visibleRegion: VisibleRegion? = null) : MapCameraPositionInterfacePropiedades
Posición de cámara
position: GeoPointInterface: El punto central geográfico de la vista de la cámarazoom: Double: El nivel de zoom (sigue aproximadamente la escala de Google Maps)bearing: Double: La orientación de brújula en grados (0 = norte, 90 = este)tilt: Double: El ángulo de inclinación de la cámara en grados (0 = vista vertical hacia abajo, 90 = horizontal)
Configuración de vista
paddings: MapPaddingsInterface?: Padding del viewport que afecta la región visiblevisibleRegion: VisibleRegion?:(solo lectura)Los límites geográficos que realmente se muestran en pantalla
Métodos de creación
Posición predeterminada
// Posición de cámara predeterminada en el origenval defaultPosition = MapCameraPosition.DefaultPosición personalizada
// Posición de cámara básicaval sanFrancisco = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), zoom = 15)
// Cámara con orientación e inclinaciónval aerialView = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), zoom = 18, bearing = 45, // Northeast direction tilt = 60 // Angled view)Niveles de zoom
Los niveles de zoom de MapConductor siguen aproximadamente la escala de Google Maps, aunque pueden variar ligeramente entre SDKs de mapas:
- 0-2: Vista mundial, se muestran continentes
- 3-5: Nivel de país
- 6-9: Nivel de estado/región
- 10-12: Nivel de ciudad
- 13-15: Nivel de distrito/barrio
- 16-18: Nivel de calle
- 19-21: Nivel de edificio (alto detalle)
// Different zoom levels for different use casesval worldView = MapCameraPosition( position = GeoPoint.fromLatLong(0, 0), zoom = 2 // Mostrar continentes)
val cityView = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), zoom = 12 // Mostrar toda la ciudad)
val streetView = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), zoom = 17 // Mostrar calles individuales)Orientación e inclinación
Orientación (rotación)
La orientación rota el mapa alrededor del punto central:
// Norte arriba (predeterminado)val northUp = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), bearing = 0)
// Este arribaval eastUp = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), bearing = 90)
// Seguir la orientación de la rutaval routeBearing = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), bearing = 135, // Sureste zoom = 18.0)Inclinación (vista 3D)
La inclinación proporciona un ángulo de visualización 3D:
// Vista desde arriba (predeterminada)val topDown = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), tilt = 0)
// Inclinación para dar profundidadval angled = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), tilt = 30, zoom = 16)
// Inclinación máxima a nivel de calleval streetLevel = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), tilt = 80, bearing = 45, zoom = 19)Valores negativos de tilt - mirar hacia adelante
Cuando tilt se establece en un valor negativo, la cámara usa una vista elevada que mira hacia arriba por encima del horizonte. Un tilt positivo se trata como una vista que mira hacia abajo al suelo, mientras que un tilt negativo se trata como una vista que mira hacia adelante en la dirección de bearing.
// 通常の俯瞰ビュー(従来の動作)MapCameraPosition( position = GeoPoint(35.68, 139.76), zoom = 15.0, tilt = 60.0, // 地面を60度の角度で見下ろす)
// 前方(水平線上方)を見るMapCameraPosition( position = GeoPoint(35.68, 139.76), zoom = 15.0, tilt = -30.0, // 水平線より30度上方を見る bearing = 45.0,)
// ArcGIS はネイティブ対応- ArcGIS: ArcGIS のカメラ仕様と同じく、負の tilt にネイティブ対応します。
- Google Maps / Mapbox / MapLibre / HERE: 上向きピッチを直接表現できないため、カメラ位置を固定し、bearing 方向の前方へターゲットを移動してシミュレーションします。ネイティブの仰角ビューと完全に同一にはなりません。
Región visible
La región visible describe el área geográfica real que se muestra en pantalla después de considerar la posición de cámara, el nivel de zoom, la orientación, la inclinación y el padding del viewport.
Clase VisibleRegion
data class VisibleRegion( val bounds: GeoRectBounds, // Rectángulo delimitador completo val nearLeft: GeoPointInterface?, // Esquina inferior izquierda (lado cercano a la cámara) val nearRight: GeoPointInterface?, // Esquina inferior derecha (lado cercano a la cámara) val farLeft: GeoPointInterface?, // Esquina superior izquierda (lado lejano a la cámara) val farRight: GeoPointInterface? // Esquina superior derecha (lado lejano a la cámara))Propiedades
bounds: GeoRectBounds: Límites geográficos del rectángulo que contiene toda la región visible. Este es el rectángulo delimitador más pequeño que contiene todo el contenido visible.nearLeft: GeoPointInterface?: Coordenadas geográficas de la esquina inferior izquierda de la región visible. “near” se refiere al lado más cercano a la posición de la cámara.nearRight: GeoPointInterface?: Coordenadas geográficas de la esquina inferior derecha de la región visible.farLeft: GeoPointInterface?: Coordenadas geográficas de la esquina superior izquierda de la región visible. “far” se refiere al lado más lejano a la posición de la cámara.farRight: GeoPointInterface?: Coordenadas geográficas de la esquina superior derecha de la región visible.
Uso de VisibleRegion
@Composablefun VisibleRegionExample() {
val mapViewState = rememberMapboxMapViewState( cameraPosition = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), zoom = 15.0 ), ) var visibleRegionInfo by remember { mutableStateOf<VisibleRegion?>(null) }
// Reemplaza MapView por el SDK de mapas que elijas, como GoogleMapView o MapboxMapView MapboxMapView( state = mapViewState, modifier = modifier, onCameraMoveEnd = { cameraPosition -> cameraPosition.visibleRegion?.let { visibleRegion -> visibleRegionInfo = visibleRegion } }, ) { // Mostrar información de la región visible visibleRegionInfo?.let { region -> // Mostrar los límites como un polígono region.bounds.let { bounds -> if (!bounds.isEmpty) { val sw = bounds.southWest!! val ne = bounds.northEast!!
Polygon( points = listOf( sw, GeoPoint.fromLatLong(sw.latitude, ne.longitude), ne, GeoPoint.fromLatLong(ne.latitude, sw.longitude), sw ), strokeColor = Color.Blue, strokeWidth = 2.dp, fillColor = Color.Blue.copy(alpha = 0.1f) ) } } } }}Animaciones y transiciones
Movimiento suave de cámara
@Composablefun AnimatedCameraExample() { val locations = listOf( GeoPoint.fromLatLong(37.7749, -122.4194), // San Francisco GeoPoint.fromLatLong(40.7128, -74.0060), // New York GeoPoint.fromLatLong(51.5074, -0.1278) // London )
val mapViewState = rememberHereMapViewState( cameraPosition = MapCameraPosition( position = locations[0], zoom = 6.0 ), )
var currentIndex by remember { mutableStateOf(0) }
// Animar a la siguiente ubicación cada 5 segundos LaunchedEffect(Unit) { while (true) { delay(5000) currentIndex = (currentIndex + 1) % locations.size
val targetPosition = MapCameraPosition( position = locations[currentIndex], zoom = 6.0, bearing = 0.0, tilt = 0.0 ) mapViewState.moveCameraTo(targetPosition, 1000) } }
// Replace MapView with your chosen map provider, such as GoogleMapView, MapboxMapView HereMapView( state = mapViewState, modifier = modifier, ) { // Add markers for each location locations.forEachIndexed { index, location -> Marker( position = location, icon = ColorDefaultIcon( fillColor = if (index == currentIndex) Color.Red else Color.Gray, label = when (index) { 0 -> "SF" 1 -> "NYC" 2 -> "LON" else -> "$index" } ) ) } }}Control interactivo de cámara
@Composablefun CameraControlExample(modifier: Modifier = Modifier) { val mapViewState = rememberMapLibreMapViewState( mapDesign = MapLibreDesignType( id = "debug-tiles", styleJsonURL = "https://demotiles.maplibre.org/debug-tiles/style.json", ), cameraPosition = MapCameraPosition( position = GeoPoint.fromLatLong(37.7749, -122.4194), zoom = 15.0 ), )
Column( modifier = modifier, ) { // Camera controls Row { Button( onClick = { val newZoom = mapViewState.cameraPosition.copy( zoom = (mapViewState.cameraPosition.zoom + 1) .coerceAtMost(21.0), ) mapViewState.moveCameraTo(newZoom, 500) } ) { Text("Zoom In") }
Button( onClick = { val newZoom = mapViewState.cameraPosition.copy( zoom = (mapViewState.cameraPosition.zoom - 1) .coerceAtMost(21.0), ) mapViewState.moveCameraTo(newZoom, 500) } ) { Text("Zoom Out") }
Button( onClick = { val newZoom = mapViewState.cameraPosition.copy( bearing = (mapViewState.cameraPosition.bearing + 45) % 360, ) mapViewState.moveCameraTo(newZoom, 500) } ) { Text("Rotate") } }
// Tilt slider Slider( value = mapViewState.cameraPosition.tilt.toFloat(), onValueChange = { tilt -> val newZoom = mapViewState.cameraPosition.copy( tilt = tilt.toDouble(), ) mapViewState.moveCameraTo(newZoom) }, valueRange = 0f..80f )
// Reemplaza MapView por el SDK de mapas que elijas, como GoogleMapView o MapboxMapView MapLibreMapView( state = mapViewState, ) { Marker( position = mapViewState.cameraPosition.position, icon = ColorDefaultIcon(fillColor = Color.Red) ) } }}Ajustar a límites
Usa fitBounds para mover y hacer zoom de la cámara de modo que un GeoRectBounds sea completamente visible:
val bounds = GeoRectBounds( southWest = GeoPoint.fromLatLong(37.7649, -122.4294), northEast = GeoPoint.fromLatLong(37.7849, -122.4094))mapViewState.fitBounds(bounds, padding = 32)El parámetro padding agrega un margen en píxeles en todos los lados del espacio de pantalla. Cada proveedor calcula el nivel de zoom resultante de forma nativa.
Mostrar múltiples puntos
Para encuadrar un conjunto de marcadores o puntos de ruta, extiende los límites y luego ajusta:
// Calculate bounds containing all points, then set appropriate zoomval allPoints = listOf(/* your points */)val bounds = GeoRectBounds()allPoints.forEach { bounds.extend(it) }
val centerCamera = MapCameraPosition( position = bounds.center ?: GeoPoint.fromLatLong(0.0, 0.0), zoom = calculateZoomForBounds(bounds), // Usa fitBounds en lugar del cálculo manual de zoom bearing = 0.0, tilt = 0.0)La llamada a fitBounds reemplaza el cálculo manual de zoom mostrado arriba:
val bounds = GeoRectBounds()allPoints.forEach { bounds.extend(it) }if (!bounds.isEmpty) { mapViewState.fitBounds(bounds, padding = 48)}