Angular2 - 如何设置google.maps.OverlayView? (将JS原型翻译成Typescript)

时间:2016-10-18 09:20:02

标签: google-maps angular typescript

我想创建一个像这样工作的谷歌地图组件: https://jsfiddle.net/gvvy5vxz/2/

基于此:https://developers.google.com/maps/documentation/javascript/examples/overlay-simple

我是打字稿的新手,我坚持原型实现,特别是这个JS片段:

USGSOverlay.prototype = new google.maps.OverlayView();

USGSOverlay(bounds, image, map) {

    // Initialize all properties.
    this.bounds_ = bounds;
    this.image_ = image;
    this.map_ = map;

    // Define a property to hold the image's div. We'll
    // actually create this div upon receipt of the onAdd()
    // method so we'll leave it null for now.
    this.div_ = null;

    // Explicitly call setMap on this overlay.
    this.setMap(map);
  }

我不知道如何以打字稿的方式翻译它以及如何正确地声明事物。

我想我应该创建一个扩展google.maps.OverlayView的类USGSOverlay,但它不起作用。

class USGSOverlay extends google.maps.OverlayView{

  bounds_;
  image_;
  map_;
  div_;

  constructor(bounds, image, map){
    // Initialize all properties.
    this.bounds_ = bounds;
    this.image_ = image;
    this.map_ = map;

    // Define a property to hold the image's div. We'll
    // actually create this div upon receipt of the onAdd()
    // method so we'll leave it null for now.
    this.div_ = null;

    // Explicitly call setMap on this overlay.
    this.setMap(map);
  }
}

这是我的工作基础组件。它在#map:

中创建了一个简单的地图
import { Component } from '@angular/core';
declare const google: any;
/*
/*  Component Map
*/
@Component({
  selector: 'map',
  template: `
    <div id="map"></div>
  `,
  styles: [
    `#map{ width:100%; height:100%; position: absolute; width:100%; height:100%; top:0; left:0;}`
  ],
})
export class MapComponent {

  ngOnInit(){
    google.maps.event.addDomListener(window, 'load', this.initMap);
  }

  initMap() {

    const map = new google.maps.Map(document.getElementById('map'), {
      zoom: 11,
      center: {lat: 62.323907, lng: -150.109291},
      mapTypeId: google.maps.MapTypeId.SATELLITE
    });

    const bounds = new google.maps.LatLngBounds(
        new google.maps.LatLng(62.281819, -150.287132),
        new google.maps.LatLng(62.400471, -150.005608));
  }
}

6 个答案:

答案 0 :(得分:2)

