yandex_map_desktop 0.1.4 copy "yandex_map_desktop: ^0.1.4" to clipboard
yandex_map_desktop: ^0.1.4 copied to clipboard

Yandex Maps JS API 2.1 for Flutter desktop via WebView. Windows (Edge WebView2) and macOS (WKWebView) support.

example/lib/main.dart

// ignore_for_file: avoid_print

import 'dart:math' as math;

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

// ---------------------------------------------------------------------------
// TODO: Replace with your own Yandex Maps JavaScript API key.
//       Get one at https://developer.tech.yandex.com — enable
//       "JavaScript API and HTTP Geocoder" and set domain restrictions
//       to "Without restrictions".
// ---------------------------------------------------------------------------
const String _kApiKey = 'YOUR_JS_API_KEY';

// Moscow city centre — used as the default camera target.
const Point _kMoscow = Point(latitude: 55.755864, longitude: 37.617698);

// Two recognisable Moscow landmarks used to draw a sample polyline.
const Point _kKremlin = Point(latitude: 55.752023, longitude: 37.617499);
const Point _kRedSquare = Point(latitude: 55.753930, longitude: 37.620795);
const Point _kBolshoyTheatre = Point(latitude: 55.760153, longitude: 37.618644);
const Point _kLubyanka = Point(latitude: 55.759968, longitude: 37.626346);

void main() {
  runApp(const MyApp());
}

// ---------------------------------------------------------------------------
// Root application widget
// ---------------------------------------------------------------------------

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Yandex Map Desktop — Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
      ),
      home: const MapDemoScreen(),
    );
  }
}

// ---------------------------------------------------------------------------
// Main demo screen
// ---------------------------------------------------------------------------

class MapDemoScreen extends StatefulWidget {
  const MapDemoScreen({super.key});

  @override
  State<MapDemoScreen> createState() => _MapDemoScreenState();
}

class _MapDemoScreenState extends State<MapDemoScreen> {
  // Holds the controller once the map signals it is ready.
  YandexMapDesktopController? _controller;

  // Running list of map objects sent to the widget.
  // Initialised with a demo polyline and two landmark placemarks.
  late List<MapObject> _mapObjects;

  // Displayed in the AppBar subtitle — updated on every camera change.
  CameraPosition _cameraPosition = const CameraPosition(
    target: _kMoscow,
    zoom: 12,
  );

  // Counter used to generate unique MapObjectIds for tap-added placemarks.
  int _tapMarkerCount = 0;

  // Random number generator for the FAB "random marker" feature.
  final math.Random _random = math.Random();

  @override
  void initState() {
    super.initState();
    _mapObjects = _buildInitialObjects();
  }

  // ---------------------------------------------------------------------------
  // Initial map objects
  // ---------------------------------------------------------------------------

  List<MapObject> _buildInitialObjects() {
    return [
      // --- A polyline tracing a short walking route through central Moscow ---
      PolylineMapObject(
        mapId: const MapObjectId('central_moscow_route'),
        coordinates: const [
          _kKremlin,
          _kRedSquare,
          _kBolshoyTheatre,
          _kLubyanka,
        ],
        strokeColor: Colors.indigo,
        strokeWidth: 4,
        onTap: (obj) {
          print('Polyline tapped: ${obj.mapId.value}');
        },
      ),

      // --- Kremlin placemark ---
      PlacemarkMapObject(
        mapId: const MapObjectId('kremlin'),
        point: _kKremlin,
        icon: const PlacemarkIcon(color: Colors.deepOrange, size: 40),
        label: 'Kremlin',
        onTap: (obj, point) {
          print('Tapped: ${obj.label} at $point');
        },
      ),

      // --- Red Square placemark ---
      PlacemarkMapObject(
        mapId: const MapObjectId('red_square'),
        point: _kRedSquare,
        icon: const PlacemarkIcon(color: Colors.red, size: 40),
        label: 'Red Square',
        onTap: (obj, point) {
          print('Tapped: ${obj.label} at $point');
        },
      ),

      // --- Bolshoy Theatre placemark ---
      PlacemarkMapObject(
        mapId: const MapObjectId('bolshoy'),
        point: _kBolshoyTheatre,
        icon: const PlacemarkIcon(color: Colors.purple, size: 36),
        label: 'Bolshoy Theatre',
        onTap: (obj, point) {
          print('Tapped: ${obj.label} at $point');
        },
      ),
    ];
  }

