Flutter地图路线绘制插件mapbox_polyline_points的使用

Flutter 地图路线绘制插件 mapbox_polyline_points 的使用

mapbox_polyline_points 是一个允许你使用 Mapbox 路径 API 在 Google 地图上绘制路径的 Flutter 插件。

开始使用

要使用此包,请在 pubspec.yaml 文件中添加 mapbox_polyline_points 作为依赖项。

dependencies:
  mapbox_polyline_points: ^<最新版本号>

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

导入包

在 Dart 文件中导入 mapbox_polyline_points 包:

import 'package:mapbox_polyline_points/mapbox_polyline_points.dart';

方法

通过地理坐标获取点列表,这将返回一个 MapboxPolylineResult 实例,其中包含 API 状态、错误消息和解码后的点列表。

MapboxPolylinePoints mapboxPolylinePoints = MapboxPolylinePoints();
MapboxPolylineResult result = await mapboxPolylinePoints.getRouteBetweenCoordinates(
  mapboxAPiKey,
  PointLatLng(latitude: _originLatitude, longitude: _originLongitude),
  PointLatLng(latitude: _destLatitude, longitude: _destLongitude),
  TravelType.walking // 或者 TravelType.driving
);
print(result.points);

示例

以下是一个完整的示例,展示了如何在 Flutter 应用中使用 mapbox_polyline_points 插件来绘制地图上的路线。

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:mapbox_polyline_points/mapbox_polyline_points.dart';

const LatLng _currentPosition = LatLng(28.6817149, 77.0534036);
const LatLng _currentPosition1 = LatLng(28.6277039, 77.1424405);
const LatLng _currentPosition2 = LatLng(40.698432, -73.924038);
const LatLng _currentPosition3 = LatLng(28.6730915, 77.0384241);
const LatLng _currentPosition4 = LatLng(28.6730915, 77.0384241);

class MapScreen extends StatefulWidget {
  static const String routerName = "/map_screen";
  const MapScreen({super.key});
  [@override](/user/override)
  State<MapScreen> createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  List<Marker>? _markers = [];
  bool? _serviceEnabled;
  late Position _locationData;
  LatLng? _center;
  List<List<LatLng>> polylineCoordinates = [];
  GoogleMapController? mapController;
  Map<PolylineId, Polyline> polylines = {};
  MapboxPolylinePoints mapboxpolylinePoints = MapboxPolylinePoints();

  [@override](/user/override)
  void initState() {
    super.initState();
    _determinePosition();
  }

