Minden webes térkép, amit valaha húzogattál — a Google Maps, az ételrendelős appod, egy túratervező — csempékből áll: apró, négyzet alakú térképdarabkákból, amiket a böngésző egyesével tölt le és illeszt össze. Ez az útmutató az egész gépezetet elmagyarázza: a csempepiramist, a raszter- és a vektorcsempe készítését, azt, hogyan rajzolja ki őket a Leaflet és a MapLibre, mit jelent a retina, miért a gyorsítótáron múlik minden, és mikor melyiket érdemes választani. Minden fejezethez tartozik egy élő példa, amit megnyithatsz és másolhatsz.
A webes térkép nagyítási szintek piramisa. A 0 szinten az egész világ elfér egyetlen 256×256 képpontos csempén. Minden szint mindkét irányban megduplázza a felbontást, tehát a csempék száma négyszereződik: az 1. szinten 4 csempe van, a 2.-on 16… a 19.-en pedig nagyjából 275 milliárd. Egy csempének három szám a címe — z/x/y, azaz nagyítás, oszlop, sor —, és pontosan ezt látod a csempe URL-jében is:
https://tilezza.eu/raster/voyager/12/2264/1432.png
└z┘ └─x─┘ └─y─┘
Amikor húzod vagy nagyítod a térképet, a térképkönyvtár kiszámolja, melyik csempékbe lóg bele a látómező (általában 6–16-ba), lekéri a hiányzókat, a többit pedig arrébb csúsztatja. Ez a trükk — a Google Maps találta ki 2005-ben, azóta „slippy map" néven szabvány — az oka, hogy egy egész bolygónyi térkép azonnalinak érződik: mindig csak azt a néhány négyzetet töltöd le, amit épp nézel.
A koordináták Web Mercator vetületben vannak (EPSG:3857). A sarkok közelében torzítja a területeket, cserébe van egy verhetetlen tulajdonsága: észak mindig felfelé van, és a négyzet minden nagyításon négyzet marad.
A rasztercsempe kész kép: egy 256×256-os PNG, amin a szerver már megrajzolta az utakat, a vizeket, a feliratokat, mindent. A böngészőnek nincs más dolga, mint képeket kirakni — számolnivaló nem marad.
OpenStreetMap data (planet, ODbL) → Protomaps build → one big .pmtiles archive (vector data, zooms 0–14) → tileserver-gl + MapLibre GL Native renders the style on the server (~0.3–1 s per tile) → nginx caches the finished PNG on disk for 30 days → every later request for that tile: ~0.6 ms (measured), like any static file
A drága lépés a kirajzolás. Ezért vár érezhetően az első látogató, aki a térkép egy addig nem nézett sarkába nagyít bele, és ezért kapja meg utána mindenki más azonnal ugyanazt a csempét — lásd lentebb a gyorsítótárat. És ezért visz el a raszter többet a havi keretedből, mint a vektor (3 egység az 1 helyett, lásd az árakat): a nehezét mi végezzük el.
A vektorcsempében (.mvt, Mapbox Vector Tile formátum) egyetlen képpont sincs. Tömör bináris csomag, amiben az adott négyzet geometriája és adatai vannak: az utak középvonala a besorolásukkal, az épületek alaprajza, a vízfelületek, a helynevek a fontossági rangjukkal. Úgy érdemes gondolni rá, mint a térkép adatbázisára, négyzetekre vágva.
A rajzolás a látogató böngészőjében történik, a videokártyán, egy stílusleírás alapján. Ez egy JSON-fájl, amiben az áll, hogy „az autópálya narancssárga és 4 képpont széles a 10. nagyításon, a városnevek Noto Sans 14 képpontosak…". Ugyanaz a csempe két stílus alatt teljesen máshogy néz ki, és a stílus menet közben is átváltható — a térképet nem kell újra letölteni.
| Alkatrész | Mi ez | A Tilezzán |
|---|---|---|
| Csempék | az .mvt adatnégyzetek | /tiles/{z}/{x}/{y}.mvt |
| Stílus-JSON | színek, vonalvastagságok, betűk, szabályok | /api/style/voyager (+10 more) |
| Betűatlasz | előre kirajzolt betűkészlet a feliratokhoz | /fonts/… self-hosted |
| Ikonlap | egyetlen kép, rajta az összes apró ikon | /sprites/… self-hosted |
| Megjelenítő | egy JS-könyvtár (MapLibre GL) | ezt is tőlünk kapod |
Mivel a munkát a böngésző végzi, a szervernek alig marad dolga: bájtokat továbbít egy archívumból. A vektorvégpontunk 1,8 ms medián idővel ad ki egy csempét, és szerény vason is bírja a másodpercenkénti 13 000 kérést. Ez a hatékonyság az oka, hogy az ingyenes csomag vektor-központú.
| Raszter (PNG) | Vektor (MVT + stílus) | |
|---|---|---|
| Ki rajzol | a szerverünk, egyszer, aztán gyorsítótárból | a látogató böngészője, minden képkockán |
| Mit kíván a klienstől | bármit, ami képet tud megjeleníteni | JS-könyvtár és WebGL (kb. 2016 óta minden telefon) |
| Nagyítás érzete | lépcsős, a szintek között kicsit életlen | folytonos, mindig éles |
| Forgatás, döntés | nincs | van |
| Átstílusozás, átszínezés | válassz egy másik kész stílust | bármi, menet közben, URL-ből |
| Feliratok nyelve | amilyenre kirajzoltuk | ?lang=de — te döntöd el |
| Sávszélesség | ~15–70 KB / csempe | ~5–50 KB / csempe + egyszeri betűkészlet |
| Beépítés munkája | 1 sor Leafletben | 2 script-hivatkozás + 3 sor |
| Mibe kerül nekünk | kirajzolás processzoron + gyorsítótár lemezen | szinte semmibe |
| Keret-súly (Tilezza) | 3 egység (retina 5) | 1 egység |
Egyik sem „jobb" a másiknál. A raszter a mindenhol működő, ráfordítást nem igénylő választás; a vektor a modern, rugalmas, olcsón kiszolgálható. A nagy lakossági térképek (Google, Apple, Mapboxra épülő appok) vektorosak; a beágyazott kis térképek, a levélbe tett térképképek, a nyomdai munkafolyamatok és a nagyon gyenge eszközökön ülő közönség viszont raszter.
A web legnépszerűbb térképkönyvtára. DOM- és Canvas-alapú, pehelysúlyú, több ezer bővítménnyel, és gyönyörűen egyszerű: egyetlen sor hozzáad egy raszterréteget. Vektorcsempét viszont nem tud magától kirajzolni — Leaflethez a raszteres végpontjainkat használd. Jó választás tartalmi oldalakhoz, műszerfalakhoz, bármihez, ami beágyazva él.
A Mapbox GL JS nyílt forrású utóda — akkor ágazott le, amikor a Mapbox 2020-ban lezárta a licencét. A vektorcsempét a videokártyán rajzolja ki WebGL-lel: folytonos nagyítás, forgatás, döntés, menet közbeni stílusozás, egymást elkerülő feliratok. Az „appszerű" térképek ezt használják. Jó választás termékekhez, SaaS-műszerfalakhoz, bármihez, ami interaktív.
A GIS-világ veterán igáslova. Gyakorlatilag minden valaha kitalált térinformatikai formátumot elolvas (WMS, WMTS, GeoJSON, KML, MVT…), és erős a vetületekben meg a tudományos-vállalati GIS-ben. A vektorcsempét Canvasra rajzolja: működik, de nem olyan vajsima, mint a GL. Jó választás GIS-nehéz alkalmazásokhoz, amelyek már amúgy is az OpenLayers világában élnek.
Mind a három működik a Tilezzával: rasztert bármelyikkel használhatsz, vektorhoz a MapLibre a legjobb — lásd a MapLibre gyorsindítást.
A mai telefonkijelzők 2–3 fizikai képpontot zsúfolnak minden CSS-képpontba. Egy sima, 256 képpontos csempe ilyenkor megnyúlik, és kissé lágynak látszik. A @2x csempe ugyanarra a földrajzi négyzetre 512×512-es méretben készül, így a feliratok borotvaélesek maradnak. Az ára: nagyjából 3–4-szer annyi bájt és kétszer annyi kirajzolási munka — ezért ér 5 egységet, és ezért csak a fizetős csomagokban van. Leafletben szó szerint egyetlen kapcsoló: detectRetina: true (5. példa). A vektortérképnek minderre nincs szüksége: eleve a kijelző saját felbontásán rajzol — még egy pont a vektornak mobilon.
A csempekiszolgálás gyorsítótár-játék. A piramis irdatlan nagy, a látogatók viszont ugyanoda csoportosulnak: városközpontokra a 10–16. szinten, egész országokra a 6–8.-on. Három gyorsítótár-réteg dolgozik érted:
A böngésző gyorsítótára — Cache-Control: public, max-age=604800 fejlécet küldünk, így a visszatérő látogató semmit nem tölt le újra. A mi lemezes gyorsítótárunk — minden kirajzolt rasztercsempét kb. 30 napig megőrzünk; mérve: a hideg kirajzolás 0,3–1 másodperc, a gyorsítótárból kiszolgált csempe 0,6 ezredmásodperc — ez ezerszeres különbség. A te CDN-ed (ha akarod) — tehetsz saját CDN-t a Tilezza elé; amit az a saját gyorsítótárából ad ki, az el sem jut hozzánk, és nem kerül semmibe. Csak azokat a kéréseket számoljuk, amelyek megérkeznek a szervereinkre — ez így, írásban is a mérési szabályunk.
Raszternél 11 kész stílus közül választasz (10 raszteres + a csak vektorban elérhető indigo). Vektornál ugyanezek a stílusok kiindulópontok lesznek: a színeket egyenesen a stílus URL-jében írod felül, építési lépés nélkül:
https://tilezza.eu/api/style/voyager?key=YOUR_KEY
&water=0088ff ← any layer color (water, land, parks, forest,
&boundaries=cc3355 roads, highway, buildings, boundaries, labels)
&labels=333333
&lang=de ← label language
&font=Montserrat ← label typeface (self-hosted glyphs)
&hide_pois=1 &lite=1 ← decluttering / mobile mode
Az URL-paramétereken túl a MapLibre menet közben bármit átállít (map.setPaintProperty('water','fill-color','#004')). Ezt a különbséget érdemes megjegyezni: raszternél kiválasztod a kinézetet, vektornál a tiéd a kinézet. Élőben a 3. példában játszhatsz vele.
Minden csempekérés elviszi a látogató IP-címét és a hivatkozó oldalt annak, aki a csempét kiszolgálja. Ha a térképed amerikai kézben lévő CDN-ről tölti a csempét, a betűket vagy magát a térképkönyvtárat, akkor a látogatóid adatai már azelőtt átlépik a joghatóságot, hogy az oldalad betöltene. Pontosan ezt marasztalták el az európai adatvédelmi hatóságok a Google Fonts-ügyekben.
A Tilezza válasza szándékosan unalmas: minden saját forrásból, minden az EU-ban. A csempék, a stílusok, a betűatlaszok, az ikonlapok — sőt a JS-könyvtárak is — egyetlen, EU-ban üzemeltetett kiszolgálóról jönnek. A hozzáférési naplóinkban tervezetten nincs IP-cím (nem szivároghat ki, amit el sem tárolunk), és nincs olyan harmadik feles kérés, amit fel kellene sorolnod az adatkezelési tájékoztatódban.
A legtöbb térképes oldalon az utolsó megmaradt külső kérés maga a könyvtár (unpkg, jsDelivr, cdnjs — mind amerikai kézben). Ezt is megspórolhatod: mindkét könyvtárból rögzített verziójú, változatlan másolatot szolgálunk ki. Másold be, és az oldalad egyetlen EU-n kívüli kérést sem indít:
<!-- Leaflet 1.9.4 (raster maps) --> <link rel="stylesheet" href="https://tilezza.eu/lib/leaflet-1.9.4.css"> <script src="https://tilezza.eu/lib/leaflet-1.9.4.js"></script> <!-- MapLibre GL 5.6.0 (vector maps) --> <link rel="stylesheet" href="https://tilezza.eu/lib/maplibre-gl-5.6.0.css"> <script src="https://tilezza.eu/lib/maplibre-gl-5.6.0.js"></script>
Verziószámos fájlnevek, hosszú és változatlan gyorsítótárazás, nyitott CORS. A Leaflet alapértelmezett jelölőképei is benne vannak (/lib/images/…). Az új verziókat új néven tesszük ki — a rögzített URL-ed alatt sosem változik meg a viselkedés.
| A te helyzeted | Ezt használd |
|---|---|
| „A lehető legkevesebb munkával akarok térképet az oldalamra" (blog, kapcsolat oldal, WordPress) | Raszter + Leaflet — öt sor, és kész |
| Termék vagy műszerfal, interakcióval és saját márkaszínekkel | Vektor + MapLibre + stílus-API |
| Nagyon régi vagy gyenge eszközökön ülő közönség | Raszter |
| Főleg mobilos közönség, és számít az élesség | Vektor (a kijelző saját felbontásán rajzol) |
| Meglévő GIS-rendszer, egzotikus vetületek, WMS-szomszédok | OpenLayers (raszter vagy vektor) |
| Ingyenes csomag, a legtöbb érték | Vektor — csempénként 1 egység, mind a 11 stílus, teljes nagyítási tartomány |
Kérek ingyenes API-kulcsot Megnézem az élő példákat
Olyan rasztercsempékbe futottál, amik még nincsenek a gyorsítótárban: a szervernek egyesével ki kell rajzolnia őket (0,3–1 másodperc darabja). Az eredmény hetekig megmarad, tehát ez az első látogató költsége, és a ritkán nézett területekre koncentrálódik. A vektorcsempénél ez a gond nem létezik.
Nem: kell egy megjelenítő (MapLibre vagy OpenLayers), ami fut a böngészőben. Ha nem tudsz szkriptet elhelyezni, használj rasztercsempét — az sima képként is működik.
Igen. A végpontok szabványosak: XYZ raszterhez, TileJSON+MVT vektorhoz. A QGIS, a MapLibre Native (iOS és Android) és a legtöbb SDK közvetlenül elfogadja őket az API-kulcsoddal.
Minden csempekérés, ami eljut a szervereinkig, a kiszolgálás költsége szerint súlyozva: vektor 1, raszter 3, retina 5 egység. Amit a saját CDN-ed ad ki a gyorsítótárából, az ingyen van. A részletek az árak oldalon — vagy nézd meg élőben a forgalommérőn.
Az OpenStreetMap közreműködőitől (ODbL licenc), a Protomaps folyamatán átcsomagolva, havonta frissítve. A forrásmegjelölés minden stílusba bele van építve — kérjük, hagyd láthatóan.