Angular-google-maps: 将地理编码器与 GoogleMapsAPIWrapper 结合使用

创建于 2016-10-01  ·  42评论  ·  资料来源: SebastianM/angular-google-maps

我在问题 #139 中看到您提供了通过 getMap() 函数访问 google.maps 对象的能力,我假设它现在是 GoogleMapsAPIWrapper 中的 getNativeMap() 函数。 我还读到其他人已经让它工作了,但我找不到任何关于如何使用 GoogleMapsAPIWrapper 和 Geocoder 的文档或示例。

import { Component, OnInit } from '@angular/core';
import { LocationService } from '../../core/location.service';
import { GoogleMapsAPIWrapper } from 'angular2-google-maps/core';

declare var google: any;

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {

  constructor(private wrapper: GoogleMapsAPIWrapper) {
    this.wrapper.getNativeMap().then((m) => {
      console.log("test");
    });

  }

  ngOnInit() {
    // var address = "1045 mission street san francisco";

    // var geocoder = new google.maps.Geocoder();

    // var result = "";

    // geocoder.geocode({ 'address': address }, (results, status) => {
    //   var latitude = results[0].geometry.location.lat();
    //   var longitude = results[0].geometry.location.lng();
    //   console.log("lat: " + latitude + ", long: " + longitude);
    // });
  }
}

现在我什至无法让 console.log 打印出“测试”。 我不确定为什么。 m 变量是否也等同于 google.maps? 这样我就可以使用 m.Geocoder() 了吗?

我也不确定我是否正确导入了 GoogleMapsAPIWrapper。 目前我将它导入 core.module,因为 Angular 2 指南说在 core.module 中有服务。 “sebm-google-map”对我来说没有任何问题,所以我认为 AgmCoreModule 已正确导入,我只是不确定如何使用 GoogleMapsAPIWrapper。

import {
    ModuleWithProviders, NgModule,
    Optional, SkipSelf
} from '@angular/core';

import { AgmCoreModule, GoogleMapsAPIWrapper } from 'angular2-google-maps/core';


import { FirebaseService, FirebaseServiceConfig } from './firebase.service';
import { LocationService } from './location.service';


@NgModule({
    imports: [AgmCoreModule.forRoot({apiKey: "blahblahapikey"}),],
    declarations: [],
    exports: [AgmCoreModule],
    providers: [FirebaseService, LocationService, GoogleMapsAPIWrapper]
})
export class CoreModule {

    constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
        if (parentModule) {
            throw new Error(
                'CoreModule is already loaded. Import it in the AppModule only');
        }
    }

    static forRoot(config: FirebaseServiceConfig): ModuleWithProviders {
        return {
            ngModule: CoreModule,
            providers: [
                { provide: FirebaseServiceConfig, useValue: config }
            ]
        };
    }
}

我已经能够让 google.maps.Geocoder() 通过 PrimeNG 的 GMap 工作,但有时我得到 google is not defined 错误。 所以我试图改用塞巴斯蒂安的谷歌地图。

stale

最有用的评论

这个怎么样 -

import { Injectable, NgZone } from '@angular/core';
import { GoogleMapsAPIWrapper } from 'angular2-google-maps/core';
import { MapsAPILoader } from 'angular2-google-maps/core';
import { Observable, Observer } from 'rxjs';

declare var google: any;

@Injectable()
export class GMapsService extends GoogleMapsAPIWrapper{ 
    constructor(private __loader: MapsAPILoader, private __zone: NgZone) {
        super(__loader, __zone);
    }

    getLatLan(address: string) {
        console.log('Getting Address - ', address);
        let geocoder = new google.maps.Geocoder();
        return Observable.create(observer => {
            geocoder.geocode( { 'address': address}, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    observer.next(results[0].geometry.location);
                    observer.complete();
                } else {
                    console.log('Error - ', results, ' & Status - ', status);
                    observer.next({});
                    observer.complete();
                }
            });
        })
    }
}

所有42条评论

如果只需要 Geocoder(),则不需要使用 getNativeMap()。