这对我有用(使用离子2):

  1. 使用以下命令:

    npm install typings --global
    typings install dt~google.maps --global --save
    typings install google.maps --global
    
  2. 在tsconfig.json中添加“typings / * .d.ts”:

    "include": [
      "src/**/*.ts",
      "typings/*.d.ts"
    ]
    
  3. 以下是TypeScript代码:

    import { Component, ViewChild, ElementRef } from '@angular/core';
    import { NavController } from 'ionic-angular';
    // import typings
    import { } from '@types/googlemaps';
    /*
    /*  Component Map
    */
    @Component({
        selector: 'page-overlay',
        templateUrl: 'overlay.html'
    })
    export class OverlayPage {
        @ViewChild('map') mapElement: ElementRef;
        map: any;
        // weird syntax, I know, but it works
        constructor(public navCtrl: NavController) {
        }
        USGSOverlay = class extends google.maps.OverlayView {
            bounds_: any;
            image_: any;
            map_: any;
            div_: any;
            constructor(bounds, image, private map) {
                super();
                // Initialize all properties.
                this.bounds_ = bounds;
                this.image_ = image;
                this.map_ = map;
                // Define a property to hold the image's div. We'll
                // actually create this div upon receipt of the onAdd()
                // method so we'll leave it null for now.
                this.div_ = null;
                // Explicitly call setMap on this overlay.
                this.setMap(map);
                this.set
            }
            /**
             * onAdd is called when the map's panes are ready and the overlay has been
             * added to the map.
             */
            onAdd() {
                const div = document.createElement('div');
                div.style.borderStyle = 'none';
                div.style.borderWidth = '0px';
                div.style.position = 'absolute';
                // Create the img element and attach it to the div.
                const img = document.createElement('img');
                img.src = this.image_;
                img.style.width = '100%';
                img.style.height = '100%';
                img.style.position = 'absolute';
                div.appendChild(img);
                this.div_ = div;
                // Add the element to the "overlayLayer" pane.
                const panes = this.getPanes();
                panes.overlayLayer.appendChild(div);
            };
            draw() {
                // We use the south-west and north-east
                // coordinates of the overlay to peg it to the correct position and size.
                // To do this, we need to retrieve the projection from the overlay.
                const overlayProjection = this.getProjection();
                // Retrieve the south-west and north-east coordinates of this overlay
                // in LatLngs and convert them to pixel coordinates.
                // We'll use these coordinates to resize the div.
                const sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
                const ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
                // Resize the image's div to fit the indicated dimensions.
                const div = this.div_;
                div.style.left = sw.x + 'px';
                div.style.top = ne.y + 'px';
                div.style.width = (ne.x - sw.x) + 'px';
                div.style.height = (sw.y - ne.y) + 'px';
            };
            // The onRemove() method will be called automatically from the API if
            // we ever set the overlay's map property to 'null'.
            onRemove() {
                this.div_.parentNode.removeChild(this.div_);
                this.div_ = null;
            };
        };
        ngOnInit() {
            this.loadMap();
            var bounds = new google.maps.LatLngBounds(
                new google.maps.LatLng(62.281819, -150.287132),
                new google.maps.LatLng(62.400471, -150.005608));
            // The photograph is courtesy of the U.S. Geological Survey.
            var srcImage = 'https://developers.google.com/maps/documentation/' +
                'javascript/examples/full/images/talkeetna.png';
            const overlay = new this.USGSOverlay(bounds, srcImage, this.map);
            //overlay.setMap(this.map);
        }
        ionViewDidLoad() {
            this.loadMap();
            var bounds = new google.maps.LatLngBounds(
                new google.maps.LatLng(62.281819, -150.287132),
                new google.maps.LatLng(62.400471, -150.005608));
            // The photograph is courtesy of the U.S. Geological Survey.
            var srcImage = 'https://developers.google.com/maps/documentation/' +
                'javascript/examples/full/images/talkeetna.png';
            const overlay = new this.USGSOverlay(bounds, srcImage, this.map);
            //overlay.setMap(this.map);
        }
        loadMap() {        
            let latLng = new google.maps.LatLng(62.323907, -150.109291);
            var mapOptions = {
                zoom :15,
                center : latLng,
                enableHighAccuracy: true,
                timeout: 5000,
                maximumAge: 0
            };
            this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
        }
    }
    

答案 1 :(得分:1)

我的工作方式很好......

import { Component } from '@angular/core';
declare const google: any;

class USGSOverlay extends google.maps.OverlayView{

  bounds_;
  image_;
  map_;
  div_;

  constructor(bounds, image, map){
    // Initialize all properties.
    this.bounds_ = bounds;
    this.image_ = image;
    this.map_ = map;

    // Define a property to hold the image's div. We'll
    // actually create this div upon receipt of the onAdd()
    // method so we'll leave it null for now.
    this.div_ = null;

    // Explicitly call setMap on this overlay.
    this.setMap(map);
  }

  /**
   * onAdd is called when the map's panes are ready and the overlay has been
   * added to the map.
   */
  onAdd(){
    const div = document.createElement('div');
    div.style.borderStyle = 'none';
    div.style.borderWidth = '0px';
    div.style.position = 'absolute';

    // Create the img element and attach it to the div.
    const img = document.createElement('img');
    img.src = this.image_;
    img.style.width = '100%';
    img.style.height = '100%';
    img.style.position = 'absolute';
    div.appendChild(img);

    this.div_ = div;

    // Add the element to the "overlayLayer" pane.
    const panes = this.getPanes();
    panes.overlayLayer.appendChild(div);
  };

