Javascript GoogleMapsAPI在单页应用程序中的重用实例

Javascript GoogleMapsAPI在单页应用程序中的重用实例,javascript,angularjs,google-maps,google-maps-api-3,Javascript,Angularjs,Google Maps,Google Maps Api 3,假设我有一个单页应用程序(Angular JS应用程序),我在元素idgoogleMap- var mapInstance = new google.maps.Map(document.getElementById(`googleMap`), mapOption) 然后我浏览应用程序路由,由于这个原因,我销毁了googleMapDOM元素,最后我使用这个元素返回路由,现在我必须在这个元素上重新绘制地图 重新绘制地图的正确方法是什么 正如我在中所读到的,我不必重新创建它,而是使用相同的实例 这个

假设我有一个单页应用程序(Angular JS应用程序),我在元素id
googleMap
-

var mapInstance = new google.maps.Map(document.getElementById(`googleMap`), mapOption)
然后我浏览应用程序路由,由于这个原因,我销毁了
googleMap
DOM元素,最后我使用这个元素返回路由,现在我必须在这个元素上重新绘制地图

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


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

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

您可以使用预先存在的指令,如或编写自己的指令

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

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

我会小心的

$scope.on('$destroy', function(){
    mapInstance = null;
})
我有一个包含map-DOM元素的指令,调用此方法从数据层、所有侦听器中删除所有映射引用,然后将映射设置为null。我正在检查页面导航和映射实例之间的堆,但旧映射仍在堆中,导致内存使用率不断增加

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

ng视图元素

<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);
      }
    };
  });
angular.module('project'))
.directive('mapContainer',function($timeout,mapService){
返回{
模板:“”,
限制:'E',
替换:正确,
链接:功能(范围、元素){
$timeout(函数(){
//使用$timeout确保DOM已完成渲染
createMap(元素).then(函数(){
//地图现在已经存在,你想用它做什么都行
});
});
}
};
})
服务

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);
      }
    };
  });
angular.module('project'))
.service('mapService',函数($q){
var lat=-33.1798;
var lng=146.2625;
var-minZoom=5;
var-maxZoom=20;
var-zoom=6;
var-mapOptions=null;
var-map=null;
函数initialiseGmap(元素){
返回$q(函数(解析){
如果(地图){
//映射已存在,请附加它
append(map.getDiv());
解决();
}否则{
//还没有地图,创建一个
元素。追加(“”);
映射选项={
缩放:缩放,
中心:新google.maps.LatLng(lat,lng),
样式:hybridMap,//您的样式在这里
minZoom:minZoom,
maxZoom:maxZoom,
mapTypeId:google.maps.mapTypeId.ROADMAP,
mapTypeControl:false,
街景控制:错误,
泛控制:错误,
scaleControl:对,
动物控制:错误
};
map=new google.maps.map(document.getElementById('map_canvas'),mapOptions);
//在这里创建您想要的任何映射侦听器。如果您想向映射添加数据并向这些映射添加侦听器,我建议使用单独的服务。
解决();
}
});
}
返回{
createMap:函数(元素){
返回初始ISegmap(elem);
},
getMap:function(){
返回图;
},
//创建与贴图对象交互的任意多个函数
//根据我们的项目,我们有一个与街景互动,触发调整大小事件等。
getZoom:function(){
返回缩放;
},
setZoom:函数(值){
map.setZoom(缩放);
}
};
});

在我的例子中,超时帮助重新初始化Google地图解决了这个问题

 setTimeout(function(){ initialize() }, 30);
通过销毁以前动态创建的元素可以杀死初始化的实例,但这更难

每次打电话时:

map = new google.maps.Map(document.getElementById('xx'), mapOptions);
你使用你的谷歌地图配额。
小心

是的,这是一个角度的JS应用程序在一个案例中,我写了我自己的指令,我必须在
$destroy
函数中做什么,以及如何重新绘制它?我已经更新了我的答案,告诉我如何销毁它。我不知道为什么需要重新绘制它,因为它所连接的DOM已经不存在了。编译新指令时,只需创建一个新的mapInstance。我确实在您的链接中看到了关于不销毁和重新创建地图的其他问题。我不确定这是否是常见做法,如果在指令中创建mapInstance,您将无法做到这一点。您需要在应用程序的更高级别上创建一个mapInstance并重用它。你可能想深入研究谷歌地图的代码,看看他们是如何做到的。我已经为这个问题添加了一个答案,我觉得它解决了这个问题。我希望你能过来看看。它为我工作,我能够在单页应用程序中重用和访问同一实例。作为一个经验有限的人,如果你们中的任何一方/双方都认为这个答案解决了这个问题,那么什么是确保其他人直接找到答案的最佳方法@URL87