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

Yandex Maps JavaScript API 2.1 for Flutter desktop — renders real Yandex tiles, placemarks and polylines inside an Edge WebView2 (Windows) or WKWebView (macOS). Same widget API as yandex_mapkit so it [...]

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 Windows — 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.
  YandexMapWindowsController? _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(YandexMapWindowsController controller) {
    setState(() => _controller = controller);
    print('YandexMapWindows: 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: YandexMapWindows(
        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
0
points
12
downloads

Publisher

verified publisherxlkv.uz

Weekly Downloads

Yandex Maps JavaScript API 2.1 for Flutter desktop — renders real Yandex tiles, placemarks and polylines inside an Edge WebView2 (Windows) or WKWebView (macOS). Same widget API as yandex_mapkit so it is easy to use alongside it.

Repository (GitHub)
View/report issues

Topics

#map #yandex #windows #macos #webview

License

unknown (license)

Dependencies

flutter, webview_flutter, webview_windows

More

Packages that depend on yandex_map_desktop