Chapter 4. Geolocation and Mapping APIs Chapter 3 introduced us to using the W3C Geolocation API to collect location information from the user's browser ...
Skiptomaincontent
HTML5GeolocationbyAnthonyT.Holdener
GetfullaccesstoHTML5Geolocationand60K+othertitles,withfree10-daytrialofO'Reilly.
There'salsoliveonlineevents,interactivecontent,certificationprepmaterials,andmore.
Startyourfreetrial
Chapter 4. GeolocationandMappingAPIsChapter 3introducedustousingtheW3C
GeolocationAPItocollectlocationinformationfromtheuser’sbrowserwith
JavaScriptcode.Althoughthatisthewholepointofthisbook,itisnot
extremelyusefultocollectgeolocationinformationunlessyou,the
developer,aregoingtodosomethingwithit.Oneeffectiveapplicationfor
collectingauser’slocationistoplacethatpointonamap.Let’sfaceit,
mappingalocation(ormultiplelocations)isacommonthingtodointhe
worldofGIS.Therearemanysolutionsavailableforweb-mappingapplications—GoogleMaps
JavaScriptAPIV3,BingMapsAJAX
Control,Version7.0,EsriArcGIS
JavaScriptAPI2.2,YahooMapsAJAXAPI,and
OpenStreetMapAPI
v0.6tonameafew(morethanafewactually).MostoftheAPIs
availabletodowebmappingareverysimilarinnature.Becauseofthis,I
havedecidedtofocusonjustacoupleoftheAPIsavailable,andleaveit
uptoyoutopicktheAPIthatbestsuitsyourneeds.AftergivingyouatasteoftheseAPIsforuseinyourapplications,
wecanthenexplorewhattodowiththeinformationyouhavecollectedso
thatitcanbereferencedbyotherapplicationsorreplottedinthefuture.
Thisisasimportantasbeingabletomapthegeolocationsbeingcollected,
sincemostGISapplicationsaregoingtobeinterestedinmorethanasingle
user’spointinformation.Tothisend,wewilllookatdifferentwaysto
saveourgeolocationinformationsothatitcanbeconsumedbytheseother
applications.AGoogleMapsExampleTheGoogleMapsJavaScriptAPIletsyouembedGoogleMapsinyour
ownwebpages.Version3ofthisAPIisespeciallydesignedtobefaster
andmoreapplicabletomobiledevices,aswellastraditionaldesktop
browserapplications.[9]WiththisAPI,itiseasyforadevelopertoembedamap
thatfunctionsjustlikethehttp://maps.google.com/
webpage,andtocustomizeitslookandfunctionalitytosuittheneedsof
theapplicationbeingbuilt.ItisaverypopularAPIforbuildingweb
applications,currentlybeingusedinover150,000websites.[10]TheGoogleMapsAPI,BrieflyForthepurposesofthisbook,Ihaveincludedallofthecodefor
theGoogleMapsapplicationintoasingleHTMLfiletomakeiteasierto
read.IfIweretocreateanactualapplication,Iwouldbreakthe
CascadingStyleSheet(CSS)rulesandJavaScriptintotheirownfiles
(perhapsmultiplefilesshouldtheapplicationbemorecomplex)asa
betterprogrammingpractice.TakealookatthecodeinExample 4-1,which
containseverythingneededtocreateasimpleGoogleMap
application.Example 4-1. AsimpleGoogleMap
ASimpleGoogleMap
html{height:100%}
body{height:100%;margin:0;padding:0}
#map{height:100%}
varmap;
/*Thisiscalledoncethepagehasloaded*/
functionInitMap(){
/*Setalloftheoptionsforthemap*/
varoptions={
zoom:4,
center:newgoogle.maps.LatLng(38.6201,-90.2003),
mapTypeId:google.maps.MapTypeId.ROADMAP,
mapTypeControl:true,
mapTypeControlOptions:{
style:google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position:google.maps.ControlPosition.BOTTOM_CENTER
},
panControl:true,
panControlOptions:{
position:google.maps.ControlPosition.TOP_RIGHT
},
zoomControl:true,
zoomControlOptions:{
style:google.maps.ZoomControlStyle.LARGE,
position:google.maps.ControlPosition.LEFT_CENTER
},
scaleControl:true,
scaleControlOptions:{
position:google.maps.ControlPosition.BOTTOM_LEFT
},
streetViewControl:true,
streetViewControlOptions:{
position:google.maps.ControlPosition.LEFT_TOP
}
};
/*CreateanewMapfortheapplication*/
map=newgoogle.maps.Map(document.getElementById('map'),options);
}
/*Autilityobjectforsimpleeventhandlilng*/
varUtils={};
Utils.addEvent=(function(){
returnfunctionaddEvent(eventObj,event,eventHandler){
if(eventObj.addEventListener){
eventObj.addEventListener(event,eventHandler,false);
}elseif(eventObj.attachEvent){
event='on'+event;
eventObj.attachEvent(event,eventHandler);
}else{
eventObj['on'+event]=function(){eventHandler()};
}
};
}());
Utils.removeEvent=(function(){
returnfunctionremoveEvent(event){
if(event.preventDefault){
event.preventDefault();
event.stopProgagation();
}else{
event.returnValue=false;
event.cancelBubble=true;
}
};
}());
Utils.addEvent(window,'load',InitMap);
ThecodeinExample 4-1producesamaplike
thatshowninFigure 4-1.Iwillstepthrough
thiscodeinmoredetailinamoment,butthereareseveralthingsthat
shouldbenotedrightaway:TheapplicationiswritteninHTML5.TheGoogleMapsJavaScriptAPIisincludedintheapplication
bycallingitfromGoogle’ssite.ThereareacoupleofutilityJavaScriptfunctionsthataidin
cross-browsercomplianteventhandling.AGoogleMapiscreatedbyspecifyingthecontainer,a
element,toholdthe
map,andasetofoptionsthatallowthedevelopertocustomizethe
lookofthemap’scontrols.Figure 4-1. AsimpleGoogleMapinChromeSpecifyingaDOCTYPEinthe
applicationguaranteesthatbrowserswillrenderinstandards-compliantmode,makingitmore
cross-browserfriendly.IchoseHTML5asitwillsoonbetheindustry
standard,butanytrueDOCTYPEmaybe
used.TheGoogleMapsJavaScriptAPIisincludedintheapplicationwith
thefollowingline:
ThismakesthelatestversionoftheAPIavailableforthe
application.Theparametersensoris
settofalsetoindicatethatthemapisnotusing
asensortodeterminetheuser’slocation.NoteWhengeolocationisaddedtoExample 4-1,
thevalueofthesensorparameter
willbechangedtotruesothattheAPIknows
thatalocationwillbegatheredbya“sensor,”liketheGPSlocator
inaphone.Lastly,beforelookingattheGoogleMapJavaScriptAPIspecific
code,theelement
specifyingaviewportisrecognized
onlybytheiPhonerightnow,andtellsittosettheapplicationto
full-screenandnotallowtheusertoresizetheapplication.Other
smartphonesmaytakeadvantageofthiselementinthefuture.TheUtilsvariableisnothing
morethananobjectthatholdscross-browsereventhandlingfunctions
thatareusedtocreateamoreflexibleapplication.Byusingthe
Utils.addEvent()method,thiscode
canbepluggedintoanexistingapplicationandthedeveloperdoesnot
havetoworryaboutoverwritinganexistingonloadfunctionthatmayalreadybepresent.
IfaJavaScriptlibrarylikejQueryorDojoisbeingusedinthe
application,thenitwillmostlikelyhavebuilt-inmethodsthatalso
takethehassleoutofcross-browsereventhandling.AMapiscreatedbyinstantiatinganew
google.maps.Mapobjectandspecifying
theelementthatwillcontainthemap.Theelementisreferencedusing
thedocument.getElementById()DOM
method.TheMapobjectalsotakesan
optionsobjectthatcontrolseverythingelseabout
themap.MapOptionsBydefault,theGoogleMapsJavaScriptAPIprovidescontrols
thatenablebasicmapnavigationandtypeswitching.Inaddition,all
deviceshavekeyboardhandlingonbydefault.Thedefaultcontrolscan
bedisabledusingtheMap’sdisableDefaultUIproperty,andindividual
controlscanbemanipulatedusingtheircorresponding
properties.InExample 4-1,thefollowingcontrolswere
configuredforthemap:zoomThedefaultzoomlevelwassetto
4intheexample.Thezoomproperty
canrangefrom0to
21+,where
0isaviewofthewholeworld,and
21isdowntoindividual
buildings.centerDefinesthecenterofthemapbyapairof
coordinates.mapTypeTheGoogleMapsJavaScriptAPImakesthefollowingmap
typesavailable:ROADMAP,
SATELLITE,HYBRID,andTERRAIN.mapTypeControl,panControl,zoomControl,scaleControl,
streetViewControlThesecontrolsaretoggledonoroffwithvaluesof
trueandfalse.In
addition,eachhasspecificconfigurationoptionsalongwitha
positionproperty.Formoreinformationonoptionsavailableforthe
Mapobject,visittheGoogleMapsJavaScriptAPI
V3Developer’s
GuideandAPI
Reference.AddingGeolocationtoGoogleMapsAswesawinChapter 3,thereare
threemaincomponentsneededinordertoaddgeolocationtotheGoogle
mapinExample 4-1:acalltogetCurrentPosition(),a
successCallbackfunctiontodosomethingwiththe
positionwhenwegetit,andanerrorCallback
functionincasesomethinggoeswrong.Wewillcreateafunctioncalled
getLocation()tohandlecheckingfor
thenavigator.geolocationobjectand
formakingourinitialcallforalocation.Thisfunctionwilltake
advantageofaglobalvariablecalledbrowserSupportthatwilleventuallyletour
errorCallbackfunctionknowiftheerrorisfrom
theAPIoralackofbrowsersupport.Iamdoingthissothatallofour
errorhandlingisinonefunctioninsteadofhavingerroralertsspread
throughoutthecode.Thisway,ifIchoosetodosomethingmorerobust
withmyerrorhandlingotherthansimplyalerttheusertoaproblem,
alloftheerrorcodeisinoneplace.Example 4-2illustratesthisnew
functionalityimplementedintoourGoogleMapexample.Notethatchanges
andadditionstothecodearehighlightedinboldforeasier
identification.Example 4-2. AddinggeolocationtoaGoogleMap
AddingGeolocationtoaGoogleMap
html{height:100%}–
body{height:100%;margin:0;padding:0}
#map{height:100%}
varmap;
varbrowserSupport=false;
varattempts=0;
/*Thisiscalledoncethepagehasloaded*/
functionInitMap(){
/*Setalloftheoptionsforthemap*/
varoptions={
zoom:4,
center:newgoogle.maps.LatLng(38.6201,-90.2003),
mapTypeId:google.maps.MapTypeId.ROADMAP,
mapTypeControl:true,
mapTypeControlOptions:{
style:google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position:google.maps.ControlPosition.BOTTOM_CENTER
},
panControl:true,
panControlOptions:{
position:google.maps.ControlPosition.TOP_RIGHT
},
zoomControl:true,
zoomControlOptions:{
style:google.maps.ZoomControlStyle.LARGE,
position:google.maps.ControlPosition.LEFT_CENTER
},
scaleControl:true,
scaleControlOptions:{
position:google.maps.ControlPosition.BOTTOM_LEFT
},
streetViewControl:true,
streetViewControlOptions:{
position:google.maps.ControlPosition.LEFT_TOP
}
};
/*CreateanewMapfortheapplication*/
map=newgoogle.maps.Map(document.getElementById('map'),options);
/*AddGeolocation*/
getLocation();
}
/*
*IftheW3CGeolocationobjectisavailablethengetthecurrent
*location,otherwisereporttheproblem
*/
functiongetLocation(){
/*CheckifthebrowsersupportstheW3CGeolocationAPI*/
if(navigator.geolocation){
browserSupport=true;
navigator.geolocation.getCurrentPosition(plotLocation,
reportProblem,{timeout:45000});
}else
reportProblem();
}
/*Plotthelocationonthemapandzoomtoit*/
functionplotLocation(position){
attempts=0;
varpoint=newgoogle.maps.LatLng(position.coords.latitude,
position.coords.longitude);
varmarker=newgoogle.maps.Marker({
position:point
});
marker.setMap(map);
map.setCenter(point);
map.setZoom(15);
}
/*Reportanyerrorsusingthisfunction*/
functionreportProblem(e){
/*IsthisasupportissueoranAPIissue?*/
if(browserSupport){
switch(e.code){
casee.PERMISSION_DENIED:
alert('Youhavedeniedaccesstoyourposition.Youwill'+
'notgetthemostoutoftheapplicationnow.');
break;
casee.POSITION_UNAVAILABLE:
alert('Therewasaproblemgettingyourposition.');
break;
casee.TIMEOUT:
/*Threechangestogetthelocationbeforeatruetimeout*/
if(++attempts<3){
navigator.geolocation.getCurrentPosition(plotLocation,
reportProblem);
}else
alert('Theapplicationhastimedoutattemptingtoget'+
'yourlocation.');
break;
default:
alert('TherewasahorribleGeolocationerrorthathas'+
'notbeendefined.');
}
}else
alert('Geolocationisnotsupportedbyyourbrowser.');
}
/*Autilityobjectforsimpleeventhandlilng*/
varUtils={};
Utils.addEvent=(function(){
returnfunctionaddEvent(eventObj,event,eventHandler){
if(eventObj.addEventListener){
eventObj.addEventListener(event,eventHandler,false);
}elseif(eventObj.attachEvent){
event='on'+event;
eventObj.attachEvent(event,eventHandler);
}else{
eventObj['on'+event]=function(){eventHandler()};
}
};
}());
Utils.removeEvent=(function(){
returnfunctionremoveEvent(event){
if(event.preventDefault){
event.preventDefault();
event.stopProgagation();
}else{
event.returnValue=false;
event.cancelBubble=true;
}
};
}());
Utils.addEvent(window,'load',InitMap);
Thefirstthingtonoteinthisexampleisthatsensor=truewhenwemakethecalltothe
GoogleJavaScriptAPI,sinceweareusinggeolocationinthisexample.
ThegetLocation()functioniscalled
rightafterourmapobjectisinstantiated.Next,wedefineourtwocallbackfunctions:plotLocation()andreportProblem().plotLocation()willbepasseda
Positionobjectthatwillcontainallofthe
geolocationinformation,whilereportProblem()willbepasseda
PositionErrorobjectthatwillcontainanerror
codeandmessage.TheplotLocation()function
createsaLatLngobjectbasedonthepassed
latitudeandlongitudeofthePositionobject,and
fromthatLatLngobjecta
Markerobjectiscreated.The
Markerisplacedonthemap,andthenthemapis
centeredandzoomedtothecurrentgeolocation.ThereportProblem()function,
meanwhile,simplyalertstheusertothespecificerrortheapplication
has,basedeitheronthebrowserSupportvariable,orthe
PositionErrorcodethatispassedtothefunction.
Iftheerrorisatimeout,theapplicationwillmakethreeattemptsat
gettingthecurrentpositionoftheuserbeforegivingupandreporting
aproblem.AddingGeolocationforOtherBrowsersThecodeinExample 4-2worksfor
browsersthatsupporttheW3CGeolocationAPI,butwhataboutbrowsers
thatdonot?RememberbackinChapter 1whenI
discussedotherbrowsersolutions,andinparticulargeo-location-javascript?Thereareseverelimitationstothe
geolocationfunctionalitythatthisJavaScriptlibrarygives,butit
isonesolutionthatattemptscross-browsercompatibility.OurGoogle
Mapsexampleissimpleenoughthatwecanusethislibraryandnot
worrytoomuchaboutthelackoffunctionality.Example 4-3showsimplementingacross-browser
geolocationsolutionusingthegeo-location-javascriptlibrary.Again,
changesandadditionstothecodearehighlightedinboldforeasier
identification.Example 4-3. AddinggeolocationforotherbrowserstoaGoogleMap
AddingGeolocationforOtherBrowserstoaGoogleMap
html{height:100%}
body{height:100%;margin:0;padding:0}
#map{height:100%}
varmap;
varbrowserSupport=false;
/*Thisiscalledoncethepagehasloaded*/
functionInitMap(){
/*Setalloftheoptionsforthemap*/
varoptions={
zoom:4,
center:newgoogle.maps.LatLng(38.6201,-90.2003),
mapTypeId:google.maps.MapTypeId.ROADMAP,
mapTypeControl:true,
mapTypeControlOptions:{
style:google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position:google.maps.ControlPosition.BOTTOM_CENTER
},
panControl:true,
panControlOptions:{
position:google.maps.ControlPosition.TOP_RIGHT
},
zoomControl:true,
zoomControlOptions:{
style:google.maps.ZoomControlStyle.LARGE,
position:google.maps.ControlPosition.LEFT_CENTER
},
scaleControl:true,
scaleControlOptions:{
position:google.maps.ControlPosition.BOTTOM_LEFT
},
streetViewControl:true,
streetViewControlOptions:{
position:google.maps.ControlPosition.LEFT_TOP
}
};
/*CreateanewMapfortheapplication*/
map=newgoogle.maps.Map(document.getElementById('map'),options);
/*AddGeolocation*/
getLocation();
}
/*
*ThebrowserwillnowusewhatevergeolocationAPIisavailableto
*it;hopefullyitwillbetheW3CGeolocationobjectthatisusedto
*getthecurrentlocation.Ifthereisnogeolocationsupportatall,
*thenreporttheproblem.
*/
functiongetLocation(){
/*CheckifthebrowsersupportsanygeolocationAPI*/
if(geo_position_js.init()){
browserSupport=true;
geo_position_js.getCurrentPosition(plotLocation,
reportProblem);
}else
reportProblem();
}
/*Plotthelocationonthemapandzoomtoit*/
functionplotLocation(position){
varpoint=newgoogle.maps.LatLng(position.coords.latitude,
position.coords.longitude);
varmarker=newgoogle.maps.Marker({
position:point
});
marker.setMap(map);
map.setCenter(point);
map.setZoom(15);
}
/*Reportanyerrorsusingthisfunction*/
functionreportProblem(){
/*IsthisasupportissueoranAPIissue?*/
if(browserSupport)
alert('Couldnotlocateyourdevice.');
else
alert('Geolocationisnotsupportedbyyourbrowser.');
}
/*Autilityobjectforsimpleeventhandlilng*/
varUtils={};
Utils.addEvent=(function(){
returnfunctionaddEvent(eventObj,event,eventHandler){
if(eventObj.addEventListener){
eventObj.addEventListener(event,eventHandler,false);
}elseif(eventObj.attachEvent){
event='on'+event;
eventObj.attachEvent(event,eventHandler);
}else{
eventObj['on'+event]=function(){eventHandler()};
}
};
}());
Utils.removeEvent=(function(){
returnfunctionremoveEvent(event){
if(event.preventDefault){
event.preventDefault();
event.stopProgagation();
}else{
event.returnValue=false;
event.cancelBubble=true;
}
};
}());
Utils.addEvent(window,'load',InitMap);
Callstogears_init.jsand
geo.jsloadthelibrariesweare
usingforgeolocationinthisexample.Allofthe
MapfunctionalityremainsthesameasinExample 4-2.Insteadofcheckingfornavigation.geolocation,inthisexample,the
geo-location-javascriptAPIisinitializedandwillreturnwhetheror
notthebrowsersupportsanyofthegeolocationAPIsthat
geo-location-javascriptdoes.AsimplercalltogetCurrentPosition()ismade,withoutthe
timeoutset,butotherwisethegetLocation()functionisverysimilarto
thissamefunctioninExample 4-2.Nothingchangedbetweenthetwogeolocationexamplesinthe
plotLocation()function,however
therearebigchangesinthereportProblem()function.First,notethat
thereisnoPositionErrorobjectpassedtothe
function—geo-location-javascriptdoesnothavethisfunctionality.The
errorhandlingisverysimplistic,andthisisoneofthebiggest
drawbacksofthisAPI.AsIsaidearlier,thisworksadequately
becauseweareusingasimpleexample.However,shouldthegeolocation
needsbemorecomplex,alotofadditionalcodingwillbeneededto
gettheapplicationworkingcorrectly.AnArcGISJavaScriptAPIExampleEsri’sArcGISAPIforJavaScriptallowsthedevelopertotake
advantageofallthemapping,editing,geocoding,andgeoprocessing
servicesthatEsrioffers.WiththisAPI,adeveloperisabletoembeda
mapthatfunctions,likethoseonhttp://www.arcgis.com/,andtocustomizeitslookand
functionalitytosatisfytheneedsoftheapplicationbeingbuilt.The
JavaScriptAPIishostedonArcGISOnlineandisfreelyavailableforuse.
ManysitesusethisAPIfortheirGISneeds,especiallywhentheirdesktop
andserverGISneedsaremetusingEsrienterprisesoftware.Atthetime
ofthiswriting,thecurrentversionoftheAPIis2.2.TheArcGISJavaScriptAPI,BrieflyAgain,forthisbook,Ihaveincludedallofthecodeforthe
ArcGISJavaScriptMapapplicationintoasingleHTMLfiletomakeit
easiertoread.Inaproductionapplication,IwouldbreaktheCSSand
JavaScriptintotheirownfiles.TakealookatthecodeinExample 4-4,which
containseverythingneededtocreateasimpleArcGISJavaScriptMap
application.Example 4-4. AsimpleEsriArcGISMap
ASimpleEsriArcGISMap
html,body{
height:100%;
margin:0;
padding:0;
width:100%;
}
#map{
height:100%;
width:100%;
}
vardjConfig={parseOnLoad:true};
dojo.require('esri.map');
varmap;
varinitialExtent={
xmin:-119.3324,
ymin:26.3156,
xmax:-72.3568,
ymax:55.0558,
/*
*WebMercator(102113),orWGS84(4326)-thesearethe
*onlytwothatsupportcontinuouspanacrossthedateline
*/
spatialReference:{wkid:4326}
};
varstartExtent;
varbasemap;
functioninitApp(){
varstartExtent=newesri.geometry.Extent(initialExtent);
map=newesri.Map('map',{
extent:startExtent,
wrapAround180:true
});
basemap=newesri.layers.ArcGISTiledMapServiceLayer(
'http://server.arcgisonline.com/ArcGIS/rest/services/'+
'ESRI_StreetMap_World_2D/MapServer');
map.addLayer(basemap);
}
dojo.addOnLoad(initApp);
ThecodeinExample 4-4producesamaplike
thatshowninFigure 4-2.Iwillstepthroughthis
codeinmoredetailinamoment,butthereareseveralthingsthat
shouldbenotedrightaway:TheapplicationiswritteninHTML5.TheEsriArcGISAPIforJavaScriptisincludedinthe
applicationbycallingitfromArcGISOnline.TheDojoToolkit,
withitsimmensefunctionality,isalsoincludedintheAPIcallto
ArcGISOnline.AnArcGISJavaScriptMapiscreatedbyspecifyingthe
container,a
element,
toholdthemap,andasetofinlineoptionsthatdefineaspectsof
themapbeingcreated.AswiththeGoogleMapexamples,Ichosetowritethisapplication
inHTML5,asitwillsoonbetheindustrystandard.Plusthiswillgive
itadditionalfunctionalityforcreatingmoreimpressivemapsinthe
future.AnytrueDOCTYPEmay,of
course,beusedandtheapplicationwillrunfine.Figure 4-2. AsimpleEsriArcGISMapinChromeTheEsriArcGISJavaScriptAPIandDojoToolkitareincludedin
theapplicationwiththefollowingline:
TheversionoftheAPIyouwishtouseisspecifiedinthe
querystringoftheAPIcall,inthiscasethe
latestversion:2.2.Onceagain,Iamusingaelementtospecifytheviewport,tellingittosettheapplicationto
full-screenandnotallowtheusertoresizetheapplication—thisisan
iPhonerecognizableelement.Thereisasecondelement,however,thatisused
forInternetExplorerbrowsers,tellingthemtointerpretanddisplay
theapplicationasInternetExplorer7would.Thiselementshouldchange
asusageoftheIE7browserfinallydisappears.AMapiscreatedbyinstantiatinganew
esri.Mapobjectandspecifyingthe
elementthatwillcontainthemap.Theelementisreferencedbyits
idvalue.The
Mapobjectalsoacceptsan“options”objectthat
controlsinitialextentandothermapvalues.Forexample,thewrapAround180property,whichisnewtothe
2.2API,tellsthemapwhetherornottocontinuouslypanacrossthe
dateline.InallpreviousversionsoftheJavaScriptAPI,themapwould
notscrollacrossthedatelinelikeotherweb-mappingapplications
do.Formoreinformationonoptionsavailableforthe
Mapobject,orAPIdetailsingeneral,visitthe
ArcGIS
APIforJavaScriptResourcepage.AddingGeolocationtoEsriMapsYouprobablynoticedthesimilaritiesbetweenthemapapplications
inExample 4-1andExample 4-4
or,morespecifically,thewayinwhichamapwascreatedwitheachAPI.
Whiletheapplicationsthemselvesarefairlysimilar,theway
geolocationisaddedtobothofthemisnearlyidentical.ToaddW3C
GeolocationAPIcodetotheArcGISJavaScriptapplication,weaddthe
samebasiccodethatwedidfortheGoogleMap.First,wewillcreateafunctiongetLocation()tohandlecheckingforthe
navigator.geolocationobjectandfor
makingthecalltogetCurrentPosition().Thisfunctionwillonce
againtakeadvantageofaglobalvariablecalledbrowserSupportthatwilleventuallyletour
errorCallBackfunctionknowiftheerrorisfrom
theAPIoralackofbrowsersupport.Example 4-5showsthegeolocationfunctionalityadded
toourEsriArcGISMapexample.Changesandadditionstotheoriginal
codearehighlightedinbold.Example 4-5. AddinggeolocationtoanEsriArcGISMap
AddingGeolocationtoanEsriArcGISMap
html,body{
height:100%;
margin:0;
padding:0;
width:100%;
}
#map{
height:100%;
width:100%;
}
vardjConfig={parseOnLoad:true};
dojo.require('esri.map');
varmap;
varinitialExtent={
xmin:-119.3324,
ymin:26.3156,
xmax:-72.3568,
ymax:55.0558,
/*
*WebMercator(102113),orWGS84(4326)-thesearethe
*onlytwothatsupportcontinuouspanacrossthedateline
*/
spatialReference:{wkid:4326}
};
varstartExtent;
varbasemap;
varbrowserSupport=false;
varattempts=0;
functioninitApp(){
varstartExtent=newesri.geometry.Extent(initialExtent);
map=newesri.Map('map',{
extent:startExtent,
wrapAround180:true
});
basemap=newesri.layers.ArcGISTiledMapServiceLayer(
'http://server.arcgisonline.com/ArcGIS/rest/services/'+
'ESRI_StreetMap_World_2D/MapServer');
map.addLayer(basemap);
/*AddGeolocation*/
dojo.connect(map,'onLoad',function(){
getLocation();
});
}
/*
*IftheW3CGeolocationobjectisavailablethengetthecurrent
*location,otherwisereporttheproblem
*/
functiongetLocation(){
/*CheckifthebrowsersupportstheW3CGeolocationAPI*/
if(navigator.geolocation){
browserSupport=true;
navigator.geolocation.getCurrentPosition(plotLocation,
reportProblem,{timeout:45000});
}else
reportProblem();
}
/*Plotthelocationonthemapandzoomtoit*/
functionplotLocation(position){
attempts=0;
varpointsLayer=newesri.layers.GraphicsLayer();
map.addLayer(pointsLayer);
varpoint=newesri.geometry.Point(position.coords.longitude,
position.coords.latitude,newesri.SpatialReference({
wkid:4326
}));
pointsLayer.add(
newesri.Graphic(
point,
newesri.symbol.SimpleMarkerSymbol().setColor(
newdojo.Color([255,0,0,0.5]))
)
);
map.centerAndZoom(point,13);
}
/*Reportanyerrorsusingthisfunction*/
functionreportProblem(e){
/*IsthisasupportissueoranAPIissue?*/
if(browserSupport){
switch(e.code){
casee.PERMISSION_DENIED:
alert('Youhavedeniedaccesstoyourposition.Youwill'+
'notgetthemostoutoftheapplicationnow.');
break;
casee.POSITION_UNAVAILABLE:
alert('Therewasaproblemgettingyourposition.');
break;
casee.TIMEOUT:
/*Threechangestogetthelocationbeforeatruetimeout*/
if(++attempts<3){
navigator.geolocation.getCurrentPosition(plotLocation,
reportProblem);
}else
alert('Theapplicationhastimedoutattemptingtoget'+
'yourlocation.');
break;
default:
alert('TherewasahorribleGeolocationerrorthathas'+
'notbeendefined.');
}
}else
alert('Geolocationisnotsupportedbyyourbrowser.');
}
dojo.addOnLoad(initApp);
Inthisexample,thecalltothegetLocation()functionisinsideananonymous
functionthatwillbecalledonanonLoadeventfromthe
Map.Next,wedefineourtwocallbackfunctions:
plotLocation()andreportProblem().ThereportProblem()functionisexactlylikeitscounterpartinExample 4-2,sothereisnoneedtogointoit
again.plotLocation(),however,ismuchchanged
asdifferentAPIshandleaddingpointsdifferently.TheplotLocation()function
firstcreatesanesri.layers.GraphicsLayercalledpointsLayer,whichiswherethenewpointwill
beplaced,andaddsthislayertothemap.Itthencreatesanew
esri.geometry.Point,point,withthecoordinatespassedfromthe
Positionobject.Next,itaddsanewgraphiconthe
pointsLayerlayer,atpoint,withanesri.symbol.SimpleMarkerSymbol.Finally,the
mapiscenteredandzoomedtothecurrentgeolocation.SupportforOtherBrowsersThecodeinExample 4-5willprovide
geolocationsupportforbrowsersthatimplementtheW3CGeolocation
API.Onceagain,weneedtorewriteourcodetoutilizethe
geo-location-javascriptlibrarytogiveuscross-browsersupportfor
ourgeolocationapplication.
Example 4-6showsanimplementationofa
cross-browsergeolocationapplicationusinggeo-location-javascript
withintheEsriArcGISJavaScriptAPI.Ihaveagainhighlightedthe
changesinthecodeinboldsotheyareeasiertosee.Example 4-6. AddinggeolocationforotherbrowserstoanEsriArcGIS
Map
AddingGeolocationforOtherBrowserstoanEsriMap
html,body{
height:100%;
margin:0;
padding:0;
width:100%;
}
#map{
height:100%;
width:100%;
}
vardjConfig={parseOnLoad:true};
dojo.require('esri.map');
varmap;
varinitialExtent={
xmin:-119.3324,
ymin:26.3156,
xmax:-72.3568,
ymax:55.0558,
/*
*WebMercator(102113),orWGS84(4326)-thesearethe
*onlytwothatsupportcontinuouspanacrossthedateline
*/
spatialReference:{wkid:4326}
};
varstartExtent;
varbasemap;
varbrowserSupport=false;
functioninitApp(){
varstartExtent=newesri.geometry.Extent(initialExtent);
map=newesri.Map('map',{
extent:startExtent,
wrapAround180:true
});
basemap=newesri.layers.ArcGISTiledMapServiceLayer(
'http://server.arcgisonline.com/ArcGIS/rest/services/'+
'ESRI_StreetMap_World_2D/MapServer');
map.addLayer(basemap);
/*AddGeolocation*/
dojo.connect(map,'onLoad',function(){
getLocation();
});
}
/*
*ThebrowserwillnowusewhatevergeolocationAPIisavailableto
*it;hopefullyitwillbetheW3CGeolocationobjectthatisusedto
*getthecurrentlocation.Ifthereisnogeolocationsupportatall,
*thenreporttheproblem.
*/
functiongetLocation(){
/*CheckifthebrowsersupportsanygeolocationAPI*/
if(geo_position_js.init()){
browserSupport=true;
geo_position_js.getCurrentPosition(plotLocation,
reportProblem);
}else
reportProblem();
}
/*Plotthelocationonthemapandzoomtoit*/
functionplotLocation(position){
attempts=0;
varpointsLayer=newesri.layers.GraphicsLayer();
map.addLayer(pointsLayer);
varpoint=newesri.geometry.Point(position.coords.longitude,
position.coords.latitude,newesri.SpatialReference({
wkid:4326
}));
pointsLayer.add(
newesri.Graphic(
point,
newesri.symbol.SimpleMarkerSymbol().setColor(
newdojo.Color([255,0,0,0.5]))
)
);
map.centerAndZoom(point,13);
}
/*Reportanyerrorsusingthisfunction*/
functionreportProblem(){
/*IsthisasupportissueoranAPIissue?*/
if(browserSupport)
alert('Couldnotlocateyourdevice.');
else
alert('Geolocationisnotsupportedbyyourbrowser.');
}
dojo.addOnLoad(initApp);
Callstogears_init.jsand
geo.jsloadthelibrariesweare
usingforgeolocationinthisexample.TheMap
functionalityitselfremainsthesameasinExample 4-5.Insteadofcheckingfornavigator.geolocation,the
geo-location-javascriptinit()
functioniscalled,whichreturnswhetherornotthebrowsersupports
anygeolocationAPI.AsimplercalltogetCurrentPosition()ismade,withoutthe
timeoutset,butotherwisethegetLocation()functionisverysimilarto
thissamefunctioninExample 4-5.NothingchangedbetweenthetwoEsrigeolocationexamplesinthe
plotLocation()function,butthere
are,obviously,bigchangesinthereportProblem()functionbecauseofthelack
ofaPositionErrorobjectwith
geo-location-javascript.ThisiswhatwesawbackinExample 4-3.Formorecomplicatedcross-browsergeolocationneeds,additional
andmorecomplexcodingwillberequiredtogetthejobdone.
Hopefullythegeo-location-javascriptlibrarywilleventuallyaddmore
functionalitytoitscodebasesothatitbettermirrorstheW3C
GeolocationAPImethodsandproperties.Untilthatday,itisupto
applicationdeveloperstowritethisfunctionalitythemselves.Itis
eitherthat,oreveryoneneedstostopusingoutdatedlegacybrowsers
andphones—butunfortunatelyIdonotseethathappeningforafew
yearsstill.[9]GoogleMapsJavaScriptAPIV3.http://code.google.com/apis/maps/documentation/javascript/.[10]MappingSuccess:GoogleMapsCaseStudies.
http://maps.google.com/help/maps/casestudies/.
GetHTML5GeolocationnowwiththeO’Reillylearningplatform.
O’Reillymembersexperienceliveonlinetraining,plusbooks,videos,anddigitalcontentfromnearly200publishers.
Startyourfreetrial
Don’tleaveempty-handed
GetMarkRichards’sSoftwareArchitecturePatternsebooktobetterunderstandhowtodesigncomponents—andhowtheyshouldinteract.
It’syours,free.
Getitnow
Close