【问题标题】:Reuse instance of Google Maps API on Single Page Application在单页应用程序上重用 Google Maps API 的实例
【发布时间】:2016-07-16 21:30:22
【问题描述】:

假设我有一个单页应用程序(Angular JS 应用程序),并且我在元素 id googleMap 上绘制了一个 Google 地图实例 -

var mapInstance = new google.maps.Map(document.getElementById(`googleMap`), mapOption)

然后我浏览应用程序路由,由于这个,破坏了googleMap DOM 元素,最后我回到了这个元素的路由,现在我必须在这个元素上重新绘制地图。

重绘地图的正确方法是什么?

正如我在this answer 中所读到的,我不必重新创建它,而是使用相同的实例。

【问题讨论】:

    标签: javascript angularjs google-maps google-maps-api-3


    【解决方案1】:

    我会小心的

    $scope.on('$destroy', function(){
        mapInstance = null;
    })
    

    我有一个包含我的地图 DOM 元素的指令,并且正在调用此方法以从数据层、所有侦听器中删除所有地图引用,然后将地图设置为 null。我正在检查页面导航之间的堆,并且正在重新创建地图实例,但旧地图仍在堆中,导致内存使用量不断增加。

    您链接的答案还建议重新使用您的地图实例,而不是尝试删除它。谷歌地图开发人员也推荐这种方法。我找到的解决方案是将您的指令元素传递给服务,并将子元素附加到在新子元素上创建地图的那个。如果地图已经存在,只需将地图 div 附加到指令元素。下面是我的代码。

    ng-view 元素

    <map-container></map-container>
    

    指令

    angular.module('project')
      .directive('mapContainer', function($timeout, mapService) {
         return {
           template: '<div></div>',
           restrict: 'E',
           replace: true,
           link: function(scope, element) {
             $timeout(function () {
               //Use the $timeout to ensure the DOM has finished rendering
               mapService.createMap(element).then(function() {
                  //map now exists, do whatever you want with it
               });
            });
          }
        };
     })
    

    服务

    angular.module('project')
      .service('mapService', function($q) {
    
        var lat = -33.1798;
        var lng = 146.2625;
        var minZoom = 5;
        var maxZoom = 20;
        var zoom =  6;
        var mapOptions = null;
        var map = null;
    
        function initialiseGmap(element) {
    
          return $q(function (resolve) {
            if (map) {
              //Map already exists, append it
              element.append(map.getDiv());
              resolve();
            } else {
              //No map yet, create one
              element.append('<div id="map_canvas"></div>');
    
              mapOptions = {
                zoom: zoom,
                center: new google.maps.LatLng(lat, lng),
                styles: hybridMap, //your style here
                minZoom: minZoom,
                maxZoom: maxZoom,
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                mapTypeControl: false,
                streetViewControl: false,
                panControl: false,
                scaleControl: true,
                zoomControl: false
              };
    
              map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
    
              //create any map listeners you want here. If you want to add data to the map and add listeners to those, I suggest a seperate service.
    
              resolve();
            }
          });
        }
    
        return {
          createMap: function(elem) {
            return initialiseGmap(elem);
          },
          getMap: function() {
            return map;
          },
          //Create as many functions as you like to interact with the map object
          //depending on our project we have had ones to interact with street view, trigger resize events etc etc.
          getZoom: function() {
            return zoom;
          },
          setZoom: function(value) {
            map.setZoom(zoom);
          }
        };
      });
    

    【讨论】:

      【解决方案2】:

      这个问题有 angularjs 标签,所以我假设这是一个 Angular JS 应用程序。在这种情况下,您可能不应该在页面控制器中执行此操作。

      您可以使用预先存在的指令,例如 https://angular-ui.github.io/angular-google-maps/#!/,或者您可以编写自己的指令。

      如果您编写自己的指令,那么您应该在每次使用 $scope.on('$destroy', fn) 事件销毁指令时销毁 google map 实例。像这样..

      $scope.on('$destroy', function(){
          mapInstance = null;
      })
      

      【讨论】:

      • 是的,它是 Angular JS 应用程序
      • 如果我编写自己的指令,我必须在$destroy 函数中做什么以及如何重绘它?
      • 我已经更新了我的答案,说明如何销毁它。我不确定你为什么需要重新绘制它,因为它附加到的 DOM 已经消失了。编译新指令时只需创建一个新的 mapInstance 即可。
      • 我确实在您的链接中看到了关于不破坏和重新创建地图的其他问题的内容。我不确定这是常见的做法,如果您在指令中创建 mapInstance ,您将无法做到这一点。您需要在应用程序的更高级别创建单个 mapInstance 并重用它。您可能想深入研究 angular-google-maps 代码,看看他们是如何做到的。
      • 我已经为这个问题添加了一个我认为可以解决问题的答案。我将不胜感激。它对我有用,我能够在单页应用程序中重用和访问同一个实例。作为 Stackoverflow 经验有限的人,如果你们中的任何一个/两个都觉得这个答案解决了这个问题,那么确保其他人被引导到答案的最佳方法是什么? @URL87
      【解决方案3】:

      每次调用:

      map = new google.maps.Map(document.getElementById('xx'), mapOptions);
      

      您消耗了您的 Google 地图配额。 小心!

      【讨论】:

        【解决方案4】:

        在我的情况下,通过超时重新初始化谷歌地图解决了这个问题。

         setTimeout(function(){ initialize() }, 30);
        

        可以通过销毁之前动态创建的元素来杀死已初始化的实例,但这更难......

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多