Använda OpenLayers med GeoNames WebServices

I den här handledningen visar jag dig hur du använder OpenLayers, ett enkelt att använda open source JavaScript-bibliotek för att ladda, visa och göra kartor, med GeoNames.org WFS för att visa markörer på din karta, precis som du ser på Google Kartor. Allt som krävs är en del HTML, CSS och JavaScript - det är det!


Steg 1: Ställa in ditt GeoNames.org-konto

Innan vi gör någonting måste vi först skapa vårt GeoNames.org-konto. GeoNames WebServices gör att du kan göra förfrågningar på 30000 poäng per dag, en timgräns på 2000 poäng. Olika frågor kräver olika kreditpoäng, utan att det är fråga om att "kosta" mer än 4. För många små webbplatser och enkel utvecklingstestning borde detta vara mer än tillräckligt. De erbjuder premiumtjänster till ett pris, men idag kommer vi att hantera de fria sakerna. Gratis är alltid trevligt, är det inte?

För att skapa ditt konto, gå till GeoNames.org login och skapa ditt gratis konto. Du måste bekräfta kontot i ditt email, men det borde gå ganska snabbt. När du är bekräftad är du redo att gå.

"Det finns över 30 olika typer av frågor du kan göra med GeoNames WebServices. En lista över dem finns här."


Steg 2: JavaScript-bibliotek

Nästa måste vi ta tag i OpenLayers källkod och bilder. De finns på OpenLayers hemsida. Du kan antingen ladda ner .zip eller .tar.gz. För den här handledningen är allt vi behöver är OpenLayers.js-filen och img-mappen. För extra smak och användbarhet kommer vi att inkludera Kelvin Lucks JScrollPane och Brandon Aarons jQuery mousewheel plugins, för att bara förbättra och försköna våra resultat div. Ta tag i js och css från JScrollPane. Jag har gjort några små förändringar i css, bara för att passa den stil jag ville ha för denna handledning, men stil det som du vill. Ta tag i mousewheel-plugin från GitHub. Sist men inte minst, ta den senaste versionen av jQuery.

"Naturligtvis kan alla nödvändiga filer för den här handledningen återfinnas i källfilerna Ladda ner länken längst upp."

Dagens handledning kommer att ta itu med findNearbyPostalCodes. Nu börjar vi skriva några koden!


Steg 3: Katalogstruktur, HTML och CSS

Gå vidare och skapa en katalogstruktur för din ansökan. Jag har namngivit min geonames. Inne i geonames, inkludera tre ytterligare mappar: img, js och css. Bilderna från OpenLayers kommer att gå i img-mappen, JavaScript-filerna från OpenLayers, JScrollPane och jQuery mousewheel, och jQuery kommer att gå i js-mappen och stylesheet från JScrollPane kommer att gå i css-mappen. Dessutom har några bilder jag har skapat och ett par tagit från ikonfinnare hittats i källfilerna. Sätt dem i img mapp också.

  • geonames
    • img
    • js
    • css

Här har vi en enkel sida med vissa HTML-element. Det mesta av vårt kött kommer att finnas i vår JavaScript, så den här delen är ganska kort. Spara den här filen som index.html.

    Openlayers / Geonames handledning     
Sök


Resultat

