A Complete Guide to Sources and Layers in React and ...

文章推薦指數: 80 %
投票人數:10人

We will use Mapbox GL JS and React to build an interactive map with several custom sources and layers. We will be adding sources and layers ... HomeAboutWritingReadingAboutIliketowritealmostasmuchasIliketobuild.Iwriteaboutdashboards,maps,freelancing,music,andtheoutdoors.Ifthisinterestsyoutoo,pleasejoinmymailinglisttogetupdateswheneverIpublishnewcontent.SubscribeIliketowritealmostasmuchasIliketobuild.Iwriteaboutdashboards,maps,freelancing,music,andtheoutdoors.Ifthisinterestsyoutoo,pleasejoinmymailinglisttogetupdateswheneverIpublishnewcontent.SubscribeACompleteGuidetoSourcesandLayersinReactandMapboxGLJSDate:2/22/2021TimetoRead:6minutesThispostispartofmyBuildingInteractiveMapswithReactcourse-acourseforanyonewantingtolearnhowtobuildinteractivemapsandintegratethemintotheirReactapplications.Ifyouenjoythisguide,thenchancesareyouwillenjoythecoursetoo!ThepreviouspostsintheserieshavecoveredhowtouseMapboxStudiotomanagespatialdataandcreatecustombasemaps(readpost)howtocreateabasicapplicationusingMapboxandReact(readpost).ThesepostsarehelpfulinunderstandingthebasicsofMapboxStudioandtherelationbetweenStudioandMapboxGLJS.Understandingthesefundamentalsisessentialwhenyoustartdevelopingmuchlarger,data-drivenmappingapplications.TheaimofthispostistoprovideanintroductiontoaddingavarietyofspatialdataformatstoaReactapplicationusingMapboxGLJS.UnderstandinghowtoaddsourcesandlayerstoamapwillopenalotofdoorsforthetypesofapplicationsyoucanbuildusingMapboxGLJS.Ifyoudonotcaretoomuchabouttheexplanationsandarejustlookingforasnippet,checkouttheCodeSandboxforthisguideorscrolltothebottomofthepost.DecidingBetweenaCustomStyleandCustomCodeIcoveredhowtomanagespatialdatainMapboxStudiousingDatasetsandTilesetsaswellashowtoaddcustomlayerstoaMapboxstyleinearlierposts.Ifyourspatialdataisstaticandwillnotneedtorespondmuchtouserinputsinyourapplication,addingthespatialdatatoacustomMapboxStyleandthenusingthatstyleinyourapplicationisprobablythemostidealworkflow.However,ifyourapplicationandmaparefairlydata-driven,thisguideshouldbeveryrelevanttoyourworkflow.HereareafewcommonexamplesofwhenitisprobablyeasiertobringspatialdataintoyourmapandapplicationusingMapboxGLJSversusacustomstyleinMapboxStudio.TherearewaystoaccommodatetheseusecasesusingMapboxStudio,butIjustfinditeasiertomanagethementirelyusingMapboxGLJS.themapneedstodisplaydatathatupdatesfrequentlyi.e.adeliverymapthatshowsnearreal-timestatusandpositionofdriversthemapneedstousedatafromathirdpartyAPIthemapneedstheabilitytostyleandfilterlayerfeaturesbasedonuserinputWhatWeWillBuildWewilluseMapboxGLJSandReacttobuildaninteractivemapwithseveralcustomsourcesandlayers.Wewillbeaddingsourcesandlayersforavalancheslidepathsnearbyweatherstationsbusroutes3DterraintheskyThenextsectionswillprovideanoverviewofSourcesandLayersfollowedbysomeconcreteusageexamples.Ifyoudonotcaretoomuchabouttheexplanationsandarejustlookingforasnippet,checkouttheCodeSandboxforthisguide.SourcesIliketothinkofaSourceasaminidatastoreformymap.IttellsMapboxwheretofindmydataaswellashowtorepresentit.TherearemultipletypesofSourcesthatyoucanuseincluding:vector,raster,raster-dem,geojson,image,andvideo.ThisprovidesalotofflexibilityintermsofwhatkindofdatacanbeaddedtoaMapboxGLJSapplication.Eachsourcetypehastheirownconfigurationoptions,butyoucangenerallydothingslikesettheminandmaxzoomthresholdsforasource.TheMapboxStyleSpecificationprovidesacomprehensivesummaryofeachtype.Forthisguidethough,wewillbefocusedonthevectorandgeojsonsourcetypes.AddingaVectorSourcehttps://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#vectorProbablythemostcommonwayofaddingspatialdatatoamapisaddingavectortilesourcehostedbyMapbox.Sidenote:IfyouarenotoverlyfamiliarwiththedifferencebetweenvectorandrasterdatainthecontextofGIS,checkoutthishelpfulguidefromCarto.YoucanaddoneofMapbox'stilesetsoraddyourowncustomtilesetthatishostedonMapbox.Seethisearlierpostforinstructionsonhowtocreateyourowntileset.1//addingaMapboxtileset2//methodexpectsyoutoprovideanidforthesource3//aswellsomeconfigurationoptions4map.addSource("mapbox-streets",{5type:"vector",6url:"mapbox://mapbox.mapbox-streets-v8",7})8 9//addingyourowntileset10map.addSource("avalanche-paths",{11type:"vector",12url:"mapbox://lcdesigns.arckuvnm",13})14 AddingaGeoJSONSourcehttps://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#geojsonThismethodisgreatforaddinginspatialdatafromthirdpartyAPIsorpullingindatafromyourownAPIs.YoucandefinetheGeoJSONinline,readGeoJSONdirectlyfromalocalfile,orhitanAPIendpointthatreturnsGeoJSON.1//inlinegeojson2//methodexpectsyoutoprovideanidforthesource3//aswellsomeconfigurationoptions4map.addSource("mapbox-streets",{5type:"geojson",6data:{7"type":"Feature",8"geometry":{9"type":"Polygon",10"coordinates":[11[12[-67.13734351262877,45.137451890638886],13[-66.96466,44.8097],14[-68.03252,44.3252],15[-69.06,43.98],16[-70.11617,43.68405],17[-70.64573401557249,43.090083319667144],18[-70.75102474636725,43.08003225358635],19[-70.79761105007827,43.21973948828747],20[-70.98176001655037,43.36789581966826],21[-70.94416541205806,43.46633942318431],22[-71.08482,45.3052400000002],23[-70.6600225491012,45.46022288673396],24[-70.30495378282376,45.914794623389355],25[-70.00014034695016,46.69317088478567],26[-69.23708614772835,47.44777598732787],27[-68.90478084987546,47.184794623394396],28[-68.23430497910454,47.35462921812177],29[-67.79035274928509,47.066248887716995],30[-67.79141211614706,45.702585354182816],31[-67.13734351262877,45.137451890638886]32]33]34}35});36 37//addingGeoJSONreadfromafile38importExampleDatafrom"./ExampleData.json";39map.addSource("avalanche-paths",{40type:"geojson",41data:ExampleData,42});43 44//addingGeoJSONfromanAPI45importExampleDatafrom"./ExampleData.json";46map.addSource("avalanche-paths",{47type:"geojson",48data:"https://opendata.arcgis.com/datasets/4347f3565fbe4d5dbb97b016768b8907_0.geojson",49});50 LayersLayersarethevisualrepresentationofasource'sdata,theyarewhatactuallygetrenderedonthemap.Onceyouaddasourcetoamap,youcancreateanynumberoflayersusingit.Forinstance,ifIaddedasourcethatcontainedcityparks,Icouldcreatethefollowingthreelayersfromthatsinglesource.afilllayerthatrepresentstheparkboundariesasshadedpolygonsalinelayerthatrepresentstheboundariesasanoutlineasymbollayerthatdisplaystheparknamesastextlabelsMapboxsupportsalotofdifferentlayertypesincludingbackground,fill,line,symbol,raster,circle,fill-extrusion,heatmap,hillshade,andsky.Itisbeyondthescopeofthisguidetocoveralloftheselayertypes,butthisguidewillfocusonthewhatyouwillbemostlikelytouse,fill,line,symbol,andcircle.Anoteaboutlayersisthattheyarerenderedintheordertheyaredefined.Soifyouwantalayertobebelowanotheroneofyourlayers,makesureyouadditfirst.Alternativelythough,youcantellMapboxwhichlayeralayershouldbeaddedbefore/after.Seethisguidetolearnhowtodoso.Eachlayeriscreatedinasimilarfashion,buthasitsownuniquesetoflayoutandpaintproperties(akahowitlooks)thatcanbeconfigured.Itisunfortunatelybeyondthescopeofthisguidetocoveralloftheseconfigurationoptions,buttheMapboxdocsdoagreatjob.Foradeeperdiveintolayers,checkouttheMapboxStyleSpecification.AddingaFillLayerhttps://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#fillFilllayerswillbeyourgotoforvisualizingpolygonsonamap.Thinkusecaseslikeboundaries,censustracts,bodiesofwater,avalanchepaths,buildingfootprints,etc.Thegeneralsyntaxforaddingalayerismoreorlessthesameregardlessoflayertype.Themajordifferencesbetweenlayertypesisinthelayoutandpaintconfigurationoptions(i.ehowthelayerispresentedandstyled).1//addafilllayertothemap2map.addLayer({3id:"avalanche-paths-fill",4type:"fill",5source:"avalanche-paths",6"source-layer":"Utah_Avalanche_Paths-9s9ups",7paint:{8"fill-opacity":0.5,9"fill-color":"#f05c5c",10},11})12 AddingaCircleLayerhttps://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#circleCirclelayersareusefulanytimeyouwanttovisualizepointdata.Asymbollayercanalsobeusedtovisualizepointdatabutthesimplicityofthecirclelayertypecanbenice,especiallyifyouwantdothingslikedata-drivenstyling.1//addacirclelayertothemap2map.addLayer({3id:"snotel-sites-circle",4type:"circle",5source:"snotel-sites",6paint:{7"circle-color":"#ffff00",8"circle-radius":8,9"circle-stroke-color":"#333333",10"circle-stroke-width":2,11},12})13 AddingaLineLayerhttps://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#lineLinelayersareyourbestfriendanytimeyouwanttovisualizealinestring,thinkusecaseslikebusroutes,Lyftroutes,hikingtracks,riversandstreams,etc.1//addalinelayer2map.addLayer({3id:"bus-routes-line",4type:"line",5source:"bus-routes",6paint:{7"line-color":"#15cc09",8"line-width":4,9},10})11 AddingaSymbolLayerSymbollayersaretheonesthattookmethelongesttogetmyheadaround.Therearetwoprimaryusecasesforsymbollayers:1)ifyouwanttovisualizedatausinganiconand2)ifyouwanttolabelmapfeatureswithsometext.Youcanseealloftheiconsthatareavailableforuseasasymbollayeroveratthispage.Justhoveroveranyoftheiconstoseethename(i.e.airfield-15).Youcanalsocreateanduploadyourownicons,butthatwilllikelybethetopicofanotherpost.Addingalabellayerisrelativelystraightforwardtooandyoucanuseanyoftheproperties(fields)inyourdatasourceaslabels.Intheexamplebelow,thereisafieldcalled"StationName"thatIamusingtolabelfeatures.IamusingaMapboxExpression(["get","StationName"])tograbthevaluesfromtheStationNamefield.1//addasymbollayer-icon2map.addLayer({3id:"bus-stops-symbol",4type:"symbol",5source:"bus-stops",6layout:{7icon-image:'bus-15',8}9});10 11//addasymbollayer-textlabel12map.addLayer({13id:"snotel-sites-label",14type:"symbol",15source:"snotel-sites",16layout:{17"text-field":["get","StationName"],18"text-size":14,19"text-offset":[0,-1.5],20},21paint:{22"text-color":"#ffff00",23"text-halo-color":"#333333",24"text-halo-width":1,25},26});27 AddingSourcesandLayerstoaReactMapWithallofthatfoundationestablished(alotofit!),thefollowingstepsshouldhopefullymakeabitmoresense.Inthissection,wearegoingtousethesespecificmethodsfromMapboxGLJStoaddsourcesandlayerstoaninteractivemapinaReactapplication.ProcessOverviewRegardlessofwhattypeofspatialdatayouareaddingtoyourapplication,therewillalwaysbetwokeycomponents:AddingasourceAddingalayerAddingthesourcetellsMapboxthat"hey,thisisadatastorethatcontainsormorelayersthatcouldgetaddedtothemap".Whenyouaddalayertoamap,youthenpointitatthesourceandtellMapboxhowtorepresentthesourceonthemap.Ifyouwanttofollowalongoutsideofthispost,youcanchecktheCodeSandboxortheGithubrepo.ProcessImplementationTherestoftheguideisgoingtopickupwheremyearlierIntroductiontoMapboxandReactpostleftoff.Ihaveputtogetheraworkingsnippetbelowfilledwithcomments.IstartedouttryingtoexplaineverylastbitofwhatwashappeningbutthinkitisalotmoreapparentinalotofwaysifIletthecodespeakforitself.IhaveprovidedlinkstotherelevantMapboxdocswhichdoamuchbetterjobofexplainingthanIevercould.Youcanalsorefertotheprimeraboveonsourcesandlayers.1importReact,{useRef,useEffect}from"react"2importmapboxglfrom"mapbox-gl"3importSnotelSitesfrom"./lcc_snotel_sites.json"4//importthemapboxstyles5//alternativelycanusealinktagintheheadofpublic/index.html6//seehttps://docs.mapbox.com/mapbox-gl-js/api/7import"mapbox-gl/dist/mapbox-gl.css"8import"./app.css"9 10//GrabtheaccesstokenfromyourMapboxaccount11//Itypicallyliketostoresensitivethingslikethis12//ina.envfile13mapboxgl.accessToken=process.env.REACT_APP_MAPBOX_TOKEN14 15constApp=()=>{16constmapContainer=useRef()17 18//thisiswhereallofourmaplogicisgoingtolive19//addingtheemptydependencyarrayensuresthatthemap20//isonlyrenderedonce21useEffect(()=>{22//createthemapandconfigureit23//checkouttheAPIreferenceformoreoptions24//https://docs.mapbox.com/mapbox-gl-js/api/map/25constmap=newmapboxgl.Map({26container:mapContainer.current,27style:"mapbox://styles/mapbox/outdoors-v11",28center:[-111.75,40.581],29zoom:12,30pitch:60,31bearing:80,32})33 34//onlywanttoworkwiththemapafterithasfullyloaded35//ifyoutrytoaddsourcesandlayersbeforethemaphasloaded36//thingswillnotworkproperly37map.on("load",()=>{38//addmapboxterraindemsourcefor3dterrainrendering39map.addSource("mapbox-dem",{40type:"raster-dem",41url:"mapbox://mapbox.mapbox-terrain-dem-v1",42tileSize:512,43maxZoom:16,44})45map.setTerrain({source:"mapbox-dem"})46 47//avalanchepathssource48//exampleofhowtoaddacustomtilesethostedonMapbox49//youcangrabtheurlfromthedetailspageforanytileset50//youhavecreatedinMapboxstudio51//seehttps://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#vector52map.addSource("avalanche-paths",{53type:"vector",54url:"mapbox://lcdesigns.arckuvnm",55})56 57//snotelsitessource58//exampleofusingageojsonsource59//dataishostedlocallyaspartoftheapplication60//seehttps://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#geojson61map.addSource("snotel-sites",{62type:"geojson",63data:SnotelSites,64})65 66//busroutessource67//anotherexampleofusingageojsonsource68//thistimewearehittinganESRIAPIthatreturns69//datainthegeojsonformat70//seehttps://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#geojson71map.addSource("bus-routes",{72type:"geojson",73data:74"https://opendata.arcgis.com/datasets/4347f3565fbe4d5dbb97b016768b8907_0.geojson",75})76 77//avalanchepaths-filllayer78//source-layercanbegrabbedfromthetilesetdetailspage79//inMapboxstudio80//seehttps://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#fill81map.addLayer({82id:"avalanche-paths-fill",83type:"fill",84source:"avalanche-paths",85"source-layer":"Utah_Avalanche_Paths-9s9ups",86paint:{87"fill-opacity":0.5,88"fill-color":"#f05c5c",89},90})91 92//snotelsites-circlelayer93//seehttps://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#circle94map.addLayer({95id:"snotel-sites-circle",96type:"circle",97source:"snotel-sites",98paint:{99"circle-color":"#1d1485",100"circle-radius":8,101"circle-stroke-color":"#ffffff",102"circle-stroke-width":2,103},104})105 106//snotelsites-labellayer107//seehttps://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#symbol108map.addLayer({109id:"snotel-sites-label",110type:"symbol",111source:"snotel-sites",112layout:{113"text-field":["get","StationName"],114"text-size":16,115"text-offset":[0,-1.5],116},117paint:{118"text-color":"#1d1485",119"text-halo-color":"#ffffff",120"text-halo-width":0.5,121},122})123 124//busroutes-linelayer125//seehttps://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#line126map.addLayer({127id:"bus-routes-line",128type:"line",129source:"bus-routes",130paint:{131"line-color":"#15cc09",132"line-width":4,133},134})135 136//addaskylayer137//theskylayerisacustommapboxlayertype138//seehttps://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#sky139map.addLayer({140id:"sky",141type:"sky",142paint:{143"sky-type":"atmosphere",144"sky-atmosphere-sun":[0.0,90.0],145"sky-atmosphere-sun-intensity":15,146},147})148})149 150//cleanupfunctiontoremovemaponunmount151return()=>map.remove()152},[])153 154return155}156 157exportdefaultApp158 NextStepsThisguidejustscratchesthesurfaceintermsofthetypesofsourcesandlayersthatcanbeaddedtoamapusingMapboxGLJS.IencourageyoutoexploretheMapboxdocsandextendmyexamples.Youcouldtrythingslike...tweakingandexpandingthelayerstylingaddingyourownsourcesandlayersIfyoufoundthuspostuseful,givemeafollowonTwitterorconsiderpickingupacopyoftheBuildingInteractiveMapswithReactcourse.UsefulLinksandResourcesCodeSandboxGithubrepoforthisguideVectorvsRasterDataSourcesStyleSpecVectorsourceGeoJSONsourceLayersStyleSpecFillLayerCircleLayerSymbolLayerLineLayerSkyLayerMapboxExpressionsMapboxMakiIconsAddanewlayerbelowlabelsJointheNewsletterIperiodicallysendoutanewsletter.Interested?Signupbelow.Youcanunsubscribeatanytime.Interestedinworkingtogether?Dropmealine



請為這篇文章評分?