Flutter地图工具插件flutter_map_toolkit的使用

Flutter地图工具插件flutter_map_toolkit的使用

本包包含了一些用于flutter_map包的插件。

安装

首先,您必须在FlutterMap中添加插件。

final plugins = [
  PointSelectorPlugin(),
  DirectionsPlugin(),
  LiveMarkerPlugin(),
];

然后,在FlutterMap小部件中设置插件属性。

FlutterMap(
  plugins: plugins, 
  ...
)

现在,您可以使用FlutterMap的小部件层属性来使用这些插件。

FlutterMap(
  plugins: plugins, 
  layers:[
    TileLayerOptions(
      ...,
    ),
    LiveMarkerOptionsWithStream(
      ...
    ),
    ...
  ]
  ...
)

插件

点选择器插件

点选择器插件包含两种模式:

中心点选择器
  • 选择单个点在地图上
  • 单击点选择器

center_point_selector

点击点选择器
  • 当用户点击地图时选择一个点

tap_point_selector

活动标记插件

活动标记插件有两种方式:

带刷新率的活动标记
  • 使用LiveMarkerOptionsWithRefreshRate设置刷新率和标记信息提供者
带流的活动标记
  • 使用LiveMarkerOptionsWithStreamPointInfoStreamedProvider
  • 此插件将在流更新时刷新标记
  • 用户与地图交互时,此插件将向提供者发送新的MapInformationRequestParams

注意:此插件没有默认提供者,因此您必须在代码中实现PointInfoProviderPointInfoStreamedProvider

方向插件(WIP)

  • 可以用来在地图上绘制路线,并可以使用DirectionsLayerController进行控制

注意:此插件自带MapboxDirectionProvider

  • 这将使用Mapbox API为给定的航路点获取方向
DirectionsLayerOptions(
  provider: mapboxProvider,
  controller: directionController,
  loadingBuilder: (context) {
    return const Center(
      child: CircularProgressIndicator(),
    );
  },
  ...
)

示例代码

以下是一个完整的示例代码,展示了如何在应用中使用flutter_map_toolkit插件。

import 'dart:math';