Här är CSS som vi har skapat för användning i denna handledning. Inget fruktansvärt banbrytande här, bara lite styling. Spara den här filen som style.css i css mapp du skapade.

 * font-family: Helvetica; svart färg;  html höjd: 100%; marginal: 0; överflöde-y: bläddra  kropp bakgrundsfärg: vit; typsnitt: normal 13px arial, sans-serif; höjd: 100%; marginal: 0;  # map background: #ccc; höjd: 100%; position: absolut; bredd: 100%; z-index: 1;  #searchContainer border-radius: 2px; -moz-gränsen-radien: 2px; -gränsradien: 2px; -webkit-gräns-radie: 2px; bakgrundsfärg: rgba (247.247.247,0.5); gränsen: 1px solid #ffffff; boxskugga: 0 0 3px # C5C5C5; -moz-box-skugga: 0 0 3px # C5C5C5; -webkit-box-skugga: 0 0 3px # C5C5C5; höjd: 158px; bredd: 250px; position: absolute; z-index: 2; topp: 20px; höger: 20px; vaddering: 4px 4px 4px 4px;  #searchBox bakgrundsfärg: rgba (247.247.247,0.7); border-bottom-left-radie: 2px; border-bottom-right-radie: 2px; gränsen: 1px solid #ffffff; höjd: 136px; bredd: 250px; text-align: center; linjehöjd: 44px;  #resultContainer border-radius: 2px; -moz-gränsen-radien: 2px; -gränsradien: 2px; -webkit-gräns-radie: 2px; bakgrundsfärg: rgba (247.247.247,0.5); gränsen: 1px solid #ffffff; -moz-box-skugga: 0 0 3px # C5C5C5; -webkit-box-skugga: 0 0 3px # C5C5C5; boxskugga: 0 0 3px # C5C5C5; bredd: 252px; position: absolute; z-index: 2; topp: 208px; höger: 20px; vaddering: 4px 4px 4px 4px; display: none;  #resultHeader, #searchHeader width: 250px; höjd: 20px; border-top-left-radie: 2px; border-top-right-radie: 2px; gränsen till vänster: 1px solid #ffffff; border-top: 1px solid #ffffff; gräns-höger: 1px solid #ffffff; position: relativ; bakgrundsrepetition: repetera-x; bakgrund: -webkit-gradient (linjär, 0% 0%, 0% 100%, från (# C2DCFD), till (#DDECFD)); bakgrund: -webkit-linjär-gradient (topp, #DDECFD, # C2DCFD); bakgrund: -moz-linjär-gradient (topp, #DDECFD, # C2DCFD); bakgrund: -ms-linjär gradient (topp, #DDECFD, # C2DCFD); bakgrund: -o-linjär-gradient (topp, #DDECFD, # C2DCFD); text-align: center; font-size: 16px; textskugga: 0px 0px 1px # 96B0BB;  #resultBox bakgrundsfärg: rgba (247.247.247,0.7); border-bottom-left-radie: 2px; border-bottom-right-radie: 2px; gränsen: 1px solid #ffffff; max-höjd: 418px; min-höjd: 250px; bredd: 250px; överflöde: auto;  .item0, .item1 float: left; vaddering: 5px 4px 5px 4px; bredd: 242px; border-top: 1px solid #dcdcdc;  .item1 bakgrundsfärg: #FFFFFF;  .clear clear: both;  .olPopupCloseBox background: url ("... /img/close.gif") no-repeat; markör: pekare;  .olFramedCloudPopupContent vaddering: 5px; överflöde: auto; 

Vid den här tiden borde din sida se ut så här:

Det är inte så mycket att titta på, så låt oss komma in i de bra sakerna.


Steg 4: GeoNames JavaScript

variabler

 var $ r = $ ('# resultat'), $ rContainer = $ ('# resultContainer'), $ rBox = $ ('# resultBox');

Du vill alltid ställa in dina jQuery-objekt till variabler. Alltid bästa praxis!

Event Listener

 var Observation = funktion (mål) _target = target; _arrObservers = []; var bindemedel = funktion (observatör) _arrObservers.push (observatör); ; var inform = funktion () för (var x = 0; x<_arrObservers.length; x++)  _arrObservers[x](_target);  ; return  binder: binder, inform: inform  ;

Det här är bara en enkel lyssnarefunktion som vi har skapat. När vi skapar det evenemang som vi vill lyssna på, skickar vi det objekt som vi vill lyssna på. Jag har kallat detta argument: mål. Den innehåller två variabler: _mål - en variabel vi ställer lika med vårt argument och _arrObservers - en tom array som vi ska använda för att fylla med lyssnare. Observation innehåller även två funktioner: bindemedel och underrätta.

 var bindemedel = funktion (observatör) _arrObservers.push (observatör); ;

Fungera bindemedel lägger till varje lyssnare eller observatör till en rad lyssnare. I denna handledning kommer vi bara att skapa en anpassad händelse, men när du lägger till varje lyssnare i en array kan du tilldela flera lyssnare med en funktion.

 var inform = funktion () för (var x = 0; x<_arrObservers.length; x++)  _arrObservers[x](_target);  ;

