Flutter地图点聚合插件clustering_google_maps的使用

插件简介

clustering_google_maps 是一个用于在 Flutter 中实现 Google 地图点聚合功能的插件。它通过将大量的点聚合成更少的聚合点来优化地图性能。

下图展示了该插件的效果:

示例效果

开发者预览状态

该插件实现了在 Google 地图上的聚类技术。它支持两种数据处理方式:

  1. 数据库方式(DB TECHNIQUE):从 SQLite 数据库中读取数据。
  2. 内存方式(MEMORY TECHNIQUE):直接使用内存中的数据列表。

使用方法

添加依赖

pubspec.yaml 文件中添加以下依赖项:

dependencies:
  clustering_google_maps: ^版本号

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

快速开始

数据库方式(DB TECHNIQUE)

初始化

在数据库方式下,你需要确保点的数据存储在 SQLite 数据库中,并包含以下三个字段:

  • 纬度 (latitude)
  • 经度 (longitude)
  • geohash 字符串

如果尚未保存 geohash,建议安装 geohash 插件并将其保存到数据库中。

初始化时使用 ClusteringHelper.forDB 构造函数:

import 'package:clustering_google_maps/clustering_google_maps.dart';

ClusteringHelper clusteringHelper = ClusteringHelper.forDB(
  dbGeohashColumn: 'geohash', // 数据库中 geohash 字段名
  dbLatColumn: 'latitude',    // 数据库中纬度字段名
  dbLongColumn: 'longitude',  // 数据库中经度字段名
  dbTable: 'your_table_name', // 数据库表名
  updateMarkers: updateMarkers, // 更新标记的回调
  aggregationSetup: AggregationSetup(), // 聚合设置
);

更新地图

在地图创建完成后调用 updateMap() 方法更新地图:

void _onMapCreated(GoogleMapController mapController) {
  clusteringHelper.mapController = mapController;
  clusteringHelper.updateMap();
}

内存方式(MEMORY TECHNIQUE)

初始化

在内存方式下,你需要一个包含 LatLngAndGeohash 对象的列表。LatLngAndGeohash 是一个简单的对象,包含位置和 geohash 属性,后者会自动生成。

初始化时使用 ClusteringHelper.forMemory 构造函数:

ClusteringHelper clusteringHelper = ClusteringHelper.forMemory(
  list: yourListOfLatLngAndGeohash, // 包含 LatLngAndGeohash 对象的列表
  updateMarkers: updateMarkers, // 更新标记的回调
  aggregationSetup: AggregationSetup(markerSize: 150), // 聚合设置
);

更新地图

同样,在地图创建完成后调用 updateMap() 方法更新地图:

void _onMapCreated(GoogleMapController mapController) {
  clusteringHelper.mapController = mapController;
  clusteringHelper.updateMap();
}

完整示例代码

以下是一个完整的示例代码,展示了如何使用 clustering_google_maps 插件:

import 'package:example/app_db.dart';
import 'package:example/fake_point.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:clustering_google_maps/clustering_google_maps.dart';

class HomeScreen extends StatefulWidget {
  final List<LatLngAndGeohash> list;

  HomeScreen({Key key, this.list}) : super(key: key);

  [@override](/user/override)
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  ClusteringHelper clusteringHelper;
  final CameraPosition initialCameraPosition =
      CameraPosition(target: LatLng(0.000000, 0.000000), zoom: 0.0);

  Set<Marker> markers = Set();

  void _onMapCreated(GoogleMapController mapController) async {
    print("onMapCreated");
    clusteringHelper.mapController = mapController;
    if (widget.list == null) {
      clusteringHelper.database = await AppDatabase.get().getDb();
    }
    clusteringHelper.updateMap();
  }

  updateMarkers(Set<Marker> markers) {
    setState(() {
      this.markers = markers;
    });
  }

  [@override](/user/override)
  void initState() {
    if (widget.list != null) {
      initMemoryClustering();
    } else {
      initDatabaseClustering();
    }

    super.initState();
  }

  // 初始化数据库方式
  initDatabaseClustering() {
    clusteringHelper = ClusteringHelper.forDB(
      dbGeohashColumn: FakePoint.dbGeohash,
      dbLatColumn: FakePoint.dbLat,
      dbLongColumn: FakePoint.dbLong,
      dbTable: FakePoint.tblFakePoints,
      updateMarkers: updateMarkers,
      aggregationSetup: AggregationSetup(),
    );
  }

  // 初始化内存方式
  initMemoryClustering() {
    clusteringHelper = ClusteringHelper.forMemory(
      list: widget.list,
      updateMarkers: updateMarkers,
      aggregationSetup: AggregationSetup(markerSize: 150),
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Clustering Example"),
      ),
      body: GoogleMap(
        onMapCreated: _onMapCreated,
        initialCameraPosition: initialCameraPosition,
        markers: markers,
        onCameraMove: (newPosition) =>
            clusteringHelper.onCameraMove(newPosition, forceUpdate: false),
        onCameraIdle: clusteringHelper.onMapIdle,
      ),
      floatingActionButton: FloatingActionButton(
        child:
            widget.list == null ? Icon(Icons.content_cut) : Icon(Icons.update),
        onPressed: () {
          if (widget.list == null) {
            // 测试 WHERE 子句
            clusteringHelper.whereClause = "WHERE ${FakePoint.dbLat} > 42.6";
          }
          // 强制更新地图
          clusteringHelper.updateMap();
        },
      ),
    );
  }
}

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

