[Flutter]google_maps_flutter2.9.0で追加されたクラスタリング機能を触ってみる
Flutterのgoogle_maps_flutter で、今までライブラリ単独では実装が難しかったクラスタリング機能が追加されたらしいので試してみました!
- ChangeLog
- 関連PR👇
対象の読者
- google_maps_flutterで何ができるのか調べている人
- google_maps_flutter2.9.0から追加されたクラスタリング機能について知りたい方
この記事で書かないこと
- google_maps_flutterの使い方
- マーカーのクラスタリングとは何かについて(公式例がわかりやすいと思います!)
実施の背景
今までFlutterでクラスタリングを実現する時は、google_maps_flutter + google_maps_cluster_managerの組み合わせで行っていました。
この組み合わせに不満はないのですが、少し前からgoogle_maps_flutter側でもクラスタリング対応のPRが上がっており、2.9.0でマージされたので試してみたいと思った次第です。
期待としては、google_maps_cluster_managerを使わずにクラスタリングを実現することで、以下を実現したいと考えました。
- 公式から提供されたライブラリのみで機能を実現したい
- google_maps_cluster_managerに依存している部分を脱却したい
検証
実行環境は以下のとおりです。
$ flutter --version
Flutter 3.27.1 • channel stable
Tools • Dart 3.6.0 • DevTools 2.40.2
google_maps_flutter: ^2.10.0
PRのexampleを参考にしながら実装してみました。
試してみたリポジトリを公開しています。
マップ部分だけ抜き取ったもの
class ClusteringMap extends StatefulWidget {
const ClusteringMap({super.key});
State<ClusteringMap> createState() => MapSampleState();
}
class MapSampleState extends State<ClusteringMap> {
final Completer<GoogleMapController> _controller =
Completer<GoogleMapController>();
static const CameraPosition _kTokyo = CameraPosition(
target: LatLng(35.681236, 139.767125), // Tokyo Station coordinates
zoom: 14,
);
final Set<Marker> _markers = {};
void _addMarkers() {
final List<LatLng> positions = [
LatLng(35.682839, 139.759455), // Marunouchi
// マーカー群の配列
// ...
];
for (int i = 0; i < positions.length; i++) {
_markers.add(
Marker(
markerId: MarkerId('marker_$i'),
position: positions[i],
infoWindow: InfoWindow(title: 'Marker $i'),
clusterManagerId: ClusterManagerId('1'),
),
);
}
}
Set<ClusterManager> clusterManagers = {
ClusterManager(
clusterManagerId: ClusterManagerId('1'),
onClusterTap: (Cluster cluster) => print(cluster.count),
)
};
void initState() {
super.initState();
_addMarkers();
}
Widget build(BuildContext context) {
return Scaffold(
body: GoogleMap(
initialCameraPosition: _kTokyo,
markers: _markers,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
clusterManagers: clusterManagers,
),
);
}
}
クラスタリングが想定通り動くところまで実装できました。
マーカーがクラスタリングされる時/解除される時のアニメーションが今までの google_maps_flutter
+ google_maps_cluster_manager
では表現できなかった動きだなと言うのが率直な感想です。
検証して気づいたこと
-
google_maps_cluster_manager
を使う場合と、ClusterManagerの作り方に大差はないと感じた -
ClusterManagerのプロパティはまだ
clusterManagerId
(クラスタリング群を特定するためのID)とonClusterTap
(タップ時に呼び出されるコールバック)くらいしかなさそう-
google_maps_cluster_manager
にあるようなマーカーのカスタマイズなどはできなさそう
-
- GoogleMapウィジェットのプロパティにclusterManagersが増えている
- 複数のClusterManager運用もできるということ(サンプルは複数作成していた)
- MarkerウィジェットのプロパティにclusterManagerIdが増えている
- 検証結果のGIFを見ても分かるとおり、マーカーが10以上クラスタリングされると
10+
表記になる
結論
現時点ではgoogle_maps_flutterに追加されたクラスタリング機能では特にクラスタリングマーカーのカスタマイズができないこともあるので、完全にgoogle_maps_cluster_managerの代替まではできないと思いました(そんなことないよ!と言う方いたらコメントいただけると嬉しいです!)。
その一方で、公式ライブラリ一つでできることの強みや、クラスタリング時のアニメーションの表現力の高さは採用したい理由になると思います。
ぜひこれからのバージョンアップにも期待したいですし、そのためにもよりgoogle_maps_flutterのクラスタリングを使い倒してみます!
Discussion