Skip to content

Both copy text to your clipboard — Build with AI copies a setup prompt to paste into Claude Code, Cursor, Codex or Copilot; Copy page as Markdown copies this page to paste into a chat. How it works

Display the Whole World in Flutter

Static pins render better with MarkerLayer

This page uses WidgetLayer, which repositions each marker in Dart every frame — it lags a frame while panning, ignores tilt and bearing, and does not scale past a few dozen markers. If your markers are plain pins with no Flutter content or gestures, use MarkerLayer instead; see Markers and Annotations.

This tutorial shows how to display a zoomed-out view of the entire world — perfect for global dashboards, flight maps, or selecting a region.

Prerequisites

Before you begin, ensure you have:

Basic World View

Show the entire world with a low zoom level:

dart
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';

class WholeWorldScreen extends StatefulWidget {
  @override
  _WholeWorldScreenState createState() => _WholeWorldScreenState();
}

class _WholeWorldScreenState extends State<WholeWorldScreen> {
  MapController? mapController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('World View')),
      body: MapMetricsView(
        options: MapOptions(
          initCenter: Position(0.0, 20.0), // Center on equator
          initZoom: 1.0, // Zoomed out to see the whole world
          initStyle:
              'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY',
        ),
        onMapCreated: (MapController controller) {
          mapController = controller;
        },
      ),
    );
  }
}

World Map with Global Markers

Display markers for major world cities on a global view. There's no BitmapDescriptor/hue API for tinting built-in marker icons, so this uses WidgetLayer with a colored Icon per continent — each marker is an ordinary Flutter widget wrapped in a GestureDetector for the tap handler:

dart
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';

class GlobalMarkersScreen extends StatefulWidget {
  @override
  _GlobalMarkersScreenState createState() => _GlobalMarkersScreenState();
}

class _GlobalMarkersScreenState extends State<GlobalMarkersScreen> {
  MapController? mapController;

  final List<Map<String, dynamic>> worldCities = [
    {'name': 'New York', 'position': Position(-74.006, 40.7128), 'continent': 'NA'},
    {'name': 'Los Angeles', 'position': Position(-118.2437, 34.0522), 'continent': 'NA'},
    {'name': 'London', 'position': Position(-0.1276, 51.5074), 'continent': 'EU'},
    {'name': 'Paris', 'position': Position(2.3522, 48.8566), 'continent': 'EU'},
    {'name': 'Tokyo', 'position': Position(139.6503, 35.6762), 'continent': 'AS'},
    {'name': 'Shanghai', 'position': Position(121.4737, 31.2304), 'continent': 'AS'},
    {'name': 'Dubai', 'position': Position(55.2708, 25.2048), 'continent': 'AS'},
    {'name': 'Mumbai', 'position': Position(72.8777, 19.076), 'continent': 'AS'},
    {'name': 'Sydney', 'position': Position(151.2093, -33.8688), 'continent': 'OC'},
    {'name': 'Sao Paulo', 'position': Position(-46.6333, -23.5505), 'continent': 'SA'},
    {'name': 'Cairo', 'position': Position(31.2357, 30.0444), 'continent': 'AF'},
    {'name': 'Lagos', 'position': Position(3.3792, 6.5244), 'continent': 'AF'},
    {'name': 'Singapore', 'position': Position(103.8198, 1.3521), 'continent': 'AS'},
    {'name': 'Moscow', 'position': Position(37.6173, 55.7558), 'continent': 'EU'},
    {'name': 'Mexico City', 'position': Position(-99.1332, 19.4326), 'continent': 'NA'},
  ];

