Cambiar diseño de mapa (teselas)
La apariencia del mapa se decide solo con mapDesignType. Elija un preset preparado para el proveedor o defina su propio diseño especificando un JSON de estilo y una URL de teselas. El cambio solo requiere asignar la propiedad; no es necesario volver a crear el mapa.
01 · Tipo de diseño
Cualquier diseño de proveedor implementa MapDesignTypeInterface (en iOS, MapDesignTypeProtocol). Con solo recordar los tres elementos comunes, la forma de manejarlo es la misma incluso si cambia el proveedor.
Valor que identifica el diseño. Un valor nativo del proveedor (como la constante mapType de Google) o una cadena.
El valor real que se pasa al motor de mapas del proveedor. Incluye la URL del JSON de estilo o definiciones de mosaicos.
Reglas para cambiar la atribución según el nivel de zoom y el área visible. Obligatorio al usar mosaicos personalizados.
02 · Presets
Los paquetes de cada proveedor incluyen los diseños estándar disponibles para ese proveedor como constantes. La aplicación de ejemplo usa esta lista tal cual como opciones.
iOS · React
React: MapboxDesign
En React: Streets · Outdoors · Light · Dark · SatelliteStreets, más el JSON de estilo de la familia OsmBright / MapTiler
iOS / React: ArcGISMapDesign
React: TomTomDesign
React tiene además StandardLight / Dark · DrivingLight / Dark · MonoLight / Dark
React
React
React
React
Solo se señalan las diferencias entre plataformas. Las filas sin notas tienen el mismo nombre de tipo y el mismo nombre de constante de preset en las tres plataformas.
03 · Cambiar
Asigne un valor a mapDesignType del objeto de estado de la vista de mapa. Como el estado se observa, la apariencia del mapa cambia en el momento de la asignación.
// state es MapViewStateInterface<*>; acótalo al tipo del proveedor antes de asignar
when (state) {
is GoogleMapViewStateInterface ->
state.mapDesignType = GoogleMapDesign.Satellite
is MapLibreViewStateInterface ->
state.mapDesignType = MapLibreDesign.OsmBrightJa
is MapTilerViewStateInterface ->
state.mapDesignType = MapTilerDesign.Toner
}// El diseño inicial se pasa al crear el estado
@StateObject private var mapLibreState = MapLibreViewState(
mapDesignType: MapLibreDesign.DemoTiles,
cameraPosition: viewModel.initCameraPosition
)
// Cambiar es solo asignar a una propiedad @Published
mapLibreState.mapDesignType = MapLibreDesign.OsmBrightJaconst [mapViewState, setMapViewState] =
useState<MapViewStateInterface<MapDesignTypeInterface<unknown>> | null>(null);
const handleDesignChange = (designId: string) => {
const option = mapDesignOptions.find(item => item.design.id === designId);
if (!mapViewState || !option) return;
mapViewState.mapDesignType = option.design;
};04 · Definir un diseño personalizado
El tipo de preset está expuesto directamente como constructor. Si pasa un ID y una URL del JSON de estilo (vector) o una plantilla de URL de teselas (ráster), puede usar estilos propios o teselas del GSI igual que los presets.
// MapLibreDesign es una data class: dale la URL de un JSON de estilo y ya tienes tu propio diseño
val GsiPale =
MapLibreDesign(
id = "gsi-pale",
styleJsonURL = "https://example.com/styles/gsi-pale/style.json",
attributionRules =
listOf(
AttributionRule(attribution = "Mosaicos del GSI"),
AttributionRule(attribution = "GEBCO", minZoom = 5, maxZoom = 8),
),
)private val mapLibreDesigns =
listOf(
MapDesignOption(label = "OsmBright", design = MapLibreDesign.OsmBright),
MapDesignOption(label = "GSI Pale", design = GsiPale),
)// Envuelve la constante nativa mapType tal cual y solo añade la atribución
val NormalWithNotice =
GoogleMapDesign.Custom(
id = MAP_TYPE_NORMAL,
attributionRules = listOf(AttributionRule(attribution = "Datos propios 2026")),
)En proveedores donde el tipo de mapa se decide mediante constantes nativas (como Google Maps), use GoogleMapDesign.Custom y pase una constante a id para reemplazar solo el atribución. MapTiler, Mapbox, HERE, etc., también tienen un constructor de la misma forma.
// public init(id:styleJsonURL:attributionRules:) es la entrada para tu propio diseño
let gsiPale = MapLibreDesign(
id: "gsi-pale",
styleJsonURL: "https://example.com/styles/gsi-pale/style.json",
attributionRules: [
AttributionRule(attribution: "Mosaicos del GSI"),
AttributionRule(attribution: "GEBCO", minZoom: 5, maxZoom: 8),
]
)private let mapLibreDesigns = [
MapDesignOption(label: "DemoTiles", design: MapLibreDesign.DemoTiles),
MapDesignOption(label: "GSI Pale", design: gsiPale),
]
// Haz cast al tipo del proveedor al aplicarlo
if let design = option.design as? MapLibreDesign {
mapLibreState.mapDesignType = design
}Al ser una estructura, se define con let y se puede compartir en cualquier lugar. Como MapDesignOption en ViewModel tiene design: Any, se filtra al tipo del proveedor con as? al aplicarlo.
const GSI_STANDARD_DESIGN = new LeafletDesign({
id: 'gsi-standard',
tileUrl: 'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png',
tileOptions: { minZoom: 5, maxZoom: 18, tileSize: 256 },
attributionRules: GSI_STANDARD_ATTRIBUTION_RULES,
});
export const LEAFLET_DESIGNS: MapDesignOption[] = [
{ label: 'OpenStreetMap', design: LeafletDesign.OpenStreetMap },
{ label: 'GSI Standard', design: GSI_STANDARD_DESIGN },
{ label: 'None', design: LeafletDesign.None },
];// new MapLibreDesign(id, styleJsonURL, attributionRules?)
const GSI_PALE = new MapLibreDesign(
'gsi-pale',
'https://example.com/styles/gsi-pale/style.json',
[{ attribution: GSI_ATTRIBUTION }],
);
export const MAPLIBRE_DESIGNS: MapDesignOption[] = [
{ label: 'OsmBrightJa', design: MapLibreDesign.OsmBrightJa },
{ label: 'GSI Pale', design: GSI_PALE },
];Leaflet se define con mosaicos ráster, MapLibre con JSON de estilo. Dado que los metadatos del diseño están en el mismo paquete que los SDK de tiempo de ejecución pesados de cada proveedor, en los ejemplos se hace una importación dinámica por proveedor para separar los fragmentos.
05 · Notas de origen (attributionRules)
Al usar mosaicos propios, se incluyen las condiciones de notificación del proveedor de mosaicos como reglas. Solo se seleccionan automáticamente las notificaciones necesarias según el zoom y el área visible de la cámara.
06 · Aplicación de ejemplo
Las 3 plataformas incluyen una interfaz de usuario para cambiar el diseño. La construcción de la interfaz es una implementación directa en cada plataforma; solo el proceso de asignación es común.
val mapViewState = rememberMapLibreMapViewState(
mapDesign = MapLibreDesign.DemoTiles,
cameraPosition = MapCameraPosition(
position = GeoPoint.fromLatLong(21.382314, -157.933097),
zoom = 12.0,
),
)
val designs = listOf(
"Demo" to MapLibreDesign.DemoTiles,
"OSM Bright" to MapLibreDesign.OsmBrightJa,
"Toner" to MapLibreDesign.MapTilerTonerJa,
)
MapLibreMapView(state = mapViewState, modifier = Modifier.weight(1f))
Row {
designs.forEach { (label, design) ->
// Just an assignment. The map is not rebuilt, so the camera stays where it is
Button(onClick = { mapViewState.mapDesignType = design }) { Text(label) }
}
}