yarrow_map_flutter_sdk 0.0.5
yarrow_map_flutter_sdk: ^0.0.5 copied to clipboard
Flutter SDK for Yarrow Maps with API parity to the web SDK.
Yarrow Map Flutter SDK #
Flutter SDK for integrating Yarrow maps in mobile apps, with an API aligned to the Yarrow web SDK.
Table of Contents #
- Getting Started
- Basic Map Manipulation
- Handling Events
- Working with Layers and Data
- Routing
- Search
- Public Transport
- Utility Methods
- API Reference
Getting Started #
Installation #
First, add the Yarrow Map Flutter SDK to your project:
flutter pub add yarrow_map_flutter_sdk
Initialization #
To get started, create a YarrowMapController and use YarrowMapView widget to render the map.
Important - Coordinate Format: This SDK uses (lng: number, lat: number) named tuples for map configuration, matching the MapLibre convention.
import 'package:flutter/material.dart';
import 'package:yarrow_map_flutter_sdk/yarrow_map_flutter_sdk.dart';
class MapScreen extends StatefulWidget {
const MapScreen({super.key});
@override
State<MapScreen> createState() => _MapScreenState();
}
class _MapScreenState extends State<MapScreen> {
final controller = YarrowMapController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: YarrowMapView(
config: const YarrowMapConfig(
center: (lng: 69.2401, lat: 41.2995),
apiKey: 'YOUR_API_KEY',
zoom: 12,
),
controller: controller,
onReady: (map) async {
await map.zoomTo(41.2995, 69.2401, 14);
},
),
);
}
}
Configuration Options #
The YarrowMapConfig class accepts the following configuration options:
const mapConfig = YarrowMapConfig(
center: (lng: 69.2401, lat: 41.2995), // Required: center coordinates
apiKey: 'YOUR_API_KEY', // Required: your Yarrow API key
zoom: 12, // Initial zoom level (default: 10)
minZoom: 5, // Minimum zoom level (default: 0)
maxZoom: 18, // Maximum zoom level (default: 19)
theme: YarrowMapTheme.dark, // 'light' or 'dark' (default: 'light')
brandBadgePosition: BrandBadgePosition.topRight, // Badge position
controls: YarrowControlsConfig(
enabled: true, // Controls are OFF by default
position: YarrowControlsPosition.rightBottom, // Optional placement
showZoom: true, // Show zoom buttons
showCompass: true, // Show compass
),
);
Example with all options:
import 'package:flutter/material.dart';
import 'package:yarrow_map_flutter_sdk/yarrow_map_flutter_sdk.dart';
class FullConfigMapScreen extends StatelessWidget {
const FullConfigMapScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: YarrowMapView(
config: const YarrowMapConfig(
center: (lng: 69.2401, lat: 41.2995),
apiKey: 'YOUR_API_KEY',
zoom: 12,
minZoom: 5,
maxZoom: 18,
theme: YarrowMapTheme.dark,
brandBadgePosition: BrandBadgePosition.topRight,
controls: YarrowControlsConfig(
enabled: true,
position: YarrowControlsPosition.rightBottom,
showZoom: true,
showCompass: true,
),
),
controller: YarrowMapController(),
onReady: (map) {
print('Map ready!');
},
),
);
}
}
When controls and the brand badge are placed in the same corner (for example rightBottom with brandBadgePosition.bottomRight), the SDK automatically adds spacing so they do not overlap.
Basic Map Manipulation #
Changing the Map Style #
You can change the map's visual style. The available styles are satellite, hybrid, and the default map style.
// Switch to satellite view
await map.changeStyles(styleType: YarrowMapStyleType.satellite);
// Switch to hybrid view (satellite with labels)
await map.changeStyles(styleType: YarrowMapStyleType.hybrid);
// Switch back to the default map style
await map.changeStyles();
Changing the Map Theme #
You can set the initial theme in the configuration or switch between light and dark themes dynamically after initialization.
Setting initial theme:
const mapConfig = YarrowMapConfig(
center: (lng: 69.2401, lat: 41.2995),
apiKey: 'YOUR_API_KEY',
zoom: 12,
theme: YarrowMapTheme.dark, // Set initial theme to dark
);
Switching theme dynamically:
// Switch to dark mode
await map.changeTheme(YarrowMapTheme.dark);
// Switch to light mode (default)
await map.changeTheme(YarrowMapTheme.light);
Changing Brand Badge Position #
You can set the initial badge position in config or change it dynamically after map initialization.
// Move badge to the top-right corner
map.changeBrandBadgePosition(BrandBadgePosition.topRight);
// Other values: BrandBadgePosition.topLeft, .bottomLeft, .bottomRight
Moving the Map View #
You can programmatically move the map to a new location or fit it to a specific geographic area.
Zooming to a specific point:
// Fly to a new location with a specific zoom level
map.zoomTo(41.3111, 69.2797, 15); // Latitude, Longitude, Zoom Level
Fitting the map to a set of features:
This is useful when you want to display a set of points, lines, or polygons and ensure they are all visible.
final geojsonData = {
'type': 'FeatureCollection',
'features': [
// Your GeoJSON features here
],
};
map.fitBounds(geojsonData);
Handling Events #
You can listen for various user interactions with the map.
Listen for Map Movement #
Execute a callback function whenever the map finishes moving.
map.onMoveEnd((lat, lng, zoom) {
print('Map moved to: $lat, $lng with zoom: $zoom');
});
Listen for Map Clicks #
Execute a callback when the user clicks on the map.
map.onMapClick((lat, lng) {
print('Map clicked at: $lat, $lng');
});
Listen for Clicks on POIs or Buildings #
You can add click listeners to specific groups of features on the map, like points of interest (POIs) or buildings.
// Listen for clicks on POIs
map.onIconClick(YarrowLayerGroup.pois, (lat, lng, properties) {
print('POI clicked: $properties');
});
// Listen for clicks on buildings
map.onIconClick(YarrowLayerGroup.buildings, (lat, lng, properties) {
print('Building clicked: $properties');
});
Working with Layers and Data #
Adding a GeoJSON Layer #
You can add custom data to the map in the form of a GeoJSON layer. This is useful for displaying points, lines, or polygons.
final myData = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [69.2797, 41.3111],
},
'properties': {
'name': 'My Point',
},
},
],
};
map.addLayer(
'my-custom-layer', // A unique name for the layer
'circle', // The type of layer (e.g., 'circle', 'line', 'fill', 'symbol')
myData,
paint: {
'circle-radius': 10,
'circle-color': '#ff0000',
},
);
Advanced Layer Configuration #
The addLayer method supports advanced configuration options for different layer types:
map.addLayer(
'layerName', // String - Unique identifier for the layer
'symbol', // Layer type: 'symbol', 'fill', 'line', 'background', 'raster', 'circle', 'heatmap', 'fill-extrusion', 'hillshade'
featureCollection, // GeoJSON FeatureCollection
paint: { // Paint properties map
'text-halo-color': '#ffffff',
'text-halo-width': 2,
},
layout: { // Layout properties map
'icon-image': 'custom-icon',
'icon-size': 0.8,
'text-field': ['get', 'name'],
},
options: YarrowAddLayerOptions(
sourceId: 'my-source',
filter: ['==', ['get', 'status'], 'active'],
),
);
Managing Sources Explicitly #
map.addSource('vehicles-source', vehicleFeatureCollection);
map.updateSourceData('vehicles-source', nextVehicleFeatureCollection);
map.addLayer(
'active-vehicles',
'circle',
nextVehicleFeatureCollection,
paint: {
'circle-radius': {'type': 'interpolate', 'input': {'type': 'zoom'}, 'stops': [[10, 4], [16, 10]]},
'circle-color': {'type': 'case', 'condition': ['==', ['get', 'status'], 'active'], 'true': '#16a34a', 'false': '#9ca3af']},
},
options: YarrowAddLayerOptions(
sourceId: 'vehicles-source',
filter: ['==', ['get', 'status'], 'active'],
),
);
Feature State and Rendered Queries:
map.setFeatureState(
source: 'vehicles-source',
id: 101,
state: {'selected': true},
);
final features = map.queryRenderedFeatures(
options: YarrowQueryRenderedFeaturesOptions(layers: ['active-vehicles']),
);
Adding and Removing Markers #
You can add markers to the map to indicate specific locations.
// Add a simple marker
final marker = map.addMarker(41.3111, 69.2797); // latitude, longitude
// Add a marker with options
final customMarker = map.addMarker(
41.2995,
69.2401,
color: '#0000ff', // Marker color (default: '#FF0000')
draggable: true, // Allow dragging (default: false)
anchor: YarrowMarkerAnchor.bottom, // Anchor position
onClick: () { // Click event handler
print('Marker clicked!');
},
);
// Remove a marker
map.removeMarker(marker);
Removing a Layer #
You can remove a layer that you've previously added.
map.removeLayer('my-custom-layer');
Routing #
The SDK provides powerful routing capabilities.
Building and Displaying a Simple Route #
Calculate and display a route between a start and end point.
final start = (lat: 41.2995, lng: 69.2401);
final end = (lat: 41.3111, lng: 69.2797);
const profile = 'car'; // 'car', 'bicycle', or 'pedestrian'
final result = await map.buildRouteWithLabels(start, end, profile);
print('Route built: ${result.features}');
print('Directions: ${result.directions}');
Building and Displaying a Multi-Stop Route #
You can also create a route that passes through multiple waypoints.
final coordinates = [
(lat: 41.2995, lng: 69.2401), // Start
(lat: 41.3111, lng: 69.2797), // Waypoint 1
(lat: 41.325, lng: 69.285), // End
];
const profile = 'car';
const language = 'en'; // Optional: 'en', 'ru', etc. (default: 'ru')
final result = await map.buildMultiSegmentRouteWithLabels(coordinates, profile, language);
print('Multi-segment route built: ${result.features}');
print('Directions: ${result.directions}');
Clearing Routes #
To remove all route-related layers from the map:
map.clearAllRoutes();
Search #
Highlighting Search Results #
You can perform a search and display the results on the map. The search is performed around the current map center.
const query = 'Tashkent';
final clearHighlights = map.highlightSearchResults(
query,
zoomToResults: true, // Automatically zoom to fit the results
onResultsUpdate: (results) {
print('Search results: $results');
},
onLoadingStateChange: (state) {
// state can be 'firstRender', 'rerender', or null
print('Loading state: $state');
},
);
// To remove the search results from the map later
clearHighlights();
Public Transport #
Displaying Real-Time Bus Locations #
You can display the real-time locations of buses on the map.
Show buses for a specific route:
const routeId = 'some-route-id';
final clearBusRoute = await map.showBusRoute(routeId);
// To stop showing the bus route later
// clearBusRoute();
Show all buses in the current map view:
If you don't provide a routeId, the map will show all buses within the visible area.
final clearBusRoutes = await map.showBusRoute();
// To stop showing all bus routes
// clearBusRoutes();
Clearing Bus Routes #
The showBusRoute method returns a cleanup function that you can call to stop displaying bus locations and remove all related data:
// Store the cleanup function
final clearBuses = await map.showBusRoute('route-123');
// Later, clear the bus route display
clearBuses();
Utility Methods #
Calculating Bounding Box #
The SDK provides a utility method to calculate the bounding box of GeoJSON data:
final geojsonData = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [69.2797, 41.3111],
},
},
{
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': [
[69.240, 41.299],
[69.280, 41.311],
],
},
},
],
};
final boundingBox = map.getBoundingBox(geojsonData);
print(boundingBox);
// Output: { xMin: 69.240, xMax: 69.280, yMin: 41.299, yMax: 41.3111 }
Supported Geometry Types:
- Point
- LineString
- Polygon
The bounding box contains:
xMin: Minimum longitudexMax: Maximum longitudeyMin: Minimum latitudeyMax: Maximum latitude
API Reference #
YarrowMapConfig #
class YarrowMapConfig {
final ({double lng, double lat}) center; // Required
final String apiKey; // Required: Yarrow API key
final double zoom; // default: 10
final double minZoom; // default: 0
final double maxZoom; // default: 19
final YarrowMapTheme theme; // default: light
final BrandBadgePosition? brandBadgePosition;
final YarrowControlsConfig? controls;
}
YarrowControlsConfig #
class YarrowControlsConfig {
final bool enabled; // default: false
final YarrowControlsPosition position; // default: right
final bool showZoom; // default: true
final bool showCompass; // default: true
}
YarrowMapController #
| Method | Parameters | Return Type | Description |
|---|---|---|---|
zoomTo |
lat: double, lng: double, zoom: double |
void |
Fly to specific coordinates |
fitBounds |
data: Map<String, dynamic> |
void |
Fit map to show all features |
getBoundingBox |
data: Map<String, dynamic> |
YarrowBoundingBox |
Calculate bounding box of features |
changeStyles |
styleType?: YarrowMapStyleType |
Future<void> |
Change map style |
changeTheme |
theme: YarrowMapTheme |
Future<void> |
Switch between light and dark themes |
changeBrandBadgePosition |
position: BrandBadgePosition |
void |
Change brand badge position at runtime |
onMoveEnd |
callback: Function |
void |
Listen for map movement end |
onMapClick |
callback: Function |
void |
Listen for map clicks |
onIconClick |
layerGroup: YarrowLayerGroup, callback: Function |
void |
Listen for icon clicks |
addSource |
sourceId: String, data: Map<String, dynamic> |
void |
Add/replace a GeoJSON source |
updateSourceData |
sourceId: String, data: Map<String, dynamic> |
void |
Update data for an existing GeoJSON source |
addLayer |
name: String, type: String, data: Map<String, dynamic>, ... |
void |
Add a layer to the map |
setFeatureState |
{source: String, id: dynamic}, state: Map<String, dynamic> |
void |
Set state for a specific feature |
queryRenderedFeatures |
options: YarrowQueryRenderedFeaturesOptions |
List<Map<String, dynamic>> |
Query currently rendered features |
removeLayer |
layerName: String |
void |
Remove a layer from the map |
addMarker |
lat: double, lng: double, options?: YarrowMarkerOptions |
YarrowMarker? |
Add a marker to the map |
removeMarker |
marker: YarrowMarker |
void |
Remove a marker from the map |
buildRouteWithLabels |
start: (lat: double, lng: double), end: (lat: double, lng: double), profile: String |
Future<YarrowRouteResult> |
Build and display a route |
buildMultiSegmentRouteWithLabels |
coordinates: List<(lat: double, lng: double)>, profile: String, language?: String |
Future<YarrowRouteResult> |
Build multi-segment route |
clearAllRoutes |
None | void |
Clear all route layers and popups |
highlightSearchResults |
query: String, options?: YarrowSearchOptions |
void Function() |
Highlight search results with cleanup function |
showBusRoute |
routeId?: String |
Future<void Function()> |
Show bus locations with cleanup function |
Type Definitions #
// Bounding Box
class YarrowBoundingBox {
final double xMin;
final double xMax;
final double yMin;
final double yMax;
}
// Route Result
class YarrowRouteResult {
final List<dynamic> features;
final List<dynamic> directions;
}
// Marker Options
class YarrowMarkerOptions {
final String? color;
final bool draggable;
final YarrowMarkerAnchor anchor;
final void Function()? onClick;
}
// Search Options
class YarrowSearchOptions {
final String? layerName;
final String? iconImage;
final String? highlightColor;
final bool pulseAnimation;
final bool zoomToResults;
final void Function(double lat, double lng, Map<String, dynamic> properties)? onIconClick;
final void Function(List<dynamic> results)? onResultsUpdate;
final void Function(String? state)? onLoadingStateChange;
}
// Layer Options
class YarrowAddLayerOptions {
final String? sourceId;
final List<dynamic>? filter;
}
// Query Options
class YarrowQueryRenderedFeaturesOptions {
final List<String>? layers;
final List<String>? sourceLayers;
}
Version Information #
- Current Version: 0.0.5
- Dependencies: maplibre_gl ^0.25.0, dio ^5.9.0, flutter_cache_manager ^3.4.1, flutter_svg ^2.2.2
- Changelog:
CHANGELOG.md
Notes #
- This package uses
maplibre_glunder the hood. - Ensure platform setup for Flutter + MapLibre is completed in your app.
Support #
For issues, questions, or contributions, contact the Yarrow development team.