  void _determinePosition() async {
    bool serviceEnabled;
    LocationPermission permission;

    serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      return Future.error('Location services are disabled.');
    }

    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.denied) {
        return Future.error('Location permissions are denied');
      }
    }

    if (permission == LocationPermission.deniedForever) {
      return Future.error(
        'Location permissions are permanently denied, we cannot request permissions.',
      );
    }

    _locationData = await Geolocator.getCurrentPosition();
    _getPolyline();
    setState(() {
      _center = LatLng(_locationData.latitude, _locationData.longitude);
    });
  }

  void _addPolyLine() {
    PolylineId id = PolylineId("poly");
    Polyline polyline = Polyline(
      polylineId: id,
      width: 5,
      color: Colors.greenAccent,
      points: polylineCoordinates[0],
    );
    polylines[id] = polyline;
    setState(() {});
  }

  void _getPolyline() async {
    MapboxPolylineResult result = await mapboxpolylinePoints.getRouteBetweenCoordinates(
      'pk.eyJ1IjoiYWxva2phZGhhdiIsImEiOiJjbGNnNGQxZGUwcmNiM3lrNTM3YjFnaWc4In0.4sdA4V90-ZAsGyxKxuNLiw',
      PointLatLng(latitude: _locationData.latitude, longitude: _locationData.longitude),
      PointLatLng(latitude: _currentPosition.latitude, longitude: _currentPosition.longitude),
      TravelType.walking,
    );

    if (result.points.isNotEmpty) {
      for (List<PointLatLng> element in result.points) {
        polylineCoordinates.add(decodeEncodedPolyline(element));
      }
    }

    _addPolyLine();
  }

  List<LatLng> decodeEncodedPolyline(List<PointLatLng> encoded) {
    List<LatLng> poly = [];
    for (int i = 0; i < encoded.length; i++) {
      poly.add(LatLng(encoded[i].latitude, encoded[i].longitude));
    }
    return poly;
  }

  List<Map> listSaloon = [
    {
      "image": "assets/images/outlate.jpg",
      "shop-name": "Afzal Cutting and sallon",
      "name": "Afzal khan",
      "distance": "14km"
    },
    {
      "image": "assets/images/outlet2.jpg",
      "shop-name": "Afzal Cutting and sallon",
      "name": "Afzal khan",
      "distance": "14km"
    },
    {
      "image": "assets/images/outlet3.jpg",
      "shop-name": "Afzal Cutting and sallon",
      "name": "Afzal khan",
      "distance": "14km"
    },
    {
      "image": "assets/images/outlet4.jpg",
      "shop-name": "Afzal Cutting and sallon",
      "name": "Afzal khan",
      "distance": "14km"
    },
    {
      "image": "assets/images/outlet5.jpg",
      "shop-name": "Afzal Cutting and sallon",
      "name": "Afzal khan",
      "distance": "14km"
    },
  ];

  [@override](/user/override)
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;

    return Scaffold(
      body: (_center == null)
          ? const Center(child: CircularProgressIndicator())
          : SizedBox(
              width: size.width,
              height: size.height,
              child: Stack(
                children: [
                  SizedBox(
                    width: size.width,
                    height: size.height,
                    child: GoogleMap(
                      initialCameraPosition: CameraPosition(
                        target: _center!,
                        zoom: 16,
                      ),
                      onMapCreated: (controller) async {
                        mapController = controller;
                        var currentMarker = await BitmapDescriptor.fromAssetImage(
                            ImageConfiguration.empty,
                            "assets/images/location.png");
                        var markerIcon = await BitmapDescriptor.fromAssetImage(
                            ImageConfiguration.empty,
                            "assets/images/locations.png");
                        _markers = [
                          Marker(
                            markerId: const MarkerId("djf0"),
                            position: LatLng(_locationData.latitude, _locationData.longitude),
                            icon: currentMarker,
                            onTap: () {
                              _center = LatLng(_locationData.latitude, _locationData.longitude);
                              setState(() {});
                            },
                          ),
                          Marker(
                            markerId: const MarkerId("djf"),
                            position: _currentPosition,
                            icon: markerIcon,
                            onTap: () {
                              _center = _currentPosition;
                              setState(() {});
                            },
                          ),
                          Marker(
                            markerId: const MarkerId("djf1"),
                            position: _currentPosition1,
                            icon: markerIcon,
                            onTap: () {
                              _center = _currentPosition1;
                              setState(() {});
                            },
                          ),
                          Marker(
                            markerId: const MarkerId("djf2"),
                            position: _currentPosition2,
                            icon: markerIcon,
                            onTap: () {
                              _center = _currentPosition2;
                              setState(() {});
                            },
                          ),
                          Marker(
                            markerId: const MarkerId("djf3"),
                            position: _currentPosition3,
                            icon: markerIcon,
                            onTap: () {
                              _center = _currentPosition3;
                              setState(() {});
                            },
                          ),
                          Marker(
                            markerId: const MarkerId("djf5"),
                            position: _currentPosition4,
                            icon: markerIcon,
                            onTap: () {
                              _center = _currentPosition4;
                              setState(() {});
                            },
                          ),
                        ];
                        setState(() {});
                      },
                      markers: _markers!.asMap().values.toSet(),
                      myLocationButtonEnabled: true,
                      polylines: Set<Polyline>.of(polylines.values),
                    ),
                  ),
                  Positioned(
                    bottom: 4,
                    left: 0,
                    child: SizedBox(
                      width: size.width,
                      height: size.height * 0.15,
                      child: ListView.builder(
                        itemCount: listSaloon.length,
                        scrollDirection: Axis.horizontal,
                        itemBuilder: (context, index) => InkWell(
                          onTap: () => _getPolyline(),
                          child: Container(
                            width: size.width * 0.35,
                            height: size.height * 0.15,
                            margin: EdgeInsets.symmetric(horizontal: 8.0),
                            decoration: BoxDecoration(
                              color: Colors.white,
                              boxShadow: [
                                BoxShadow(
                                  offset: Offset(2.5, 2.5),
                                  blurRadius: 5,
                                  color: Colors.grey,
                                )
                              ],
                            ),
                            child: Flex(
                              direction: Axis.vertical,
                              crossAxisAlignment: CrossAxisAlignment.center,
                              children: [
                                Expanded(
                                  flex: 2,
                                  child: Image.asset(
                                    listSaloon[index]["image"],
                                    fit: BoxFit.fitWidth,
                                  ),
                                ),
                                Expanded(
                                  child: Column(
                                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                    children: [
                                      Text(
                                        listSaloon[index]["shop-name"],
                                        style: TextStyle(fontSize: 10.0, fontWeight: FontWeight.w600, color: Colors.black),
                                      ),
                                      Row(
                                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                        crossAxisAlignment: CrossAxisAlignment.center,
                                        children: [
                                          Text(
                                            listSaloon[index]["name"],
                                            style: TextStyle(fontSize: 8.0, fontWeight: FontWeight.w400, color: Colors.black),
                                          ),
                                          Row(
                                            children: [
                                              Icon(Icons.directions_walk, size: 10),
                                              Text(
                                                listSaloon[index]["distance"],
                                                style: TextStyle(fontSize: 8.0, fontWeight: FontWeight.w600, color: Colors.black),
                                              ),
                                            ],
                                          ),
                                        ],
                                      ),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                  Positioned(
                    top: 30,
                    left: 10,
                    child: ElevatedButton.icon(
                      style: ElevatedButton.styleFrom(
                        foregroundColor: Colors.black,
                        backgroundColor: Colors.white.withOpacity(0.2),
                      ),
                      onPressed: () {
                        Navigator.pop(context);
                      },
                      icon: const Icon(Icons.arrow_back),
                      label: const Text('back'),
                    ),
                  ),
                ],
              ),
            ),
    );
  }
}

// 你还可以添加距离和持续时间,并且结果是一个 MapboxPolylineResult 实例

double distance = (result.distance[0].floor()) / 1000;
print(distance);

double seconds = result.distance[0];

// 将秒数转换为 Duration 对象
Duration duration = Duration(seconds: seconds.toInt());

// 提取小时、分钟和剩余的秒数
int hours = duration.inHours;
int minutes = duration.inMinutes.remainder(60);
int remainingSeconds = duration.inSeconds.remainder(60);

// 打印结果
print('$hours 小时 $minutes 分钟 $remainingSeconds 秒');

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

1 回复

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


当然,以下是一个关于如何在Flutter中使用mapbox_polyline_points插件来绘制地图路线的示例代码。这个插件主要用于将GPS坐标点转换成Polyline编码格式,并可以在Mapbox或其他地图服务上绘制这些路线。

首先,确保你已经在pubspec.yaml文件中添加了mapbox_polyline_points和地图服务插件(例如flutter_mapbox_gl)的依赖:

dependencies:
  flutter:
    sdk: flutter
  mapbox_polyline_points: ^0.2.0  # 请检查最新版本号
  flutter_mapbox_gl: ^0.14.0  # 请检查最新版本号,这里以Mapbox为例

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

接下来,在你的Flutter应用中,你可以按照以下步骤使用这些插件:

  1. 导入必要的包
import 'package:flutter/material.dart';
import 'package:mapbox_polyline_points/mapbox_polyline_points.dart';
import 'package:flutter_mapbox_gl/flutter_mapbox_gl.dart';
  1. 定义你的地图和路线数据
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> {
  final MapboxMapController _controller = MapboxMapController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Mapbox Polyline Example'),
      ),
      body: MapboxMap(
        accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN', // 替换为你的Mapbox访问令牌
        initialCameraPosition: CameraPosition(
          target: LatLng(37.7749, -122.4194),
          zoom: 13.0,
        ),
        mapController: _controller,
        onMapCreated: (controller) async {
          _controller.complete(controller);
          await _addPolyline(controller);
        },
      ),
    );
  }

  Future<void> _addPolyline(MapboxMapController controller) async {
    // 定义路线坐标点
    List<LatLng> points = [
      LatLng(37.7749, -122.4194), // 旧金山
      LatLng(34.0522, -118.2437), // 洛杉矶
    ];

    // 使用mapbox_polyline_points将坐标点转换为Polyline字符串
    PolylinePoints polylinePoints = PolylinePoints();
    List<PointLatLng> result = polylinePoints.decodePolyline(
      polylinePoints.encodePolyline(points),
    );

    // 在地图上添加PolylineLayer
    controller.addPolyline(
      PolylineOptions(
        geometries: [
          LineString(result.map((point) => LatLng(point.latitude, point.longitude)).toList()),
        ],
        color: Colors.blue.withOpacity(0.8),
        width: 5.0,
      ),
    );
  }
}

注意

  • 你需要替换YOUR_MAPBOX_ACCESS_TOKEN为你的实际Mapbox访问令牌。
  • mapbox_polyline_points插件主要用于编码和解码Polyline,这里示例中虽然直接使用了points列表进行编码和解码(实际上这样做是多余的,因为points已经是一个坐标列表),但在实际应用中,你可能会从服务器获取已经编码的Polyline字符串,然后解码它以获取坐标点。
  • flutter_mapbox_gl插件用于在Flutter应用中显示Mapbox地图,并提供了添加PolylineLayer的方法。

这个示例展示了如何在Flutter中使用mapbox_polyline_pointsflutter_mapbox_gl插件来绘制地图上的路线。根据你的实际需求,你可能需要调整坐标点、样式等参数。

回到顶部