🌐

【Flutter】Google Maps上に線を引く為にPolylineを試してみる

2024/06/30に公開

概要

Google Maps上にPolylineで線を描画する際に、Flutterでどのように実装するかを試してみたいと思います。

方法

どうやら調べた所以下の2つのPubがひっかかったので、それぞれを試して比較してみたいと思います。

  1. google_maps_flutter で polyline を指定する方法

https://pub.dev/documentation/google_maps_flutter/latest/google_maps_flutter/GoogleMap/polylines.html

  1. flutter_polyline_points パッケージを使う方法

https://pub.dev/packages/flutter_polyline_points

google_maps_flutter で polyline を試す

早速 google_maps_flutterpoyline を試してみたいと思います。

パッケージインストール

dependencies:
  google_maps_flutter: ^2.7.0

まずはMapを表示するだけの画面を作成

google_maps_flutter_polyline.dart を以下内容で作成します。

import 'dart:async';

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

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

  
  State<GoogleMapsFlutterPolyline> createState() =>
      GoogleMapsFlutterPolylineState();
}

class GoogleMapsFlutterPolylineState extends State<GoogleMapsFlutterPolyline> {
  final Completer<GoogleMapController> _controller =
      Completer<GoogleMapController>();

  static const CameraPosition _initialCameraPosition = CameraPosition(
    target: LatLng(35.68123428932672, 139.76714355230686),
    zoom: 14.4746,
  );

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Google Maps Flutter Polyline')),
      body: GoogleMap(
        mapType: MapType.normal,
        initialCameraPosition: _initialCameraPosition,
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },
      ),
    );
  }
}

実行すると以下のようなMapが表示されるだけの画面が表示されるかと思います。

image1.png

実際にPolylineを使ってみる

次に本題のPolylineを使って線をひいてみたいと思います。google_maps_flutter_polyline.dart を以下に修正します。

import 'dart:async';

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

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

  
  State<GoogleMapsFlutterPolyline> createState() =>
      GoogleMapsFlutterPolylineState();
}

class GoogleMapsFlutterPolylineState extends State<GoogleMapsFlutterPolyline> {
  final Completer<GoogleMapController> _controller =
      Completer<GoogleMapController>();

  static const CameraPosition _initialCameraPosition = CameraPosition(
    target: LatLng(35.68123428932672, 139.76714355230686),
    zoom: 14.4746,
  );
  final Set<Polyline> _polylines = {};

  
  void initState() {
    super.initState();
    _setPolylines();
  }

  void _setPolylines() {
    setState(() {
      _polylines.add(
        const Polyline(
          polylineId: PolylineId('polyline_1'),
          points: [
            LatLng(35.681236, 139.767125),
            LatLng(35.680959, 139.767552),
            LatLng(35.680583, 139.767998),
          ],
          color: Colors.red,
          width: 5,
        ),
      );
      _polylines.add(
        const Polyline(
          polylineId: PolylineId('polyline_2'),
          points: [
            LatLng(35.681236, 139.767125),
            LatLng(35.682839, 139.769435),
            LatLng(35.683342, 139.770674),
          ],
          color: Colors.green,
          width: 5,
        ),
      );
      _polylines.add(
        const Polyline(
          polylineId: PolylineId('polyline_3'),
          points: [
            LatLng(35.681236, 139.767125),
            LatLng(35.680178, 139.766273),
            LatLng(35.679694, 139.765451),
          ],
          color: Colors.blue,
          width: 5,
        ),
      );
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Google Maps Flutter Polyline')),
      body: GoogleMap(
        mapType: MapType.normal,
        initialCameraPosition: _initialCameraPosition,
        polylines: _polylines,
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },
      ),
    );
  }
}

こちらを実行すると以下の様に3つの異なる色のラインが表示されるかと思います。

image2.png

Polylineクラス

https://pub.dev/documentation/google_maps_flutter/latest/google_maps_flutter/Polyline-class.html

サンプルの実装を見ていただけると分かるように、 Polyline の Set を GoogleMap クラスの polylines に設定する事で線を描画してくれます。

設定する主なプロパティは以下になります。

  • polylineId
    • PolylineId を指定します
    • PolylineIdは これはグローバルに一意である必要はなく、リスト内で一意であるだけで十分です とあるように、Polyline の Set 内でユニークになれば良いみたいです
  • points
    • 描画するポリラインの頂点で List<LatLng> を指定します
  • color
    • 線分の色を ARGB フォーマットで指定
  • width
    • 描画する線分の幅

点線にする

pattens に PatternItem の dash を設定してやると点線にする事ができます。

Polyline(
  // ...
  patterns: [PatternItem.dash(20), PatternItem.gap(20)], // ←追加
),

上記の意味として20pxで赤線を引いて、20pxの空白を作るのを繰り返し点線にしてます。

image3.png

flutter_polyline_points で polyline を試す

次は flutter_polyline_points を試してみたいと思います。

パッケージインストール

dependencies:
  flutter_polyline_points: ^2.0.1

実際に使ってみる

flutter_polyline_points.dart というファイル名で以下内容で作成します。

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

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

  
  State<FlutterPolylinePoints> createState() => FlutterPolylinePointsState();
}

class FlutterPolylinePointsState extends State<FlutterPolylinePoints> {
  final Completer<GoogleMapController> _controller =
      Completer<GoogleMapController>();

  static const CameraPosition _initialCameraPosition = CameraPosition(
    target: LatLng(35.68123428932672, 139.76714355230686),
    zoom: 14.4746,
  );
  final Set<Polyline> _polylines = {};
  final PolylinePoints polylinePoints = PolylinePoints();

  
  void initState() {
    super.initState();
    _setPolylines();
  }

  void _setPolylines() async {
    PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
      request: PolylineRequest(
        origin: const PointLatLng(26.48424, 50.04551),
        destination: const PointLatLng(26.46423, 50.06358),
        mode: TravelMode.walking,
        wayPoints: [PolylineWayPoint(location: "Sabo, Yaba Lagos Nigeria")],
      ),
      googleApiKey: 'YOUR_API_KEY',
    );
    if (result.points.isNotEmpty) {
      setState(() {
        _polylines.add(
          Polyline(
            polylineId: const PolylineId('polyline_1'),
            points: result.points
                .map((p) => LatLng(p.latitude, p.longitude))
                .toList(),
            color: Colors.red,
            width: 5,
          ),
        );
      });
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('FlutterPolylinePoints')),
      body: GoogleMap(
        mapType: MapType.normal,
        initialCameraPosition: _initialCameraPosition,
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },
        polylines: _polylines,
      ),
    );
  }
}

googleApiKey には事前に取得したAPI Keyを設定します。↑を実行すると↓の様になります。

image4.gif

このパッケージがGoogle Maps Platformの Routes API を使っているようで、

事前にfrom-toの位置を指定し、その間のルートを計算して各pointを配列で返してくれる様です。

flutter_polyline_points 自体がPolylineをひいてくれるという訳ではなく、google_maps_flutter でPolylineを引くためのpointsを計算してくれるという様な位置付けのPubの様でした。

まとめ

基本は google_maps_flutter を使って、特定の地点間のルートを求めたいなどの要求が出た場合に flutter_polyline_points を使えば良さそうかなという感想でした。

参考URL

https://zenn.dev/10_tofu_01/articles/271b5b338734e7

Discussion