import 'package:bloc/bloc.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_toolkit/flutter_map_toolkit.dart';
import 'package:latlong2/latlong.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter_Map_Toolkit Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  DistanceInfo? distanceInfo;
  static const _mapboxPublicToken =
      'pk.eyJ1IjoiZm1vdGFsbGxlbGIiLCJhIjoiY2w2amFycmIwMDBkbDNsbmduNnpwczZrNyJ9.sDOg7Y2k9Nxat1MlkPj2lg';
  final httpClient = Dio();
  final _mapEventTap = MapTapEventHandler();
  late final directionProvider = MapboxDirectionProvider(
    mapboxToken: _mapboxPublicToken,
    getRequestHandler: (String url) async {
      final response = await httpClient.get<Map<String, dynamic>>(
        url,
      );
      return response.data!;
    },
  );
  final directionController = DirectionsLayerController();
  final _points = <LatLng>[];
  final plugins = [
    PointSelectorPlugin(),
    DirectionsPlugin(),
    LiveMarkerPlugin(),
  ];
  final _mapBoxAddress = mapBoxUrlBuilder(
    style: 'fmotalleb/cl6m8kuee009v16pkv7m6mxgs',
    is2x: true,
    accessToken: _mapboxPublicToken,
  );

  final pointProvider = SampleStreamedPointProvider();
  void onPointSelect(PointSelectionEvent event) {
    if (event.state == PointSelectionState.select) {
      if (event.point != null) {
        // _points.add(event.point!);
        setState(() {
          distanceInfo = directionController.lastPath?.distanceToPoint(
            event.point!,
          );
        });
        pointProvider.controller.insert(event.point!);
      }
    } else if (event.point != null) {
      _points.remove(event.point);
      pointProvider.controller.remove(event.point!);
    }
    if (_points.length > 1) {
      directionController.requestDirections(_points);
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Flexible(
              child: FlutterMap(
                options: MapOptions(
                  plugins: plugins,
                  minZoom: 5,
                  maxZoom: 18,
                  adaptiveBoundaries: false,
                  onTap: (tapPosition, point) {
                    _mapEventTap.update(point);
                  },
                  center: LatLng(32.553447, 53.064549),
                  zoom: 5,
                ),
                layers: [
                  /// base map tile backed by mapbox
                  TileLayerOptions(
                    maxNativeZoom: 15,
                    urlTemplate: _mapBoxAddress,
                  ),

                  if (distanceInfo != null) ...[
                    MarkerLayerOptions(
                      markers: [
                        Marker(
                          width: 80,
                          height: 80,
                          point: distanceInfo!.source,
                          builder: (ctx) => const Icon(
                            Icons.location_on,
                            color: Colors.red,
                          ),
                        ),
                        Marker(
                          width: 80,
                          height: 80,
                          point: distanceInfo!.destination,
                          builder: (ctx) => const Icon(
                            Icons.location_off,
                            color: Colors.red,
                          ),
                        ),
                      ],
                    ),
                    PolylineLayerOptions(
                      polylines: [
                        Polyline(
                          points: [
                            distanceInfo!.source,
                            distanceInfo!.destination,
                          ],
                          strokeWidth: 3,
                          color: Colors.red,
                        ),
                      ],
                    ),
                  ],

                  /// direction layer for showing the route between selected points
                  // DirectionsLayerOptions(
                  //   provider: directionProvider,
                  //   useCachedRoute: true,
                  //   controller: directionController,
                  //   loadingBuilder: (context) {
                  //     return const Center(
                  //       child: CircularProgressIndicator(),
                  //     );
                  //   },
                  // ),

                  PointSelectorOptions(
                    onPointSelected: onPointSelect,
                    marker: MarkerInfo(
                      view: (context, __) => SizedBox(),
                    ),
                    removeOnTap: true,
                    mapEventLink: _mapEventTap,
                  ),

                  /// draw selected points on map
                  LiveMarkerOptionsWithStream(
                    pointsInfoProvider: pointProvider,
                    markers: {
                      'm0': MarkerInfo(
                          view: (_, __) => Icon(
                                Icons.gpp_good_sharp,
                                color: Colors.black.withOpacity(0.2),
                              )),
                    },
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

extension Randomize<T> on List<T> {
  T get random => this[Random().nextInt(length)];
  List<T> randomize() {
    final result = toList();
    result.shuffle();
    return result;
  }
}

class SamplePointsEventCubit extends Cubit<List<PointInfo>> {
  SamplePointsEventCubit(this.iconIds, [super.initialState = const []]);
  final List<String> iconIds;
  final _points = <LatLng>[];
  int get pointsCount => _points.length;
  Iterable<PointInfo> get _information {
    return _points.map(
      (e) => PointInfo(
        rotation: 0,
        position: e,
        iconId: iconIds.random,
        metaData: {},
      ),
    );
  }

  void refresh() {
    emit(
      _information.toList(),
    );
  }

  void removeAll() {
    _points.clear();
    emit([]);
  }

  void insert(LatLng point) {
    _points.add(point);
    emit(_information.toList());
  }

  void remove(LatLng point) {
    _points.remove(point);
    emit(_information.toList());
  }
}

class SampleStreamedPointProvider extends PointInfoStreamedProvider {
  final controller = SamplePointsEventCubit([
    'm0',
  ]);
  [@override](/user/override)
  Stream<List<PointInfo>> getPointStream(
    Stream<MapInformationRequestParams?> params,
  ) =>
      controller.stream;

  [@override](/user/override)
  void invoke() {
    controller.refresh();
  }
}

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

1 回复

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


当然,下面是一个关于如何使用Flutter地图工具插件flutter_map_toolkit的示例代码。这个插件可以帮助你更方便地在Flutter应用中使用地图功能。

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

dependencies:
  flutter:
    sdk: flutter
  flutter_map: ^0.x.x  # 请使用最新版本号
  flutter_map_toolkit: ^0.x.x  # 请使用最新版本号

然后,运行flutter pub get来获取这些依赖。

接下来是一个简单的示例代码,展示了如何使用flutter_map_toolkit在Flutter应用中显示一个地图,并添加一些基本的地图控件,比如缩放控件和定位控件。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Map Toolkit Example'),
        ),
        body: FlutterMapExample(),
      ),
    );
  }
}

class FlutterMapExample extends StatefulWidget {
  @override
  _FlutterMapExampleState createState() => _FlutterMapExampleState();
}

class _FlutterMapExampleState extends State<FlutterMapExample> {
  final MapController _controller = MapController();

  @override
  Widget build(BuildContext context) {
    return FlutterMap(
      mapController: _controller,
      options: MapOptions(
        center: LatLng(45.5236, -122.6750), // 地图中心点
        zoom: 13.0,
      ),
      layers: [
        TileLayerOptions(
          urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
          subdomains: ['a', 'b', 'c'],
        ),
        // 添加定位控件
        MapToolkitLayer(
          options: MapToolkitOptions(
            myLocationEnabled: true,
            myLocationButtonBuilder: (context) {
              return IconButton(
                icon: Icon(Icons.location_on),
                onPressed: () {
                  // 处理定位按钮点击事件
                  // 这里可以调用_controller.moveTo来移动到当前位置
                },
              );
            },
          ),
        ),
        // 添加缩放控件
        MapToolkitLayer(
          options: MapToolkitOptions(
            zoomControlEnabled: true,
          ),
        ),
      ],
    );
  }
}

在这个示例中,我们创建了一个Flutter应用,并在主页上展示了一个地图。我们使用了flutter_mapflutter_map_toolkit来配置和显示地图。以下是几个关键点:

  1. MapController:用于控制地图的状态,比如缩放和移动。
  2. MapOptions:配置地图的中心点、缩放级别等。
  3. TileLayerOptions:配置地图的图层,这里使用的是OpenStreetMap的图层。
  4. MapToolkitLayerflutter_map_toolkit提供的图层,用于添加各种地图控件,比如定位控件和缩放控件。

注意:

  • 你可能需要根据实际情况调整urlTemplate和其他配置。
  • 定位功能可能需要额外的权限和设置,特别是在移动设备上。
  • 确保你使用的flutter_mapflutter_map_toolkit版本兼容。

希望这个示例代码能帮助你开始使用flutter_map_toolkit

回到顶部