Si necesitas una alternativa a Google Maps para Capacitor, tienes tres caminos realistas: mantener el plugin oficial @capacitor/google-maps y trabajar alrededor de sus limitaciones, renderizar el mapa dentro del WebView con una biblioteca JavaScript como MapLibre GL JS o Leaflet, o usar un plugin de mapa nativo construido sobre otro SDK. Capgo no incluye su propio plugin de renderizado de mapas, por lo que esta guía compara las opciones de forma neutral y muestra los plugins de Capgo que funcionan bien junto a cualquier mapa: transferencia de navegación, geocodificación y ubicación en segundo plano.
Por qué los desarrolladores buscan alternativas a @capacitor/google-maps
El plugin oficial (versión 8 para Capacitor 8) integra el SDK nativo de Google Maps en iOS y Android, y el API de JavaScript de Google Maps en la web. Funciona, pero estos puntos se repiten una y otra vez.
Una cuenta de Google Cloud con facturación activa en cada plataforma
El plugin necesita API keys vinculadas a una cuenta de Google Cloud con facturación habilitada en Android, iOS y web. Los precios de Google para las cargas de mapas nativos en móvil son generosos, pero aun así tienes que configurar la facturación, restringir las keys por plataforma y vigilar las cuotas. Las cargas de mapas web y servicios como Places y Directions se facturan por uso una vez superados los límites gratuitos. Revisa la página de precios actual de Google Maps Platform antes de decidirte, porque el modelo cambió en 2025.
En Android, el mapa se dibuja detrás del WebView
En iOS, la vista del mapa se coloca dentro del scroll view del WebView. En Android, se renderiza debajo de todo el WebView, y el plugin la mueve para seguir al <capacitor-google-map> elemento. Cada capa que esté por encima debe ser transparente:
/* Required on Android with @capacitor/google-maps */
html,
body,
ion-content,
ion-content::part(background) {
background: transparent !important;
--background: transparent;
}
Este es el problema número uno de «mi mapa aparece en blanco». También dificulta los overlays personalizados, los modales y las transiciones de página, porque tu HTML queda encima de una vista nativa.
Los marcadores se pueden añadir y eliminar, pero no actualizar
El API tiene addMarker, addMarkers, removeMarker y removeMarkers, pero no updateMarker. Una posición de vehículo en tiempo real implica eliminar y añadir en cada actualización, lo que puede causar parpadeos y consume llamadas al bridge.
Estilo y funciones limitados en nativo
Algunas opciones son solo para web, por ejemplo mapId para estilos basados en la nube, y region y language. Obtienes marcadores, clustering, polilíneas, polígonos, círculos, superposiciones de teselas, control de cámara y listeners de clic. Si necesitas estilos basados en datos, heatmaps o edificios 3D de la misma manera en todas las plataformas, te encontrarás con límites.
Las opciones de un vistazo
| Opción | Renderizado | Se necesita clave de API | Fuente de teselas | Ideal para |
|---|---|---|---|---|
@capacitor/google-maps |
SDK nativo (Android, iOS), JS en web | Sí, facturación habilitada | Apps que desean datos de Google y rendimiento nativo | |
| MapLibre GL JS | WebGL en el WebView | Depende del proveedor de tiles | Cualquier fuente de vector tiles, autoalojado posible | Mapas con estilo personalizado, casi offline, sin vendor lock in |
| Leaflet | DOM y canvas en el WebView | Depende del proveedor de tiles | Tiles ráster (basados en OSM u otros) | Mapas simples, bundle pequeño, muchos plugins |
| Google Maps JS API en WebView | Renderizador JS de Google | Sí | Same Google look on all platforms, full JS feature set | |
| Plugins nativos de MapLibre o Mapbox | SDK nativo | Depende | Cualquiera / Mapbox | Datos pesados, sesiones largas, gestos nativos |
No hay un único ganador. La elección depende del volumen de datos, las necesidades de estilo y cuánto quieras depender de un solo proveedor.
Opción 1: MapLibre GL JS en el WebView
MapLibre GL JS es el fork de código abierto de Mapbox GL JS v1. Renderiza vector tiles con WebGL y funciona bien en WKWebView y Android System WebView. Es la opción más flexible si no necesitas los datos de Google.
bun add maplibre-gl
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
const map = new maplibregl.Map({
container: 'map',
style: 'https://your-tile-provider.example.com/styles/streets/style.json',
center: [2.3522, 48.8566], // [lng, lat]
zoom: 12,
});
map.addControl(new maplibregl.NavigationControl(), 'top-right');
// A marker you can move without remove/add
const courier = new maplibregl.Marker({ color: '#1d4ed8' })
.setLngLat([2.35, 48.85])
.addTo(map);
export function moveCourier(lng: number, lat: number) {
courier.setLngLat([lng, lat]);
}
Las capas GeoJSON, el estilo basado en datos y las líneas de ruta son funciones nativas:
map.on('load', () => {
map.addSource('route', {
type: 'geojson',
data: {
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: [
[2.3522, 48.8566],
[2.3376, 48.8606],
[2.2945, 48.8584],
],
},
},
});
map.addLayer({
id: 'route-line',
type: 'line',
source: 'route',
paint: { 'line-color': '#2563eb', 'line-width': 5 },
});
});
Cosas a tener en cuenta:
- Necesitas una fuente de tiles. Las opciones incluyen hosts comerciales de vector tiles o el self-hosting de tiles generados con datos de OpenStreetMap. Los servidores públicos de OpenStreetMap tienen una política de uso que no permite tráfico pesado de apps.
- Muestra siempre la atribución que requiera tu proveedor de tiles.
- Al ser code web puro, el mismo mapa funciona en una vista previa del navegador, lo que acelera el desarrollo.
Opción 2: Leaflet
Leaflet es ligero y maduro. Es ideal para mapas con unos cientos de marcadores, raster tiles e interacciones sencillas.
bun add leaflet
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
const map = L.map('map').setView([48.8566, 2.3522], 13);
L.tileLayer('https://tiles.example.com/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors',
}).addTo(map);
L.marker([48.8584, 2.2945]).addTo(map).bindPopup('Eiffel Tower');
En apps con bundle, las rutas de los iconos de marcador por defecto de Leaflet suelen fallar. Importa las imágenes del icono y establece L.Icon.Default las opciones, o usa las tuyas L.divIcon.
Opción 3: API de Google Maps JavaScript en el WebView
Si necesitas los datos y el estilo de Google, pero quieres que el mapa se comporte como cualquier otro elemento HTML, carga el API de Maps JavaScript en el WebView en lugar del SDK nativo. Pierdes algo de fluidez nativa y cada carga de mapa cuenta como una carga web facturable, pero obtienes todo el API de JS: estilos en la nube con map IDs, marcadores avanzados y capas de datos.
Restringe la clave web por HTTP referrer. En iOS, Capacitor sirve la app desde capacitor://localhost por defecto, y en Android desde https://localhost, así que añade esos orígenes a las restricciones de la clave y prueba ambos.
Opción 4: Plugins nativos basados en otros SDKs
La comunidad ofrece wrappers nativos para MapLibre Native o los SDKs de Mapbox. Ofrecen gestos y rendimiento nativos con cualquier fuente de tiles. Antes de elegir uno, verifica que soporte Capacitor 8, tenga una versión reciente, soporte Swift Package Manager en iOS (la opción por defecto en nuevos proyectos iOS de Capacitor 8) y cubra los tipos de overlay que necesitas. Los plugins de mapas nativos tienen el mismo trade-off de capas que el plugin oficial: el mapa es una vista nativa y tu HTML tiene que maquetarse alrededor.
Mantén @capacitor/google-maps si
- Necesitas el mapa base de Google, Places y datos de Street View.
- Tu mapa es una vista a pantalla completa, no una tarjeta pequeña dentro de contenido con scroll.
- Puedes asumir quitar y volver a añadir para mover marcadores, o actualizar posiciones con poca frecuencia.
Si decides mantenerlo, configura la transparencia CSS de arriba y aplica el <capacitor-google-map> elemento un tamaño explícito, llama a destroy() al salir de la página, y establece skipLibCheck: true en tsconfig.json como exige el README del plugin.
Plugins que combinan bien con cualquier mapa
Sin importar qué renderice el mapa, estos plugins Capgo cubren las partes nativas que un mapa WebView no puede hacer por sí solo.
Entregar la navegación paso a paso
Crear la navegación es un proyecto en sí mismo. La mayoría de las apps abren la app de navegación preferida del usuario. @capgo/capacitor-launch-navigator soporta Apple Maps, Google Maps, Waze y muchos otros:
import { LaunchNavigator, TransportMode } from '@capgo/capacitor-launch-navigator';
await LaunchNavigator.navigate({
destination: [48.8584, 2.2945], // [lat, lng]
options: { transportMode: TransportMode.DRIVING },
});
Geocodificar sin un servicio web
@capgo/capacitor-nativegeocoder usa los geocodificadores de la plataforma en iOS y Android, que no necesitan una clave de Google en el dispositivo:
import { NativeGeocoder } from '@capgo/capacitor-nativegeocoder';
const { addresses } = await NativeGeocoder.reverseGeocode({
latitude: 48.8584,
longitude: 2.2945,
maxResults: 1,
});
console.log(addresses[0]?.thoroughfare, addresses[0]?.locality);
const result = await NativeGeocoder.forwardGeocode({
addressString: '5 Avenue Anatole France, Paris',
maxResults: 1,
});
console.log(result.addresses[0]?.latitude, result.addresses[0]?.longitude);
En la web, el plugin usa la API de Google y necesita la apiKey opción.
Mostrar la posición del usuario, incluso en segundo plano
Para un "punto azul" en primer plano, @capacitor/geolocation es suficiente. Para seguir rastreando mientras la app está en segundo plano, o para disparar eventos cuando los usuarios entran en lugares, usa @capgo/background-geolocation, y pasa los puntos al mapa que hayas elegido.
Solución de problemas con los mapas en Capacitor
Mapa en blanco en Android con el plugin oficial. Falta transparencia en un elemento padre. Inspecciona con Chrome DevTools mediante chrome://inspect y busca cualquier color de fondo entre <html> y el elemento del mapa.
El elemento del mapa tiene altura cero. Los contenedores de mapa no tienen tamaño intrínseco. Establece una altura explícita o usa flex layout con una altura fija en el padre.
El mapa WebGL se ve borroso o lento en Android. Asegúrate de que el System WebView esté actualizado, reduce el número de capas y evita recrear el mapa en cada cambio de ruta. Créalo una vez y reutilízalo.
Los tiles no cargan en builds de release. Revisa tu Content Security Policy y la configuración de seguridad de red; asegúrate de que el host de los tiles use HTTPS.
El mapa falla tras cambiar la URL del estilo de los tiles. Las URLs de estilo y tiles son solo configuración de JavaScript. Puedes cambiar de proveedor para los usuarios actuales con actualizaciones Live Update de Capgo, sin necesidad de un release en la app store, siempre que no cambie ningún code nativo.
Cómo decidir
- Necesitas datos de Google y rendimiento nativo en un mapa a pantalla completa: quédate con
@capacitor/google-maps. - Necesitas estilos personalizados, sin facturación de Google y un mapa tipo HTML: MapLibre GL JS.
- Necesitas un mapa sencillo con pocos marcadores: Leaflet.
- Necesitas el aspecto de Google en un layout con scroll: Google Maps JS API en el WebView.
Sea cual sea la opción, pruébalo pronto en un dispositivo Android de gama baja. Para más bloques nativos, explora directorio del plugin Capgo.