  // ---------------------------------------------------------------------------
  // Map callbacks
  // ---------------------------------------------------------------------------

  void _onMapCreated(YandexMapDesktopController controller) {
    setState(() => _controller = controller);
    print('YandexMapDesktop: map ready');
  }

  /// When the user taps the map background, drop a blue marker and show a
  /// SnackBar with the tapped coordinate.
  void _onMapTap(Point point) {
    final id = 'tap_marker_${++_tapMarkerCount}';
    final marker = PlacemarkMapObject(
      mapId: MapObjectId(id),
      point: point,
      icon: const PlacemarkIcon(color: Colors.blue, size: 32),
      label: 'Tap #$_tapMarkerCount',
      onTap: (obj, _) => _removeMarker(obj.mapId),
    );

    setState(() {
      _mapObjects = [..._mapObjects, marker];
    });

    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(
          'Marker added at '
          '${point.latitude.toStringAsFixed(5)}, '
          '${point.longitude.toStringAsFixed(5)}   '
          '(tap it to remove)',
        ),
        duration: const Duration(seconds: 3),
        behavior: SnackBarBehavior.floating,
      ),
    );
  }

  /// Right-click / long-press asks whether to add a marker at that position.
  void _onMapLongTap(Point point) {
    showDialog<bool>(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('Add marker here?'),
        content: Text(
          '${point.latitude.toStringAsFixed(5)}, '
          '${point.longitude.toStringAsFixed(5)}',
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(ctx, false),
            child: const Text('Cancel'),
          ),
          FilledButton(
            onPressed: () => Navigator.pop(ctx, true),
            child: const Text('Add'),
          ),
        ],
      ),
    ).then((confirmed) {
      if (confirmed == true) _onMapTap(point);
    });
  }

  /// Keeps the AppBar subtitle in sync with camera movement.
  void _onCameraPositionChanged(CameraPosition pos, bool finished) {
    // Only trigger a rebuild once the movement ends to avoid excessive redraws.
    if (finished) {
      setState(() => _cameraPosition = pos);
    }
  }

  // ---------------------------------------------------------------------------
  // FAB — random placemark near Moscow
  // ---------------------------------------------------------------------------

  void _addRandomMarker() {
    // Scatter within ±0.05 degrees (~5 km) around Moscow centre.
    final lat = _kMoscow.latitude + (_random.nextDouble() - 0.5) * 0.1;
    final lng = _kMoscow.longitude + (_random.nextDouble() - 0.5) * 0.1;
    final point = Point(latitude: lat, longitude: lng);

    final id = 'random_${++_tapMarkerCount}';
    final colors = [
      Colors.green,
      Colors.teal,
      Colors.amber,
      Colors.cyan,
      Colors.pink,
    ];
    final color = colors[_tapMarkerCount % colors.length];

    setState(() {
      _mapObjects = [
        ..._mapObjects,
        PlacemarkMapObject(
          mapId: MapObjectId(id),
          point: point,
          icon: PlacemarkIcon(color: color, size: 34),
          label: 'Random #$_tapMarkerCount',
          onTap: (obj, _) => _removeMarker(obj.mapId),
        ),
      ];
    });
  }

  // ---------------------------------------------------------------------------
  // Helpers
  // ---------------------------------------------------------------------------

  /// Removes a map object by its [id] from the list.
  void _removeMarker(MapObjectId id) {
    setState(() {
      _mapObjects = _mapObjects.where((o) => o.mapId != id).toList();
    });
  }

  /// Clears every dynamically-added marker (anything after the initial set).
  void _clearDynamicMarkers() {
    final initial = _buildInitialObjects();
    final initialIds = initial.map((o) => o.mapId).toSet();
    setState(() {
      _mapObjects =
          _mapObjects.where((o) => initialIds.contains(o.mapId)).toList();
      _tapMarkerCount = 0;
    });
  }

  // ---------------------------------------------------------------------------
  // Build
  // ---------------------------------------------------------------------------

  @override
  Widget build(BuildContext context) {
    final lat = _cameraPosition.target.latitude.toStringAsFixed(4);
    final lng = _cameraPosition.target.longitude.toStringAsFixed(4);
    final zoom = _cameraPosition.zoom.toStringAsFixed(1);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Yandex Map Windows Demo'),
        // Live camera subtitle — updated whenever the camera stops moving.
        bottom: PreferredSize(
          preferredSize: const Size.fromHeight(20),
          child: Padding(
            padding: const EdgeInsets.only(bottom: 6),
            child: Text(
              'lat $lat  lng $lng  zoom $zoom',
              style: Theme.of(context)
                  .textTheme
                  .labelSmall
                  ?.copyWith(color: Colors.white70),
            ),
          ),
        ),
        backgroundColor: Theme.of(context).colorScheme.primary,
        foregroundColor: Colors.white,
        actions: [
          // ---- Zoom in ----
          IconButton(
            tooltip: 'Zoom in',
            icon: const Icon(Icons.add),
            onPressed: _controller == null
                ? null
                : () => _controller!.moveCamera(CameraUpdate.zoomIn()),
          ),
          // ---- Zoom out ----
          IconButton(
            tooltip: 'Zoom out',
            icon: const Icon(Icons.remove),
            onPressed: _controller == null
                ? null
                : () => _controller!.moveCamera(CameraUpdate.zoomOut()),
          ),
          // ---- Fly to Moscow centre ----
          IconButton(
            tooltip: 'Reset to Moscow',
            icon: const Icon(Icons.my_location),
            onPressed: _controller == null
                ? null
                : () => _controller!.moveCamera(
                      CameraUpdate.newCameraPosition(
                        const CameraPosition(target: _kMoscow, zoom: 12),
                      ),
                    ),
          ),
          // ---- Clear dynamic markers ----
          IconButton(
            tooltip: 'Clear added markers',
            icon: const Icon(Icons.delete_sweep_outlined),
            onPressed: _clearDynamicMarkers,
          ),
        ],
      ),

      // ---- Map fills the remaining space ----
      body: YandexMapDesktop(
        apiKey: _kApiKey,
        initialCameraPosition: const CameraPosition(
          target: _kMoscow,
          zoom: 12,
        ),
        mapObjects: _mapObjects,
        onMapCreated: _onMapCreated,
        onMapTap: _onMapTap,
        onMapLongTap: _onMapLongTap,
        onCameraPositionChanged: _onCameraPositionChanged,
      ),

      // ---- FAB drops a random marker ----
      floatingActionButton: FloatingActionButton.extended(
        onPressed: _addRandomMarker,
        icon: const Icon(Icons.add_location_alt_outlined),
        label: const Text('Random marker'),
        tooltip: 'Add a random placemark near Moscow',
      ),
    );
  }
}
0
likes
160
points
12
downloads

Documentation

API reference

Publisher

verified publisherxlkv.uz

Weekly Downloads

Yandex Maps JS API 2.1 for Flutter desktop via WebView. Windows (Edge WebView2) and macOS (WKWebView) support.

Repository (GitHub)
View/report issues

Topics

#map #yandex #windows #macos #webview

License

MIT (license)

Dependencies

flutter, webview_flutter, webview_windows

More

Packages that depend on yandex_map_desktop