16
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flutter #1Advent Calendar 2020

Day 18

google_maps_flutterパッケージのGoogle Map ClassやGoogleMapController Classのまとめ

Last updated at Posted at 2020-12-17

はじめに

この記事は Flutter #1 AdventCalendar2020 の18日目の記事です。

普段はフリーランスでFlutter案件のお仕事を中心に行っています。
今回はお仕事でGoogle Mapを使っていろいろな機能を作った時に「今まで、何となくGoogle Mapを実装してたけど、ちゃんと勉強してみよう!」と思いよく使うプロパティやメソッドなどなどをまとめました。

Google Map Class

  • onCameraMoveStarted 
    マップをドラッグして移動した時に呼び出される。

  • onCameraMove
    onCameraMoveStarted開始後に常に地図の中心の緯度と経度を取得できる。
    ドラッグやピンチなどのジェスチャ操作でも発生します。
    状態変化があるたびに呼ばれます。printなど入れているとすごい数のprintが吐き出されるので注意です。
    コールバックはCameraPositionが返ります。


CameraPosition(bearing: 0.0, target: LatLng(latitude, longitude), tilt: 0.0, zoom: 17.0)
  • onCameraIdle 
    アニメーションがキャンセルされた時やマップをドラッグして移動などマップの変化が起こるときには、最後にonCameraIdleが必ず1回呼ばれます。
    コールバックはなし。

  • onLongPress 
    マップを長押しした場所の緯度と経度が返される。

  • onTap 
    マップをタップした場所の緯度と経度が返される。


GoogleMap(
  initialCameraPosition: CameraPosition(
    target: LatLng(latitude, longitude),
    zoom: 17,
  ),
  myLocationEnabled: true,
  markers: _markers,
  myLocationButtonEnabled: false,
  onMapCreated: (GoogleMapController googleMap) {
    _googleMapController.complete(googleMap);
  },
  onTap: (LatLng latLang) {
    print('Clicked: $latLang');
  },
  onLongPress: (LatLng latLang) {
    print('Tapped: $latLang');
  },
  onCameraIdle: () {
    print('CameraIdle');
  },
  onCameraMoveStarted: () {
    print('Move Started');
  },
  onCameraMove: (CameraPosition position) {
    print('Camera Move: $position');
  },
);
  • circles

Set<Circle>
マップ上に円を表示。
地図上に範囲を示すのに使用します。
「指定エリアから〇〇km圏内」などの機能で使用される範囲です。

final circles = <Circle>{
  Circle(
    circleId: CircleId(id),
    center: LatLng(latitude, longitude),
    strokeWidth: 1,
    strokeColor: Colors.lightBlue,
    fillColor: Colors.lightBlue.withOpacity(0.1),
    radius: 100,
  )
};
GoogleMap(
  initialCameraPosition: CameraPosition(
    target: LatLng(latitude, longitude),
    zoom: 17,
  ),
  myLocationEnabled: true,
  markers: _markers,
  myLocationButtonEnabled: false,
  onMapCreated: (GoogleMapController googleMap) {
    _googleMapController.complete(googleMap);
  },
  circles: circles,
);
  • polygons

Set<Polygon>
マップ上に指定した形のポリゴンを表示します。
ポリゴンの形は緯度と経度で指定して作ります。
こちらもcirclesと同様、地図上に範囲を示すのに使用します。

GoogleMap(
  initialCameraPosition: CameraPosition(
    target: LatLng(latitude, longitude),
    zoom: 17,
  ),
  myLocationEnabled: true,
  markers: _markers,
  myLocationButtonEnabled: false,
  onMapCreated: (GoogleMapController googleMap) {
    _googleMapController.complete(googleMap);
  },
  polygons: rhombusPolygon(),
);

// ひし形のポリゴンを表示
Set<Polygon> rhombusPolygon() {
  const lat = 34.59370; // 値は適当です
  const lng = 135.53810; // 値は適当です
  const offSet = 0.001;
  final polygonCords = <LatLng>[];

  polygonCords.add(LatLng(lat, lng - offSet));
  polygonCords.add(LatLng(lat + offSet, lng));
  polygonCords.add(LatLng(lat, lng + offSet));
  polygonCords.add(LatLng(lat - offSet, lng));
  polygonCords.add(LatLng(lat, lng - offSet));

  final polygonSet = <Polygon>{};
  polygonSet.add(Polygon(
    polygonId: PolygonId('test'),
    points: polygonCords,
    strokeWidth: 1,
    strokeColor: Colors.blue,
    fillColor: Colors.lightBlue.withOpacity(0.1),
  ));

  return polygonSet;
}
  • polylines

