22/03/2008
En el desarrollo de aplicaciones móviles, los mapas se han convertido en una herramienta fundamental para ofrecer contexto geográfico, visualizar datos y mejorar la experiencia del usuario. Ya sea para mostrar la ubicación de tiendas, seguir una ruta en tiempo real o señalar puntos de interés, la capacidad de marcar ubicaciones específicas es crucial. En el ecosistema de Flutter, el paquete SfMaps de Syncfusion ofrece una solución robusta y altamente personalizable para este propósito, y su componente estrella para esta tarea es el MapMarker. A lo largo de este artículo, exploraremos en profundidad qué es un MapMarker, cómo puedes implementarlo en tus aplicaciones y cómo llevar tus mapas al siguiente nivel mediante la personalización y la gestión dinámica.

- ¿Qué es un MapMarker en Flutter SfMaps?
- Primeros Pasos: Añadiendo Marcadores a tu Mapa
- Personalización al Detalle: Dando Estilo a tus Marcadores
- Más Allá de los Símbolos: Usando Widgets Personalizados
- Mapas Vivos: Gestión Dinámica de Marcadores
- Interacción con el Usuario: Marcadores al Toque
- Preguntas Frecuentes (FAQ)
- Conclusión
¿Qué es un MapMarker en Flutter SfMaps?
Un MapMarker es un widget que te permite señalar una ubicación geográfica específica en un mapa utilizando coordenadas de latitud y longitud. Lejos de ser un simple pin en el mapa, SfMaps te da el poder de utilizar símbolos predefinidos con un alto grado de personalización o, si lo prefieres, emplear cualquier widget de Flutter que puedas imaginar como tu marcador. Esto abre un abanico de posibilidades para crear mapas visualmente atractivos y funcionales que se integren perfectamente con el diseño de tu aplicación.
Primeros Pasos: Añadiendo Marcadores a tu Mapa
Agregar marcadores es un proceso sencillo que se puede realizar tanto en capas de formas (MapShapeLayer) como en capas de mosaico (MapTileLayer). El concepto central es el mismo: utilizar la propiedad markerBuilder, que es un callback que construye un MapMarker para cada punto de datos.
Implementación en una Capa de Formas (MapShapeLayer)
Una MapShapeLayer es ideal cuando trabajas con mapas basados en datos geoJSON, como un mapa de países o regiones. Para añadir marcadores, necesitas definir un origen de datos (MapShapeSource), especificar el número inicial de marcadores con initialMarkersCount y construir cada MapMarker en el markerBuilder.

