angular2 google map infowindow opens so many times and it starts lagging

1.3k views Asked by At

I'm using angular-google-map. In the project, I create hundreds of markers and all of them share one info window. Below is the code in the template:

<div *ngFor="let property of _properties">
  <agm-marker [latitude]="property.Lat"
              [longitude]="property.Lng"
              [iconUrl]="_markerIconUrl"
              (mouseOver)="infoWindow.open();"
              (mouseOut)="infoWindow.close();">
  </agm-marker>
</div>
...
<agm-info-window #infoWindow>
</agm-info-window>

At the begining it works well. But as I mouseover many markers, it starts slow down. Here is the screenshot of performance and memory:

performance

memory

It seems like garbage collection slows down the page and I really don't know how to fix it..

I tried these:

  1. I thought it might be mouseover/mouseout emitter slows it down. But if I replace infoWindow.open() to other function, it works fine.
  2. Then I checked the angular-google-map source code, and found the infoWindow.open():
  open(infoWindow: AgmInfoWindow): Promise<void> {
    return this._infoWindows.get(infoWindow).then((w) => {
      if (infoWindow.hostMarker != null) {
        return this._markerManager.getNativeMarker(infoWindow.hostMarker).then((marker) => {
          return this._mapsWrapper.getNativeMap().then((map) => w.open(map, marker));
        });
      }
      return this._mapsWrapper.getNativeMap().then((map) => w.open(map));
    });
  }

I thought it might be the Promise slows it down, but when I comment out w.open(map) and w.open(map, marker) it works fine.

So I think the problem might be because it called w.open(map) so many times? I found that open function is from Google Map API infoWindow. I tried clear the conent and set infoWindow conent='' and close it everytime, but still can't fix it.

1

There are 1 answers

0
Frank On BEST ANSWER

I finally fixed it. The issue caused by too many change detections. And I found the solution here: https://github.com/angular/angular/issues/10883#issuecomment-240423378
What I did is called the infowindow.open() outside of Angular to avoid change detections:

map.component.html

<div *ngFor="let property of _properties">
  <agm-marker [latitude]="property.Lat"
              [longitude]="property.Lng"
              [iconUrl]="_markerIconUrl"
              (mouseOver)="_infoWindowOpen($event, infoWindow);"
              (mouseOut)="_infoWindowClose($event, infoWindow);">
  </agm-marker>
</div>
...
<agm-info-window #infoWindow>
</agm-info-window>

map.component.ts

import { Component, OnInit, NgZone } from '@angular/core';
...
constructor(private _zone: NgZone) {...}
...
  private _infoWindowOpen(mouseEvent: any, infoWindow: any) {
    infoWindow.hostMarker = mouseEvent.marker;
    this._zone.runOutsideAngular(() => {
      infoWindow.open();
    });
  }
...
  private _infoWindowClose(mouseEvent: any, infoWindow: any) {
    this._zone.runOutsideAngular(() => {
      infoWindow.close();
    });
  }