Fungera underrätta bränder ett meddelande till lyssnaren och låter det veta att händelsen inträffar. Slutligen, som du ser ovan, returnerar vi båda dessa funktioner så att de är tillgängliga för användning.

GeoNames Modell

 var makeGeoNamesModel = funktion () var _results = , country = 'US', radie = 30, användarnamn = 'openlayers_tutorial', maxRows = 20; var notifySearchComplete = ny Observation (this); var sökning = funktion (val) $ .ajax (url: 'http://api.geonames.org/findNearbyPostalCodesJSON'), data: postnummer: val, land: land, rad: radie, användarnamn: användarnamn, maxRows: maxRows, dataType: 'jsonp', jsonpCallback: 'geoNamesResponse'); ; geoNamesResponse = funktion (geoData) _results = geoData; notifySearchComplete.inform (); ; var getResults = function () return _results; ; var klart = funktion () _results = ; ; returnera notifySearchComplete: notifySearchComplete, sök: sök, geoNamesResponse: geoNamesResponse, getResults: getResults, clear: clear; ;

Här har vi vår GeoNames-modell. Denna modell hanterar att skapa, lagra och returnera värdet av vår GeoNames WebServices-begäran.

 var _results = , country = 'US', radius = 30, användarnamn = 'openlayers_tutorial', maxRows = 20;

Det här är bara några variabler vi ska använda, mestadels i vår ajaxförfrågan. För användningen av vår handledning kommer vi bara att söka i USA (förlåt, jag är partisk), men du kan ändra din ansökan för att acceptera landskodsinmatning om du vill. Den maximala radie vi tillåts med vårt gratis konto är 30 kilometer. Jag har också ställt in de maximala returnerade platserna till 20, men du kan upp det värdet om du vill. Sträng openlayers_tutorial är namnet på det konto jag har konfigurerat för denna handledning, så ändra den här strängen till användarnamnet du skapade när du ställde in kontot ovan. Slutligen förbereder vi vår modell med ett tomt objekt som heter _resultat att fyllas vid en senare tidpunkt.

 var notifySearchComplete = ny Observation (this); var sökning = funktion (val) $ .ajax (url: 'http://api.geonames.org/findNearbyPostalCodesJSON'), data: postnummer: val, land: land, rad: radie, användarnamn: användarnamn, maxRows: maxRows, dataType: 'jsonp', jsonpCallback: 'geoNamesResponse'); ; geoNamesResponse = funktion (geoData) _results = geoData; notifySearchComplete.inform (); ;

Här har vi alla viktiga webbtjänstförfrågningar: Sök och vår händelseanmälan. Eftersom det här är en begäran från tredje part ställer vi in ​​dataType till "jsonp" och skickar förfrågan till våra variabler som vi definierade tidigare. Argument val kommer att definieras senare enligt vår uppfattning. Vi kommer också att uttryckligen ange återuppringningsfunktionsnamnet - geoNamesResponse - och hantera den framgångsrika förfrågan. Jag kunde ha lagt till kod för att hantera felaktig inmatning, men för den här handledningen antar vi att du ska sätta in en korrekt 5-siffrig postnummer. Vi skickar GeoNames den postnummer som användaren har angett, men för den här frågan kan du skicka latitud och longitud som lat och lng om du ville. Vid denna tidpunkt meddelar vi också vår lyssnare att den här sökningen har slutförts.

 var getResults = function () return _results; ; var klart = funktion () _results = ; ;

Den sista delen av vår modell handlar om att returnera våra resultat när vi frågade dem och tömmer även vårt resultatobjekt när användaren klickar på knappen "Clear Markers".

GeoNames Controller

 var makeGeoNamesFormController = function () return handleSearch: function (txtVal, geoNamesModel) geoNamesModel.search (txtVal); , handleClear: funktion (geoNamesModel) geoNamesModel.clear (); , handledningResultat: funktion (geoNamesModel) testResults = geoNamesModel.getResults (); retur testResults; ; ;

