Angular12使用@angular/google-maps标记聚合性能远逊于supercluster咨询
问题根因分析
- 性能问题既不是代码逻辑错误,也不是Google Maps API本身的缺陷,核心原因是
@angular/google-maps自带的<map-marker-clusterer>组件实现逻辑存在严重的性能缺陷:- 该组件会先初始化所有传入的
<map-marker>子组件,再对已经创建的标记实例做聚合计算。你传入15000个标记时,会先触发15000个Angular组件的初始化、变更检测、DOM创建流程,叠加起来的开销直接导致页面卡死。 - 你用React+supercluster的方案是先做聚合计算、再按需渲染需要展示的节点,全程不需要创建全量的标记实例,自然性能差距极大。
- 该组件会先初始化所有传入的
- 你当前的写法也放大了性能问题:
*ngFor直接遍历全量markerList,相当于不管当前缩放层级和视口范围,先把15000个DOM节点全部创建完再聚合隐藏,额外增加了大量无效开销。
完全可以在Angular中使用supercluster,实现步骤如下
- 安装依赖:
npm install supercluster @types/supercluster
- 初始化supercluster实例,加载全量标记数据:你只需要把你的标记经纬度数据传入supercluster,不需要提前创建任何地图标记组件。
- 监听地图的
boundsChanged、zoomChanged事件,每次事件触发时调用supercluster的getClusters方法,拿到当前视口、当前缩放层级下需要展示的聚合点+散点列表,这个列表的数量通常只有几十到上百个。 - 用
*ngFor只遍历这个按需生成的小列表,渲染对应的聚合标记或者散点标记即可。
额外优化建议
- 给
*ngFor加上trackBy函数,返回每个标记的唯一ID,避免不必要的组件销毁重建。 - 把地图相关的组件变更检测策略改为
OnPush,减少不必要的变更检测触发。 - 彻底弃用自带的
<map-marker-clusterer>组件,自己基于supercluster实现聚合逻辑,完全避开全量渲染标记的问题,实测10万级标记也可以做到流畅交互。
内容的提问来源于stack exchange,提问作者Francesco Clementi
相关产品推荐
相关产品推荐

