Loading...
Loading...
Implements Syncfusion Flutter Maps (SfMaps) for interactive geographical data visualization in Flutter apps. Use when working with shape layers, tile layers, choropleth maps, or map markers and overlays. This skill covers GeoJSON rendering, OpenStreetMap/Bing Maps integration, bubbles, legends, tooltips, zoom and pan, and spatial data visualization.
npx skill4agent add syncfusion/flutter-ui-components-skills syncfusion-flutter-mapsSfMapsTheme| Feature | MapShapeLayer | MapTileLayer |
|---|---|---|
| Data Source | GeoJSON files | Web tile services (URLs) |
| Offline Support | ✅ Yes (embedded GeoJSON) | ❌ Requires internet |
| Data Binding | ✅ Full support | ❌ Limited to markers |
| Choropleth Maps | ✅ Yes | ❌ No |
| Bubble Visualization | ✅ Yes | ❌ No |
| Data Labels | ✅ Yes | ❌ No |
| Shape Selection | ✅ Yes | ❌ No |
| Color Mapping | ✅ Yes | ❌ No |
| Legend | ✅ Yes | ❌ No |
| Markers | ✅ Yes | ✅ Yes |
| Zoom & Pan | ✅ Yes | ✅ Yes |
| Street Maps | ❌ No | ✅ Yes |
| Sublayers | ✅ Yes | ✅ Yes |
| Vector Layers | ✅ Yes (arc, circle, line, etc.) | ✅ Yes (arc, circle, line, etc.) |
| Tooltips | ✅ Yes (shapes & bubbles) | ❌ Limited |
| Real-world Detail | ❌ Limited | ✅ High detail |
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_maps/maps.dart';
class MyShapeMap extends StatefulWidget {
_MyShapeMapState createState() => _MyShapeMapState();
}
class _MyShapeMapState extends State<MyShapeMap> {
late MapShapeSource _dataSource;
void initState() {
super.initState();
_dataSource = MapShapeSource.asset(
'assets/world_map.json',
shapeDataField: 'name',
);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('World Map')),
body: Padding(
padding: EdgeInsets.all(15),
child: SfMaps(
layers: [
MapShapeLayer(
source: _dataSource,
color: Colors.blue[100],
strokeColor: Colors.blue,
strokeWidth: 0.5,
),
],
),
),
);
}
}import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_maps/maps.dart';
class MyTileMap extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('OpenStreetMap')),
body: SfMaps(
layers: [
MapTileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
initialFocalLatLng: MapLatLng(27.1751, 78.0421),
initialZoomLevel: 5,
),
],
),
);
}
}class ChoroplethMap extends StatefulWidget {
_ChoroplethMapState createState() => _ChoroplethMapState();
}
class _ChoroplethMapState extends State<ChoroplethMap> {
late List<Model> _data;
late MapShapeSource _dataSource;
void initState() {
super.initState();
_data = [
Model('India', 280),
Model('United States of America', 190),
Model('Brazil', 120),
];
_dataSource = MapShapeSource.asset(
'assets/world_map.json',
shapeDataField: 'name',
dataCount: _data.length,
primaryValueMapper: (int index) => _data[index].country,
shapeColorValueMapper: (int index) => _data[index].value,
shapeColorMappers: [
MapColorMapper(from: 0, to: 100, color: Colors.red),
MapColorMapper(from: 101, to: 300, color: Colors.green),
],
);
}
Widget build(BuildContext context) {
return Scaffold(
body: SfMaps(
layers: [
MapShapeLayer(
source: _dataSource,
legend: MapLegend(MapElement.shape),
showDataLabels: true,
),
],
),
);
}
}
class Model {
Model(this.country, this.value);
final String country;
final double value;
}class MapWithMarkers extends StatefulWidget {
_MapWithMarkersState createState() => _MapWithMarkersState();
}
class _MapWithMarkersState extends State<MapWithMarkers> {
late List<MarkerData> _markers;
late MapShapeSource _dataSource;
void initState() {
super.initState();
_markers = [
MarkerData('New York', 40.7128, -74.0060),
MarkerData('London', 51.5074, -0.1278),
MarkerData('Tokyo', 35.6762, 139.6503),
];
_dataSource = MapShapeSource.asset(
'assets/world_map.json',
shapeDataField: 'name',
);
}
Widget build(BuildContext context) {
return Scaffold(
body: SfMaps(
layers: [
MapShapeLayer(
source: _dataSource,
initialMarkersCount: _markers.length,
markerBuilder: (BuildContext context, int index) {
return MapMarker(
latitude: _markers[index].latitude,
longitude: _markers[index].longitude,
iconColor: Colors.red,
iconType: MapIconType.circle,
size: Size(15, 15),
child: null,
);
},
),
],
),
);
}
}
class MarkerData {
MarkerData(this.city, this.latitude, this.longitude);
final String city;
final double latitude;
final double longitude;
}// Common pattern for election results, sales data by region, etc.
late MapShapeSource _dataSource;
int? _selectedIndex;
_dataSource = MapShapeSource.asset(
'assets/usa_states.json',
shapeDataField: 'name',
dataCount: _statesData.length,
primaryValueMapper: (index) => _statesData[index].state,
shapeColorValueMapper: (index) => _statesData[index].value,
shapeColorMappers: [
MapColorMapper(from: 0, to: 50, color: Colors.red),
MapColorMapper(from: 51, to: 100, color: Colors.blue),
],
);
MapShapeLayer(
source: _dataSource,
legend: MapLegend(MapElement.shape),
showDataLabels: true,
onSelectionChanged: (int index) {
setState(() {
_selectedIndex = index;
});
},
selectionSettings: MapSelectionSettings(
color: Colors.yellow,
strokeColor: Colors.black,
strokeWidth: 2,
),
)// Common pattern for store locator, delivery tracking
late List<LocationData> _locations;
late MapTileLayerController _controller;
void initState() {
_controller = MapTileLayerController();
_locations = [/* your location data */];
super.initState();
}
MapTileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
initialFocalLatLng: MapLatLng(37.7749, -122.4194),
initialZoomLevel: 10,
controller: _controller,
initialMarkersCount: _locations.length,
markerBuilder: (context, index) {
return MapMarker(
latitude: _locations[index].latitude,
longitude: _locations[index].longitude,
child: Icon(Icons.location_pin, color: Colors.red, size: 30),
);
},
zoomPanBehavior: MapZoomPanBehavior(
enableDoubleTapZooming: true,
enablePinching: true,
enablePanning: true,
),
)// Common pattern for population density, sales volume visualization
_dataSource = MapShapeSource.asset(
'assets/world_map.json',
shapeDataField: 'name',
dataCount: _data.length,
primaryValueMapper: (index) => _data[index].country,
bubbleSizeMapper: (index) => _data[index].population,
bubbleColorValueMapper: (index) => _data[index].density,
);
MapShapeLayer(
source: _dataSource,
showDataLabels: true,
legend: MapLegend.bar(MapElement.bubble),
bubbleSettings: MapBubbleSettings(
maxRadius: 50,
minRadius: 10,
color: Colors.blue,
),
shapeTooltipBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(8),
child: Text(
'${_data[index].country}: ${_data[index].population}M',
style: TextStyle(color: Colors.white),
),
);
},
bubbleTooltipBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(8),
child: Text(
'Density: ${_data[index].density}/km²',
style: TextStyle(color: Colors.white),
),
);
},
)// Show specific region with markers
late MapZoomPanBehavior _zoomPanBehavior;
void initState() {
_zoomPanBehavior = MapZoomPanBehavior(
enableDoubleTapZooming: true,
enablePinching: true,
enablePanning: true,
);
super.initState();
}
// Button to fit bounds
void _fitToMarkers() {
setState(() {
// Define bounds to show all markers
_zoomPanBehavior.latLngBounds = MapLatLngBounds(
MapLatLng(southwestLat, southwestLng),
MapLatLng(northeastLat, northeastLng),
);
});
}
MapShapeLayer(
source: _dataSource,
zoomPanBehavior: _zoomPanBehavior,
// ... markers
)// Add markers where user taps
late MapLatLng _markerPosition;
late MapShapeLayerController _controller;
late CustomZoomPanBehavior _zoomPanBehavior;
void initState() {
_controller = MapShapeLayerController();
_zoomPanBehavior = CustomZoomPanBehavior()
..onTap = _handleTap;
super.initState();
}
void _handleTap(Offset position) {
_markerPosition = _controller.pixelToLatLng(position);
if (_controller.markersCount > 0) {
_controller.clearMarkers();
}
_controller.insertMarker(0);
}
MapShapeLayer(
source: _dataSource,
controller: _controller,
zoomPanBehavior: _zoomPanBehavior,
markerBuilder: (context, index) {
return MapMarker(
latitude: _markerPosition.latitude,
longitude: _markerPosition.longitude,
child: Icon(Icons.location_on, color: Colors.red),
);
},
)
class CustomZoomPanBehavior extends MapZoomPanBehavior {
late Function(Offset) onTap;
void handleEvent(PointerEvent event) {
if (event is PointerUpEvent) {
onTap(event.localPosition);
}
super.handleEvent(event);
}
}sourcecolorstrokeColorstrokeWidthlegendshowDataLabelsinitialMarkersCountmarkerBuildercontrollerzoomPanBehavioronSelectionChangedselectionSettingsshapeTooltipBuilderbubbleTooltipBuildermarkerTooltipBuildertooltipSettingsbubbleSettingsdataLabelSettingslegendSettingssublayersloadingBuilderurlTemplateinitialFocalLatLnginitialZoomLevelinitialMarkersCountmarkerBuildercontrollerzoomPanBehaviormarkerTooltipBuilderinitialLatLngBoundsshapeDataFielddataCountprimaryValueMapperdataLabelMappershapeColorValueMappershapeColorMappersbubbleSizeMapperbubbleColorValueMapperbubbleColorMappersenableDoubleTapZoomingenablePinchingenablePanningenableMouseWheelZoomingshowToolbartoolbarSettingszoomLevelfocalLatLnglatLngBoundsminZoomLevelmaxZoomLevelonZoomingonPanning