Vår controller gör egentligen ingenting annat än tillgång till funktioner och returnerar variabler från vår GeoNames-modell baserat på inmatning från användargränssnittet. Vi returnerar tre funktioner:

handleSearch - Detta tar värdet av användarens inmatning och geoNamesModel som argument, och uppmanar geoNamesModel s Sök funktion, överför det värde vi vill skicka till GeoNames WebServices.

handleClear - detta åberopar geoNamesModel s klar funktion så att vi kan rensa ut vårt resultatobjekt.

handleResult - detta åberopar geoNamesModel s getResults funktion så att vi kan få tillgång till resultaten från vår WFS-förfrågan.

GeoNames View

 var makeGeoNamesFormView = funktion (initGeoNamesModel, initOpenLayersMapModel, initGeoNamesFormController, initOpenLayersMapController) var _geoNamesModel = initGeoNamesModel, _openLayersMapModel = initOpenLayersMapModel, _geoNamesFormController = initGeoNamesFormController, _openLayersMapController = initOpenLayersMapController, $ txtSearch = $ ( '# txtSearch'), $ btnSearch = $ ( '# btnSearch '), $ btnClear = $ (' # btnClear '); $ btnSearch.on ("click", funktion () _geoNamesFormController.handleClear (_geoNamesModel); _openLayersMapController.handleClear (_openLayersMapModel); $ r.html (""); _geoNamesFormController.handleSearch ($ txtSearch.val (), _ geoNamesModel); ); $ btnClear.on ("click", funktion () _geoNamesFormController.handleClear (_geoNamesModel); _openLayersMapController.handleClear (_openLayersMapModel); $ r.html (""); $ txtSearch.val (""); $ rContainer.slideUp 500);); $ (fönster) .on ("ladda", funktion () _openLayersMapController.render (_openLayersMapModel);); var showPoints = function () var olPoints = _geoNamesFormController.handleResult (_geoNamesModel); var olResults = _openLayersMapController.handleMarkers (_openLayersMapModel, olPoints); $ (# ResultContainer) slideDown (500). $ r.append (olResults.join (")); $ rBox.jScrollPane (showArrows: true, autoReinitialise: true);; _geoNamesModel.notifySearchComplete.binder (funktion () showPoints (););;

GeoNames View definierar våra klickhändelser och handtag som kallar kontrollfunktionerna för att manipulera vår syn. Det fungerar nära regulatorn, men låter modellen komma åt och manipulera upp till regulatorn.

 var _geoNamesModel = initGeoNamesModel, _openLayersMapModel = initOpenLayersMapModel, _geoNamesFormController = initGeoNamesFormController, _openLayersMapController = initOpenLayersMapController, $ txtSearch = $ ('# txtSearch'), $ btnSearch = $ ('# btnSearch'), $ btnClear = $ ('# btnClear');

Allt vi gör här är inställda variabler som är lika med respektive funktionsargument, och som alltid ställer du in dina jQuery-objekt till variabler.

 $ btnSearch.on ("click", funktion () _geoNamesFormController.handleClear (_geoNamesModel); _openLayersMapController.handleClear (_openLayersMapModel); $ r.html (""); _geoNamesFormController.handleSearch ($ txtSearch.val (), _ geoNamesModel); ); $ btnClear.on ("click", funktion () _geoNamesFormController.handleClear (_geoNamesModel); _openLayersMapController.handleClear (_openLayersMapModel); $ r.html (""); $ txtSearch.val (""); $ rContainer.slideUp 500);); $ (fönster) .on ("ladda", funktion () _openLayersMapController.render (_openLayersMapModel););

