Поиск на карте Google Maps в Angular

В данной статье я покажу вам как можно создать поиск на карте Google Maps в фреймворке Angular, с подсказками (автозаполнения).

Официальная документация полезная но в фреймворке Angular существует модуль Angular Google Maps (agm) который ещё больше облегчает работу с API карт.

Начало работы

Первое что нам нужно сделать это установить 2 пакета, используя Node Package Manager (npm):

npm install @agm/core --save
npm install @types/googlemaps --save-dev

Дальше, должны поменять декоратор @NgModule:

import { AgmCoreModule } from '@agm/core';

@NgModule({
  imports: [
    AgmCoreModule.forRoot({
      apiKey: "вставьте тут ваш API_KEY от Google приложения",
      libraries: ["places"]
    }),
    BrowserModule,
    FormsModule,
    ReactiveFormsModule
  ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule() {}

Что делает выше описанный код?

  1. Подключаем AgmCoreModule из пакета @agm/core module.
  2. В свойстве imports используем метод AgmCoreModule.forRoot() чтобы указать рабочую зону модуля.
  3. Так-же заметите что мы используем модуль ReactiveFormsModule для работы с формами в Angular.

Создаём шаблон

Для примера добавлю стили и html код в @Component, но для реального проекта рекомендую выделить в отдельный файл стили и html.

@Component({
  selector: 'my-app',
  styles: [`
    agm-map {
      height: 300px;
    }
  `],
  template: `
    <div class="container">
      <h1>Поиск с автозаполнением в Google Maps через Angular</h1>
      <div class="form-group">
        <input placeholder="search for location" autocorrect="off" autocapitalize="off" spellcheck="off" type="text" class="form-control" #search [formControl]="searchControl">
      </div>
      <agm-map [latitude]="latitude" [longitude]="longitude" [scrollwheel]="false" [zoom]="zoom">
        <agm-marker [latitude]="latitude" [longitude]="longitude"></agm-marker>
      </agm-map>
    </div>
  `
})
export class App implements OnInit {}

Объяснения:

  • Не забудьте задать высоту для карты. В данном случае я задал 300px.
  • Для данного примера я использовал Bootstrap CSS стили, чтобы шаблон выглядел адекватно.
  • Переменную связанную с input назвал search. Она объявлена в шаблоне при помощи символа решетка (#).
  • Мой input имеет одностороннюю привязку данных с FormControl к общедоступной (в контроллере) переменной searchControl.
  • Дальше я использую компонент agm-map передавая ему широту, долготу и zoom свойствами из моего контроллера, scrollwheel значением false.
  • Добавил маркер на карту agm-marker передавая ему позицию на карте.

Реализуем Controller

Дальше мы должны создать controller. Он выглядит примерно так:

import { ElementRef, NgZone, OnInit, ViewChild } from '@angular/core';
import { FormControl } from '@angular/forms';
import { } from 'googlemaps';
import { MapsAPILoader } from '@agm/core';

export class App implements OnInit {

  public latitude: number;
  public longitude: number;
  public searchControl: FormControl;
  public zoom: number;

  @ViewChild("search")
  public searchElementRef: ElementRef;

  constructor(
    private mapsAPILoader: MapsAPILoader,
    private ngZone: NgZone
  ) {}

  ngOnInit() {
    // установим широту и долготу и zoom по умолчанию
    this.zoom = 4;
    this.latitude = 47.017950;
    this.longitude = 28.812735;

    // создаём новый search FormControl
    this.searchControl = new FormControl();

    // устанавливаем на карту текущее местоположение посетителя
    this.setCurrentPosition();

    // загружаем места для автодополнения
    this.mapsAPILoader.load().then(() => {
      const autocomplete = new google.maps.places.Autocomplete(this.searchElementRef.nativeElement, {
        types: ["address"]
      });
      autocomplete.addListener("place_changed", () => {
        this.ngZone.run(() => {
          // получаем результаты с местом
          const place: google.maps.places.PlaceResult = autocomplete.getPlace();

          // проверяем результат
          if (place.geometry === undefined || place.geometry === null) {
            return;
          }

          // установим широту, долготу и zoom
          this.latitude = place.geometry.location.lat();
          this.longitude = place.geometry.location.lng();
          this.zoom = 12;
        });
      });
    });
  }

  private setCurrentPosition() {
    if ("geolocation" in navigator) {
      navigator.geolocation.getCurrentPosition((position) => {
        this.latitude = position.coords.latitude;
        this.longitude = position.coords.longitude;
        this.zoom = 12;
      });
    }
  }
}

Рекомендую

Если хотите изучить быстро Angular и чтоб объяснили простым языком сложные вещи, то рекомендую платный курс по Angular от WebForMySelf. А если ещё не знакомы с данным издательством, можете пройти бесплатный курс по Angular.

Demo

Оригинал на английском можно почитать тут.

Valeriu :