Flutter地图控制插件map_controller_plus的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter地图控制插件map_controller_plus的使用

简介

map_controller_plus 是一个用于 Flutter 地图的有状态控制器。它可以帮助你管理地图上的标记(markers)、线(lines)和多边形(polygons)。这个插件是 synw's map_controller package 的一个分支,因为它已经被废弃,所以这个新的改进版本支持最新的 flutter_map 包。

如果你需要任何功能或修复,可以在 forked repository 上打开一个 issue。

使用方法

导入依赖

首先,在你的 pubspec.yaml 文件中添加 map_controller_plus 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_map: ^0.13.1
  latlong2: ^0.8.1
  map_controller_plus: ^0.7.0

然后运行 flutter pub get 来安装依赖。

基本用法

以下是一个基本的示例,展示了如何使用 map_controller_plus 控制器来管理地图上的标记、线和多边形。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:map_controller_plus/map_controller_plus.dart';

class MapPage extends StatefulWidget {
  @override
  _MapPageState createState() => _MapPageState();
}

class _MapPageState extends State<MapPage> {
  late final MapController mapController;
  late final StatefulMapController statefulMapController;
  late final StreamSubscription<StatefulMapControllerStateChange> sub;

  @override
  void initState() {
    super.initState();

    // 初始化控制器
    mapController = MapController();
    statefulMapController = StatefulMapController(mapController: mapController);

    /// [重要] 监听变更流以在变更时重建地图:
    /// 这将在调用 addMarker 或其他修改地图资产的方法时重建地图
    sub = statefulMapController.changeFeed.listen((change) => setState(() {}));
  }

  @override
  void dispose() {
    sub.cancel();
    mapController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Map Controller Plus Demo'),
      ),
      body: SafeArea(
        child: Stack(
          children: [
            FlutterMap(
              mapController: mapController,
              options: MapOptions(
                center: LatLng(48.853831, 2.348722),
                zoom: 11.0,
              ),
              children: [
                MarkerLayer(markers: statefulMapController.markers),
                PolylineLayer(polylines: statefulMapController.lines),
                PolygonLayer(polygons: statefulMapController.polygons),
              ],
            ),
            // 其他控件可以放在这里
          ],
        ),
      ),
    );
  }
}

API

地图控制

  • Zoom

    • zoom: 获取当前的缩放级别。
    • zoomIn(): 缩放级别增加 1。
    • zoomOut(): 缩放级别减少 1。
    • zoomTo(): 缩放到指定的值。
  • Center

    • center: 获取当前的中心点 LatLng
    • centerOnPoint(): 将地图中心移动到指定的 LatLng

地图资产

  • Markers

    • addMarker(): 在地图上添加一个命名的标记。
    • addMarkers(): 在地图上添加多个命名的标记。
    • removeMarker(): 从地图上移除一个命名的标记。
    • removeMarkers(): 从地图上移除多个命名的标记。
    • markers: 获取地图上的所有标记。
    • namedMarkers: 获取地图上的所有带有名称的标记。
    • getMarker(): 返回具有相应名称的标记。
    • getMarkers(): 返回具有相应名称的标记。
  • Stateful Markers (新特性,0.7 版本开始)

    • addStatefulMarker(): 添加一个带有状态的标记。
    • mutateMarker(): 修改标记的状态。
statefulMapController.addStatefulMarker(
  name: "some marker",
  statefulMarker: StatefulMarker(
    height: 80.0,
    width: 120.0,
    state: {"showText": false},
    point: LatLng(48.853831, 2.348722),
    builder: (BuildContext context, Map<String, dynamic> state) {
      Widget w;
      final markerIcon = IconButton(
        icon: const Icon(Icons.location_on),
        onPressed: () => statefulMapController.mutateMarker(
          name: "some marker",
          property: "showText",
          value: !(state["showText"] as bool),
        ),
      );
      if (state["showText"] == true) {
        w = Column(
          children: [
            markerIcon,
            Container(
              color: Colors.white,
              child: Padding(
                padding: const EdgeInsets.all(5.0),
                child: Text("Place Name", textScaleFactor: 1.3),
              ),
            ),
          ],
        );
      } else {
        w = markerIcon;
      }
      return w;
    },
  ),
);
  • Lines

    • addLine(): 在地图上添加一条线。
    • lines: 获取地图上的所有线。
  • Polygons

    • addPolygon(): 在地图上添加一个多边形。
    • polygons: 获取地图上的所有多边形。

