angular - 尝试在页面上呈现 Google map 时出错

标签 angular typescript google-maps-api-3

问题

我正在尝试使用 Angular 2 和 TypeScript 中的 API 创建 Google map 的自定义实现。我已经完成了应该在页面上呈现 map 的部分。

不幸的是, map 呈现为一个空白的灰色方 block ,并且尝试与其交互会导致一个非常不起眼的 Cannot read property 'x' of undefined 错误。

我在网站上阅读了其他几个问题,这通常是由于 map 试图呈现到隐藏的 DOM 元素中,加载到不存在的 DOM 元素中(不在页面加载函数中),或者它失去了对其呈现的 DOM 元素的引用。

从我在这里看到的情况来看,我已经满足了所有这些条件,除非我遗漏了一些关于 Angular 在这里工作的方式?

有人可以在这里指出正确的方向吗?

代码

declare let google: any;

/**
 * @Component: Map
 * @Section: Miscellaneous
 * @Description: Generates an interactive map
 */
@Component({
    selector: 'mymap',
    template: `<div #map style="min-width:600px; min-height: 600px;"></div>`
})
export class MyMapComponent {

    // A reference to the map DOM element
    @ViewChild("map") mapEl: ElementRef;

    // A reference to the map object
    map: any;

    // Intializes the map
    initMap: Function = function(){

        // Set the map to a new google map
        this.map = new google.maps.Map(this.mapEl.nativeElement, {

            // Default zoom level
            zoom: this.zoomLevel | 6
        })

        console.log(this.map);
    };

    // Sets the center of the map
    setMapCenter: Function = function( latlng: any ){
        if ( this.map && latlng ){
            this.map.setCenter();
        }
    }

    // Callback for the call to the browser to request the users estimated lat/lng
    getUserLocationCallback: any = function( position: any ){

        // Catches a Geoposition object:
        // coords
        //  - accuracy
        //  - altitude
        //  - altitudeAccuracy
        //  - heading
        //  - latitude
        //  - longitude
        //  - speed
        // timestamp
        this.setMapCenter(new google.maps.LatLng({lat: position.coords.latitude, lng: position.coords.latitude}));
    }

    // On Init
    ngAfterViewInit(){

        // Set the key for the Google Maps API
        var gmap_api_key = "[KEY_REMOVED]";

        // Create the script tag and add it to the document
        var gmap = document.createElement('script');
        gmap.type = 'text/javascript';
        gmap.async = true;
        gmap.src = "https://maps.googleapis.com/maps/api/js?key=" + gmap_api_key;
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(gmap, s);

        // Wait for the script to load
        var mapsInterval = setInterval( () => {

            // If the script is loaded and the maps functions are available
            if ( typeof google !== "undefined" && google.maps && google.maps.Map){

                // Clear our interval
                clearInterval(mapsInterval);

                // Initialize the map
                this.initMap();

                // Request location from the browser. Arrow function used to maintain scope.
                navigator.geolocation.getCurrentPosition( () => { this.getUserLocationCallback } );
            }
        }, 0);
    }

    /**
     * @Property: displayedMarkers
     * @Description: A list of markers current displayed on the map.
     * @Type: array
     * @Two-way: output only
     */
    @Output() displayedMarkersChange: EventEmitter<any[]> = new EventEmitter;

    /**
     * @Property: mapCenter
     * @Description: lat/long of the center of the map being displayed
     * @Type: object {lat: "N", lng: "N"}
     * @Two-way: true
     */
    @Input()
    set mapCenter( position: any ){

        // If a position was provided
        if ( typeof position !== "undefined" ){

            // Set thet map center using the provided position
            this.setMapCenter( new google.maps.LatLng (position ) );
        }
    }
    @Output() mapCenterChange: EventEmitter<any[]> = new EventEmitter;

    /**
     * @Property: zoomLevel
     * @Description: Current zoom level of the map. Accepts values between 0 (shows the entire earth) and up 21
     * @Type: array
     * @Two-way: true
     */
    @Input() zoomLevel: number;
    @Output() zoomLevelChange: EventEmitter<number> = new EventEmitter;

    /**
     * @Property: filters
     * @Description: Filters to be applied to the marker results.
     * @Type: array
     * @Two-way: false
     */
    @Input() filters: any[];
} 

笨蛋

https://plnkr.co/edit/pIVOCSJ5eb1PUVXoEffS?p=preview

最佳答案

首先,感谢您提供谷歌地图 API key ;-)。

您的问题是在尝试与之交互时尚未加载谷歌地图。您需要提供回调才能使其正常工作。

This question可能有帮助。

关于angular - 尝试在页面上呈现 Google map 时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43186325/

相关文章:

javascript - 如何在 TypeScript 中用文本框替换单词?

typescript - Protractor : browser.getCurrentUrl().then ( ( url ) => { return url; } );总是返回未定义

python - 从 Pandas 数据框到 Google Map API 的 json 文件

jquery - 如何让谷歌地图 API v3 显示点?

json - 服务器上的JSON.parse错误,但本地主机上没有

angular - 如何在 rxjs retryWhen 方法中使用 Angular 服务

arrays - Typescript:过滤条件类型数组并具有正确的返回类型

javascript - 页面加载时如何将 map 标记设置在 div 中心

Angular 不会在启用缓存的情况下更新页面

javascript - 如何从编码中的字符串中删除文本