Det här är våra enda två klickhändelser, plus en fönsterhändelse. Den första binder till vår "Sök GeoNames.org" -knapp och skickar värdet på textrutan och modellen vi vill hantera till vår controller för att hantera arbetet. Den andra binder till vår "Clear Markers" -knapp som vi nämnde i avsnittet GeoNames Model. Denna händelse kallar rensningen av resultatobjektet i GeoNames-modellen och även markörerna i vyn, som vi kommer att adressera nedan. Slutligen uppdaterar vi även vår formulär och resultatavsnitt enligt vår uppfattning, och döljer resultaten eftersom det här området nu är tomt. Fönsterhanteringshändelser hanterar kartan när fönstret har laddats helt.

 var showPoints = function () var olPoints = _geoNamesFormController.handleResult (_geoNamesModel); var olResults = _openLayersMapController.handleMarkers (_openLayersMapModel, olPoints); $ (# ResultContainer) slideDown (500). $ r.append (olResults.join (")); $ rBox.jScrollPane (showArrows: true, autoReinitialise: true);; _geoNamesModel.notifySearchComplete.binder (funktion () showPoints (););

Den sista delen av vår GeoNames View handlar om att ta våra resultat och manipulera både vår resultatvy och kartan. Vyn vet att den måste uppdatera kartan och resultatet visas eftersom den har tecknat på GeoNames-modellen notifySearchComplete händelse som vi kan se ovan. När den händelsen avslutas kallas vyn showPoints funktionen och hanterar uppdateringen av resultaten div och visar markörerna på kartan.


Steg 5: OpenLayers JavaScript

OpenLayers Modell

 var makeOpenLayersMapModel = funktion () var karta, centrum = nya OpenLayers.LonLat (-90.3658472,38.742575), // Centrerad på Lambert St Louis International eftersom jag är partisk zoomLevel = 6, numZoomLevels = 15, iconSize = 32, autoSizeFramedCloud = OpenLayers .Class (OpenLayers.Popup.FramedCloud, 'autoSize': true), storlek = nya OpenLayers.Size (iconSize, iconSize), calculateOffset = funktion (storlek) returnera nya OpenLayers.Pixel (-size.w / 2, -size.h / 2); , ikon = nya OpenLayers.Icon ('img / redpin.png', storlek, null, beräknaOffset); var renderMap = funktion () var options = kontroller: [nya OpenLayers.Control.Navigation (), nya OpenLayers.Control.PanZoomBar (), nya OpenLayers.Control.KeyboardDefaults ()], enheter: "km", numZoomLevels: numZoomLevels, maxExtent: nya OpenLayers.Bounds (-170.0, 10, -60, 80), center: center; map = nya OpenLayersMap ('map', options); wmslayer = nya OpenLayers.Layer.WMS ("OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0", layers: "basic"); markörer = nya OpenLayers.Layer.Markers ("Zip Code Markers"); map.addLayers ([wmslayer, markörer]); map.zoomTo (zoomLevel); ; var addMarker = funktion (ll, ikon, popupClass, popupContentHTML) var marker = nya OpenLayers.Marker (ll, ikon); markers.addMarker (markör); marker.events.register ('mousedown', markör, funktion (evt) för (var i = map.popups.length-1; i> = 0; i -) map.removePopup (map.popups [i] ); var popup = nya OpenLayers.Popup.FramedCloud (null, marker.lonlat, null, popupContentHTML, null, true, null); popup.closeOnMove = true; map.addPopup (popup); OpenLayers.Event.stop evt);); ; var buildMarkers = funktion (pts) var rHTML = [], y = 0; $ .each (pts.postalCodes, funktion (i, v) if (i === 0) newCenterLL = nya OpenLayers.LonLat (v.lng, v.lat); latit = v.lat; longit = v .lng; markerIcon = icon.clone (); lonLatMarker = nya OpenLayers.LonLat (longit, latit); popupClass = autoSizeFramedCloud; popupContentHTML = '

'+ v.placeName +', '+ v.adminCode1 + "+ v.postalCode +'

'; rHTML [y ++] = '
'; rHTML [y ++] = (i + 1) + ')' + v.placeName + ',' + v.adminCode1 + "+ v.postalCode + '
'; rHTML [y ++] = v.lat.toFixed (5) + ',' + v.lng.toFixed (5); rHTML [y ++] = '
'; addMarker (lonLatMarker, markerIcon, popupClass, popupContentHTML); ); map.setCenter (newCenterLL, 12); returnera rHTML; ; var klart = funktion () för (var x = markörer.markörer.längd-1; x> = 0; x--) markers.markers [x] .destroy (); markers.removeMarker (markers.markers [x]); map.setCenter (center, zoomLevel); ; returnera renderMap: renderMap, addMarker: addMarker, buildMarkers: buildMarkers, clear: clear;