我正在导入MapsAPILoader ,所以我可以这样使用它:

this.mapsAPILoader.load().then(() => {
    console.log('google script loaded');
    var geocoder = new google.maps.Geocoder();
});

但是如果你想获得原生地图,你的 TestComponent 必须加载到谷歌地图组件中:

<sebm-google-map [latitude]="lat" [longitude]="lng">
    <app-test></app-test>
</sebm-google-map>

并且您必须确保TestComponent中的 GoogleMapsAPIWrapper 实例与SebmGoogleMap使用的实例相同

@gnujeremie 感谢使用 MapsAPILoader 的提示。 我该如何导入它? 您是否将它与 AgmCoreModule 一起导入?

不,AgmCoreModule 仅使用谷歌地图导入我的模块中。
我直接在我的服务中导入import { MapsAPILoader } from 'angular2-google-maps/core';

这个怎么样 -

import { Injectable, NgZone } from '@angular/core';
import { GoogleMapsAPIWrapper } from 'angular2-google-maps/core';
import { MapsAPILoader } from 'angular2-google-maps/core';
import { Observable, Observer } from 'rxjs';

declare var google: any;

@Injectable()
export class GMapsService extends GoogleMapsAPIWrapper{ 
    constructor(private __loader: MapsAPILoader, private __zone: NgZone) {
        super(__loader, __zone);
    }

    getLatLan(address: string) {
        console.log('Getting Address - ', address);
        let geocoder = new google.maps.Geocoder();
        return Observable.create(observer => {
            geocoder.geocode( { 'address': address}, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    observer.next(results[0].geometry.location);
                    observer.complete();
                } else {
                    console.log('Error - ', results, ' & Status - ', status);
                    observer.next({});
                    observer.complete();
                }
            });
        })
    }
}

除了@vintesh提出的解决方案之外,我还必须更新 NgZone 中的 lat 和 lng 以更新地图。

clickSearchAddress() {
        this._mapsService.getLatLan(this.model.address)
            .subscribe(
            result => {
                // needs to run inside zone to update the map
                this._zone.run(() => {
                    this.model.lat = result.lat();
                    this.model.lng = result.lng();
                });
            },
            error => console.log(error),
            () => console.log('Geocoding completed!')
            );
    }

尝试使用地理编码器时,我仍然遇到问题。 这是我的代码。