变更流

变更流是一个包含所有地图控制器状态变化的流。你可以使用它在发生变更时更新地图:

statefulMapController.changeFeed.listen((change) => setState(() {}));

GeoJSON 数据

地图控制器可以从 GeoJSON 数据绘制地图:

void loadData() async {
  print("Loading geojson data");
  final data = await rootBundle.loadString('assets/airports.geojson');
  await statefulMapController.fromGeoJson(
    data,
    markerIcon: Icon(Icons.local_airport),
    verbose: true,
  );
}

@override
void initState() {
  super.initState();
  mapController = MapController();
  statefulMapController = StatefulMapController(mapController: mapController);
  loadData();
  sub = statefulMapController.changeFeed.listen((change) => setState(() {}));
}

瓦片层管理

预定义了一些瓦片层:

FlutterMap(
  mapController: mapController,
  options: MapOptions(
    center: LatLng(48.853831, 2.348722),
    zoom: 11.0,
  ),
  children: [
    TileLayer(
      urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
      subdomains: const ['a', 'b', 'c'],
      userAgentPackageName: 'dev.fleaflet.flutter_map.example',
    ),
    MarkerLayer(markers: statefulMapController.markers),
    // 其他层可以放在这里
  ],
)

示例代码

以下是一个完整的示例,展示了如何使用 map_controller_plus 控制器来管理地图上的标记、线和多边形,并提供导航功能。

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:map_controller_plus/map_controller_plus.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Map Controller Demo',
      routes: {
        '/': (BuildContext context) => MapPage(),
        '/markers': (BuildContext context) => MarkersPage(),
        '/tile_layer': (BuildContext context) => TileLayerPage(),
        '/stateful_markers': (BuildContext context) => StatefulMarkersPage(),
      },
    );
  }
}

class MapPage extends StatefulWidget {
  @override
  _MapPageState createState() => _MapPageState();
}

class _MapPageState extends State<MapPage> {
  late final MapController mapController;
  late final StatefulMapController statefulMapController;
  late final StreamSubscription<StatefulMapControllerStateChange> sub;

  @override
  void initState() {
    super.initState();

    // 初始化控制器
    mapController = MapController();
    statefulMapController = StatefulMapController(mapController: mapController);

    // 监听变更流
    sub = statefulMapController.changeFeed.listen((change) => setState(() {}));
  }

  @override
  void dispose() {
    sub.cancel();
    mapController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Map Controller Plus Demo'),
      ),
      body: SafeArea(
        child: Stack(
          children: [
            FlutterMap(
              mapController: mapController,
              options: MapOptions(
                center: LatLng(48.853831, 2.348722),
                zoom: 11.0,
              ),
              children: [
                MarkerLayer(markers: statefulMapController.markers),
                PolylineLayer(polylines: statefulMapController.lines),
                PolygonLayer(polygons: statefulMapController.polygons),
              ],
            ),
            Positioned(
              bottom: 20,
              left: 20,
              child: Column(
                children: [
                  ElevatedButton(
                    onPressed: () {
                      statefulMapController.addMarker(
                        name: 'marker1',
                        marker: Marker(
                          point: LatLng(48.853831, 2.348722),
                          builder: (ctx) => Icon(Icons.location_on, color: Colors.red),
                        ),
                      );
                    },
                    child: Text('Add Marker'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      statefulMapController.addLine(
                        name: 'line1',
                        polyline: Polyline(
                          points: [
                            LatLng(48.853831, 2.348722),
                            LatLng(48.863831, 2.358722),
                          ],
                          color: Colors.blue,
                          strokeWidth: 5,
                        ),
                      );
                    },
                    child: Text('Add Line'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      statefulMapController.addPolygon(
                        name: 'polygon1',
                        polygon: Polygon(
                          points: [
                            LatLng(48.853831, 2.348722),
                            LatLng(48.863831, 2.358722),
                            LatLng(48.873831, 2.368722),
                          ],
                          color: Colors.green.withOpacity(0.5),
                          borderColor: Colors.green,
                          borderStrokeWidth: 2,
                        ),
                      );
                    },
                    child: Text('Add Polygon'),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// 其他页面的实现可以根据需要添加
class MarkersPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Markers Page'),
      ),
      body: Center(
        child: Text('Markers Page Content'),
      ),
    );
  }
}

class TileLayerPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Tile Layer Page'),
      ),
      body: Center(
        child: Text('Tile Layer Page Content'),
      ),
    );
  }
}

class StatefulMarkersPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Stateful Markers Page'),
      ),
      body: Center(
        child: Text('Stateful Markers Page Content'),
      ),
    );
  }
}

以上代码展示了如何使用 map_controller_plus 插件来管理和控制 Flutter 地图上的各种元素。希望对你有所帮助!


更多关于Flutter地图控制插件map_controller_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地图控制插件map_controller_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用Flutter中的map_controller_plus插件来控制地图的示例代码。这个插件是对flutter_map的增强,提供了更丰富的地图控制功能。

首先,确保你已经在pubspec.yaml文件中添加了依赖项:

dependencies:
  flutter:
    sdk: flutter
  flutter_map: ^0.x.x  # 请根据需要替换为最新版本
  map_controller_plus: ^0.x.x  # 请根据需要替换为最新版本

然后,运行flutter pub get来安装依赖。

接下来,是一个简单的示例,展示了如何使用map_controller_plus来控制地图:

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:map_controller_plus/map_controller_plus.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MapScreen(),
    );
  }
}

class MapScreen extends StatefulWidget {
  @override
  _MapScreenState createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  late MapControllerPlus _mapController;

  @override
  void initState() {
    super.initState();
    _mapController = MapControllerPlus(
      initialPosition: LatLng(0.0, 0.0), // 初始位置
      initialZoom: 2.0, // 初始缩放级别
    )..addListener(() {
        // 监听地图变化,例如缩放或平移
        print('Map position changed: ${_mapController.position}');
      });
  }

  @override
  void dispose() {
    _mapController.dispose(); // 释放资源
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Map with map_controller_plus'),
      ),
      body: Column(
        children: [
          Expanded(
            child: FlutterMap(
              mapController: _mapController,
              options: MapOptions(
                center: _mapController.position,
                zoom: _mapController.zoom,
              ),
              layers: [
                TileLayerOptions(
                  urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
                  subdomains: ['a', 'b', 'c'],
                ),
              ],
            ),
          ),
          ElevatedButton(
            onPressed: () {
              // 示例:移动到新位置
              _mapController.moveTo(LatLng(40.7128, -74.0060), zoom: 13.0);
            },
            child: Text('Move to New York'),
          ),
          ElevatedButton(
            onPressed: () {
              // 示例:缩放地图
              _mapController.zoomIn();
            },
            child: Text('Zoom In'),
          ),
          ElevatedButton(
            onPressed: () {
              // 示例:平移地图
              _mapController.pan(LatLng(1, 1)); // 向右下方平移(相对当前位置)
            },
            child: Text('Pan Map'),
          ),
        ],
      ),
    );
  }
}

在这个示例中:

  1. 我们创建了一个MapControllerPlus实例,并在initState中初始化了它。
  2. 使用FlutterMap组件并将mapController属性设置为我们的_mapController实例。
  3. 在UI中添加了几个按钮,用于演示如何使用_mapController来控制地图(移动到新位置、缩放、平移)。

这个示例展示了如何使用map_controller_plus插件提供的API来控制地图。你可以根据需要进一步扩展这个示例,例如添加更多的地图层、标记、覆盖物等。

回到顶部