Här har vi vår OpenLayers-modell. Den här modellen kommer att hantera att skapa OpenLayers-kartan, våra kartmarkörer för att visa resultatuppsättningen GeoNames WebServices, samt att rensa dessa markörer från vår karta.

 var map, center = nya OpenLayers.LonLat (-90.3658472,38.742575), // Centrerad på Lambert St Louis International eftersom jag är partisk zoomLevel = 6, numZoomLevels = 15, iconSize = 32, autoSizeFramedCloud = OpenLayers.Class (OpenLayers.Popup. FramedCloud, 'autoSize': true), storlek = nya OpenLayers.Size (iconSize, iconSize), calculateOffset = funktion (storlek) returnera nya OpenLayers.Pixel (-size.w / 2, -size.h / 2) ; , ikon = nya OpenLayers.Icon ('img / redpin.png', storlek, null, beräknaOffset);

Vi har fördefinierat några värden för vår karta - zoomLevel är variabeln som vi kommer att ställa in vår första zoom. Zoomnivåerna ökar när du kommer närmare och närmare jorden. Som du kan gissa, numZoomLevels är antalet zoomnivåer som den här kartan tillåter. För våra push pin markörer måste vi förklara storleken på markören, så iconSize, medan det inte uttryckligen sägs så, är inställt på 32, och OpenLayers förstår att detta värde är i pixlar. De andra objekten du ser här är OpenLayers specifika. De calculateOffset berättar helt enkelt ikonen för att kompensera ikonbilden så att bilden centreras på punktens latitud och längd, inte längst upp till vänster eller upp till höger. De OpenLayers.Size konstruktören skapar en storlek baserat på ikonen storlek vi vill ha. Slutligen, den OpenLayers.Icon konstruktör definierar ikonen som vi ska använda som våra markörer på kartan.

 var renderMap = funktion () var options = kontroller: [nya OpenLayers.Control.Navigation (), nya OpenLayers.Control.PanZoomBar (), nya OpenLayers.Control.KeyboardDefaults ()], enheter: "km", numZoomLevels: numZoomLevels, maxExtent: nya OpenLayers.Bounds (-170.0, 10, -60, 80), center: center; map = nya OpenLayersMap ('map', options); wmslayer = nya OpenLayers.Layer.WMS ("OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0", layers: "basic"); markörer = nya OpenLayers.Layer.Markers ("Zip Code Markers"); map.addLayers ([wmslayer, markörer]); map.zoomTo (zoomLevel); ;

Här är all viktig kod för att skapa vår karta. De OpenLayers.Map konstruktorn tar två parametrar, DOM-objektet som ska hysa kartan och alternativen, vilket är ett valfritt objekt med egenskaper som kartan kommer att ha. Låt oss ta en titt på alternativen jag har med.

OpenLayers ger dig flexibiliteten att använda flera olika källor för dina kartor.

De kontroller Lägg bara till grundläggande mus och tangentbord interaktion med kartan. Dessa lägger också till zoomfältet och riktningsknapparna ovanför kartan. De enheter är i kilometer, men i den här handledningen är det inte nödvändigt med det här alternativet eftersom vi inte gör några beräkningar med OpenLayers, bara GeoNames. De numZoomLevels anger antalet zoomnivåer den här kartan kommer att ha. De Centrum berättar kartan där man ska koncentrera sig på rendering. De maxExtent alternativet är inställt på ett OpenLayers-element som heter Bounds. Du förklarar bara en ny OpenLayers.Bounds, och vi ger de 4 parametrarna - SouthWest Longitude, SouthWest Latitude, NorthEast Longitude och NorthEast Latitude. Detta ger oss, vad vi kallar i GIS-världen, en avgränsningsruta. Eftersom vi bara handlar om Förenta staterna i denna handledning ställer jag gränserna för att bara inkludera Nordamerika i visning av kartan. Om du vill visa hela världen, lämna bara det här alternativet. Vid denna tidpunkt har vi vår karta redo. Nu kan vi börja lägga till lager på kartan.

