How to set map to center on a marker? - Angular Google Maps
Asked Answered
C

3

5

I cannot center my Google map on a marker after I geocode.

I have two markers: The initial marker (the one that is centered on, does not change), the other one changes based on the geocoding, and after geocoding, it will be centered on every time.

My code: TS

zoom = 10;

addressData: FormGroup;
submitted = false;
success = false;

lat: number;
lng: number;

userLat: number;
userLng: number;

currentCenter = { lat: null, lng: null };

private geoCoder: google.maps.Geocoder;

@ViewChild('googleMap') googleMap: AgmMap;

constructor(private maps: MapsAPILoader, private bulider: FormBuilder) { }

ngOnInit() {
    this.addressData = this.bulider.group({
        address: ["", Validators.required],
    });

    this.maps.load().then(() => {
        this.geoCoder = new google.maps.Geocoder();
    });
}

getAddress() {

    this.submitted = true;

    if (this.addressData.invalid) {
        return;
    }

    this.success = true;

    this.googleMap.mapReady.subscribe(map => {

        // Need to use two parameters in order to use Geocoder
        this.geoCoder.geocode(this.addressData.controls['address'].value, (results, status) => {
        if (status === google.maps.GeocoderStatus.OK) {
            this.userLat = results[0].geometry.location.lat();
            this.userLng = results[0].geometry.location.lng();
        } else {
            alert('Geocode was not successful for the following reason: ' + status);
        }

    }).then(place => {
        this.currentCenter = { lat: place.geometry.location.lat(), lng: place.geometry.location.lng() };
    }).catch(err => {
        console.log("Error: " + err);
    });

    this.submitted = false;
}

HTML

<!-- Google maps, the starting latitude & longitude -->
<agm-map [latitude]="currentCenter.lat" [longitude]="currentCenter.lng" [zoom]="zoom" [mapTypeControl]='true'
#googleMap>
    <!-- Static marker -->
    <agm-marker [latitude]="defaultCenter.lat" [longitude]="defaultCenter.lng"></agm-marker>

    <!-- User geolocation marker, changes -->
    <agm-marker [latitude]="currentCenter.userLat" [longitude]="currentCenter.userLng"></agm-marker>
</agm-map>

Expected:

After Geocoding, the map should center on the marker from the given address every time.

Actual:

The Geocoder finds the address but does not center the map on the placed marker based on the address.

Update

I cannot use Vadim's code because the compiler tells me that I need two arguments for the Geocode, but Vadim's code only has one. I cannot use this code. Also, if I add the second argument, it will then say that then does not exist.

this.googleMap.mapReady.subscribe(map => {
    // This line needs two parameters not one      

    this.geoCoder.geocode(this.addressData.controls['address'].value)
    .then(place => {
        this.currentCenter = { lat: place.geometry.location.lat(), lng: place.geometry.location.lng() };
    }).catch(err => {
        console.log("Error: " + err);
    });
});
Cauley answered 4/7, 2019 at 15:36 Comment(0)
H
6

There is no need to resort to Google Maps API or invoke Map component triggerResize method, to update map center the following approach could be considered:

a) set map center to default value once the map is loaded

<agm-map
  [latitude]="currentCenter.lat"
  [longitude]="currentCenter.lng"
  [zoom]="zoom"
  [mapTypeControl]="true"
>
  <!-- Static marker -->
  <agm-marker
    [latitude]="defaultCenter.lat"
    [longitude]="defaultCenter.lng"
  ></agm-marker>

  <!-- User geolocation marker, changes -->
  <agm-marker
    [latitude]="currentCenter.lat"
    [longitude]="currentCenter.lng"
  ></agm-marker>
</agm-map>

For that matter two properties are introduced:

  • currentCenter - current map center
  • defaultCenter - default (original) map center

b) once the address is resolved, update map center like this:

ngOnInit() {
    this.agmMap.mapReady.subscribe(map => {
      this.geocode("New York, USA").then(place => {
        this.currentCenter = { lat: place.geometry.location.lat(), lng: place.geometry.location.lng()};
      })
      .catch(err => {
        console.log(err);
      });
    });
 }