  draw(){

    // We use the south-west and north-east
    // coordinates of the overlay to peg it to the correct position and size.
    // To do this, we need to retrieve the projection from the overlay.
    const overlayProjection = this.getProjection();

    // Retrieve the south-west and north-east coordinates of this overlay
    // in LatLngs and convert them to pixel coordinates.
    // We'll use these coordinates to resize the div.
    const sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
    const ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

    // Resize the image's div to fit the indicated dimensions.
    const div = this.div_;
    div.style.left = sw.x + 'px';
    div.style.top = ne.y + 'px';
    div.style.width = (ne.x - sw.x) + 'px';
    div.style.height = (sw.y - ne.y) + 'px';
  };

  // The onRemove() method will be called automatically from the API if
  // we ever set the overlay's map property to 'null'.
  onRemove(){
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  };
};



/*
/*  Component Map
*/
@Component({
  selector: 'map',
  template: `
    <div id="map"></div>
  `,
  styles: [
    `#map{ width:100%; height:100%; position: absolute; width:100%; height:100%; top:0; left:0;}`
  ],
})
export class MapComponent {

  overlay;

  ngOnInit(){
    google.maps.event.addDomListener(window, 'load', this.initMap);
  }

  initMap() {

    const map = new google.maps.Map(document.getElementById('map'), {
      zoom: 11,
      center: {lat: 62.323907, lng: -150.109291},
      mapTypeId: google.maps.MapTypeId.SATELLITE
    });

    const bounds = new google.maps.LatLngBounds(
        new google.maps.LatLng(62.281819, -150.287132),
        new google.maps.LatLng(62.400471, -150.005608));

    // The photograph is courtesy of the U.S. Geological Survey.
    const srcImage = 'https://developers.google.com/maps/documentation/' +
        'javascript/examples/full/images/talkeetna.png';

    // The custom USGSOverlay object contains the USGS image,
    // the bounds of the image, and a reference to the map.
    this.overlay = new USGSOverlay(bounds, srcImage, map);
  }
}

答案 2 :(得分:1)

我也遇到了很多麻烦,但最终还是顺利的。至关重要的是谷歌地图脚本是预先加载的(我在我的路线解析器中加载了我的),否则你会得到一个'谷歌'没有定义错误。请参阅here我如何安装打字并导入库。

至于语法,我最终使用了一个内部类。这是因为,如果它是一个顶级类,WebPack尝试(不成功)在编译时找到谷歌地图库:

// import typings
import {} from '@types/googlemaps';

@Component({...})
export class MapComponent implements OnInit {
  // weird syntax, I know, but it works
  USGSOverlay = class extends google.maps.OverlayView {
    constructor(bounds, image, private map){
      super();
      ...
      this.setMap(this.map);
    }
    onAdd(){...}
    draw(){...}
  }
  ngOnInit() {
    const overlay = new this.Overlay(bounds, image, map);
  }
}

答案 3 :(得分:1)

使用此简单代码创建自定义叠加层。

"axes": [
      {
        "orient": "bottom", 
        "scale": "x", 
        "labelAngle": -45,
        "tickOffset": 0,
        "labelAlign": "right",
        "domain": false,
        "title": "Features"
      },
      {
        "orient": "left", 
        "scale": "y", 
        "domain": false,
        "title": "Features"
      }
  ],
  "legends": [
    {
      "orient": "right", 
      "direction" : "vertical",
      "fill": "color",
      "type": "gradient",
      "title": "Correlation",
      "titleFontSize": 12,
      "titlePadding": 4,
      "gradientLength": {"signal": "height - 16"}
    }
  ],

答案 4 :(得分:0)

由于我的代码异步加载了Google Maps API,因此上述答案对我不起作用。 我的问题是在加载Google API之前,打字稿使用google变量。

这是我找到的解决方案。