OpenLayers ger dig flexibiliteten att använda flera olika källor för dina kartor. Några av dem inkluderar Bing Maps, Google Maps och OpenStreetMap. Du kan också använda dina egna kartor om du har den typen av inställningar. I den här handledningen använder vi de generiska OSGeo-plattorna som OpenLayers använder i sina egna exempel. Vi gör det genom att skapa en ny OpenLayers.Layer.WMS konstruktör. WMS står för webbmappningstjänster. Vi ger den en titel, en URL för att peka på plattorna och parametrarna som är specifika för kakelvärden. Nästa skapar vi ett markörlager med hjälp av OpenLayers.Layer.Markers konstruktör. Allt vi behöver göra vid denna punkt är att ge det ett namn. Slutligen lägger vi till de två lager som vi har skapat på vår karta med addLayers funktionen, och vi zoomar till lämplig zoomnivå som vi definierat.

 var addMarker = funktion (ll, ikon, popupClass, popupContentHTML) var marker = nya OpenLayers.Marker (ll, ikon); markers.addMarker (markör); marker.events.register ('mousedown', markör, funktion (evt) för (var i = map.popups.length-1; i> = 0; i -) map.removePopup (map.popups [i] ); var popup = nya OpenLayers.Popup.FramedCloud (null, marker.lonlat, null, popupContentHTML, null, true, null); popup.closeOnMove = true; map.addPopup (popup); OpenLayers.Event.stop evt);); ;

De addMarker funktionen tar markörinformationen som vi tillhandahåller i nästa avsnitt och skapar markörer och popup-moln som ska läggas till i vår karta. Vi först gör vår markör med OpenLayers.Marker konstruktör. Allt vi behöver göra är att skicka det till vår LonLat-variabel och ikonen som vi vill använda. Då använder vi helt enkelt addMarker funktionen med markörvariabeln som argument och markören läggs till i kartan. För att få ett popup-fönster att fungera om vi klickar på markören registrerar vi bara en händelse för denna markör. Vi gör detta genom att ringa evenemang egenskapen för denna markör och använd Registrera funktion för att binda händelsen som vi skulle i jQuery. Popupen skapas med hjälp av OpenLayers.Popup.FramedCloud konstruktör, som tar sju parametrar: id, lonlat, contentSize, contentHTML, ankare, closeBox, closeBoxCallback. Allt vi verkligen behöver är lonlat, contentHTML och möjligheten att stänga popupen, så allting kan vara noll. För att lägga till popupen använder vi helt enkelt bara funktionen addPopup passerar popupvariabeln. Så enkelt är det.

 var buildMarkers = funktion (pts) var rHTML = [], y = 0; $ .each (pts.postalCodes, funktion (i, v) if (i === 0) newCenterLL = nya OpenLayers.LonLat (v.lng, v.lat); latit = v.lat; longit = v .lng; markerIcon = icon.clone (); lonLatMarker = nya OpenLayers.LonLat (longit, latit); popupClass = autoSizeFramedCloud; popupContentHTML = '

'+ v.placeName +', '+ v.adminCode1 + "+ v.postalCode +'

'; rHTML [y ++] = '
'; rHTML [y ++] = (i + 1) + ')' + v.placeName + ',' + v.adminCode1 + "+ v.postalCode + '
'; rHTML [y ++] = v.lat.toFixed (5) + ',' + v.lng.toFixed (5); rHTML [y ++] = '
'; addMarker (lonLatMarker, markerIcon, popupClass, popupContentHTML); ); map.setCenter (newCenterLL, 12); returnera rHTML; ;

