@angular/google-maps新增标记时实现聚合簇与标记一致的动画效果
Angular谷歌地图标记聚合簇动画实现方案
基础信息
- 依赖版本:
@angular/google-maps: 13.3.4 - 需求:新增地图标记时,标记聚合簇与普通独立标记保持一致的
DROP下落动画效果
原有问题代码
组件模板(app.component.html)
<google-map height="400px" width="750px" [center]="center" [zoom]="zoom" > <map-marker-clusterer [zoomOnClick]="true" [imagePath]="markerClustererImagePath"> <map-marker *ngFor="let markerPosition of markerPositions" [options]="markerOptions" [position]="markerPosition" ></map-marker> </map-marker-clusterer> </google-map> <button (click)="addSingleMarker($event)">Add new Marker</button> <button (click)="addMarkerToCluster($event)">Add new Cluster</button>
组件逻辑(app.component.ts)
@Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { center = { lat: 24, lng: 12 }; zoom = 4; markerPositions = [ { lat: 24, lng: 12 }, { lat: 24, lng: 12 }, { lat: 15, lng: 6 }, ]; markerOptions: google.maps.MarkerOptions = { animation: google.maps.Animation.DROP }; markerClustererImagePath = 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'; public addMarkerToCluster($event: google.maps.MapMouseEvent) { if ($event.latLng !== null) { this.markerPositions.push({ lat: 24, lng: 12 }); } } public addSingleMarker($event: google.maps.MapMouseEvent) { if ($event.latLng !== null) { this.markerPositions.push({ lat: 21, lng: 2 }); } } }
实现步骤
默认的map-marker-clusterer没有内置簇图标更新时的动画逻辑,当前给普通map-marker配置的DROP动画只会作用于独立标记,不会作用于聚合生成的簇图标,按以下步骤修改即可:
- 获取聚合簇实例
给模板中的聚合簇组件添加模板引用变量,通过ViewChild在组件类中拿到实例:
模板部分修改聚合簇标签:
组件类新增依赖引入和实例声明:<map-marker-clusterer #clusterer [zoomOnClick]="true" [imagePath]="markerClustererImagePath">import { ViewChild } from '@angular/core'; import { MapMarkerClusterer } from '@angular/google-maps'; export class AppComponent { // 其他原有属性保留 @ViewChild('clusterer') clusterer!: MapMarkerClusterer; } - 绑定簇渲染事件,手动添加动画
在ngAfterViewInit生命周期中监听聚合完成事件,每次簇重绘时给新生成的簇标记设置DROP动画,增加判断避免重复触发已有簇的动画:import { AfterViewInit } from '@angular/core'; export class AppComponent implements AfterViewInit { // 其他原有属性保留 ngAfterViewInit(): void { this.clusterer.clustererInstance.addListener('clusteringend', () => { this.clusterer.clusters.forEach(cluster => { // 访问簇内部的标记实例,TS类型报错可加@ts-ignore忽略,不影响运行 // @ts-ignore const clusterMarker = cluster.clusterIcon_.marker_; if (!clusterMarker.getAnimation()) { clusterMarker.setAnimation(google.maps.Animation.DROP); } }) }) } } - 修复新增标记的逻辑bug
原有代码中绑定到普通button点击事件的方法,入参是按钮点击事件而非地图鼠标事件,不存在latLng属性,会导致点击按钮无法新增标记。同时直接push数组在OnPush变更检测模式下不会触发视图更新,替换为返回新数组的写法:public addMarkerToCluster() { // 可替换为实际业务需要的聚合点坐标 this.markerPositions = [...this.markerPositions, { lat: 24, lng: 12 }]; } public addSingleMarker() { // 可替换为实际业务需要的独立标记坐标 this.markerPositions = [...this.markerPositions, { lat: 21, lng: 2 }]; }
补充:如果需要调整动画时长,可以在设置动画后加延时手动清除动画状态,避免动画效果残留。
内容的提问来源于stack exchange,提问作者Veronika89
相关产品推荐
相关产品推荐

