【问题标题】:refresh leaflet map: map container is already initialized刷新传单地图:地图容器已经初始化
【发布时间】:2013-10-11 18:13:11
【问题描述】:

我有一个页面,用户可以在其中选择他可以切换我显示的传单地图。

在初始传单地图加载后,我的问题是何时我想刷新地图。

我总是得到“地图容器已经初始化”:

问题线是:

var map = L.map('mapa').setView([lat, lon], 15);

最初它加载得很好,但是当我在表单中选择另一个参数并想再次显示地图时它崩溃了。

顺便说一句,我尝试在第二个 setView() 之前使用 jQuery 销毁和重新创建 $('#mapa') 但它显示相同的错误。

【问题讨论】:

    标签: javascript leaflet


    【解决方案1】:

    在尝试重新加载地图之前尝试map.remove();。这使用 Leaflet 的库(而不是 jquery 的)删除了以前的地图元素。

    【讨论】:

    • if (map != undefined) { map.remove(); } 如果您不确定地图是否存在..
    【解决方案2】:

    HTML:

    <div id="weathermap"></div>
    

    JavaScript:

    function buildMap(lat,lon)  {
        document.getElementById('weathermap').innerHTML = "<div id='map' style='width: 100%; height: 100%;'></div>";
        var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                        osmAttribution = 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors,' +
                            ' <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
        osmLayer = new L.TileLayer(osmUrl, {maxZoom: 18, attribution: osmAttribution});
        var map = new L.Map('map');
        map.setView(new L.LatLng(lat,lon), 9 );
        map.addLayer(osmLayer);
        var validatorsLayer = new OsmJs.Weather.LeafletLayer({lang: 'en'});
        map.addLayer(validatorsLayer);
    }
    

    我用这个:

    document.getElementById('weathermap').innerHTML = "<div id='map' style='width: 100%; height: 100%;'></div>";
    

    在渲染地图的地方重新加载 div 的内容。

    【讨论】:

    • 可能适用于普通 html,但在 React 等库中,由于选择性 div 操作,它不是。
    【解决方案3】:

    最好的方法

    map.off();
    map.remove();
    

    你应该添加 map.off(),它也工作得更快,并且不会导致事件出现问题

    【讨论】:

    • 对不起,你怎么用这个?
    • @djack109 保留地图处理程序对象的引用。您可以从地图的 onReady 事件中获取此信息。然后您可以在该处理程序对象上调用这两个方法。如果不清楚,我很乐意提供一个例子。
    【解决方案4】:

    在初始化地图之前检查地图是否已经启动

    var container = L.DomUtil.get('map');
          if(container != null){
            container._leaflet_id = null;
          }
    

    【讨论】:

      【解决方案5】:

      只用这个

      map.invalidateSize();
      

      https://github.com/Leaflet/Leaflet/issues/690

      【讨论】:

      • 这是唯一对我有用的解决方案。
      【解决方案6】:

      在初始化地图之前检查地图是否已经启动

      var container = L.DomUtil.get('map');
      
      if(container != null){
      
      container._leaflet_id = null;
      
      }
      

      map.invalidateSize();

      对我有用

      【讨论】:

        【解决方案7】:

        好吧,经过多次寻找,我意识到它在 http://leafletjs.com/examples/layers-control.html 上有很好的记录

        我已经结束了不重新绘制地图,而是打印一次并在每个新的 ajax 调用上重新绘制点,所以问题是如何清理旧点并只打印新点。我已经结束了:

        var point = L.marker([new_marker[0], new_marker[1]]).addTo(map).bindPopup('blah blah');
        points.push(point); 
        //points is a temporary array where i store the points for removing them afterwards
        

        所以,在每个新的 ajax 调用中,绘制新点之前,我会执行以下操作:

        for (i=0;i<points.length;i++) {
          map.removeLayer(points[i]);
        }
        points=[];
        

        到目前为止,一切都很好:-)

        【讨论】:

          【解决方案8】:

          当你只是删除一个地图时,它会破坏 div id 引用,因此,在 remove() 之后,你需要再次构建将显示地图的 div,以避免“未捕获错误:未找到地图容器” ”。

          if(map != undefined || map != null){
              map.remove();
             $("#map").html("");
             $("#preMap").empty();
             $( "<div id=\"map\" style=\"height: 500px;\"></div>" ).appendTo("#preMap");
          }
          

          【讨论】:

            【解决方案9】:

            您可以尝试在初始化地图之前或离开页面时删除地图:

            if(this.map) {
              this.map.remove();
            }
            

            【讨论】:

              【解决方案10】:

              我在切换页面时遇到了同样的问题。我必须在离开页面之前添加此代码才能使其正常工作:

                  $scope.$on('$locationChangeStart', function( event ) {
                  if(map != undefined)
                  {
                    map.remove();
                    map = undefined
                    document.getElementById('mapLayer').innerHTML = "";
                  }
              });
              

              没有document.getElementById('mapLayer').innerHTML = "",地图不会显示在下一页。

              【讨论】:

              • 这对我有帮助。我正在使用 Angular 6 并根据用户单击的位置更改地图。我只有一个方法来创建一个返回地图对象的新地图。当我更新地图时,我将现有的地图对象传入并在没有 innerHTML 部分的情况下执行上述操作...
              • 这种方法有效,但是我不太明白map.remove()map = undefined 语句有什么不同
              【解决方案11】:

              如果你想更新地图视图,例如改变地图中心,你不必删除然后重新创建地图,你可以更新坐标

              const mapInit = () => {
               let map.current = w.L.map('map');
              
               L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
                  attribution: '&copy; <a href="http://osm.org/copyright" target="_blank">OpenStreetMap</a> contributors'
               }).addTo(map.current);
              }
              
              const setCoordinate = (gps_lat, gps_long) => {
                map.setView([gps_lat, gps_long], 13);
              }
              
              initMap();
              
              setCoordinate(50.403723 30.623538);
              
              setTimeout(() => {
                setCoordinate(51.505, -0.09);
              }, 3000);
              

              【讨论】:

                【解决方案12】:

                我遇到了同样的问题。然后我设置了全局地图变量,例如 var map= null 然后我检查显示地图

                if(map==null)then map=new L.Map('idopenstreet').setView();
                

                通过此解决方案,您的地图只会在 L.Map 填充该地图后的第一次初始化,然后它不会为空。所以不会出现像地图容器已经初始化的错误。

                【讨论】:

                  【解决方案13】:

                  要在同一页面中刷新地图,您可以使用以下代码在页面上创建地图

                  if (!map) {
                      this.map = new L.map("mapDiv", {
                          center: [24.7136, 46.6753],
                          zoom: 5,
                          renderer: L.canvas(),
                          attributionControl: true,
                      });
                  }
                  

                  然后使用下面的行刷新地图,但请确保使用相同的纬度、经度和缩放选项

                  map.setView([24.7136, 46.6753], 5);  
                  

                  此外,我在使用 Angular 2+ 在同一页面中的选项卡之间切换时遇到了同样的问题,我可以通过在组件 constructor 中添加以下代码来修复它

                  var container = L.DomUtil.get('mapDiv');
                  if (container != null) {
                      container.outerHTML = ""; // Clear map generated HTML
                      // container._leaflet_id = null; << didn't work for me
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    你应该尝试在 react js 中卸载该函数以删除现有的地图。

                    const Map = () => {
                    
                        const mapContainer = useRef();
                        const [map, setMap] = useState({});
                    
                        useEffect(()=>{
                            const map = L.map(mapContainer.current, {attributionControl: false}).setView([51.505, -0.09], 13);
                    
                        L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
                            maxZoom: 18,
                            attribution: 'Map',
                            id: 'mapbox/streets-v11',
                            tileSize: 512,
                            zoomOffset: -1
                        }).addTo(map);
                    
                        // unmount map function
                        return () => map.remove();
                        }, []);
                    
                        return (
                            <div style={{padding: 0, margin: 0, width: "100%", height: "100vh",}}
                                 ref={el => mapContainer.current = el}>
                            </div>
                        );
                    }
                    

                    【讨论】:

                      【解决方案15】:

                      使用 redrawAll() 函数而不是 renderAll()。

                      【讨论】:

                        【解决方案16】:

                        我们今天遇到了这个问题,我们解决了。我们做什么?

                        传单地图加载 div 如下。

                        <div id="map_container">
                           <div id="listing_map" class="right_listing"></div>
                        </div>
                        

                        当表单输入更改或提交时,我们按照以下步骤操作。在我的页面中删除传单地图容器并重新创建后。

                        $( '#map_container' ).html( ' ' ).append( '<div id="listing_map" class="right_listing"></div>' );
                        

                        在此代码之后,我的传单地图可以正常使用表单过滤器重新加载。

                        谢谢。

                        【讨论】:

                          【解决方案17】:

                          如果您不全局存储地图对象引用,我建议

                          if (L.DomUtil.get('map-canvas') !== undefined) { 
                             L.DomUtil.get('map-canvas')._leaflet_id = null; 
                          }
                          
                          

                          &lt;div id="map-canvas"&gt;&lt;/div&gt; 是地图被绘制到的对象。

                          这样您就可以避免重新创建 html 元素,如果您使用 remove() 它就会发生这种情况。

                          【讨论】:

                            【解决方案18】:

                            对于刷新传单地图,您可以使用此代码:

                            this.map.fitBounds(this.map.getBounds());

                            【讨论】:

                              【解决方案19】:

                              我在反应时遇到了同样的问题,我通过在 useEffect 的顶部初始化解决了它 这是我的反应代码。

                              const mapContainerRef = useRef(null);
                              
                              useEffect( async () => {
                                const res =await Axios.get(BASE_PATH + 'fetchProperty')
                              
                                const container = L.DomUtil.get(mapContainerRef.current); if(container != null){ container._leaflet_id = null; }
                              
                                if(container) {
                              
                              
                                const mapView = L.map( mapContainerRef.current, {
                                  zoom: 13,
                                  center: [19.059984, 72.889999]
                                  //  maxZoom: 13
                                  // minZoom: 15
                                });
                                // const canvas = mapView.getCanvasContainer();
                                mapView.zoomControl.setPosition("bottomright");
                                mapView.attributionControl.addAttribution(
                                  "<a href='https://mascots.pro'>Mascots. pro</a>"
                                );
                                L.tileLayer(
                                  // "https://api.mapbox.com/styles/v1/mapbox/dark-v9/tiles/{z}/{x}/{y}?access_token=" + https://api.mapbox.com/styles/v1/anonymousmw/cko1eb1r20mdu18qqtps8i03p/tiles/{z}/{x}/{y}?access_token=
                                  "https://api.mapbox.com/styles/v1/mapbox/dark-v9/tiles/{z}/{x}/{y}?access_token=" +
                                    access_token,
                                  {
                                    attribution: '<a href="http://mascots.work">Mascots</a>'
                                  }
                                ).addTo(mapView);
                              
                                const mask = L.tileLayer.mask(
                                  "https://api.mapbox.com/styles/v1/anonymousmw/cko1eb1r20mdu18qqtps8i03p/tiles/{z}/{x}/{y}?access_token=" +
                                    access_token,
                                  {
                                    attribution: '<a href="https://mascots.pro">Mascots pro</a>',
                                    maskSize: 300
                                    // maxZoom: 18,
                                    // maxNativeZoom: 16
                                    // tms: true
                                  }
                                )
                                .addTo(mapView);
                              
                                mapView.on("mousemove", function (e) {
                                  mask.setCenter(e.containerPoint);
                                });
                                res.data.map((marker) => {
                                
                                  const innerHtmlContent = `<div id='popup-container' class='popup-container'> <h3> Property Details</h3>
                                  <div class='popup-label'>Building Name :<p>${marker.Building}</p></div>
                                  <div class='popup-address-label'> Address : <p>${marker.Landmark}, ${marker.Location}</p></div>
                                  <div class='popup-rent-label'>Monthly Rent : <p> ₹ ${marker.Price}</p></div>
                                  </div>`;
                                  const divElement = document.createElement("div");
                                  const assignBtn = document.createElement("div");
                                  assignBtn.className = "map-link";
                                  assignBtn.innerHTML = `<button class="view-btn">View Property</button>`;
                                  divElement.innerHTML = innerHtmlContent;
                                  divElement.appendChild(assignBtn);
                                  assignBtn.addEventListener("click", (e) => {
                                    console.log("dsvsdvb");
                                  });
                                  var iconOptions = {
                                    iconUrl: "/images/location_pin2.svg",
                                    iconSize: [25, 25]
                                  };
                                  var customIcon = L.icon(iconOptions);
                              
                                  // create popup contents
                                  var customPopup = divElement;
                              
                                  // specify popup options
                                  var customOptions = {
                                    maxWidth: "500",
                                    className: "custom"
                                  };
                              
                                  const markerOptions = {
                                    // title: "MyLocation",
                                    //    draggable: true
                                    clickable: true,
                                    icon: customIcon
                                  };
                                  const mark = L.marker([marker.Latitude,marker.Longitude], markerOptions);
                                  mark.bindPopup(customPopup, customOptions);
                                  mark.addTo(mapView);
                                  // return mapView.off();
                                 
                                });
                                return () => mapView.remove();
                              }
                              }, [])
                              
                              return (
                                <div className="map-box">
                                      <div className="map-container" ref={mapContainerRef}></div>
                                  </div>
                              );
                              

                              【讨论】:

                                【解决方案20】:

                                我遇到了同样的问题,所以我在地图实例中创建了一个方法来重新加载它。

                                var map = L.map('mapa').setView([lat, lon], 15);
                                map.reload = function(){
                                   map.remove();
                                   map = L.map('mapa').setView([lat, lon], 15);
                                }
                                
                                ....
                                
                                map.reload();
                                
                                

                                【讨论】:

                                  【解决方案21】:

                                  我在 reactjs 中做了这个

                                  // Create map (dev = reuse existing map)
                                  let myMap = L.DomUtil.get('map');
                                  if(myMap == null){
                                    myMap = L.map('mapid').setView(currentLocation, zoom);
                                  }
                                  

                                  【讨论】:

                                    【解决方案22】:

                                    HTML:

                                    <div id='leaflet-map' #leafletMap></div>
                                    

                                    JavaScript:

                                    @ViewChild('leafletMap')
                                    private mapElement: ElementRef;
                                    
                                    private initMap(): void {
                                       this.map = leaflet.map(this.mapElement.nativeElement, {
                                           center: [39.01860177826393, 35.30274319309024],
                                           zoom: 4,
                                       });
                                    
                                       leaflet
                                       .tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                                          attribution: '',
                                          maxZoom: 18,
                                       })
                                       .addTo(this.map);
                                    }
                                    

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2022-07-09
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多