Set<Polyline>
マップ上の区間に線を表示します。
区間は緯度と経度で指定します。
ルート案内などで表示される出発点から到着点までの経路などに使います。


GoogleMap(
  initialCameraPosition: CameraPosition(
    target: LatLng(latitude, longitude),
    zoom: 17,
  ),
  myLocationEnabled: true,
  markers: _markers,
  myLocationButtonEnabled: false,
  onMapCreated: (GoogleMapController googleMap) {
    _googleMapController.complete(googleMap);
  },
  polylines: testPolyline(),
);

Set<Polyline> testPolyline() {
  final _polyLine = <Polyline>[];

  _polyLine.add(Polyline(
    polylineId: PolylineId('route'),
    visible: true,
    color: Colors.blue,
    patterns: [PatternItem.dash(20), PatternItem.gap(10)],
      width: 3,
    points: const [
      LatLng(latitude, latitude), // 始点
      LatLng(latitude2, latitude2), // 終点
    ],
  ),
);

GoogleMapController class

  • animateCamera(CameraUpdate cameraUpdate)
    カメラの位置をアニメーションにより変更します。
    タップしたマーカーにギュイーンとアニメーションで移動するときに使います。

  • moveCamera(CameraUpdate cameraUpdate)
    Future
    カメラの位置を変更します。
    animateCameraのアニメーションが必要ない時はこちらを使用します。
    使い方はanimateCameraと同様です。


// 選択した場所を表示とzoomを設定
Future<void> _changePosition(LatLng latLng, double zoom) async {
  if (latLng != null) {
    final completer = await _googleMapController.future;
    final cameraPosition = CameraPosition(target: latLng, zoom: zoom);
    await completer
        .animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
  }
}
  • hideMarkerInfoWindow(MarkerId markerId)
    Future<null>
    マーカーのInfoWindowを非表示にします。

  • showMarkerInfoWindow(MarkerId markerId)
    Future<null>
    マーカーのInfoWindowを表示します。

  • isMarkerInfoWindowShown(MarkerId markerId)
    Future<bool>
    InfoWindowが表示されているときにTrueが返ります。
    showMarkerInfoWindowやhideMarkerInfoWindowのメソッドと一緒に使うとInfoWindowの表示/非表示を制御できます。
    ↓多分これで動くはず....(ちゃんと検証できてないですゴメンなさい)


final Completer<GoogleMapController> _googleMapController =
    Completer<GoogleMapController>();

  // 選択したinfoViewを出す
void _updateSelectedPlace(OneDayJobDetail newJobs) {
  _infoWindowForSelectedPlace();
  setState(() {
    selectedPlace = newJobs;
  });
  _infoWindowForSelectedPlace();
}

Future<void> _infoWindowForSelectedPlace() async {
  if (selectedPlace != null && _googleMapController.isCompleted) {
    final selectedPlaceMarker = MarkerId(selectedPlace.id.value);
    final googleMap = await _googleMapController.future;
    final isSelectedPlaceMarkerShown =
        await googleMap.isMarkerInfoWindowShown(selectedPlaceMarker);
    if (!isSelectedPlaceMarkerShown) {
      await googleMap.hideMarkerInfoWindow(selectedPlaceMarker);
    } else {
      await googleMap.showMarkerInfoWindow(selectedPlaceMarker);
    }
  }
}
  • takeSnapshot()

Future<Uint8List>
マップの画像byteが返ってきます。
GoogleMap内ではなく、ボタンをタップするとその時表示されているGoogleMapのsnapshotをとる感じで実装します。

FlatButton(
  child: const Text('snapshotとるー'),
  onPressed: () async {

    // Completerを使用する場合はこんな感じ
    final googleMap = await _googleMapController.future;
    final imageBytes = await googleMap.takeSnapshot();

    // GoogleMapControllerの場合はこんな感じで
    // final imageBytes = await _mapController?.takeSnapshot();
    setState(() {
      _imageBytes = imageBytes;
    });
  },
),
Container(
  decoration: BoxDecoration(color: Colors.blueGrey[50]),
  height: 180,
  // ここに写真が表示される
  child: _imageBytes != null ? Image.memory(_imageBytes) : null,
),

さいごに

全体のコードをここに載せようと思いましたが、時間が足りずできませんでした。スミマセン...
いつもはその場限りで、何度もドキュメントを見にいって同じ事を調べていましたが、今回ちゃんとまとめる事ができ理解も深まったので今後、開発中に調べる手間が無くなればと思います。

あまり大した事が書けませんでしたが、これからFlutterを始める初心者の方のお役に立てれば幸いです!

もし、間違いなどがありましたらご教授ください。

参考文献

16
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?