Ultimamente me he estado pegando más de la cuenta con Leaflet, así que comparto aquí el problema encontrado, y la solución, por si le puede servir de ayuda a alguien.
Origen del problema: tenemos un objeto javascript L.Map de Leaflet, al que hemos añadido una serie de elementos vectoriales (objetos de tipo L.Layer).
Si queremos cambiar la capa, y mostrar otra distinta, reutilizando el objeto mapa existente, tenemos que seguir estos dos pasos:
a) Eliminar los objetos "Layer" previamente cargados. En este caso lo más comodo es haberlos agrupado previamente en un contenedor denominado "LayerGroup".
b) Añadir la nueva capa (objetos Layer) agrupada en un contenedor.
c) Cambiar el nivel de zoom del mapa, para que se nos muestra la nueva "capa" que vamos a añadir.
Y ¡ojo! Aquí empiezan a aparecer los problemas. Es muy posible que el nivel de zoom que se nos muestre sea siempre el máximo, y que el mapa (la capa de tiles con ortofoto, open street map, o lo que sea que hayamos querido cargar como capa de base) no aparezca centrado. ¿Cual es el motivo?
Si cambiamos nuestro código de cambio del nivel de zoom, por el siguiente:
Veremos que zoomLevel toma el valor 0.
ACTUALIZACIÓN: En este bug reportado en la web del proyecto Leaflet se describe perfectamente el problema. No solo zoomLevel toma el valor 0, getSize() devuelve un objeto con valores w=0 y h=0.
En este punto es cuando entra en juego el método invalidateSize() del objeto map. Si lo hacemos así:
Nuestro mapa se dibujará sin problemas, mostrando la capa que acabamos de añadir.
Moraleja: map.invalidateSize() recalcula los parámetros del objeto map,parámetros que pueden cambiar con un cambio del área de visualización del dispositivo (horizontal a vertical en móvil, cambio del tamaño del navegador en desktop, etc) o con el "bounds" de las geometrías cargadas. Así que es conveniente siempre llamar a map.invalidateSize() antes de cambiar el nivel de zoom, si pensamos que se ha producido un cambio en la inforamación de estado del mapa.
Origen del problema: tenemos un objeto javascript L.Map de Leaflet, al que hemos añadido una serie de elementos vectoriales (objetos de tipo L.Layer).
Si queremos cambiar la capa, y mostrar otra distinta, reutilizando el objeto mapa existente, tenemos que seguir estos dos pasos:
a) Eliminar los objetos "Layer" previamente cargados. En este caso lo más comodo es haberlos agrupado previamente en un contenedor denominado "LayerGroup".
if(currentLayer){
if(currentLayer instanceof L.LayerGroup)
currentLayer.clearLayers();
map.removeLayer(currentLayer);
}
}
b) Añadir la nueva capa (objetos Layer) agrupada en un contenedor.
var lyrs = [];//array donde guardar las geometrias
var layerGroup = L.featureGroup(lyrs);
c) Cambiar el nivel de zoom del mapa, para que se nos muestra la nueva "capa" que vamos a añadir.
map.fitBounds(layerGroup.getBounds());
Y ¡ojo! Aquí empiezan a aparecer los problemas. Es muy posible que el nivel de zoom que se nos muestre sea siempre el máximo, y que el mapa (la capa de tiles con ortofoto, open street map, o lo que sea que hayamos querido cargar como capa de base) no aparezca centrado. ¿Cual es el motivo?
Si cambiamos nuestro código de cambio del nivel de zoom, por el siguiente:
var bounds = _layerGroup.getBounds();
var center = bounds.getCenter();
var zoomLevel = map.getBoundsZoom(bounds);
map.setView(center, zoomLevel, true);
Veremos que zoomLevel toma el valor 0.
ACTUALIZACIÓN: En este bug reportado en la web del proyecto Leaflet se describe perfectamente el problema. No solo zoomLevel toma el valor 0, getSize() devuelve un objeto con valores w=0 y h=0.
En este punto es cuando entra en juego el método invalidateSize() del objeto map. Si lo hacemos así:
var layerGroup = L.featureGroup(lyrs);
map.invalidateSize();
map.fitBounds(layerGroup.getBounds());
Nuestro mapa se dibujará sin problemas, mostrando la capa que acabamos de añadir.
Moraleja: map.invalidateSize() recalcula los parámetros del objeto map,parámetros que pueden cambiar con un cambio del área de visualización del dispositivo (horizontal a vertical en móvil, cambio del tamaño del navegador en desktop, etc) o con el "bounds" de las geometrías cargadas. Así que es conveniente siempre llamar a map.invalidateSize() antes de cambiar el nivel de zoom, si pensamos que se ha producido un cambio en la inforamación de estado del mapa.
No hay comentarios:
Publicar un comentario