【问题标题】:Angular2 - How to setup a google.maps.OverlayView? (translate JS prototype into Typescript)Angular2 - 如何设置 google.maps.OverlayView? (将 JS 原型翻译成 Typescript)
【发布时间】:2016-10-18 09:20:01
【问题描述】:

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

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

我是 typescript 的新手,我被原型实现困住了,特别是这个 JS sn-p:

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));
  }
}

【问题讨论】:

    标签: google-maps angular typescript


    【解决方案1】:

    这对我有用(使用 ionic 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);
          }
      }
      

    【讨论】:

    【解决方案2】:

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

    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);
      }
    }
    

    【讨论】:

      【解决方案3】:

      我也遇到了很多麻烦,但最终还是做对了。预先加载谷歌地图脚本至关重要(我在路线解析器中加载了我的),否则您将收到“谷歌”未定义错误。请参阅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);
        }
      }
      

      【讨论】:

        【解决方案4】:

        由于我的代码异步加载谷歌地图 API,上述答案对我不起作用。 我的问题是打字稿在加载谷歌 API 之前使用谷歌变量。

        这是我找到的解决方案。

        要查看异步地图加载器代码,请参阅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】:

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

          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);
          

          【讨论】:

            【解决方案6】:

            使用这个简单的代码创建自定义叠加层。

                // this.userPositionDiv is defined as variable
                let overlayView = new google.maps.OverlayView();
                overlayView.draw = () => {
                    if (!this.userPositionDiv) {
                        this.userPositionDiv = document.createElement('div');
                        this.userPositionDiv.className = 'marker';
                        this.userPositionDiv.style.cssText = `width: 35px; height: 35px; text-align: center; line-height: 35px; position: absolute; cursor: pointer; border-radius: 50%; color: #fff; background: #000`;
                        this.userPositionDiv.innerHTML = `<span class="number-id">Hello</span>`;
                        const panes = overlayView.getPanes();
                        panes.overlayImage.appendChild(this.userPositionDiv);
                    }
                    const point = this.overlayView.getProjection().fromLatLngToDivPixel(this.latLng);
                    if (point) {
                        this.userPositionDiv.style.left = (point.x - 10) + 'px';
                        this.userPositionDiv.style.top = (point.y - 10) + 'px';
                    }
                }
                overlayView.setMap(this.gmap);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-02-25
              • 2021-10-22
              • 2012-11-18
              • 2012-11-20
              • 1970-01-01
              • 2017-09-18
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多