1 回复

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


clustering_google_maps 是一个用于在 Flutter 中使用 Google Maps 进行点聚合的插件。它可以帮助你在大量标记点的情况下,将相近的点聚合在一起,以提高地图的可读性和性能。

安装插件

首先,你需要在 pubspec.yaml 文件中添加 clustering_google_maps 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  clustering_google_maps: ^1.0.0

然后运行 flutter pub get 来安装插件。

基本使用

  1. 导入插件

    在你的 Dart 文件中导入 clustering_google_maps 插件:

    import 'package:clustering_google_maps/clustering_google_maps.dart';
    
  2. 创建地图

    使用 GoogleMap 组件来创建地图,并设置 markers 属性来显示标记点。

    import 'package:flutter/material.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    import 'package:clustering_google_maps/clustering_google_maps.dart';
    
    class MapScreen extends StatefulWidget {
      [@override](/user/override)
      _MapScreenState createState() => _MapScreenState();
    }
    
    class _MapScreenState extends State<MapScreen> {
      late GoogleMapController mapController;
      final Set<Marker> markers = {};
    
      [@override](/user/override)
      void initState() {
        super.initState();
        _loadMarkers();
      }
    
      void _loadMarkers() async {
        final List<ClusterItem> items = [
          ClusterItem(LatLng(37.7749, -122.4194), 'San Francisco'),
          ClusterItem(LatLng(34.0522, -118.2437), 'Los Angeles'),
          ClusterItem(LatLng(36.1699, -115.1398), 'Las Vegas'),
          // 添加更多标记点
        ];
    
        final clusterManager = ClusterManager<ClusterItem>(items, _updateMarkers);
        await clusterManager.setMap(mapController);
      }
    
      void _updateMarkers(Set<Marker> markers) {
        setState(() {
          this.markers.clear();
          this.markers.addAll(markers);
        });
      }
    
      [@override](/user/override)
      Widget build(BuildContext context) {
        return Scaffold(
          body: GoogleMap(
            onMapCreated: (GoogleMapController controller) {
              mapController = controller;
            },
            initialCameraPosition: CameraPosition(
              target: LatLng(37.7749, -122.4194),
              zoom: 10,
            ),
            markers: markers,
          ),
        );
      }
    }
    
  3. 处理聚合

    ClusterManager 负责处理标记点的聚合。你需要将标记点列表传递给 ClusterManager,并提供一个回调函数 _updateMarkers 来更新地图上的标记。

    final clusterManager = ClusterManager<ClusterItem>(items, _updateMarkers);
    await clusterManager.setMap(mapController);
    
  4. 自定义聚合标记

    你可以自定义聚合标记的外观。例如,可以设置聚合标记的颜色、大小和文本。

    final clusterManager = ClusterManager<ClusterItem>(
      items,
      _updateMarkers,
      markerBuilder: (Cluster<ClusterItem> cluster) {
        return Marker(
          markerId: MarkerId(cluster.getId()),
          position: cluster.location,
          icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
          infoWindow: InfoWindow(title: 'Cluster ${cluster.size}'),
        );
      },
    );
    

完整示例

以下是一个完整的示例,展示了如何使用 clustering_google_maps 插件在 Google Maps 上进行点聚合:

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

class MapScreen extends StatefulWidget {
  [@override](/user/override)
  _MapScreenState createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  late GoogleMapController mapController;
  final Set<Marker> markers = {};

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

  void _loadMarkers() async {
    final List<ClusterItem> items = [
      ClusterItem(LatLng(37.7749, -122.4194), 'San Francisco'),
      ClusterItem(LatLng(34.0522, -118.2437), 'Los Angeles'),
      ClusterItem(LatLng(36.1699, -115.1398), 'Las Vegas'),
      // 添加更多标记点
    ];

    final clusterManager = ClusterManager<ClusterItem>(
      items,
      _updateMarkers,
      markerBuilder: (Cluster<ClusterItem> cluster) {
        return Marker(
          markerId: MarkerId(cluster.getId()),
          position: cluster.location,
          icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
          infoWindow: InfoWindow(title: 'Cluster ${cluster.size}'),
        );
      },
    );

    await clusterManager.setMap(mapController);
  }

  void _updateMarkers(Set<Marker> markers) {
    setState(() {
      this.markers.clear();
      this.markers.addAll(markers);
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
        onMapCreated: (GoogleMapController controller) {
          mapController = controller;
        },
        initialCameraPosition: CameraPosition(
          target: LatLng(37.7749, -122.4194),
          zoom: 10,
        ),
        markers: markers,
      ),
    );
  }
}

void main() {
  runApp(MaterialApp(
    home: MapScreen(),
  ));
}
回到顶部