绘制海量点图层 最后更新时间: 2026年01月06日
在地图上加载显示海量点,支持高达十万级点位的流畅显示。
第 1 步:初始化 MapView 并获取 AMap 实例
通过 MapViewComponent 创建地图视图,并在回调中获取底层 AMap 对象,用于后续操作。
@Builder
buildMapMultiPointOverlay() {
Stack() {
MapViewComponent({ mapViewName: Constants.MAP_MULTIPOINTOVERLAY_FUNC })
}
.width('100%')
.height('100%')
}
private mapViewCreateCallback = (mapview?: MapView, mapViewName?: string) => {
if (!mapview || mapViewName !== Constants.MAP_MULTIPOINTOVERLAY_FUNC) return;
this.mapView = mapview;
this.mapView.onCreate();
this.mapView.getMapAsync(async (map: AMap) => {
this.aMap = map;
await this.setupMultiPointOverlay();
});
};
第 2 步:准备点位数据源
支持两种方式加载点位数据:
方式一:从本地文件加载(推荐用于真实数据)
将经纬度数据以 CSV 格式保存在 resources/rawfile/point10w.txt 文件中,每行格式为:
经度,纬度 116.397026,39.90976 116.401,39.912 ...
private async loadPointItemsFromFile(): Promise<MultiPointItem[]>方式二:动态生成测试数据(用于调试)
可生成指定数量的随机点,中心坐标为中国北京附近。
const testPoints = this.generateTestPoints(10000);第 3 步:创建 MultiPointOverlay 图层
配置 MultiPointOverlayOptions,设置图标、锚点及初始点集。
const overlayOptions = new MultiPointOverlayOptions();
overlayOptions.icon(bitmapDescriptor); // 设置点图标
overlayOptions.anchor(0.5, 0.5); // 图标中心对齐
overlayOptions.setMultiPointItems([]); // 初始为空数组
this.multiPointOverlay = this.aMap.addMultiPointOverlay(overlayOptions);其中:
参数
说明
icon(BitmapDescriptor)
点的显示图标,建议尺寸较小以提升性能
anchor(x, y)
图标锚点位置,(0.5, 0.5) 表示居中对齐
setMultiPointItems(items)
设置要渲染的点列表
第 4 步:加载并渲染点数据
调用 loadAndRenderPoints() 方法异步加载文件中的点数据,并更新到 MultiPointOverlay。
流程如下:
- 读取 rawfile/point10w.txt 文件内容;
- 解析每一行为 LatLng 坐标;
- 构造 MultiPointItem 并绑定自定义数据;
- 保存至 this.allPointItems(用于点击检测);
- 调用 multiPointOverlay.setItems(items) 更新视图;
- 启用图层 .setEnable(true)。
第 5 步:实现地图点击交互
监听地图点击事件,在所有点中查找距离最近的一个,并用红色 Marker 高亮显示。
this.aMap.setOnMapClickListener(async (latLng: LatLng) => {
let closestItem: MultiPointItem | null = null;
let minDistSq = 0.1; // 阈值
for (const item of this.allPointItems) {
const dLat = item.getLatLng().latitude - latLng.latitude;
const dLon = item.getLatLng().longitude - latLng.longitude;
const distSq = dLat * dLat + dLon * dLon;
if (distSq < minDistSq) {
minDistSq = distSq;
closestItem = item;
}
}
if (closestItem) {
// 显示/移动红色 Marker
if (!this.marker) {
const redIcon = await BitmapDescriptorFactory.defaultMarkerASync(globalContext, BitmapDescriptorFactory.HUE_RED);
const options = new MarkerOptions();
options.setIcon(redIcon);
this.marker = this.aMap?.addMarker(options);
}
this.marker.setPosition(closestItem.getLatLng());
this.marker.setZIndex(1000); // 置顶显示
}
});
其他:生命周期管理
在页面销毁时释放资源:
aboutToDisappear(): void {
this.isDestroy = true;
MapViewManager.getInstance().unregisterMapViewCreatedCallback(this.mapViewCreateCallback);
if (this.mapView) {
this.mapView.onDestroy();
this.mapView = undefined;
this.aMap = undefined;
}
}