  final Map<String, Color> continentColors = {
    'NA': Colors.blue,
    'SA': Colors.green,
    'EU': Colors.red,
    'AF': Colors.orange,
    'AS': Colors.purple,
    'OC': Colors.cyan,
  };

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Global Cities')),
      body: Stack(
        children: [
          MapMetricsView(
            options: MapOptions(
              initCenter: Position(0.0, 20.0),
              initZoom: 1.5,
              initStyle:
                  'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY',
            ),
            onMapCreated: (MapController controller) {
              mapController = controller;
            },
            mapChildren: [
              WidgetLayer(
                allowInteraction: true,
                markers: worldCities.map((city) {
                  final position = city['position'] as Position;
                  return Marker(
                    point: position,
                    size: const Size.square(22),
                    alignment: Alignment.center,
                    child: GestureDetector(
                      onTap: () {
                        mapController?.animateCamera(
                          center: position,
                          zoom: 10.0,
                        );
                      },
                      child: Icon(
                        Icons.circle,
                        color: continentColors[city['continent']],
                        size: 16,
                      ),
                    ),
                  );
                }).toList(),
              ),
            ],
          ),
          // Legend
          Positioned(
            bottom: 16,
            left: 16,
            child: Card(
              child: Padding(
                padding: EdgeInsets.all(10),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    _legendRow(Colors.blue, 'North America'),
                    _legendRow(Colors.green, 'South America'),
                    _legendRow(Colors.red, 'Europe'),
                    _legendRow(Colors.orange, 'Africa'),
                    _legendRow(Colors.purple, 'Asia'),
                    _legendRow(Colors.cyan, 'Oceania'),
                  ],
                ),
              ),
            ),
          ),
          // Zoom out button
          Positioned(
            top: 16,
            right: 16,
            child: FloatingActionButton.small(
              onPressed: () {
                mapController?.animateCamera(
                  center: Position(0.0, 20.0),
                  zoom: 1.5,
                );
              },
              child: Icon(Icons.public),
              tooltip: 'Show World',
            ),
          ),
        ],
      ),
    );
  }

  Widget _legendRow(Color color, String label) {
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 1),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.circle, color: color, size: 10),
          SizedBox(width: 4),
          Text(label, style: TextStyle(fontSize: 11)),
        ],
      ),
    );
  }
}

Region Selector

Let users tap a continent to zoom in:

dart
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';

class RegionSelectorScreen extends StatefulWidget {
  @override
  _RegionSelectorScreenState createState() => _RegionSelectorScreenState();
}

class _RegionSelectorScreenState extends State<RegionSelectorScreen> {
  MapController? mapController;

  final List<Map<String, dynamic>> regions = [
    {'name': 'Europe', 'position': Position(10.0, 50.0), 'zoom': 4.0},
    {'name': 'Asia', 'position': Position(100.0, 35.0), 'zoom': 3.0},
    {'name': 'N. America', 'position': Position(-100.0, 40.0), 'zoom': 3.0},
    {'name': 'S. America', 'position': Position(-60.0, -15.0), 'zoom': 3.0},
    {'name': 'Africa', 'position': Position(20.0, 5.0), 'zoom': 3.0},
    {'name': 'Oceania', 'position': Position(140.0, -25.0), 'zoom': 3.5},
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Region Selector')),
      body: Column(
        children: [
          Container(
            padding: EdgeInsets.all(8),
            child: Wrap(
              spacing: 6,
              runSpacing: 6,
              children: [
                ActionChip(
                  avatar: Icon(Icons.public, size: 16),
                  label: Text('World'),
                  onPressed: () {
                    mapController?.animateCamera(
                      center: Position(0.0, 20.0),
                      zoom: 1.0,
                    );
                  },
                ),
                ...regions.map((r) => ActionChip(
                      label: Text(r['name'] as String),
                      onPressed: () {
                        mapController?.animateCamera(
                          center: r['position'] as Position,
                          zoom: r['zoom'] as double,
                        );
                      },
                    )),
              ],
            ),
          ),
          Expanded(
            child: MapMetricsView(
              options: MapOptions(
                initCenter: Position(0.0, 20.0),
                initZoom: 1.0,
                initStyle:
                    'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY',
              ),
              onMapCreated: (MapController controller) {
                mapController = controller;
              },
            ),
          ),
        ],
      ),
    );
  }
}

World View Zoom Levels

ZoomView
0 - 1Full globe / world
2 - 3Continent
4 - 6Country
7 - 10Region / State
11 - 14City
15 - 18Street / Building

Next Steps


Tip: At zoom level 1, the map shows the whole world. Use Position(0.0, 20.0) (longitude, latitude) as the center for a balanced view that shows all continents. For global dashboards, disable pitch and rotation to keep the view clean (MapGestures.all(rotate: false, pitch: false)).