要查看异步地图加载器代码,请参见Load Google Maps JS API in component [Angular]

服务

//map.service.ts

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

...
declare var google;    
export let MyOverlay; // declare and use this from other ts file

@Injectable({ providedIn: 'root' })
export class MapService {

    private static promise;
    map: any;

    public static load() {
        if (!MapService.promise) {
            MapService.promise = new Promise((resolve) => {
              //load google api asynchronously
            });
        }

        return MapService.promise;
    }

    async initMap(gmapElement, lat = -33.92, lng = 151.25) {
        return MapService.load()  
            .then((gapi) => {
                //map init
                this.map = new google.maps.Map(gmapElement.nativeElement, {
                   //map options
                })
                /*** before init MyOverlay, 
                1. Google API should be loaded
                2. AFTER MAP init(rendering), Overlay Object has Projection to calculate Overlay location
                ***/
                this.initMyOverlay()
            })
            .catch(console.log)
    }

    initMyOverlay(){            
        class MyOverlayCls extends google.maps.OverlayView {    
         //omitted for code readability
        }
        MyOverlay = MyOverlayCls ; //assign class to variable
    }

}

组件

//map.component.ts
import { MapService, MyOverlay} from 'map.service';
...

  @ViewChild('gmap') gmapElement: any
  ...

  ngOnInit() {
    console.log("maps init")
    this.mapSvc.initMap(this.gmapElement).then(_ => {

      //At this time, google API has been loaded and assigned MyOverlay as MyOverlayCls
      let overlay= new MyOverlay(...)    

    })

答案 5 :(得分:0)

就我而言,我无法在同一类中拥有负责加载地图的内部类。我花了一些时间弄清楚该怎么做。 这就是我的方法

export class mapTextOverlayService {

  //Overlay is creatd in an inner-class because if it is at top-level class google maps library may not be available at the class load time
  mapTextOverlay = class extends google.maps.OverlayView {

    pos_;
    text_;
    map_;
    div_;

    constructor(pos, text, map) {
      super();
      // Initialize all properties.
      this.pos_ = pos;
      this.text_ = text;
      this.map_ = map;

      // Define a property to hold the text's div. We'll
      // actually create this div upon receipt of the onAdd()
      // method so we'll leave it null for now.
      this.div_ = null;

      // Explicitly call setMap on this overlay.
      this.setMap(map);
    }

    /**
     * onAdd is called when the map's panes are ready and the overlay has been
     * added to the map.
     */
    onAdd() {
      const div = document.createElement('div');
      div.style.borderStyle = 'none';
      div.style.borderWidth = '0px';
      div.style.position = 'absolute';

      div.innerHTML = this.text_;

      this.div_ = div;

      // Add the element to the "overlayLayer" pane.
      const panes = this.getPanes();
      panes.overlayLayer.appendChild(div);
    };

    draw() {
      // We are using bounds centre to peg it to the correct position.
      // To do this, we need to retrieve the projection from the overlay.
      const overlayProjection = this.getProjection();

      // Convert the centre coordinates of this overlay from LatLngs to pixel coordinates.
      // We'll use these coordinates to provide the dimensions of div.
      const pixelPos = overlayProjection.fromLatLngToDivPixel(this.pos_);

      const div = this.div_;
      div.style.left = pixelPos.x + 'px';
      div.style.top = pixelPos.y + 'px';
    };

    // The onRemove() method will be called automatically from the API if
    // we ever set the overlay's map property to 'null'.
    onRemove() {
      this.div_.parentNode.removeChild(this.div_);
      this.div_ = null;
    };

    onHide() {
      if (this.div_) {
        this.div_.style.visibility = 'hidden';
      } 
    };

  }

  createMapTextOverlay(pos, text, map) {
    return new this.mapTextOverlay(pos, text, map);
  }

};

然后在我要创建文本覆盖的组件中:

let mtos = new mapTextOverlayService();
let label = mtos.createMapTextOverlay(boundsCenter, description, this.map.mapobject);