// Modelo de datos para nuestras ubicaciones class Model { const Model(this.country, this.latitude, this.longitude); final String country; final double latitude; final double longitude; } // En tu State widget... late List<Model> _data; late MapShapeSource _dataSource; @override void initState() { _data = const <Model>[ Model('Brazil', -14.235004, -51.92528), Model('Germany', 51.16569, 10.451526), Model('Australia', -25.274398, 133.775136), Model('India', 20.593684, 78.96288), Model('Russia', 61.52401, 105.318756) ]; _dataSource = MapShapeSource.asset( 'assets/world_map.json', // Tu archivo geoJSON shapeDataField: 'name', ); super.initState(); } // En el método build... SfMaps( layers: <MapLayer>[ MapShapeLayer( source: _dataSource, initialMarkersCount: _data.length, // El número de marcadores a renderizar markerBuilder: (BuildContext context, int index) { // Construimos un MapMarker para cada elemento de la lista _data return MapMarker( latitude: _data[index].latitude, longitude: _data[index].longitude, iconColor: Colors.blue, // Personalización básica ); }, ), ], ) Implementación en una Capa de Mosaico (MapTileLayer)
Si tu aplicación requiere un mapa más detallado, como los de OpenStreetMap, usarás una MapTileLayer. El proceso para añadir marcadores es prácticamente idéntico al anterior, lo que demuestra la consistencia de la API de SfMaps.
// Usamos el mismo modelo de datos 'Model' // En tu State widget... late List<Model> _data; @override void initState() { _data = const <Model>[ Model('Brazil', -14.235004, -51.92528), Model('Germany', 51.16569, 10.451526), // ... resto de los datos ]; super.initState(); } // En el método build... SfMaps( layers: <MapLayer>[ MapTileLayer( urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', initialMarkersCount: _data.length, markerBuilder: (BuildContext context, int index) { return MapMarker( latitude: _data[index].latitude, longitude: _data[index].longitude, iconColor: Colors.red, // Un color diferente para este mapa ); }, ), ], ) Personalización al Detalle: Dando Estilo a tus Marcadores
La verdadera potencia de MapMarker reside en su capacidad de personalización. Puedes modificar casi todos los aspectos visuales de los marcadores predefinidos para que coincidan con la identidad de tu marca o para transmitir información específica a través del diseño.
A continuación, se presenta una tabla con las propiedades más importantes para personalizar la apariencia de tus marcadores:
| Propiedad | Descripción | Valor por Defecto |
|---|---|---|
iconType | Define la forma del marcador. Opciones como MapIconType.circle, MapIconType.triangle, MapIconType.diamond, etc. | MapIconType.circle |
iconColor | Establece el color de relleno del ícono del marcador. | Colors.blue |
iconStrokeColor | Define el color del borde del ícono. | null |
iconStrokeWidth | Establece el grosor del borde del ícono. | 1.0 |
size | Controla el tamaño (ancho y alto) del marcador. | Size(14.0, 14.0) |
alignment | Ajusta el punto de anclaje del marcador respecto a su coordenada. Útil para que la punta de un pin señale la ubicación exacta. | Alignment.center |
offset | Aplica un desplazamiento en píxeles desde la coordenada original. | Offset.zero |
Veamos un ejemplo práctico donde transformamos nuestros marcadores en triángulos verdes con un borde más grueso y un desplazamiento para que la punta del triángulo apunte a la coordenada exacta.

// Dentro del markerBuilder... return MapMarker( latitude: _data[index].latitude, longitude: _data[index].longitude, iconType: MapIconType.triangle, // Cambiamos la forma a un triángulo size: Size(18, 18), // Hacemos el marcador un poco más grande alignment: Alignment.center, // Mantenemos la alineación offset: Offset(0, 9), // Desplazamos hacia abajo para que la punta coincida iconColor: Colors.green[200], // Color de relleno verde claro iconStrokeColor: Colors.green[900], // Borde verde oscuro iconStrokeWidth: 2, // Borde más grueso ); Más Allá de los Símbolos: Usando Widgets Personalizados
La flexibilidad de Flutter brilla cuando te das cuenta de que puedes usar cualquier widget como marcador. Esto se logra a través de la propiedad child del MapMarker. ¿Quieres usar un ícono de Material Design, una imagen de tus assets o incluso un widget animado? ¡Todo es posible!
// Lista de widgets que usaremos como marcadores late List<Widget> _iconsList; @override void initState() { // ... inicialización de _data _iconsList = <Widget>[ Icon(Icons.add_location, color: Colors.purple), Icon(Icons.airplanemode_active, color: Colors.orange), Icon(Icons.add_alarm, color: Colors.teal), Icon(Icons.accessibility_new, color: Colors.pink), Icon(Icons.account_balance, color: Colors.brown) ]; // ... inicialización de _dataSource super.initState(); } // Dentro del markerBuilder... return MapMarker( latitude: _data[index].latitude, longitude: _data[index].longitude, child: _iconsList[index], // ¡Asignamos un widget personalizado! ); Mapas Vivos: Gestión Dinámica de Marcadores
Las aplicaciones modernas a menudo requieren que los mapas cambien en tiempo de real. Para lograr esta interactividad, SfMaps proporciona controladores como MapShapeLayerController y MapTileLayerController. Estos controladores te permiten añadir, actualizar y eliminar marcadores después de que el mapa ha sido renderizado inicialmente.
Añadir, Actualizar y Eliminar Marcadores
Para gestionar marcadores dinámicamente, primero debes asociar un controlador a tu capa de mapa. Una vez hecho esto, puedes invocar sus métodos para manipular los marcadores.
- Añadir un marcador: Usa el método
controller.insertMarker(index). Esto volverá a llamar almarkerBuilderpara el nuevo índice. - Actualizar marcadores: Llama a
controller.updateMarkers(List<int> indices)para reconstruir los marcadores en los índices especificados. - Eliminar un marcador: Con
controller.removeMarkerAt(index)puedes quitar un marcador específico. - Limpiar todo: El método
controller.clearMarkers()elimina todos los marcadores de la capa.
// Ejemplo de cómo añadir un marcador dinámicamente con un botón late MapShapeLayerController _controller; @override void initState() { _controller = MapShapeLayerController(); // ... resto del código initState super.initState(); } // En tu widget MapShapeLayer, asigna el controlador MapShapeLayer( // ... otras propiedades controller: _controller, ) // Botón para añadir un nuevo marcador en una ubicación aleatoria ElevatedButton( child: Text('Añadir marcador'), onPressed: () { // Añadimos nuevos datos de coordenadas a nuestra lista _data.add(Model( -180 + Random().nextInt(360).toDouble(), -55 + Random().nextInt(139).toDouble() )); // Insertamos el marcador en la última posición _controller.insertMarker(_data.length - 1); }, ) Interacción con el Usuario: Marcadores al Toque
Una funcionalidad muy común es permitir que el usuario coloque un marcador tocando el mapa. Esto se puede lograr combinando un controlador con un MapZoomPanBehavior personalizado para capturar los eventos de toque. El método clave aquí es controller.pixelToLatLng(offset), que convierte las coordenadas de píxeles de la pantalla en coordenadas geográficas de latitud y longitud.

