将 DrawingManager 与 @angular/google-maps 一起使用

Using DrawingManager with @angular/google-maps

我一直在尝试将 DrawingManager 与地图 API 的官方 Angular 组件包装器一起使用,但它没有发挥应有的作用。如果有人能让它工作,我将不胜感激为此找到解决方案。这是我尝试过但没有成功的解决方案的代码片段和 stackblitz link。 (在 stackblitz 中它不识别 google 命名空间,但如果你下载它在本地机器上就没问题)

this.drawingManager = new google.maps.drawing.DrawingManager({
      drawingMode: google.maps.drawing.OverlayType.POLYGON,
      drawingControl: true,
      drawingControlOptions: {
        position: google.maps.ControlPosition.TOP_CENTER,
        drawingModes: [google.maps.drawing.OverlayType.POLYGON]
      }
});
this.drawingManager.setMap(this.map._googleMap);

https://stackblitz.com/edit/angular-vvwbdg

Github 问题 link: https://github.com/angular/components/issues/18599

编辑 1: 原来问题是地图没有完全加载并且之前设置 DrawingManager 没有生效。包装器模块中没有加载回调。但是 Angular 的 AfterViewInit 似乎做得很好。

首先你需要添加一个 Google API 键来使用地图 api,描述 here.

对于 angular,建议使用 angular-maps components. Here 你可以找到一个可用的 Stackblitz。

如果您想在没有 agm 的情况下工作,您必须实现自己的服务来加载脚本,就像在 this Stackblitz 中所做的那样。

我遇到过这样的讨论:

https://github.com/angular/components/issues/17828

https://github.com/angular/components/issues/18015

How can I check whether Google Maps is fully loaded?

Maps 组件的主要贡献者表示他不打算添加加载回调或任何与底层地图相关的内容 API 因此我采用了另一种 hacky 方法来了解地图是否加载到组件内部。

component.ts:

mapLoaded = false;
idleMap(event: any)  {
    if(this.mapLoaded)
      return;
    this.mapLoaded = true;
    this.drawingManager = new google.maps.drawing.DrawingManager({
      drawingMode: google.maps.drawing.OverlayType.POLYGON,
      drawingControl: true,
      map:this.map._googleMap,
      drawingControlOptions: {
        position: google.maps.ControlPosition.TOP_CENTER,
        drawingModes: [google.maps.drawing.OverlayType.POLYGON]
      }
    });
    google.maps.event.addListener(this.drawingManager, 'overlaycomplete', (event) => {
      if (event.type === google.maps.drawing.OverlayType.POLYGON) {
        let ar = event.overlay.getPath().getArray();
        ar.push(ar[0]);
        this.model.location.push(ar);
      }
    });
  }

html:

<google-map
    (tilesloaded)="idleMap($event)">
  </google-map>

在组件可用后使用 @ViewChild 创建 DrawingManager setter:

home.component.html:

<div *ngIf="apiLoaded | async">
    <google-map [options]="options"></google-map>
</div>

home.component.ts:

export class HomeComponent implements OnInit {

  @ViewChild(GoogleMap, { static: false }) set map(m: GoogleMap) {
    if (m) {
      this.initDrawingManager(m);
    }
  }

  apiLoaded: Observable<boolean>;
  drawingManager: any;

  options: google.maps.MapOptions = {
    zoom: 18,
    mapTypeId: 'satellite',
    disableDefaultUI: true
  };

  constructor(httpClient: HttpClient) {
    this.apiLoaded = httpClient.jsonp('https://maps.googleapis.com/maps/api/js?key=<API_KEY>&libraries=drawing', 'callback')
      .pipe(
        map(() => true),
        catchError(() => of(false)),
      );
  }

  initDrawingManager(map: GoogleMap) {
    const drawingOptions = {
      drawingMode: google.maps.drawing.OverlayType.POLYGON,
      drawingControl: true,
      drawingControlOptions: {
        position: google.maps.ControlPosition.TOP_CENTER,
        drawingModes: [
          google.maps.drawing.OverlayType.POLYGON,
        ],
      },
      polygonOptions: {
        strokeColor: '#00ff00',
      },
    };
    this.drawingManager = new google.maps.drawing.DrawingManager(drawingOptions);
    this.drawingManager.setMap(map.googleMap);
  }