Example

declare var google: any;

import { Component, ViewChild, OnInit} from "@angular/core";
import { AgmMap } from "@agm/core";

@Component({
  selector: "app-map",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
  constructor() {}

  defaultCenter = {lat: 55.5815245, lng: 36.8251383};
  currentCenter = Object.assign({}, this.defaultCenter);
  zoom = 3;

  @ViewChild(AgmMap) agmMap;

  ngOnInit() {
    this.agmMap.mapReady.subscribe(map => {
      this.geocode("New York, USA").then(place => {
        this.currentCenter = { lat: place.geometry.location.lat(), lng: place.geometry.location.lng()};
      })
      .catch(err => {
        console.log(err);
      });
    });
  }

  geocode(address: string): Promise<any> {
    const geocoder = new google.maps.Geocoder();
    return new Promise((resolve, reject) => {
      geocoder.geocode(
        {
          address: address
        },
        (results, status) => {
          if (status === google.maps.GeocoderStatus.OK) {
            resolve(results[0]);
          } else {
            reject(new Error(status));
          }
        }
      );
    });
  }
}

Update

Getting address from input element:

<input [(ngModel)]="addressText">
<button (click)="findPlace()">Find a place</button>


findPlace() {
    this.geocode(this.addressText).then(place => {
      this.currentCenter = { lat: place.geometry.location.lat(), lng: place.geometry.location.lng()};
    })
    .catch(err => {
      console.log(err);
    });
}
Hydrant answered 10/7, 2019 at 13:13 Comment(4)
Since my address is a variable, unlike yours, is it possible to pass a variable to the this.geocode(var in here) method? And not like this: this.geocode("New York, USA").Cauley
@Compilerv2, the way how address is getting passed into geocode function is not really relevant here.. what matters is updating Map component center data-bound property and let Angular do the restHydrant
Apparently, Property 'then' does not exist on type 'void'., I cannot use the then() method because it does not exist for the geocode(). Also, I had to use (look in my updated question) 2 parameters in order to use the geocoder. I cannot use one like you've shown.Cauley
Can you please start a StackBlitz?Cauley
R
1

Parsing to the number will fix the issue when assigning the new values which coming from back-end

setLatLongValue(lat,long) {
    this.lat = Number(lat);
    this.lng = Number(long);    
  }

Please follow the link to get complete example Angular – Recenter Angular Google Maps ( AGM )

Ronn answered 20/8, 2020 at 10:29 Comment(0)
D
0

According to the docs, the triggerResize() method

gets called with the current lat/lng values or fitBounds value to recenter the map

https://angular-maps.com/api-docs/agm-core/components/agmmap#triggerResize

However you do not update the longitude/latitude of the map, since you bound the property to initLat and initLng. <agm-map [latitude]="initLat" [longitude]="initLng" [zoom]="zoom">

You need to update the map coordinates in order to recenter on triggerResize(). Be careful that you bind your template to the right attribute in your class. In the ts snippet that you showed userLat and userLng are not present so your geolocated marker will also be problematic.

Updated template:

<agm-map [latitude]="lat" [longitude]="lng" [zoom]="zoom" [mapTypeControl]='true'>
<!-- Static marker -->
<agm-marker [latitude]="initLat" [longitude]="initLng"></agm-marker>

<!-- User geolocation marker, changes -->
<agm-marker [latitude]="lat" [longitude]="lng"></agm-marker>
</agm-map>

You might need to initialise lat and lng to some value in your ts file.

Dressing answered 7/7, 2019 at 19:49 Comment(2)
I have two markers, one of which (The initial one) I do not change. The lat & lng are the ones that change based on the geocoding. So your answer is not helpful.Cauley
The markers are irrelevant for the map. If you want to use the triggerResize() method you must update it's coordinates. If you don't, nothing will happen. You can still bind your first marker to other coordinates like init if you want, those are separates.Viscose

© 2022 - 2024 — McMap. All rights reserved.