Este nivel de interacción mejora enormemente la usabilidad de la aplicación, permitiendo a los usuarios marcar lugares de interés, establecer destinos o guardar ubicaciones favoritas de forma intuitiva.
Preguntas Frecuentes (FAQ)
- ¿Puedo usar imágenes de mis assets como marcadores?
- Sí, absolutamente. Dentro del
markerBuilder, en la propiedadchilddelMapMarker, simplemente usa el widgetImage.asset('tu/ruta/imagen.png'). Puedes envolverlo en unContainerpara darle un tamaño específico si es necesario. - ¿Cuál es la diferencia entre usar un
MapShapeLayery unMapTileLayerpara los marcadores? - La implementación de los marcadores es casi idéntica en ambas capas. La diferencia fundamental radica en el mapa base.
MapShapeLayerutiliza datos vectoriales (como un archivo GeoJSON) para dibujar formas, ideal para mapas políticos o de regiones sin mucho detalle. En cambio,MapTileLayercarga imágenes (mosaicos) de un servicio de mapas como OpenStreetMap, lo que proporciona un mapa mundial detallado con calles, ciudades y geografía. - ¿Cómo puedo mostrar información cuando un usuario toca un marcador?
- Para lograr esto, debes hacer que el widget de tu marcador sea interactivo. Envuelve el widget que pasas a la propiedad
child(por ejemplo, unIcon) con unGestureDetectoro unInkWell. Luego, en la propiedadonTapde ese detector de gestos, puedes ejecutar una función para mostrar un diálogo, unSnackBar, o una ventana de información con detalles sobre esa ubicación. - ¿Es el rendimiento un problema si añado miles de marcadores?
- Aunque SfMaps está optimizado para un buen rendimiento, renderizar miles de widgets complejos simultáneamente puede afectar la fluidez de la aplicación. Si necesitas visualizar una gran cantidad de puntos, es recomendable implementar una estrategia de agrupación de marcadores (marker clustering). Esta técnica agrupa los marcadores cercanos en un solo ícono a niveles de zoom bajos y los expande a medida que el usuario se acerca, mejorando drásticamente el rendimiento y la legibilidad del mapa.
Conclusión
El widget MapMarker de SfMaps es una herramienta increíblemente versátil y poderosa para cualquier desarrollador de Flutter que trabaje con mapas. Hemos visto cómo no solo podemos añadir marcadores estáticos, sino también personalizarlos a nuestro gusto, usar nuestros propios widgets para una flexibilidad total y gestionarlos dinámicamente para crear aplicaciones interactivas y responsivas. Al dominar estas técnicas, estarás bien equipado para construir experiencias de mapeo ricas y atractivas que deleitarán a tus usuarios.
Si quieres conocer otros artículos parecidos a Domina los Marcadores en Flutter con SfMaps puedes visitar la categoría Juegos.