import { MapsAPILoader } from 'angular2-google-maps/core';
constructor(public mapsApiLoader: MapsAPILoader) {
    this.mapsApiLoader.load().then(() => {
      console.log('google script loaded');
      this.geocoder = new google.maps.Geocoder();
      console.log(this.geocoder);
    });

我收到两个错误:

Cannot find name 'google'.

rollup failed: 'MapsAPILoader' is not exported by node_modules/angular2-google-maps/core/index.js (imported by src/services/location.ts). For help fixing this error see https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module

@slooker您需要在构造函数的声明之前添加declare var google: any;

@gnujeremie这解决了谷歌未定义的问题,但它仍然告诉我 MapsAPILoader 不是由 angular2-google-maps 导出的。

@slooker我也遇到了同样的问题,并且 MapsAPILoader 错误即将到来,因为“node_modules/angular2-google-maps/core/index.js”不导出 MapsAPILoader。我已经解决了这个问题。 在“node_modules/angular2-google-maps/core/index.js”文件中插入以下代码,如下所示:

var core_module_2 = require('./core.umd'); exports.MapsAPILoader = core_module_2.MapsAPILoader;

这对我有用。 希望这也对你有用。

你们有工作版吗? 我从数据库中获取地址,我需要它们的坐标来构建标记集群。 GeoCoder 在构造函数中定义,但不能通过 nginit 方法访问。

VinTesh,为什么您列出的服务说 google 未定义? 解决这个问题的正确方法是什么? 谢谢

我面临着同样的谷歌未定义问题。 有什么建议?

我正在使用“@agm/core”:“^1.0.0-beta.0”

谢谢

getCurrentPositionSuccessCallBack(position: Position) {
    const latitude = position.coords.latitude;
    const longitude = position.coords.longitude;

    const latLng: LatLngLiteral = {
      lat: latitude,
      lng: longitude
    };

    const geoCoder = new google.maps.Geocoder();

    geoCoder.geocode({ "location": latLng }, (results, status) => {

是我的代码,它工作正常,但我正在尝试编写单元测试

fit('onGeoLocate should set the right location', () => {

    spyOn(navigator.geolocation, 'getCurrentPosition').and.callFake(function () {
      const position = { coords: { latitude: 32, longitude: -96 } };
      arguments[0](position);
    });
    component.onGeoLocate();

但它失败了

 Failed: google is not defined

请帮忙?

你好“谷歌未定义”的朋友。 您是否尝试过我们同事@gnujeremie 的建议?
这对我有用(Angular 2.2.3):

import { Injectable } from '@angular/core';
import { MapsAPILoader } from 'angular2-google-maps/core';
import { Observable } from 'rxjs/Observable';

declare var google: any;

@Injectable()
export class MapsService {
    constructor(private __loader: MapsAPILoader) {

    }

    getGeocoding(address: string) {
        return Observable.create(observer => {
            try {
                //at this point the variable google may be still undefined (google maps scripts still loading)
                //so load all the scripts, then...
                this.__loader.load().then(() => {
                    let geocoder = new google.maps.Geocoder();
                    geocoder.geocode({ address }, (results, status) => {

                        if (status === google.maps.GeocoderStatus.OK) {
                            const place = results[0].geometry.location;
                            observer.next(place);
                            observer.complete();
                        } else {
                            console.error('Error - ', results, ' & Status - ', status);
                            if (status === google.maps.GeocoderStatus.ZERO_RESULTS) {
                                observer.error('Address not found!');
                            }else {
                                observer.error(status);
                            }

                            observer.complete();
                        }
                    });
                });
            } catch (error) {
                observer.error('error getGeocoding' + error);
                observer.complete();
            }

        });
    }
}

Fabio,您能否提供一个如何调用和使用它的示例?

@DoubleExposure假设您有这样的构造函数

构造函数(私有毫秒:MapsService){
}

你可以在你的代码中调用它

this.ms.getGeocoding('10 10th Street NE, Atlanta, GA 30309').subscribe(function (x) {
控制台.log(x.toString());
});

@FabioBentoLuiz @gnujeremie您好,您已经尝试过您的代码,它运行良好。 除了总是失败的第一个电话。 我试图在 ngOnInit 中进行第一次调用,但它似乎不起作用。

这是我的使用尝试

import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { Router, ActivatedRoute, ParamMap} from '@angular/router';

import 'rxjs/add/operator/switchMap';
import { Observable } from 'rxjs/Observable';

import { Place } from './../place';
import { PlaceService } from './../place.service';
import { MapsService } from './map.service';
import { AlertService } from './../AlertComponent/alert.service';


@Component({
  selector: 'app-detailview',
  templateUrl: './detail.component.html',
  styleUrls: ['./detail.component.css'], 
})


export class DetailComponent implements OnInit {

    place: Place;  
    lat: number = 51.678418;
    lng: number = 7.809007;

    ngOnInit() {
        let selectedId = this.route.paramMap.subscribe(
                (params: ParamMap)  =>  this.place = this.placeService.getPlaceById(+params.get('id'))
            );
        this.maps.getGeocoding('')
            .subscribe(
            result => console.log(result),
            error => console.log(error),
            () => console.log('Geocoding completed!')
            );
    }

    constructor(private placeService: PlaceService,
                private route       : ActivatedRoute,
                private location    : Location,
                private alert       : AlertService,
                private maps        : MapsService) {
    }

    clickSearchAddress() {
        let address = this.place.name + " " + this.place.address + " " + this.place.city + " " + this.place.postalCode;
        this.maps.getGeocoding(address)
            .subscribe(
            result => {
                    this.lat = result.lat();
                    this.lng = result.lng();
            },
            error => console.log(error),
            () => console.log('Geocoding completed!')
            );
    }

    back(){
        this.location.back();
    }

@Canadadry
第一次通话如何失败? 您在使用 MapsAPILoader 吗?

我的地图应该以地址为中心。
所以我在一个按钮上映射了clickSearchAddress() ,它只在第二次点击时移动地图。 在第一次单击时,我只有日志:地理编码完成!
奇怪的是,我在 ngOnInit 中将clickSearchAddress()调用放在了route.paramMap的订阅上,并且该函数在第一次调用时起作用。

我尝试在开始单击之前等待以确保已加载谷歌地图脚本,但它仍然需要两个 clics。

使用的 MapsService 是您提供的。

如此处所述使用NgZone进行尝试

import { NgZone } from '@angular/core';

添加到您的构造函数

constructor(private _zone: NgZone){
}

然后像这样设置 lat 和 lng:

this.maps.getGeocoding(address)
            .subscribe(
            result => {
                    this._zone.run(() => {
                    this.lat = result.lat();
                    this.lng = result.lng();
            });

            },
            error => console.log(error),
            () => console.log('Geocoding completed!')
            );

这是另一个解释其原因的线程

让我知道它是否有效。

它似乎有效,但我不明白为什么。
谢谢

我将它与 agm 结合使用@vintesh@FabioBentoLuiz和 @neilpennell 的答案。

谷歌地图.service.ts:

import { Injectable, NgZone } from '@angular/core';
import { GoogleMapsAPIWrapper } from '@agm/core';
import { MapsAPILoader } from '@agm/core';
import { Observable, Observer } from 'rxjs';

declare var google: any;

@Injectable()
export class GMapsService extends GoogleMapsAPIWrapper{ 
    constructor(private __loader: MapsAPILoader, private __zone: NgZone) {
        super(__loader, __zone);
    }

    getLatLan(address: string) {
        console.log('Getting Address - ', address);
        let geocoder = new google.maps.Geocoder();
        return Observable.create(observer => {
            geocoder.geocode( { 'address': address}, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    observer.next(results[0].geometry.location);
                    observer.complete();                    
                } else {
                    console.log('Error - ', results, ' & Status - ', status);
                    observer.next({});
                    observer.complete();
                }
            });
        })
    }
}

商店.component.ts:

import { Component, NgZone } from '@angular/core';
import { GMapsService } from '../services/google-maps.service'

@Component({  
  templateUrl: 'shops.component.html',
  styleUrls: ['shops.component.css']
})

export class ShopsComponent {  
  constructor(private gMapsService: GMapsService, private __zone: NgZone ){}
  lat:number
  lng:number

  getAddress() {
    this.gMapsService.getLatLan('Andorra')
      .subscribe(
        result => {
            this.__zone.run(() => {
                this.lat = result.lat();
                this.lng = result.lng();
            })
        },
        error => console.log(error),
        () => console.log('Geocoding completed!')
      );
  }
}

商店.component.html:

<agm-map [latitude]="lat" [longitude]="lng"></agm-map>

商店.component.css:

agm-map {
    height: 300px;
}

多谢你们!

@taneljoeaar你知道为什么我没有定义谷歌吗
在 MappingService.getLatLan

我主要是复制并粘贴您的代码。

非常感谢。

@beachjf改用@FabioBentoLuiz解决方案来获取经纬度,因为变量“google”可能仍未定义,因为谷歌地图脚本仍在加载。 这个对我有用。

尝试
从“@agm/core”导入 { GoogleMapsAPIWrapper };
代替
从 'angular2-google-maps/core' 导入 { GoogleMapsAPIWrapper };
对于最新的角度

@taneljoeaar或在您遇到错误的任何文件中尝试import { } from 'googlemaps';
确保已安装 googlemaps 的类型。 ( npm install --save @types/googlemaps )

好吧,我知道这是一个老问题,但我想对这个主题发表评论,代码是关于获取具有城市、州和国家名称和类型的位置对象的代码。 但是,就我而言,我需要从用户的坐标中获取这些名称。 所以,为了做到这一点,我根据最后的评论写了这个:

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

...

constructor(private mapsAPILoader: MapsAPILoader) {
    // Get this 'res' from some source, like ionic native geolocation
    // Or, for test, create some object like:
    let res = {
        coords: {
            latitude: 40.826514,
            longitude: -73.914628
        }
    }
    this.codeLatLng(res.coords);
  }

...

codeLatLng(coords) {
    this.mapsAPILoader.load().then(() => {
        console.log('google script loaded');
        let latlng = new google.maps.LatLng({lat: coords.latitude, lng: coords.longitude});
        let geocoder = new google.maps.Geocoder();
        let location = {
          country: null,
          state: null,
          city: null
        };
        geocoder.geocode({
          'latLng': latlng
        }, (results, status) => {
          if (status == google.maps.GeocoderStatus.OK) {
            if (results[1]) {
              for (let i = 0; i < results[0].address_components.length; i++) {
                for (let b = 0; b < results[0].address_components[i].types.length; b++) {
                  if (results[0].address_components[i].types[b] == "country") {
                    location.country = !location.country ? results[0].address_components[i] : location.country;
                  } else if (results[0].address_components[i].types[b] == "administrative_area_level_1") {
                    location.state = !location.state ? results[0].address_components[i] : location.state;
                  } else if (results[0].address_components[i].types[b] == "administrative_area_level_2") {
                    location.city = !location.city ? results[0].address_components[i] : location.city;
                  }
                  if (location.city && location.state && location.country) {
                    break;
                  }
                }
              }

              console.log(location);
            } else {
              console.log("Results not available");
            }
          }
          else {
            console.log("Geocoder failed due to: ", status);
          }
        });
      }
    );
  }

为了获得坐标值,我使用了离子原生地理定位。
代码来自 Angular 2+ & Ionic 项目。

我已经实现了您展示的代码,但出现以下错误:

ERROR 错误:StaticInjectorError [MapsAPILoader]:
StaticInjectorError [MapsAPILoader]:
NullInjectorError:没有 MapsAPILoader 的提供者!
在 _NullInjector.get (core.js: 923)
在 resolveToken (core.js: 1211)
在 tryResolveToken (core.js: 1153)
在 StaticInjector.get (core.js: 1024)
在 resolveToken (core.js: 1211)
在 tryResolveToken (core.js: 1153)
在 StaticInjector.get (core.js: 1024)
在 resolveNgModuleDep (core.js: 10586)
在 _createClass (core.js: 10625)
在 _createProviderInstance $ 1 (core.js: 10597)

注意:我正在使用 Angular 5

你能帮我一把吗?
谢谢你。

@ronaldrenteria你放了吗

AgmCoreModule.forRoot({
      apiKey: '<YOUR-GOOGLE-API-KEY>'
    })

在 app.modules.ts 中的“导入”?
你在使用延迟加载吗?
当您忘记执行某些导入或执行 lib 工作所需的所有要求时,有时会发生该错误。
您可以在该页面上获得更多信息: Angular Maps - Getting Started

好吧,我想告诉你,我已经展示了地图和标记,但是我想做的是将一些方向转换为纬度和经度,但这是不可能的。

我在 app.modules.ts 中没有导入,因为每个组件都使用自己的模块,如果我使用的是 LazyLoading。

在这种情况下,我有一个名为 home.component.ts 的组件,而这又具有自己的名为 home.module.ts 的模块

在使用 MapsAPILoader 之前,它已经显示了地图和标记(例如通过手动放置经度和纬度),但现在我想从数据库中读取地址并获取经度纬度。

谢谢你。

地图服务.ts

import { Injectable, NgZone } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

// Manejo de Mapas
import { GoogleMapsAPIWrapper, MapsAPILoader } from '@agm/core';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';

declare var google: any;

@Injectable()
export class MapsService extends GoogleMapsAPIWrapper {
  constructor(private __loader: MapsAPILoader, private __zone: NgZone) {
    super(__loader, __zone);
  }

  getLatLan(address: string) {
    console.log('Getting Address - ', address);
    let geocoder = new google.maps.Geocoder();
    return Observable.create(observer => {
      geocoder.geocode({ address: address }, function(results, status) {
        if (status === google.maps.GeocoderStatus.OK) {
          observer.next(results[0].geometry.location);
          observer.complete();
        } else {
          console.log('Error - ', results, ' & Status - ', status);
          observer.next({});
          observer.complete();
        }
      });
    });
  }
}

home.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { homeRouting } from './home.routing';
import { SmartadminModule} from '../shared/smartadmin.module';
import { HomeComponent} from './home.component';
// 614iT
import { config_church } from './../shared/churchpro.config';
// Indispensable para manejar los mapas.
import { AgmCoreModule, MapsAPILoader } from '@agm/core';
@NgModule({
  imports: [
    CommonModule,
    homeRouting,
    SmartadminModule,
    AgmCoreModule.forRoot({
      apiKey: config_church.GOOGLE_API_KEY
    })
  ],
  declarations: [HomeComponent]
})
export class HomeModule {}

home.component.ts

import { Component, OnInit, NgZone } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
// Mapas 
import { MapsService } from '../shared/services/maps.service';
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: []
})
export class HomeComponent implements OnInit {
  title: string = 'My first AGM project';
  lat: number = 4.6517056;
  lng: number = -74.1028404;
  zoom: number = 13;
  Glat: number;
  Glng: number;

  constructor(private _mapsService: MapsService, private __zone: NgZone) {}

  ngOnInit() {}

  getAddress() {
    this._mapsService.getLatLan('Andorra').subscribe(result => {
        this.__zone.run(() => {
          this.Glat = result.lat();
          this.Glng = result.lng();
        });
      }, error => console.log(error), () => console.log('Geocoding completed!'));
  }
}

大家好你们好

也许有人面临类似的问题。

我需要自定义 AGM 库,我下载了代码并将此代码包含在我的项目中,因此我从本地 src 文件夹中添加了 agmCoreModule 到 app.module 中,就像这样。

import { AgmCoreModule } from '../agmLocalModule/core.module';

AgmCoreModule.forRoot({
apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}),

我有一个带有在 ngFor 循环中生成的标记的页面。 但我遇到了下一个错误。

```

[纬度]="ubicacion.posicion.latitud"
[经度]="ubicacion.posicion.longitud"
[markerClickable]="真"
>

```

错误错误:未捕获(承诺):ReferenceError:未定义谷歌
ReferenceError:谷歌未定义
在 MarkerManager.webpackJsonp.102.MarkerManager.addMarker (marker-manager.ts:82)
在 AgmMarker.webpackJsonp.291.AgmMarker.ngOnChanges (marker.ts:169)

知道可能是什么问题

对于所有收到“谷歌未定义”错误的人:

使用 agm-map 元素的此事件“mapReady”。
https://angular-maps.com/api-docs/agm-core/components/AgmMap.html#mapReady

有人能想出一个可行的例子吗?

地理编码服务的工作示例https://stackblitz.com/edit/angular-google-maps-demo-geocoding基于此处列出的示例。

我可以多次调用 mapsAPILoader.load() 吗?

嗨,每个人我都有一个小问题,我对 AGM 和 angular 也是新手,但问题是我得到了 place_id,我想把它改成 latlng 对象,就是这样,任何帮助都可以得到

此问题已自动标记为过时,因为它最近没有活动。 如果没有进一步的活动,它将被关闭。 感谢你的贡献。

@supruniuk天哪

有什么方法可以输入 Observable 结果?

@xanscale为什么不,只需实现接口并将其用于类型检查
出口接口位置{
纬度:数字;
液化天然气:数字;
}

@supruniuk我的意思是输入谷歌对象,如结果和状态

此页面是否有帮助?
0 / 5 - 0 等级