15 Lip 2020

Centrowanie mapy uwzględniając szerokość diva - fitBounds leaflet.

Tym razem przykład który pokazuje jak wycentrować mapę z pinem uwzględniając szerokość diva. Mapa posiada div nie jest on stworzony przez mapę tylko jest jako osobny div obok mapy a jedynie wyświetla się nad mapa. Do tego jeżeli mapę będziemy zmniejszasz/powiększać na szerokość to mapa wraz pinem będzie ustawiała się na odpowiednim miejscu.

fitBounds with leaflet

To jak konfigurujemy prostą mapę opisałem tutaj alternatywa dla google maps OSM oraz leaflet więc nie będę się już rozpisywał na ten temat.

Potrzebujemy dodatkowego diva z tekstem.

<div class="info zooom">Lorem ipsum dolor sit amet consectetur adipisicing elit.
Obcaecati a deserunt distinctio vitae! Dolores officiis animi ab
ut officia consequuntur fuga, possimus et eligendi, facilis
libero nulla repellat modi magnam!</div>
<div id="map"></div>

I oczywiście style do tego elementu o klasie info

.info {
  position: absolute;
  z-index: 999;
  border: 2px solid #0084ff;
  top: 10px;
  left: 10px;
  bottom: 10px;
  width: 30%;
  background: #fff;
  padding: 20px;
  border-radius: 5px;
  box-shadow: 0 0 10px 10px rgba(0, 140, 255, 0.2);
  overflow: hidden;
}

Tak jak widać na "załączonym obrazku" nic trudnego 😉

Teraz czas na trochę js. Najpierw podstawa do wyświetlenia mapy.

// konfiguracja mapy
let config = {
  minZoom: 7,
  maxZomm: 18,
  // zoom control wyłączamy
  // w dalszej części opiszę dlaczego 😉
  zoomControl: false
};

// powiększenie w jakim uruchomi się mapa
const zoom = 18;

// współrzędne mapy
const lat = 52.2297700;
const lon = 21.0117800;

// wstawienie mapy w div o zadanych ustawieniach
const map = L.map('map', config).setView([lat, lon], zoom);

// ta część ustawia nam warstwę "kafelków"
// które są serwowane z www.openstreetmap.org 
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

I teraz część odpowiedzialna za centrowanie mapy i nie tylko.

Przesuniemy element do powiększania/pomniejszania mapy na prawą stronę. Bo div z tekstem będzie nam zasłaniał ten element ale także i po to aby polepszyć UX na urządzeniach mobilnych.

// umieszczamy 'zoom control' w prawym górnym rogu
L.control.zoom({ position: 'topright' }).addTo(map);

Teraz przyszedł czas na funkcję która będzie odczytywała szerokość okna z tekstem, oraz centrowała mapę z pinem.

function fitBoundsPadding() {

  // jeden marker
  const marker = L.marker([lat, lon]).bindPopup('Center Warsaw');

  // pobieramy szerokość div info
  const boxInfoWith = document.querySelector('.info').offsetWidth;

  // utwórz grupę obiektów, oczywiście w naszym
  // przypadku jest to jeden marker ale może i być ich kilka
  const featureGroup = L.featureGroup([marker]).addTo(map);

  // ustawiamy widok mapy zawierający określone granice
  // geograficzne z maksymalnym możliwym poziomem powiększenia
  map.fitBounds(featureGroup.getBounds(), {

    // ustawiamy mapę oraz pin na środek uwzględniając
    // szerokość div z tekstem zaś +10 jest to odstęp
    // z lewej strony diva info do lewej krawędzi mapy
    paddingTopLeft: [boxInfoWith + 10, 10]
  });
}

Aby wszystko zadziałało, musimy tą funkcję wywołać.

// uruchamiamy funkcję po załadowaniu HTML
window.addEventListener('DOMContentLoaded', fitBoundsPadding);

// uruchamiamy ponownie funkcję podczas zmiany szerokości mapy
// w ten sposób zazwyczaj stosuję do optymalizacji 'resize'
// jest optymalny nie ma 'miliona' wywołań funkcji 😉
let timeout;
window.addEventListener('resize', () => {
  clearTimeout(timeout);
  timeout = setTimeout(() => {
    fitBoundsPadding();
  }, 75);
}, false);

I to tak naprawdę tyle, całość jest poniżej.

See the Pen
leaflet fitBounds with padding
by Greg (@Tomik23)
on CodePen.

Polecam otworzyć codepen z przykładem w osobnym oknie i przetestować zmniejszenie/powiększenie okna.

Powiązane artykuły:

Alternatywa dla google maps – Open Street Map oraz Leaflet
Jak do Open Street Map i Leaflet dodać routing – OSRM
Użycie GeoJson z Leaflet
Dodawanie, przesuwanie i kasowanie markerów – Leaflet
Jak dodać kolorowe markery w postaci svg oraz legendę do map z leaflet