Az OpenLayers egy nyílt forráskódú kliens oldali JavaScript függvénykönyvtár, melynek segítségével különféle forrásokból származó térképi adatok jeleníthetők meg interaktív térképként weboldalakon. Az OpenLayers első változatát a MetaCarta nevű amerikai cég fejlesztette ki 2006-ban. 2007 novemberétől a projektet átvette az Open Source Geospatial Foundation (OSGeo).
Az alábbi segédlet feltételezi, hogy az olvasónak vannak legalább minimális JavaScript ismeretei.
Fontos megjegyezni, hogy az OpenLayers csak az adatok megjelenítését végzi, ezért önmagában nem sokat ér: mindenképpen szükség van a háttérben valamilyen adatforrásra. Ez utóbbi rendkívül sokféle lehet: egy egyszerű raszteres képtől kezdve különféle WMS, TMS szervereken keresztül különféle vektoros adatszolgáltatókig rengeteg lehetőség akad.
Az OpenLayers weboldala, dokumentációval, és letölthető anyagokkal
Az OpenLayers kódjait kétféleképpen használhatjuk: vagy letöltjük a szükséges fájlokat szerverünkre, vagy csak linkeljük az openlayers.org-on található script fájlt. Ez utóbbinak előnye, hogy mindig a legfirssebb változattal fogunk dolgozni, hátránya viszont, hogy az oldalaink lassabban töltődnek be, illetve, hogy a térképünk teljesen használhatatlan lesz, ha valami miatt az openlayers.org nem elérhető.
<!DOCTYPE html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>OpenLayers térkép</title> <script src="http://openlayers.org/api/OpenLayers.js"></script> <script type="text/javascript"> function init() // az oldal betöltésekor végrehajtandó függvény { // létrehozzuk a térképet a 'terkep_helye' azonosítójú div elemben var map = new OpenLayers.Map('terkep_helye', {}); // létrehozunk egy OSM réteget és hozzáadjuk a térképhez map.addLayer(new OpenLayers.Layer.OSM()); // kb. Magyarországra nagyítunk map.zoomToExtent(new OpenLayers.Bounds(1790000,5730000,2560000,6210000)); } </script> </head> <body onload="init()"> <h1>OpenLayers térkép</h1> <div style="width:650px; height:400px" id="terkep_helye"></div> </body> </html>
0. példa - OSM térkép OpenLayers kezelőfelülettel.
<!DOCTYPE html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>OpenLayers - egyszerű térkép</title> <script src="http://openlayers.org/api/OpenLayers.js"></script> <script type="text/javascript"> function init() // az oldal betöltésekor végrehajtandó függvény { // létrehozzuk a térképet a 'terkep_helye' azonosítójú div elemben var map = new OpenLayers.Map('terkep_helye', {} ); // létrehozunk egy WMS réteget var wms = new OpenLayers.Layer.WMS( "OSGeo WMS", 'http://vmap0.tiles.osgeo.org/wms/vmap0', {layers: ['basic','priroad','secroad']}, {}); // hozzáadjuk a réteget a térképhez map.addLayer(wms); // kb. Magyarországra nagyítunk map.zoomToExtent(new OpenLayers.Bounds(17,46,22,49)); } </script> </head> <body onload="init()"> <h1>OpenLayers - egyszerű térkép</h1> <div style="width:600px; height:400px" id="terkep_helye"></div> </body> </html>
A térképet a weboldalon egy <div>
elem fogja tartalmazni.
Ezt definiálnunk kell a html dokumentumban. Fontos megadnunk a térkép méretét (a style
tulajdonságban) és az elem azonosítóját (id
), ami jelen esetben "terkep_helye".
A térképes weboldal lelke a térképet megjelenítő JavaScript kód lesz, ami két részből áll:
http://openlayers.org/api/OpenLayers.js
címről linkelünk be; init()
nevű függvényben helyezünk el,
amely függvényt a weboldal betöltésekor automatikusan végrehajt a böngésző, a <body>
tagben elhelyezett onload="init()"
eseménykezelő miatt.
Az init()
függvényben először létrehozunk egy OpenLayers.Map
objektumot; ez lesz maga a térkép.
Az objektumkonstruktor két paramétert vár: a térképet tartalmazó <div>
elem id
-jét, valamint egy objektumot, amelyben különféle kulcs:érték
párokkal a térkép működését befolyásoló további paramétereket lehet megadni. (Ebben a példában ez az objektum üres.)
Ha a térképszolgáltató szerver ezt lehetővé teszi, a térképünk vetületét is meghatározhatjuk. A következő példában a térképet MapServer adja, vektoros alapanyagból dolgozva. Így semmi akadálya annak, hogy a legkülönfélébb vetületekben készüljön az általa küldött raszteres kép.
... function init() // az oldal betöltésekor végrehajtandó függvény { // létrehozzuk a térképet a 'terkep_helye' azonosítójú div elemben var map = new OpenLayers.Map('terkep_helye', { projection: "EPSG:23700", // Az EPSG:23700 az EOV kódja maxExtent: new OpenLayers.Bounds(400000,45000,950000,380000), // Nem földrajzi, hanem vetületi koordinátákat használunk maxResolution: 1000, // zoom=0 esetén 1 pixel 1000 méter legyen. units: "m" } ); // létrehozunk egy WMS réteget var wms = new OpenLayers.Layer.WMS( "MapServer mintatérkép", 'http://wms.elte.hu/cgi-bin/mapserv?map=/home/saman/mapserver/p1.map', { layers: ['megye'], format: 'image/png' }, { singleTile: true }); // hozzáadjuk a réteget a térképhez map.addLayer(wms); // kb. Magyarországra nagyítunk map.zoomToMaxExtent(); } ...
1a. példa - egyszerű térkép, más vetületben
Lehetőségünk van arra is, hogy több, különféle forrásból származó réteget jelenítsünk meg egy térképen.
Ekkor fontos elkülöníteni a "base layer" típusú rétegeket, melyekből egyszerre csak egy jeleníthető meg (az, hogy melyik, azt interaktívan is kiválaszthatjuk pl. egy LayerSwitcher
control segítségével), és a "overlay" rétegeket.
Egy réteg akkor lehet "overlay", ha az isBaseLayer
tulajdonsága false
és a transparent
tulajdonsága true
.
Természetesen csak akkor kerülhet egymésra két réteg, ha azonos a vetületük.
Az alábbi példában egy OSM típusú réteget is létrehozunk, mely az OpenStreetMap térképét tartalmazza. Ennek vetülete az ún. Spherical Mercator. Mivel ez a réteg csak ebben a vetületben jeleníthető meg, a vele együtt használt többi rétegnek is ebben kell lennie.
Figyeljük meg ezen kívül a LayerSwitcher
control hozzáadásának módját.
... function init() // az oldal betöltésekor végrehajtandó függvény { // létrehozzuk a térképet a 'terkep_helye' azonosítójú div elemben var map = new OpenLayers.Map('terkep_helye', { projection: "EPSG:3857", // EPSG:3857 = Spherical Mercator maxExtent: new OpenLayers.Bounds(1800000,5700000,2600000,6300000) }); // hozáadunk egy OSM réteget map.addLayer(new OpenLayers.Layer.OSM()); // létrehozunk egy WMS réteget var wms = new OpenLayers.Layer.WMS( "vasutak", 'http://mercator.elte.hu/cgi-bin/mapserv?map=/home/oktatok/saman/public_html/mapserver/vonat/mo.map', { layers: ['vasut'], isBaseLayer: false, transparent: true }, {}); // hozzáadjuk a réteget a térképhez map.addLayer(wms); // a LayerSwitcher kezelőszerv segítsével kapcsolgathajuk a rétegeket map.addControl(new OpenLayers.Control.LayerSwitcher); // kb. Magyarországra nagyítunk map.zoomToExtent(new OpenLayers.Bounds(1800000,5700000,2600000,6300000)); } ...
2. példa - több réteg egy térképen
Használhatjuk az OpenLayersben a Google Mapsből ismert különféle rétegeket is. Ehhez azonban be kell linkelnünk a Google Maps JS API-t is.
... <!-- Google Maps 3 JS API - ez is kell, ha Google térképi rétegeket akarunk használni --> <script src="http://maps.google.com/maps/api/js?v=3.2&sensor=false"></script> <script type="text/javascript"> function init() // az oldal betöltésekor végrehajtandó függvény { // létrehozzuk a térképet a 'terkep_helye' azonosítójú div elemben var map = new OpenLayers.Map('terkep_helye', {}); // rétegek hozzáadása // Google hybrid map.addLayer(new OpenLayers.Layer.Google("Google Hybrid",{type: google.maps.MapTypeId.HYBRID, numZoomLevels: 22})); // Google satellite map.addLayer(new OpenLayers.Layer.Google("Google Satellite",{type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22})); // Google roadmap map.addLayer(new OpenLayers.Layer.Google("Google Road Map",{type: google.maps.MapTypeId.ROADMAP, numZoomLevels: 22})); // Google terrain map.addLayer(new OpenLayers.Layer.Google("Google Terrain",{type: google.maps.MapTypeId.TERRAIN, numZoomLevels: 22})); // OSM réteg map.addLayer(new OpenLayers.Layer.OSM()); // egyebek // a LayerSwitcher kezelőszerv segítsével kapcsolgathajuk a rétegeket map.addControl(new OpenLayers.Control.LayerSwitcher()); // kb. Magyarországra nagyítunk map.zoomToExtent(new OpenLayers.Bounds(1790000,5730000,2560000,6210000)); } </script> ...
2/g. példa - Google rétegek a térképen
Egy érdekes rétegtípus a GeoRSS. Ennek segítségével nagyon egyszerűen megjeleníthetünk GeoRSS forrásból származó információkat.
A GeoRSS megjelenítéséhez a JavaScriptnek egy másik szerveren lévő XML fájlt kellene olvasnia, amit biztonsági okokból nem tehet meg.
Ennek kiküszöbölésére a saját szerverünkön el kell helyezni egy egyszerű proxy-t, ami közvetíti majd az információt.
A proxy címét az OpenLayers.ProxyHost
változóban adhatjuk meg.
... // ha külső forrásból (nem az oldalt tartalmazó szerverről) akarunk XML vagy egyéb fájlt beolvasni, akkor proxyra van szükség OpenLayers.ProxyHost = "/ol/xmlproxy.php?url="; ... // létrehozunk egy GeoRSS réteget georss = new OpenLayers.Layer.GeoRSS( '', 'http://earthquake.usgs.gov/earthquakes/catalogs/1day-M0.xml', { icon: new OpenLayers.Icon('img/earthquake.png',{w:32,h:32},{x:-16,y:-16}), popupSize: new OpenLayers.Size(180,300) }); // hozzáadjuk a réteget a térképhez map.addLayer(georss); ...
2/b. példa - több réteg egy térképen - GeoRSS réteggel
Ha a szerverünkön van php értelmező, akkor a proxy nagyon egyszerűen megoldható. Esetünkben az xmlproxy.php
fájl tartalma ennyi:
<?php print file_get_contents($_GET['url']); ?>
Az eseménykezelés lényege, hogy bizonyos események megtörténtekor (pl. egérkattintás, nagyítási fokozat megváltozása, stb.) végrehajtódik egy erre a célra emgírt függvény. A függvény rendszerint megkapja paraméterként az esemény részleteit leíró adatokat (általában egy ún. esemény-objektum formájában).
A egyes OpenLayers objektumokhoz azok events.register()
metódusával tudunk eseménykezelőt rendelni.
Fontos megjegyezni, hogy amennyiben az eseményhez pozícióadat is tartozik (egér események), az mindig a térképet tartalmazó div
elem koordinátarendszerében értendő.
Ezt a térkép getLonLatFromPixel()
metódusával számíthatjuk át a térkép aktuális vetületének rendszerébe.
A különböző vetületi és/vagy földrajzi koordináta-rendszerek közti átszámításhoz létre kell hoznunk egy-egy OpenLayers.Projection
objektumpéldányt, a forrás és a cél rendszer beállításaival.
Ha a Spherical Mercator (EPSG:3857) és WGS84 lat/lon (EPSG:4326) közöttt számítunk át, másra nincs is szükség. Más vetületek esetén a proj4.js függvénykönyvtárt használhatjuk, vagy akár saját kezűleg is definiálhatjuk a transzformációs függvényeket.
... var wgs84=new OpenLayers.Projection('EPSG:4326'); var merc=new OpenLayers.Projection('EPSG:3857'); ... map.events.register("click", map, function(e) { // a kattintás helye a térképet tartalmazó div-ben var pxPos=map.events.getMousePosition(e); // átszámítva az aktuális vetületi rendszerbe var projPos=map.getLonLatFromPixel(pxPos); // átszámítva földrajzi koordinátákra var geoPos=projPos.clone().transform(merc,wgs84); alert("A kattintás helye\n - A dobozban: "+pxPos+"\n - Mercator-vetületben: "+projPos+"\n - WGS-84-ben: "+geoPos); }); ...
3. példa - kattintásra koordináták kiírása
A különféle objektumok más és más eseményeket tudnak kiváltani. Ezek közül a leggyakrabban használtak a következők:
Egér események: ezek szinte minden, a képernyőn megjelenő elemhez hozzárendelhetők.
A különböző rétegekhez tartozó események:
A Marker layer az egyik legegyszerűbb rétegtípus: pontokat helyezhetünk el rajta, melyeket valamilyen ikon jelöl.
A Marker layer konstruktorának első paraméter a réteg neve. Ezen kívül lehet még egy második paraméter is, ami egy objektum a kezdeti beállításokkal.
A réteg addMarker()
függvénye sgítségével helyezhetünk el pontokat. A következő példában minden egérkattintással lerakunk egy markert:
... // csinálunk egy marker layert var markers=new OpenLayers.Layer.Markers("pontok"); map.addLayer(markers); ... map.events.register("click", map, function(e) { // a kattintás helye a térképet tartalmazó div-ben var pxPos=map.events.getMousePosition(e); // átszámítva az aktuális vetületi rendszerbe var projPos=map.getLonLatFromPixel(pxPos); // új marker var m=new OpenLayers.Marker(projPos); markers.addMarker(m); }); ...
4. példa - kattintásra marker elhelyezése
A Marker layer lehetőségei meglehetősen korlátozottak (nem jeleníthetünk meg neveket a jelzők mellett, stb.), emiatt a legtöbb esetben célszerűbb a Vector layer alkalmazása pontszerű elemekkel.
A Vector layeren bármilyen vektoros rajz elhelyezhető. A rajzi elemek lehetnek pontok, vonalak, felületek is.
A layer elemei OpenLayers.Feature.Vector
objektumok.
Ezek az elemek a geometriai adatokon kívül attribútumokat és stílusadatokat is tartalmazhatnak.
A következő példában ismét pontokat helyezhetünk el az egérrel, ezeknek a pontoknak azonban címkéjük is van,
és a DragFeature
control segítségével azok át is helyezhetők.
... // csinálunk egy vector layert var pontok=new OpenLayers.Layer.Vector("pontok"); var dragControl=new OpenLayers.Control.DragFeature(pontok); map.addControl(dragControl); dragControl.activate(); map.addLayer(pontok); // kb. Magyarországra nagyítunk map.zoomToExtent(new OpenLayers.Bounds(1800000,5700000,2600000,6300000)); map.events.register("click", map, function(e) { // a kattintás helye a térképet tartalmazó div-ben var pxPos=map.events.getMousePosition(e); // átszámítva az aktuális vetületi rendszerbe var projPos=map.getLonLatFromPixel(pxPos); // új point feature létrehozása a kattintás helyére var m=new OpenLayers.Feature.Vector( new OpenLayers.Geometry.Point(projPos.lon, projPos.lat), {}, { externalGraphic: 'http://openlayers.org/api/img/marker.png', graphicHeight: 21, graphicWidth: 16, graphicYOffset: -21, label: ++markerCnt+'. pont', labelAlign: 'lb', fontWeight: 'bold', fontColor: 'purple', labelXOffset: 6 }); pontok.addFeatures(m); }); ...
5. példa - áthelyezhető pontok elhelyezése kattintásra egy Vector layeren
OpenLayers.Feature.Vector
objektumok szerkezeteAz OpenLayers.Feature.Vector
objektum vektoros elemek leírására szolgál. Ennek megfelelően a következő fő részei vannak:
geometry | Az elem geometriája, egy OpenLayers.Geometry objektum, vagy annak valameyik "származéka". |
|
attributes | Az elem attribútumai, JavaScript objektumként. (pl.: { nev: "Érd", ir_szam: 2030} ) |
|
style | Az elem stílusa, egy OpenLayers.Style objektum |
Egy vector réteget feltölthetünk különböző forrásokból származó elemekkel is.
Ehhez meg kell adnunk a réteg protocol
tulajdonságát. Ennek értéke egy OpenLayers.Protocol.*
objektum
(a * helyén a használt forrástól függően más és más állhat), amelyben meghatározzuk a vector rétegre kerülő elemek forrását, és a szükséges paramétereket.
A protokollon kívül meg kell még adni a strategies
tulajdonságot is, mely egy tömb; a tömb minden eleme egy OpenLayers.Strategy.*
objektum.
Ez határozza meg, hogy milyen szabályok szerint kérjen az OpenLayers elemeket a rétegre.
A Vector layert benépesíthetjük pl. WFS szolgáltatás adataival. Ekkor az OpenLayers.Protocol.WFS
-t kell használnunk.
Ebben megadjuk a WFS szolgáltató URL-jét, a kért elemek típusát (a MapServer által szolgáltatott WFS esetében ez valamelyik LAYER
neve), a vetületet, valamint azt, hogy milyen attribútumadatokat várunk az egyes elemekhez.
Itt MapServer használatakor az msGeometry
jelenti magát az elemet.
A következő példában ezen kívül alkalmazzuk a SelectFeature
controlt is,
melynek segítségével egyszerűen kijelölhetők elemek egy vector layeren, és a kijelöléshez eseménykezelőket is definiálhatunk.
Ebben a példában egy kis segédfüggvény (dump()
) segítségével kiíratjuk a kijelölt elem attribútumait.
... // csinálunk egy wfs layert... var wfs=new OpenLayers.Layer.Vector( "WFS próba", { isBaseLayer: true, strategies: [new OpenLayers.Strategy.BBOX()], protocol: new OpenLayers.Protocol.WFS( { version: "1.0.0", url: "http://wms.elte.hu/cgi-bin/mapserv?map=/home/saman/mapserver/p2wfs.map", featureType: "Megye_nepesseg", srsName: "EPSG:23700", propertyNames: ['msGeometry','Nev','Nepesseg','Gyermek','Felnott','Idos'] }) }); // és hozzáadjuk a térképhez map.addLayer(wfs); // hozzáadunk egy SelectFeature controlt. Ezzel egyszerűen kijelölhetők elemek a vektoros rétegen var sfc=new OpenLayers.Control.SelectFeature(wfs, { toggle: true, // az elemre kattintás ki-be kapcsolja a kijelölést onSelect: function(feature) { dump(feature.attributes); } // eseménykezelő - kiiratjuk az elem tulajdonságait }); map.addControl(sfc); // aktiváljuk a SelectFeature controlt sfc.activate(); ... ... function dump(o) // a paraméterként kapott objektum tulajdonságait kiírja az 'info' nevű divben { var d=document.getElementById('info'); var s=''; for(i in o) s+=i+': '+o[i]+'; '; d.innerHTML=s; } ...
6. példa - Vector layer WFS adatokkal
6c. példa - Vector layer WFS adatokkal feljavítva
MÁV vasútvonalak WFS adatokkal
Ebben a példában az OpenLayers.Protocol.HTTP
-t használjuk az OpenLayers.Format.KML
-lel.
Míg az előbbi a HTTP-n keresztül való fájlbetöltést, az utóbbi a KML adatok értelmezését végzi:
... // csinálunk egy vector layert... kml=new OpenLayers.Layer.Vector( "Túraútvonal", { isBaseLayer: false, strategies: [new OpenLayers.Strategy.Fixed()], protocol: new OpenLayers.Protocol.HTTP( { url: "data/utvonal.kml", format: new OpenLayers.Format.KML() }), style: { strokeWidth: 3, strokeColor: "#FF0000" } }); // és hozzáadjuk a térképhez map.addLayer(kml); map.addControl(new OpenLayers.Control.LayerSwitcher()); // kb. a célterületre nagyítunk map.zoomToExtent(new OpenLayers.Bounds(2108000,6020000,2115000,6025000)); ...
6/x. példa - Vector layer KML adatokkal
A fenti példában nem vesszük át a KML fájlban található stílusbeállításokat, hanem egy egységes vonalstílust definiálunk az egész rétegnek.
Ha inkább a KML fájl stílusait szeretnénk használni, akkor állítsuk be a extractStyles: true
opciót a KML formátum objektumnál, és ne írjuk felül a stílusokat:
... kml=new OpenLayers.Layer.Vector( "Túraútvonal", { isBaseLayer: false, strategies: [new OpenLayers.Strategy.Fixed()], protocol: new OpenLayers.Protocol.HTTP( { url: "data/utvonal.kml", format: new OpenLayers.Format.KML({ extractStyles: true } ) }) }); ...
Az Image layer az egyik legegyszerűbb rétegtípus: egy raszteres képet helyezünk el egy téglalap alakú területen. A kép valamilyen szabványos webes formátumban legyen (jpg, png vagy gif).
Az OpenLayers.Layer.Image
konstruktorfüggvény paraméterei sorban:
a réteg neve, a képfájl URL-je, a kép kiterjedése annak vetületi koordináta-rendszerében, a kép mérete pixelekben, és az esetleges további beállítások.
... var img = new OpenLayers.Layer.Image( "Raszteres térkép", 'http://mercator.elte.hu/~saman/webglobes/globe_greenwich.jpg', new OpenLayers.Bounds(-180, -90, 180, 90), new OpenLayers.Size(3600,1800), { numZoomLevels: 6, maxResolution: 0.4 }); ...
Bár az OpenLayers lehetőséget ad arra, hogy a különféle objektumoknál megadjuk azok vetületét, jelenleg csak az alapértelmezett WGS84 lat/lon és a Google-féle gömbi Mercator-vetület van képletekkel is definiálva.
Ez akkor okoz problémát, ha a különféle vetültetek között koordináta-átszámítást kell végeznünk.
Ilyenkor két lehetőségünk van: felhasználjuk a proj4.js
függvénykönyvtárat, vagy sajátkezűleg definiálunk vetületet, az átszámítási függvények megírásával.
A proj4.js
használatához először le kell töltenünk és el kell helyeznünk a használandó JavaScript fájlt a szerverünkön.
Emellett szükségünk lesz a használandó vetületek proj.4 formátumú definíciójára, és már használhatjuk is őket.
A következő példában WGS84-es földrajzi, gömbi Mercator és EOV koordináták között lehet átszámítani:
<!DOCTYPE html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>proj4.js - vetületi átszámítások</title> <script src="proj4js/lib/proj4js.js"></script> <script src="http://openlayers.org/api/OpenLayers.js"></script> <script type="text/javascript"> // EOV vetület proj4-es definíciója. Figyelem: az EPSG adatbázisban hibásan szerepel, a dátumtranszformáció hiányzik belőle! Proj4js.defs["EPSG:23700"] = "+title=Hungarian EOV EPSG:23700 +proj=somerc +lat_0=47.14439372222222 +lon_0=19.04857177777778 +x_0=650000 +y_0=200000 +ellps=GRS67 +datum=HD72 +towgs84=57.01,-69.97,-9.29 +units=m +no_defs" // létrehozunk egy-egy vetület objektum példányt a használandó vetületekhez var w=new OpenLayers.Projection("EPSG:4326"); var g=new OpenLayers.Projection("EPSG:900913"); var e=new OpenLayers.Projection("EPSG:23700"); // az átszámítást irányító függvény function szamit(form,p) { if (p=='wgs84') { var pt=new OpenLayers.Geometry.Point(form.la.value,form.fi.value); var proj=w; } else if (p=='google') { var pt=new OpenLayers.Geometry.Point(form.gx.value,form.gy.value); var proj=g; } else { var pt=new OpenLayers.Geometry.Point(form.ex.value,form.ey.value); var proj=e; } var p1=pt.clone().transform(proj,w); var p2=pt.clone().transform(proj,g); var p3=pt.clone().transform(proj,e); with(form) { fi.value=p1.y.toFixed(6);la.value=p1.x.toFixed(6); gx.value=p2.x.toFixed(1);gy.value=p2.y.toFixed(1); ex.value=p3.x.toFixed(1);ey.value=p3.y.toFixed(1); } } </script> </head> <body> <h1>proj4.js - vetületi átszámítások</h1> <form> <table> <tr> <td> WGS84 latlon<br/> Φ: <input type="text" name="fi"/> Λ: <input type="text" name="la"/><br/> <input type="button" value="Átszámít" onclick="szamit(this.form,'wgs84')" /> </td> <td> Google Mercator<br/> x: <input type="text" name="gx"/> y: <input type="text" name="gy"/><br/> <input type="button" value="Átszámít" onclick="szamit(this.form,'google')" /> </td> <td> EOV<br/> x: <input type="text" name="ex"/> y: <input type="text" name="ey"/><br/> <input type="button" value="Átszámít" onclick="szamit(this.form,'eov')" /> </td> </tr> </table> </form> </body> </html>
Ha a vetületi egyenletet saját magunk akarjuk definiálni, akkor meg kell adnunk egy másik (általában WGS84 latlon) rendszerbe való átszámítás oda-vissza egyenleteit a OpenLayers.Projection.addTransform
függvény segítségével.
Az átszámításokat egy-egy függvény végzi, melynek egyetlen paramétere egy point
objektum, mely az átszámítandó koordinátákat tartalmazza.
A http://www.sat24.com/image2.ashx?region=hu címen található műholdkép vetülete például a meteorológiában gyakran használt metsző sztereografikus vetület, 60°-os metsző szélességgel és 10°-os kezdőmeridiánnal.
Az ehhez való átszámítás definíciója:
... var rad=Math.PI/180; // fok/radián váltószám var R=6378137; // közepes földsugár var c=1+Math.sqrt(3)/2; // c=1+sin(60°) ... // vetületi transzformáció definiálása a metsző sztereografikus vetülethez (la0=10) OpenLayers.Projection.addTransform("EPSG:4326","meteo_stereo", function (point) { var fi=point.y; var la=point.x-10; var ro,x,y; with(Math) { ro=c*tan(PI/4-fi*rad/2); point.x=R*ro*sin(la*rad); point.y=-R*ro*cos(la*rad); } return point; }); // inverz vetületi transzformáció definiálása a metsző sztereografikus vetülethez (la0=10) OpenLayers.Projection.addTransform("meteo_stereo","EPSG:4326", function (point) { var x=point.x,y=point.y; with(Math) { ro=sqrt(x*x+y*y); if (ro==0) la=0; else la=acos(-y/ro)*sign(x)/rad; la+=10; if (la>180) la-=360; point.x=la; point.y=(PI/4-atan(ro/R/c))/rad*2; } return point; }); ...
Az OpenStreetMap Nominatim nevű szolgáltatásával egyszerűen geokódolhatunk bármilyen címet, vagy rendelhetünk címet egy koordinátapárhoz. Mindkét irányú művelet http-kérés kiadásával történik.
Az szolgáltatást kétféleképpen tudjuk használni JavaScriptben:
XMLHttpRequest
objektumával egyszerűen kiadhatunk http-kéréseket és fogadhatjuk az arra kapott választ.
Biztonsági okokból azonban ilyen kéréseket mindig csak a helyi szervernek küldhetünk, emiatt szükség van egy proxy-ra a szerveren, mely továbbítja a kéréseket külső szerver felé.
Erre a célra is alkalmazható pl. a http://mercator.elte.hu/~saman/hu/okt/ol/xmlproxy.php?url=
egyszerű php-proxy.
A válasz feldolgozása történhet szinkron vagy aszinkron módon (azaz a script futása leáll, amíg meg nem jön a válasz, vagy egy callback függvény hívódik meg a válasz befutásakor).
... var xmlhttp; // a http-kérésekhez if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } function geokodol(hely) // geokódoló kérést küldünk a Nominatimnak { if (hely=='') return; xmlhttp.open("GET",'/~saman/hu/okt/ol/xmlproxy.php?url=http://nominatim.openstreetmap.org/search?q='+hely+'%26format=json',false); xmlhttp.send(); var valasz=eval('('+xmlhttp.responseText+')'); if (valasz[0]) // ha van legalább egy eredmény... alert(valasz[0].display_name) else // ha nincs eredmény alert('Nincs találat.'); } ...
script
node-ot, amilynek src
tulajdonságának a geokódoló kérés URL-jét állítjuk be.
Ebben az esetben fontos, hogy a választ JSON formában kérjük, és állítsuk be a json_callback
paraméterben a callback függvény nevét.
Ezzel a módszerrel kikerülhető az előbb említett biztonsági korlát, viszont csak aszinkron módon dolgozható fel a válasz.... function geokodol(hely) // geokódoló kérést küldünk a Nominatimnak { if (hely=='') return; var s=document.createElement('script'); s.src='http://nominatim.openstreetmap.org/search?q='+hely+'&format=json&json_callback=helyetMutat'; document.body.appendChild(s); } function helyetMutat(valasz) { if (valasz[0]) alert(valasz[0].display_name) else // ha nincs eredmény alert('Nincs találat.'); } ...
A térképünkhöz rengeteg, előre definiált eszközt adhatunk. Ezek közös neve Control. A leggyakrabban használt eszközök a következők:
Az OpenLayers.Control.LayerSwitcher
segítségével ki-be kapcsolgathatjuk a térkép rétegeit. Példa
Ha egy réteget nem akarunk látni a LayerSwitcherben, akkor az adott réteg tulajdonságainál szerepeljen a következő: displayInLayerSwitcher: false
A kezelőszerv "Base Layer" és "Overlays" szövegeit kicserélhetjük a létrehozott LayerSwitcher objektum baseLbl.innerHTML
és layerSwitcher.dataLbl.innerHTML
elemeinek átállításával.
Ezek, és további beállítások is láthatók ebben a példában.
kiírja a térkép sarkában az egérmutató koordinátáit Példa
Fontosabb beállítható tulajdonságok:
prefix, separator, suffix
: az első koordináta elé, a kettő közé és a második után kerülő szövegek.
Pl. a { prefix:'Lon:', separator:'°, lat:', suffix:'°' }
beállítás eredményeképpen a megjelenített formátum: Lon: 19.1°, lat: 47.5°.numDigits
: tizedesjegyek számaemptyString
: szöveg, ami akor jelenik meg, ha "lemegyünk a térképről"displayProjection
: a koordináták vetülete (OpenLayers.Projection objektum). Ha nincs megadva, akkor a térkép vetülete az alapértelmezett.kiírja a térkép aktuális méretarányát. Példa
dinamikus mértéklécet helyez el a térképen
a térképre kattintva megkapjuk egy WMS rétegen az adott helyen lévő elem adatait.Példa
Ha a WMSGetFeatureInfo controlt MapServer szolgáltatáson használjuk, akkor a következő dolgok legyenek beállítva a mapfile-ban a helyes működéshez:
... WEB # a MAP objekumon belüli WEB objektum METADATA ... "wms_srs" "EPSG:4326 EPSG:3857" # itt szerepeljen az a vetület, amiben az OpenLayers kéri a térképet "wms_enable_request" "*""ows_encoding" "WINDOWS-1250" # itt az alapanyag (pl. shapefájl) karakterkódolását adjuk meg END END ... LAYER ... METADATA "wms_enable_request" "*""gml_include_items" "all" # enélkül nem kapjuk meg az attribútumadatokat ENDDUMP true # enélkül nem megy a getfeatureinfo kérés TEMPLATE "template.html" # nem kell létező fájlnévnek lennie, hacsak nem html formátumú featureinfo-t várunk ...
egy Vector réteg elemeit áthelyezhetővé teszi. Példa
egy Vector rétegen rajzolhatunk vele új elemeket. Példa
segítségével méréseket (hossz, terület stb.) végezhetünk a térképen
segítségével kijelölhetjük egy Vector réteg elemeit, és a kijelöléshez eseménykezelőt definiálhatunk