De buildMarkers funktionen tar JSON och looparna genom resultatuppsättningen. För enkelhet antar vi att den första punkten som returneras av GeoNames WebServices-förfrågan sannolikt kommer att vara den punkt du sökte, så vi gör det till vår nya mittpunkt och ställer in den till en OpenLayers.LonLat objekt. Vi har redan skapat vår OpenLayers-ikon, så att använda den om och om igen, vi ringer till klona metod, som helt enkelt gör en kopia av den ikonen. Resten av slingan skriver helt enkelt lite HTML till en array, som vi såg i GeoNames-formuläret Vis används för att skapa resultat div. Att skriva flera rader av HTML och trycka dem in i en array är ett snabbt sätt att dynamiskt skapa HTML utan att behöva komma åt DOM om och om igen. I slutet av denna slinga åberopar vi addMarker funktion som vi skapade ovan. När vi har skapat våra markörer och slingan har slutförts, kommer vi att centrera på och zooma in i våra resultat med setCenter fungera.

 var klart = funktion () för (var x = markörer.markörer.längd-1; x> = 0; x--) markers.markers [x] .destroy (); markers.removeMarker (markers.markers [x]);  map.setCenter (center, zoomLevel); ;

Denna funktion tar hand om att rensa trycketar från kartan samt ta bort dem från markörskiktet. De förstöra funktionen tar bort markören från kartan. De removeMarker funktionen tar bort markören från markörskiktet. Lägg märke till att vi minskar i vår för loop snarare än att öka som vi normalt skulle. Vi gör det för att vi använder OpenLayer förstöra och removeMarker funktioner blir markörobjektet uppdaterat. Om vi ​​till exempel hade 5 markörer ville vi ta bort, och vi ökade vår slinga, efter den första förstöringen hade vi 4 markörer kvar. Efter den andra förstörelsen skulle vi ha 3 markörer kvar. Efter den tredje förstörelsen hade vi 2 markörer kvar. Vid den tiden är våra kvarvarande markörer på position 1 och 2, så att radera den 4: e markören skulle ha ingen effekt eftersom den positionen inte existerar, därför tar vi bort dem från början och arbetar framåt.

OpenLayers Controller

 var makeOpenLayersMapController = function () return render: function (openLayersMapModel) openLayersMapModel.renderMap (); , handleMarkers: function (openLayersMapModel, mrkr) openLayersMapModel.buildMarkers (mrkr); , handleClear: funktion (openLayersMapModel) openLayersMapModel.clear (); ; ;

Denna kontroller, som med den ovanstående, gör ingenting mer än åtkomst till funktioner och returnerar variabler från modellen baserat på inmatning från användargränssnittet, bara denna gång från vår OpenLayers-modell. Vi returnerar tre funktioner:

  • göra - Detta gör faktiskt OpenLayers-kartan till skärmen.
  • handleMarkers - Detta påkallar openLayersMapModels buildMarkers-funktion så att vi kan ta vårt GeoNames WFS-resultat och skapa våra pushpins på kartan.
  • handleClear - Detta påkallar openLayersMapModels tydliga funktion så att vi kan rensa kartan över våra markörer.

När denna kodkod körs, ska din sida se ut så här:


Steg 6: Instantiation

Slutligen allt vi behöver göra är att instansera våra modeller, åsikter och contollers.

 (Function () var geoNamesModel = makeGeoNamesModel (); var openLayersMapModel = makeOpenLayersMapModel (); var geoNamesFormController = makeGeoNamesFormController (); var openLayersMapController = makeOpenLayersMapController (); var geoNamesFormView = makeGeoNamesFormView (geoNamesModel, openLayersMapModel, geoNamesFormController, openLayersMapController);) ( );

Först kommer vi att instansera våra modeller, sedan våra controllers, och slutligen vår syn. GeoNames-vyn passerar båda modellerna och båda kontrollerna, eftersom det är typ av en supervy, för avsaknad av en bättre term. Vi paketerar detta i en anonym funktion, och du är allt klar! Ditt resultat ska se ut så här när du har sökt efter en postnummer:


Medel

OpenLayers

  • OpenLayers API
  • OpenLayers-exempel

GeoNames

  • Skapa ett konto
  • Sök typöversikt

Slutsats

Jag hoppas att du alla har hittat denna handledning informativ, men viktigast, lätt att använda och förstå. GIS är ett blomstrande fält, och som jag har visat dig kan du göra dina egna geospatiala frågor direkt hemma med gratis källdata som GeoNames.org. Om du har några frågor, vänligen meddela mig det i kommentarerna, och jag gör mitt bästa för att svara på dem!