刷新传单映射:映射容器已初始化

时间:2013-10-04 16:35:28

标签: javascript leaflet

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

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

我总是得到#34;地图容器已经初始化":

问题在于:

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

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

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

21 个答案:

答案 0 :(得分:83)

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

答案 1 :(得分:19)

<强> 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内容。

答案 2 :(得分:18)

最好的方式

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

你应该添加map.off(),它也可以更快地运行,并且不会导致事件出现问题

答案 3 :(得分:5)

好吧,经过多次寻求,我意识到它在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=[];

到目前为止,非常好: - )

答案 4 :(得分:5)

当您删除地图时,它会破坏div id引用,因此,在remove()之后,您需要再次构建将显示地图的div,以避免出现&#34; Uncaught Error:Map未找到容器&#34;。

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

答案 5 :(得分:3)

在初始化地图检查之前,地图已经启动或未启动

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

答案 6 :(得分:3)

如果您想更新地图视图(例如更改地图中心),则不必删除然后重新创建地图,只需更新坐标

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

答案 7 :(得分:1)

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

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

通过此解决方案,您的地图将在该地图将由L.Map填充后第一次初始化,然后它将不为空。所以没有像地图容器已初始化那样的错误。

答案 8 :(得分:1)

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

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

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

答案 9 :(得分:1)

仅使用此

map.invalidateSize();

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

答案 10 :(得分:1)

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

var container = L.DomUtil.get('map');

if(container != null){

container._leaflet_id = null;

}

对我有用

答案 11 :(得分:0)

我在 reactjs 中做到了这一点

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

答案 12 :(得分:0)

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

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

....

map.reload();

答案 13 :(得分:0)

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

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

答案 14 :(得分:0)

您应该尝试卸载该函数以移除现有地图。

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 :(得分:0)

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

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
}

答案 16 :(得分:0)

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

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

答案 17 :(得分:0)

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

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

其中<div id="map-canvas"></div>是映射到其中的对象。

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

答案 18 :(得分:0)

我们今天面对这个问题,我们已经解决了。我们做什么?

传单地图的加载范围如下。

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

这段代码之后,我的传单地图可以与表单过滤器一起正常工作,以重新加载。

谢谢。

答案 19 :(得分:0)

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

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

答案 20 :(得分:0)

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