| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563 |
- import {
- __commonJS
- } from "./chunk-Y2F7D3TJ.js";
- // ../../../../Work2/Orienteering/mobile_h5/actMgt/node_modules/leaflet/dist/leaflet-src.js
- var require_leaflet_src = __commonJS({
- "../../../../Work2/Orienteering/mobile_h5/actMgt/node_modules/leaflet/dist/leaflet-src.js"(exports, module) {
- (function(global, factory) {
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.leaflet = {}));
- })(exports, function(exports2) {
- "use strict";
- var version = "1.9.4";
- function extend(dest) {
- var i, j, len, src;
- for (j = 1, len = arguments.length; j < len; j++) {
- src = arguments[j];
- for (i in src) {
- dest[i] = src[i];
- }
- }
- return dest;
- }
- var create$2 = Object.create || /* @__PURE__ */ function() {
- function F() {
- }
- return function(proto) {
- F.prototype = proto;
- return new F();
- };
- }();
- function bind(fn, obj) {
- var slice = Array.prototype.slice;
- if (fn.bind) {
- return fn.bind.apply(fn, slice.call(arguments, 1));
- }
- var args = slice.call(arguments, 2);
- return function() {
- return fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments);
- };
- }
- var lastId = 0;
- function stamp(obj) {
- if (!("_leaflet_id" in obj)) {
- obj["_leaflet_id"] = ++lastId;
- }
- return obj._leaflet_id;
- }
- function throttle(fn, time, context) {
- var lock, args, wrapperFn, later;
- later = function() {
- lock = false;
- if (args) {
- wrapperFn.apply(context, args);
- args = false;
- }
- };
- wrapperFn = function() {
- if (lock) {
- args = arguments;
- } else {
- fn.apply(context, arguments);
- setTimeout(later, time);
- lock = true;
- }
- };
- return wrapperFn;
- }
- function wrapNum(x, range, includeMax) {
- var max = range[1], min = range[0], d = max - min;
- return x === max && includeMax ? x : ((x - min) % d + d) % d + min;
- }
- function falseFn() {
- return false;
- }
- function formatNum(num, precision) {
- if (precision === false) {
- return num;
- }
- var pow = Math.pow(10, precision === void 0 ? 6 : precision);
- return Math.round(num * pow) / pow;
- }
- function trim(str) {
- return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, "");
- }
- function splitWords(str) {
- return trim(str).split(/\s+/);
- }
- function setOptions(obj, options) {
- if (!Object.prototype.hasOwnProperty.call(obj, "options")) {
- obj.options = obj.options ? create$2(obj.options) : {};
- }
- for (var i in options) {
- obj.options[i] = options[i];
- }
- return obj.options;
- }
- function getParamString(obj, existingUrl, uppercase) {
- var params = [];
- for (var i in obj) {
- params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + "=" + encodeURIComponent(obj[i]));
- }
- return (!existingUrl || existingUrl.indexOf("?") === -1 ? "?" : "&") + params.join("&");
- }
- var templateRe = /\{ *([\w_ -]+) *\}/g;
- function template(str, data) {
- return str.replace(templateRe, function(str2, key) {
- var value = data[key];
- if (value === void 0) {
- throw new Error("No value provided for variable " + str2);
- } else if (typeof value === "function") {
- value = value(data);
- }
- return value;
- });
- }
- var isArray = Array.isArray || function(obj) {
- return Object.prototype.toString.call(obj) === "[object Array]";
- };
- function indexOf(array, el) {
- for (var i = 0; i < array.length; i++) {
- if (array[i] === el) {
- return i;
- }
- }
- return -1;
- }
- var emptyImageUrl = "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";
- function getPrefixed(name) {
- return window["webkit" + name] || window["moz" + name] || window["ms" + name];
- }
- var lastTime = 0;
- function timeoutDefer(fn) {
- var time = +/* @__PURE__ */ new Date(), timeToCall = Math.max(0, 16 - (time - lastTime));
- lastTime = time + timeToCall;
- return window.setTimeout(fn, timeToCall);
- }
- var requestFn = window.requestAnimationFrame || getPrefixed("RequestAnimationFrame") || timeoutDefer;
- var cancelFn = window.cancelAnimationFrame || getPrefixed("CancelAnimationFrame") || getPrefixed("CancelRequestAnimationFrame") || function(id) {
- window.clearTimeout(id);
- };
- function requestAnimFrame(fn, context, immediate) {
- if (immediate && requestFn === timeoutDefer) {
- fn.call(context);
- } else {
- return requestFn.call(window, bind(fn, context));
- }
- }
- function cancelAnimFrame(id) {
- if (id) {
- cancelFn.call(window, id);
- }
- }
- var Util = {
- __proto__: null,
- extend,
- create: create$2,
- bind,
- get lastId() {
- return lastId;
- },
- stamp,
- throttle,
- wrapNum,
- falseFn,
- formatNum,
- trim,
- splitWords,
- setOptions,
- getParamString,
- template,
- isArray,
- indexOf,
- emptyImageUrl,
- requestFn,
- cancelFn,
- requestAnimFrame,
- cancelAnimFrame
- };
- function Class() {
- }
- Class.extend = function(props) {
- var NewClass = function() {
- setOptions(this);
- if (this.initialize) {
- this.initialize.apply(this, arguments);
- }
- this.callInitHooks();
- };
- var parentProto = NewClass.__super__ = this.prototype;
- var proto = create$2(parentProto);
- proto.constructor = NewClass;
- NewClass.prototype = proto;
- for (var i in this) {
- if (Object.prototype.hasOwnProperty.call(this, i) && i !== "prototype" && i !== "__super__") {
- NewClass[i] = this[i];
- }
- }
- if (props.statics) {
- extend(NewClass, props.statics);
- }
- if (props.includes) {
- checkDeprecatedMixinEvents(props.includes);
- extend.apply(null, [proto].concat(props.includes));
- }
- extend(proto, props);
- delete proto.statics;
- delete proto.includes;
- if (proto.options) {
- proto.options = parentProto.options ? create$2(parentProto.options) : {};
- extend(proto.options, props.options);
- }
- proto._initHooks = [];
- proto.callInitHooks = function() {
- if (this._initHooksCalled) {
- return;
- }
- if (parentProto.callInitHooks) {
- parentProto.callInitHooks.call(this);
- }
- this._initHooksCalled = true;
- for (var i2 = 0, len = proto._initHooks.length; i2 < len; i2++) {
- proto._initHooks[i2].call(this);
- }
- };
- return NewClass;
- };
- Class.include = function(props) {
- var parentOptions = this.prototype.options;
- extend(this.prototype, props);
- if (props.options) {
- this.prototype.options = parentOptions;
- this.mergeOptions(props.options);
- }
- return this;
- };
- Class.mergeOptions = function(options) {
- extend(this.prototype.options, options);
- return this;
- };
- Class.addInitHook = function(fn) {
- var args = Array.prototype.slice.call(arguments, 1);
- var init = typeof fn === "function" ? fn : function() {
- this[fn].apply(this, args);
- };
- this.prototype._initHooks = this.prototype._initHooks || [];
- this.prototype._initHooks.push(init);
- return this;
- };
- function checkDeprecatedMixinEvents(includes) {
- if (typeof L === "undefined" || !L || !L.Mixin) {
- return;
- }
- includes = isArray(includes) ? includes : [includes];
- for (var i = 0; i < includes.length; i++) {
- if (includes[i] === L.Mixin.Events) {
- console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.", new Error().stack);
- }
- }
- }
- var Events = {
- /* @method on(type: String, fn: Function, context?: Object): this
- * Adds a listener function (`fn`) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. `'click dblclick'`).
- *
- * @alternative
- * @method on(eventMap: Object): this
- * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
- */
- on: function(types, fn, context) {
- if (typeof types === "object") {
- for (var type in types) {
- this._on(type, types[type], fn);
- }
- } else {
- types = splitWords(types);
- for (var i = 0, len = types.length; i < len; i++) {
- this._on(types[i], fn, context);
- }
- }
- return this;
- },
- /* @method off(type: String, fn?: Function, context?: Object): this
- * Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to `on`, you must pass the same context to `off` in order to remove the listener.
- *
- * @alternative
- * @method off(eventMap: Object): this
- * Removes a set of type/listener pairs.
- *
- * @alternative
- * @method off: this
- * Removes all listeners to all events on the object. This includes implicitly attached events.
- */
- off: function(types, fn, context) {
- if (!arguments.length) {
- delete this._events;
- } else if (typeof types === "object") {
- for (var type in types) {
- this._off(type, types[type], fn);
- }
- } else {
- types = splitWords(types);
- var removeAll = arguments.length === 1;
- for (var i = 0, len = types.length; i < len; i++) {
- if (removeAll) {
- this._off(types[i]);
- } else {
- this._off(types[i], fn, context);
- }
- }
- }
- return this;
- },
- // attach listener (without syntactic sugar now)
- _on: function(type, fn, context, _once) {
- if (typeof fn !== "function") {
- console.warn("wrong listener type: " + typeof fn);
- return;
- }
- if (this._listens(type, fn, context) !== false) {
- return;
- }
- if (context === this) {
- context = void 0;
- }
- var newListener = { fn, ctx: context };
- if (_once) {
- newListener.once = true;
- }
- this._events = this._events || {};
- this._events[type] = this._events[type] || [];
- this._events[type].push(newListener);
- },
- _off: function(type, fn, context) {
- var listeners, i, len;
- if (!this._events) {
- return;
- }
- listeners = this._events[type];
- if (!listeners) {
- return;
- }
- if (arguments.length === 1) {
- if (this._firingCount) {
- for (i = 0, len = listeners.length; i < len; i++) {
- listeners[i].fn = falseFn;
- }
- }
- delete this._events[type];
- return;
- }
- if (typeof fn !== "function") {
- console.warn("wrong listener type: " + typeof fn);
- return;
- }
- var index2 = this._listens(type, fn, context);
- if (index2 !== false) {
- var listener = listeners[index2];
- if (this._firingCount) {
- listener.fn = falseFn;
- this._events[type] = listeners = listeners.slice();
- }
- listeners.splice(index2, 1);
- }
- },
- // @method fire(type: String, data?: Object, propagate?: Boolean): this
- // Fires an event of the specified type. You can optionally provide a data
- // object — the first argument of the listener function will contain its
- // properties. The event can optionally be propagated to event parents.
- fire: function(type, data, propagate) {
- if (!this.listens(type, propagate)) {
- return this;
- }
- var event = extend({}, data, {
- type,
- target: this,
- sourceTarget: data && data.sourceTarget || this
- });
- if (this._events) {
- var listeners = this._events[type];
- if (listeners) {
- this._firingCount = this._firingCount + 1 || 1;
- for (var i = 0, len = listeners.length; i < len; i++) {
- var l = listeners[i];
- var fn = l.fn;
- if (l.once) {
- this.off(type, fn, l.ctx);
- }
- fn.call(l.ctx || this, event);
- }
- this._firingCount--;
- }
- }
- if (propagate) {
- this._propagateEvent(event);
- }
- return this;
- },
- // @method listens(type: String, propagate?: Boolean): Boolean
- // @method listens(type: String, fn: Function, context?: Object, propagate?: Boolean): Boolean
- // Returns `true` if a particular event type has any listeners attached to it.
- // The verification can optionally be propagated, it will return `true` if parents have the listener attached to it.
- listens: function(type, fn, context, propagate) {
- if (typeof type !== "string") {
- console.warn('"string" type argument expected');
- }
- var _fn = fn;
- if (typeof fn !== "function") {
- propagate = !!fn;
- _fn = void 0;
- context = void 0;
- }
- var listeners = this._events && this._events[type];
- if (listeners && listeners.length) {
- if (this._listens(type, _fn, context) !== false) {
- return true;
- }
- }
- if (propagate) {
- for (var id in this._eventParents) {
- if (this._eventParents[id].listens(type, fn, context, propagate)) {
- return true;
- }
- }
- }
- return false;
- },
- // returns the index (number) or false
- _listens: function(type, fn, context) {
- if (!this._events) {
- return false;
- }
- var listeners = this._events[type] || [];
- if (!fn) {
- return !!listeners.length;
- }
- if (context === this) {
- context = void 0;
- }
- for (var i = 0, len = listeners.length; i < len; i++) {
- if (listeners[i].fn === fn && listeners[i].ctx === context) {
- return i;
- }
- }
- return false;
- },
- // @method once(…): this
- // Behaves as [`on(…)`](#evented-on), except the listener will only get fired once and then removed.
- once: function(types, fn, context) {
- if (typeof types === "object") {
- for (var type in types) {
- this._on(type, types[type], fn, true);
- }
- } else {
- types = splitWords(types);
- for (var i = 0, len = types.length; i < len; i++) {
- this._on(types[i], fn, context, true);
- }
- }
- return this;
- },
- // @method addEventParent(obj: Evented): this
- // Adds an event parent - an `Evented` that will receive propagated events
- addEventParent: function(obj) {
- this._eventParents = this._eventParents || {};
- this._eventParents[stamp(obj)] = obj;
- return this;
- },
- // @method removeEventParent(obj: Evented): this
- // Removes an event parent, so it will stop receiving propagated events
- removeEventParent: function(obj) {
- if (this._eventParents) {
- delete this._eventParents[stamp(obj)];
- }
- return this;
- },
- _propagateEvent: function(e) {
- for (var id in this._eventParents) {
- this._eventParents[id].fire(e.type, extend({
- layer: e.target,
- propagatedFrom: e.target
- }, e), true);
- }
- }
- };
- Events.addEventListener = Events.on;
- Events.removeEventListener = Events.clearAllEventListeners = Events.off;
- Events.addOneTimeEventListener = Events.once;
- Events.fireEvent = Events.fire;
- Events.hasEventListeners = Events.listens;
- var Evented = Class.extend(Events);
- function Point(x, y, round) {
- this.x = round ? Math.round(x) : x;
- this.y = round ? Math.round(y) : y;
- }
- var trunc = Math.trunc || function(v) {
- return v > 0 ? Math.floor(v) : Math.ceil(v);
- };
- Point.prototype = {
- // @method clone(): Point
- // Returns a copy of the current point.
- clone: function() {
- return new Point(this.x, this.y);
- },
- // @method add(otherPoint: Point): Point
- // Returns the result of addition of the current and the given points.
- add: function(point) {
- return this.clone()._add(toPoint(point));
- },
- _add: function(point) {
- this.x += point.x;
- this.y += point.y;
- return this;
- },
- // @method subtract(otherPoint: Point): Point
- // Returns the result of subtraction of the given point from the current.
- subtract: function(point) {
- return this.clone()._subtract(toPoint(point));
- },
- _subtract: function(point) {
- this.x -= point.x;
- this.y -= point.y;
- return this;
- },
- // @method divideBy(num: Number): Point
- // Returns the result of division of the current point by the given number.
- divideBy: function(num) {
- return this.clone()._divideBy(num);
- },
- _divideBy: function(num) {
- this.x /= num;
- this.y /= num;
- return this;
- },
- // @method multiplyBy(num: Number): Point
- // Returns the result of multiplication of the current point by the given number.
- multiplyBy: function(num) {
- return this.clone()._multiplyBy(num);
- },
- _multiplyBy: function(num) {
- this.x *= num;
- this.y *= num;
- return this;
- },
- // @method scaleBy(scale: Point): Point
- // Multiply each coordinate of the current point by each coordinate of
- // `scale`. In linear algebra terms, multiply the point by the
- // [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation)
- // defined by `scale`.
- scaleBy: function(point) {
- return new Point(this.x * point.x, this.y * point.y);
- },
- // @method unscaleBy(scale: Point): Point
- // Inverse of `scaleBy`. Divide each coordinate of the current point by
- // each coordinate of `scale`.
- unscaleBy: function(point) {
- return new Point(this.x / point.x, this.y / point.y);
- },
- // @method round(): Point
- // Returns a copy of the current point with rounded coordinates.
- round: function() {
- return this.clone()._round();
- },
- _round: function() {
- this.x = Math.round(this.x);
- this.y = Math.round(this.y);
- return this;
- },
- // @method floor(): Point
- // Returns a copy of the current point with floored coordinates (rounded down).
- floor: function() {
- return this.clone()._floor();
- },
- _floor: function() {
- this.x = Math.floor(this.x);
- this.y = Math.floor(this.y);
- return this;
- },
- // @method ceil(): Point
- // Returns a copy of the current point with ceiled coordinates (rounded up).
- ceil: function() {
- return this.clone()._ceil();
- },
- _ceil: function() {
- this.x = Math.ceil(this.x);
- this.y = Math.ceil(this.y);
- return this;
- },
- // @method trunc(): Point
- // Returns a copy of the current point with truncated coordinates (rounded towards zero).
- trunc: function() {
- return this.clone()._trunc();
- },
- _trunc: function() {
- this.x = trunc(this.x);
- this.y = trunc(this.y);
- return this;
- },
- // @method distanceTo(otherPoint: Point): Number
- // Returns the cartesian distance between the current and the given points.
- distanceTo: function(point) {
- point = toPoint(point);
- var x = point.x - this.x, y = point.y - this.y;
- return Math.sqrt(x * x + y * y);
- },
- // @method equals(otherPoint: Point): Boolean
- // Returns `true` if the given point has the same coordinates.
- equals: function(point) {
- point = toPoint(point);
- return point.x === this.x && point.y === this.y;
- },
- // @method contains(otherPoint: Point): Boolean
- // Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).
- contains: function(point) {
- point = toPoint(point);
- return Math.abs(point.x) <= Math.abs(this.x) && Math.abs(point.y) <= Math.abs(this.y);
- },
- // @method toString(): String
- // Returns a string representation of the point for debugging purposes.
- toString: function() {
- return "Point(" + formatNum(this.x) + ", " + formatNum(this.y) + ")";
- }
- };
- function toPoint(x, y, round) {
- if (x instanceof Point) {
- return x;
- }
- if (isArray(x)) {
- return new Point(x[0], x[1]);
- }
- if (x === void 0 || x === null) {
- return x;
- }
- if (typeof x === "object" && "x" in x && "y" in x) {
- return new Point(x.x, x.y);
- }
- return new Point(x, y, round);
- }
- function Bounds(a, b) {
- if (!a) {
- return;
- }
- var points = b ? [a, b] : a;
- for (var i = 0, len = points.length; i < len; i++) {
- this.extend(points[i]);
- }
- }
- Bounds.prototype = {
- // @method extend(point: Point): this
- // Extends the bounds to contain the given point.
- // @alternative
- // @method extend(otherBounds: Bounds): this
- // Extend the bounds to contain the given bounds
- extend: function(obj) {
- var min2, max2;
- if (!obj) {
- return this;
- }
- if (obj instanceof Point || typeof obj[0] === "number" || "x" in obj) {
- min2 = max2 = toPoint(obj);
- } else {
- obj = toBounds(obj);
- min2 = obj.min;
- max2 = obj.max;
- if (!min2 || !max2) {
- return this;
- }
- }
- if (!this.min && !this.max) {
- this.min = min2.clone();
- this.max = max2.clone();
- } else {
- this.min.x = Math.min(min2.x, this.min.x);
- this.max.x = Math.max(max2.x, this.max.x);
- this.min.y = Math.min(min2.y, this.min.y);
- this.max.y = Math.max(max2.y, this.max.y);
- }
- return this;
- },
- // @method getCenter(round?: Boolean): Point
- // Returns the center point of the bounds.
- getCenter: function(round) {
- return toPoint(
- (this.min.x + this.max.x) / 2,
- (this.min.y + this.max.y) / 2,
- round
- );
- },
- // @method getBottomLeft(): Point
- // Returns the bottom-left point of the bounds.
- getBottomLeft: function() {
- return toPoint(this.min.x, this.max.y);
- },
- // @method getTopRight(): Point
- // Returns the top-right point of the bounds.
- getTopRight: function() {
- return toPoint(this.max.x, this.min.y);
- },
- // @method getTopLeft(): Point
- // Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)).
- getTopLeft: function() {
- return this.min;
- },
- // @method getBottomRight(): Point
- // Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)).
- getBottomRight: function() {
- return this.max;
- },
- // @method getSize(): Point
- // Returns the size of the given bounds
- getSize: function() {
- return this.max.subtract(this.min);
- },
- // @method contains(otherBounds: Bounds): Boolean
- // Returns `true` if the rectangle contains the given one.
- // @alternative
- // @method contains(point: Point): Boolean
- // Returns `true` if the rectangle contains the given point.
- contains: function(obj) {
- var min, max;
- if (typeof obj[0] === "number" || obj instanceof Point) {
- obj = toPoint(obj);
- } else {
- obj = toBounds(obj);
- }
- if (obj instanceof Bounds) {
- min = obj.min;
- max = obj.max;
- } else {
- min = max = obj;
- }
- return min.x >= this.min.x && max.x <= this.max.x && min.y >= this.min.y && max.y <= this.max.y;
- },
- // @method intersects(otherBounds: Bounds): Boolean
- // Returns `true` if the rectangle intersects the given bounds. Two bounds
- // intersect if they have at least one point in common.
- intersects: function(bounds) {
- bounds = toBounds(bounds);
- var min = this.min, max = this.max, min2 = bounds.min, max2 = bounds.max, xIntersects = max2.x >= min.x && min2.x <= max.x, yIntersects = max2.y >= min.y && min2.y <= max.y;
- return xIntersects && yIntersects;
- },
- // @method overlaps(otherBounds: Bounds): Boolean
- // Returns `true` if the rectangle overlaps the given bounds. Two bounds
- // overlap if their intersection is an area.
- overlaps: function(bounds) {
- bounds = toBounds(bounds);
- var min = this.min, max = this.max, min2 = bounds.min, max2 = bounds.max, xOverlaps = max2.x > min.x && min2.x < max.x, yOverlaps = max2.y > min.y && min2.y < max.y;
- return xOverlaps && yOverlaps;
- },
- // @method isValid(): Boolean
- // Returns `true` if the bounds are properly initialized.
- isValid: function() {
- return !!(this.min && this.max);
- },
- // @method pad(bufferRatio: Number): Bounds
- // Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.
- // For example, a ratio of 0.5 extends the bounds by 50% in each direction.
- // Negative values will retract the bounds.
- pad: function(bufferRatio) {
- var min = this.min, max = this.max, heightBuffer = Math.abs(min.x - max.x) * bufferRatio, widthBuffer = Math.abs(min.y - max.y) * bufferRatio;
- return toBounds(
- toPoint(min.x - heightBuffer, min.y - widthBuffer),
- toPoint(max.x + heightBuffer, max.y + widthBuffer)
- );
- },
- // @method equals(otherBounds: Bounds): Boolean
- // Returns `true` if the rectangle is equivalent to the given bounds.
- equals: function(bounds) {
- if (!bounds) {
- return false;
- }
- bounds = toBounds(bounds);
- return this.min.equals(bounds.getTopLeft()) && this.max.equals(bounds.getBottomRight());
- }
- };
- function toBounds(a, b) {
- if (!a || a instanceof Bounds) {
- return a;
- }
- return new Bounds(a, b);
- }
- function LatLngBounds(corner1, corner2) {
- if (!corner1) {
- return;
- }
- var latlngs = corner2 ? [corner1, corner2] : corner1;
- for (var i = 0, len = latlngs.length; i < len; i++) {
- this.extend(latlngs[i]);
- }
- }
- LatLngBounds.prototype = {
- // @method extend(latlng: LatLng): this
- // Extend the bounds to contain the given point
- // @alternative
- // @method extend(otherBounds: LatLngBounds): this
- // Extend the bounds to contain the given bounds
- extend: function(obj) {
- var sw = this._southWest, ne = this._northEast, sw2, ne2;
- if (obj instanceof LatLng) {
- sw2 = obj;
- ne2 = obj;
- } else if (obj instanceof LatLngBounds) {
- sw2 = obj._southWest;
- ne2 = obj._northEast;
- if (!sw2 || !ne2) {
- return this;
- }
- } else {
- return obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this;
- }
- if (!sw && !ne) {
- this._southWest = new LatLng(sw2.lat, sw2.lng);
- this._northEast = new LatLng(ne2.lat, ne2.lng);
- } else {
- sw.lat = Math.min(sw2.lat, sw.lat);
- sw.lng = Math.min(sw2.lng, sw.lng);
- ne.lat = Math.max(ne2.lat, ne.lat);
- ne.lng = Math.max(ne2.lng, ne.lng);
- }
- return this;
- },
- // @method pad(bufferRatio: Number): LatLngBounds
- // Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.
- // For example, a ratio of 0.5 extends the bounds by 50% in each direction.
- // Negative values will retract the bounds.
- pad: function(bufferRatio) {
- var sw = this._southWest, ne = this._northEast, heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;
- return new LatLngBounds(
- new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),
- new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)
- );
- },
- // @method getCenter(): LatLng
- // Returns the center point of the bounds.
- getCenter: function() {
- return new LatLng(
- (this._southWest.lat + this._northEast.lat) / 2,
- (this._southWest.lng + this._northEast.lng) / 2
- );
- },
- // @method getSouthWest(): LatLng
- // Returns the south-west point of the bounds.
- getSouthWest: function() {
- return this._southWest;
- },
- // @method getNorthEast(): LatLng
- // Returns the north-east point of the bounds.
- getNorthEast: function() {
- return this._northEast;
- },
- // @method getNorthWest(): LatLng
- // Returns the north-west point of the bounds.
- getNorthWest: function() {
- return new LatLng(this.getNorth(), this.getWest());
- },
- // @method getSouthEast(): LatLng
- // Returns the south-east point of the bounds.
- getSouthEast: function() {
- return new LatLng(this.getSouth(), this.getEast());
- },
- // @method getWest(): Number
- // Returns the west longitude of the bounds
- getWest: function() {
- return this._southWest.lng;
- },
- // @method getSouth(): Number
- // Returns the south latitude of the bounds
- getSouth: function() {
- return this._southWest.lat;
- },
- // @method getEast(): Number
- // Returns the east longitude of the bounds
- getEast: function() {
- return this._northEast.lng;
- },
- // @method getNorth(): Number
- // Returns the north latitude of the bounds
- getNorth: function() {
- return this._northEast.lat;
- },
- // @method contains(otherBounds: LatLngBounds): Boolean
- // Returns `true` if the rectangle contains the given one.
- // @alternative
- // @method contains (latlng: LatLng): Boolean
- // Returns `true` if the rectangle contains the given point.
- contains: function(obj) {
- if (typeof obj[0] === "number" || obj instanceof LatLng || "lat" in obj) {
- obj = toLatLng(obj);
- } else {
- obj = toLatLngBounds(obj);
- }
- var sw = this._southWest, ne = this._northEast, sw2, ne2;
- if (obj instanceof LatLngBounds) {
- sw2 = obj.getSouthWest();
- ne2 = obj.getNorthEast();
- } else {
- sw2 = ne2 = obj;
- }
- return sw2.lat >= sw.lat && ne2.lat <= ne.lat && sw2.lng >= sw.lng && ne2.lng <= ne.lng;
- },
- // @method intersects(otherBounds: LatLngBounds): Boolean
- // Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.
- intersects: function(bounds) {
- bounds = toLatLngBounds(bounds);
- var sw = this._southWest, ne = this._northEast, sw2 = bounds.getSouthWest(), ne2 = bounds.getNorthEast(), latIntersects = ne2.lat >= sw.lat && sw2.lat <= ne.lat, lngIntersects = ne2.lng >= sw.lng && sw2.lng <= ne.lng;
- return latIntersects && lngIntersects;
- },
- // @method overlaps(otherBounds: LatLngBounds): Boolean
- // Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.
- overlaps: function(bounds) {
- bounds = toLatLngBounds(bounds);
- var sw = this._southWest, ne = this._northEast, sw2 = bounds.getSouthWest(), ne2 = bounds.getNorthEast(), latOverlaps = ne2.lat > sw.lat && sw2.lat < ne.lat, lngOverlaps = ne2.lng > sw.lng && sw2.lng < ne.lng;
- return latOverlaps && lngOverlaps;
- },
- // @method toBBoxString(): String
- // Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.
- toBBoxString: function() {
- return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(",");
- },
- // @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean
- // Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number.
- equals: function(bounds, maxMargin) {
- if (!bounds) {
- return false;
- }
- bounds = toLatLngBounds(bounds);
- return this._southWest.equals(bounds.getSouthWest(), maxMargin) && this._northEast.equals(bounds.getNorthEast(), maxMargin);
- },
- // @method isValid(): Boolean
- // Returns `true` if the bounds are properly initialized.
- isValid: function() {
- return !!(this._southWest && this._northEast);
- }
- };
- function toLatLngBounds(a, b) {
- if (a instanceof LatLngBounds) {
- return a;
- }
- return new LatLngBounds(a, b);
- }
- function LatLng(lat, lng, alt) {
- if (isNaN(lat) || isNaN(lng)) {
- throw new Error("Invalid LatLng object: (" + lat + ", " + lng + ")");
- }
- this.lat = +lat;
- this.lng = +lng;
- if (alt !== void 0) {
- this.alt = +alt;
- }
- }
- LatLng.prototype = {
- // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean
- // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number.
- equals: function(obj, maxMargin) {
- if (!obj) {
- return false;
- }
- obj = toLatLng(obj);
- var margin = Math.max(
- Math.abs(this.lat - obj.lat),
- Math.abs(this.lng - obj.lng)
- );
- return margin <= (maxMargin === void 0 ? 1e-9 : maxMargin);
- },
- // @method toString(): String
- // Returns a string representation of the point (for debugging purposes).
- toString: function(precision) {
- return "LatLng(" + formatNum(this.lat, precision) + ", " + formatNum(this.lng, precision) + ")";
- },
- // @method distanceTo(otherLatLng: LatLng): Number
- // Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines).
- distanceTo: function(other) {
- return Earth.distance(this, toLatLng(other));
- },
- // @method wrap(): LatLng
- // Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees.
- wrap: function() {
- return Earth.wrapLatLng(this);
- },
- // @method toBounds(sizeInMeters: Number): LatLngBounds
- // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`.
- toBounds: function(sizeInMeters) {
- var latAccuracy = 180 * sizeInMeters / 40075017, lngAccuracy = latAccuracy / Math.cos(Math.PI / 180 * this.lat);
- return toLatLngBounds(
- [this.lat - latAccuracy, this.lng - lngAccuracy],
- [this.lat + latAccuracy, this.lng + lngAccuracy]
- );
- },
- clone: function() {
- return new LatLng(this.lat, this.lng, this.alt);
- }
- };
- function toLatLng(a, b, c) {
- if (a instanceof LatLng) {
- return a;
- }
- if (isArray(a) && typeof a[0] !== "object") {
- if (a.length === 3) {
- return new LatLng(a[0], a[1], a[2]);
- }
- if (a.length === 2) {
- return new LatLng(a[0], a[1]);
- }
- return null;
- }
- if (a === void 0 || a === null) {
- return a;
- }
- if (typeof a === "object" && "lat" in a) {
- return new LatLng(a.lat, "lng" in a ? a.lng : a.lon, a.alt);
- }
- if (b === void 0) {
- return null;
- }
- return new LatLng(a, b, c);
- }
- var CRS = {
- // @method latLngToPoint(latlng: LatLng, zoom: Number): Point
- // Projects geographical coordinates into pixel coordinates for a given zoom.
- latLngToPoint: function(latlng, zoom2) {
- var projectedPoint = this.projection.project(latlng), scale2 = this.scale(zoom2);
- return this.transformation._transform(projectedPoint, scale2);
- },
- // @method pointToLatLng(point: Point, zoom: Number): LatLng
- // The inverse of `latLngToPoint`. Projects pixel coordinates on a given
- // zoom into geographical coordinates.
- pointToLatLng: function(point, zoom2) {
- var scale2 = this.scale(zoom2), untransformedPoint = this.transformation.untransform(point, scale2);
- return this.projection.unproject(untransformedPoint);
- },
- // @method project(latlng: LatLng): Point
- // Projects geographical coordinates into coordinates in units accepted for
- // this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).
- project: function(latlng) {
- return this.projection.project(latlng);
- },
- // @method unproject(point: Point): LatLng
- // Given a projected coordinate returns the corresponding LatLng.
- // The inverse of `project`.
- unproject: function(point) {
- return this.projection.unproject(point);
- },
- // @method scale(zoom: Number): Number
- // Returns the scale used when transforming projected coordinates into
- // pixel coordinates for a particular zoom. For example, it returns
- // `256 * 2^zoom` for Mercator-based CRS.
- scale: function(zoom2) {
- return 256 * Math.pow(2, zoom2);
- },
- // @method zoom(scale: Number): Number
- // Inverse of `scale()`, returns the zoom level corresponding to a scale
- // factor of `scale`.
- zoom: function(scale2) {
- return Math.log(scale2 / 256) / Math.LN2;
- },
- // @method getProjectedBounds(zoom: Number): Bounds
- // Returns the projection's bounds scaled and transformed for the provided `zoom`.
- getProjectedBounds: function(zoom2) {
- if (this.infinite) {
- return null;
- }
- var b = this.projection.bounds, s = this.scale(zoom2), min = this.transformation.transform(b.min, s), max = this.transformation.transform(b.max, s);
- return new Bounds(min, max);
- },
- // @method distance(latlng1: LatLng, latlng2: LatLng): Number
- // Returns the distance between two geographical coordinates.
- // @property code: String
- // Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`)
- //
- // @property wrapLng: Number[]
- // An array of two numbers defining whether the longitude (horizontal) coordinate
- // axis wraps around a given range and how. Defaults to `[-180, 180]` in most
- // geographical CRSs. If `undefined`, the longitude axis does not wrap around.
- //
- // @property wrapLat: Number[]
- // Like `wrapLng`, but for the latitude (vertical) axis.
- // wrapLng: [min, max],
- // wrapLat: [min, max],
- // @property infinite: Boolean
- // If true, the coordinate space will be unbounded (infinite in both axes)
- infinite: false,
- // @method wrapLatLng(latlng: LatLng): LatLng
- // Returns a `LatLng` where lat and lng has been wrapped according to the
- // CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds.
- wrapLatLng: function(latlng) {
- var lng = this.wrapLng ? wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng, lat = this.wrapLat ? wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat, alt = latlng.alt;
- return new LatLng(lat, lng, alt);
- },
- // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
- // Returns a `LatLngBounds` with the same size as the given one, ensuring
- // that its center is within the CRS's bounds.
- // Only accepts actual `L.LatLngBounds` instances, not arrays.
- wrapLatLngBounds: function(bounds) {
- var center = bounds.getCenter(), newCenter = this.wrapLatLng(center), latShift = center.lat - newCenter.lat, lngShift = center.lng - newCenter.lng;
- if (latShift === 0 && lngShift === 0) {
- return bounds;
- }
- var sw = bounds.getSouthWest(), ne = bounds.getNorthEast(), newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift), newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift);
- return new LatLngBounds(newSw, newNe);
- }
- };
- var Earth = extend({}, CRS, {
- wrapLng: [-180, 180],
- // Mean Earth Radius, as recommended for use by
- // the International Union of Geodesy and Geophysics,
- // see https://rosettacode.org/wiki/Haversine_formula
- R: 6371e3,
- // distance between two geographical points using spherical law of cosines approximation
- distance: function(latlng1, latlng2) {
- var rad = Math.PI / 180, lat1 = latlng1.lat * rad, lat2 = latlng2.lat * rad, sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2), sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2), a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon, c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- return this.R * c;
- }
- });
- var earthRadius = 6378137;
- var SphericalMercator = {
- R: earthRadius,
- MAX_LATITUDE: 85.0511287798,
- project: function(latlng) {
- var d = Math.PI / 180, max = this.MAX_LATITUDE, lat = Math.max(Math.min(max, latlng.lat), -max), sin = Math.sin(lat * d);
- return new Point(
- this.R * latlng.lng * d,
- this.R * Math.log((1 + sin) / (1 - sin)) / 2
- );
- },
- unproject: function(point) {
- var d = 180 / Math.PI;
- return new LatLng(
- (2 * Math.atan(Math.exp(point.y / this.R)) - Math.PI / 2) * d,
- point.x * d / this.R
- );
- },
- bounds: function() {
- var d = earthRadius * Math.PI;
- return new Bounds([-d, -d], [d, d]);
- }()
- };
- function Transformation(a, b, c, d) {
- if (isArray(a)) {
- this._a = a[0];
- this._b = a[1];
- this._c = a[2];
- this._d = a[3];
- return;
- }
- this._a = a;
- this._b = b;
- this._c = c;
- this._d = d;
- }
- Transformation.prototype = {
- // @method transform(point: Point, scale?: Number): Point
- // Returns a transformed point, optionally multiplied by the given scale.
- // Only accepts actual `L.Point` instances, not arrays.
- transform: function(point, scale2) {
- return this._transform(point.clone(), scale2);
- },
- // destructive transform (faster)
- _transform: function(point, scale2) {
- scale2 = scale2 || 1;
- point.x = scale2 * (this._a * point.x + this._b);
- point.y = scale2 * (this._c * point.y + this._d);
- return point;
- },
- // @method untransform(point: Point, scale?: Number): Point
- // Returns the reverse transformation of the given point, optionally divided
- // by the given scale. Only accepts actual `L.Point` instances, not arrays.
- untransform: function(point, scale2) {
- scale2 = scale2 || 1;
- return new Point(
- (point.x / scale2 - this._b) / this._a,
- (point.y / scale2 - this._d) / this._c
- );
- }
- };
- function toTransformation(a, b, c, d) {
- return new Transformation(a, b, c, d);
- }
- var EPSG3857 = extend({}, Earth, {
- code: "EPSG:3857",
- projection: SphericalMercator,
- transformation: function() {
- var scale2 = 0.5 / (Math.PI * SphericalMercator.R);
- return toTransformation(scale2, 0.5, -scale2, 0.5);
- }()
- });
- var EPSG900913 = extend({}, EPSG3857, {
- code: "EPSG:900913"
- });
- function svgCreate(name) {
- return document.createElementNS("http://www.w3.org/2000/svg", name);
- }
- function pointsToPath(rings, closed) {
- var str = "", i, j, len, len2, points, p;
- for (i = 0, len = rings.length; i < len; i++) {
- points = rings[i];
- for (j = 0, len2 = points.length; j < len2; j++) {
- p = points[j];
- str += (j ? "L" : "M") + p.x + " " + p.y;
- }
- str += closed ? Browser.svg ? "z" : "x" : "";
- }
- return str || "M0 0";
- }
- var style = document.documentElement.style;
- var ie = "ActiveXObject" in window;
- var ielt9 = ie && !document.addEventListener;
- var edge = "msLaunchUri" in navigator && !("documentMode" in document);
- var webkit = userAgentContains("webkit");
- var android = userAgentContains("android");
- var android23 = userAgentContains("android 2") || userAgentContains("android 3");
- var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10);
- var androidStock = android && userAgentContains("Google") && webkitVer < 537 && !("AudioNode" in window);
- var opera = !!window.opera;
- var chrome = !edge && userAgentContains("chrome");
- var gecko = userAgentContains("gecko") && !webkit && !opera && !ie;
- var safari = !chrome && userAgentContains("safari");
- var phantom = userAgentContains("phantom");
- var opera12 = "OTransition" in style;
- var win = navigator.platform.indexOf("Win") === 0;
- var ie3d = ie && "transition" in style;
- var webkit3d = "WebKitCSSMatrix" in window && "m11" in new window.WebKitCSSMatrix() && !android23;
- var gecko3d = "MozPerspective" in style;
- var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom;
- var mobile = typeof orientation !== "undefined" || userAgentContains("mobile");
- var mobileWebkit = mobile && webkit;
- var mobileWebkit3d = mobile && webkit3d;
- var msPointer = !window.PointerEvent && window.MSPointerEvent;
- var pointer = !!(window.PointerEvent || msPointer);
- var touchNative = "ontouchstart" in window || !!window.TouchEvent;
- var touch = !window.L_NO_TOUCH && (touchNative || pointer);
- var mobileOpera = mobile && opera;
- var mobileGecko = mobile && gecko;
- var retina = (window.devicePixelRatio || window.screen.deviceXDPI / window.screen.logicalXDPI) > 1;
- var passiveEvents = function() {
- var supportsPassiveOption = false;
- try {
- var opts = Object.defineProperty({}, "passive", {
- get: function() {
- supportsPassiveOption = true;
- }
- });
- window.addEventListener("testPassiveEventSupport", falseFn, opts);
- window.removeEventListener("testPassiveEventSupport", falseFn, opts);
- } catch (e) {
- }
- return supportsPassiveOption;
- }();
- var canvas$1 = function() {
- return !!document.createElement("canvas").getContext;
- }();
- var svg$1 = !!(document.createElementNS && svgCreate("svg").createSVGRect);
- var inlineSvg = !!svg$1 && function() {
- var div = document.createElement("div");
- div.innerHTML = "<svg/>";
- return (div.firstChild && div.firstChild.namespaceURI) === "http://www.w3.org/2000/svg";
- }();
- var vml = !svg$1 && function() {
- try {
- var div = document.createElement("div");
- div.innerHTML = '<v:shape adj="1"/>';
- var shape = div.firstChild;
- shape.style.behavior = "url(#default#VML)";
- return shape && typeof shape.adj === "object";
- } catch (e) {
- return false;
- }
- }();
- var mac = navigator.platform.indexOf("Mac") === 0;
- var linux = navigator.platform.indexOf("Linux") === 0;
- function userAgentContains(str) {
- return navigator.userAgent.toLowerCase().indexOf(str) >= 0;
- }
- var Browser = {
- ie,
- ielt9,
- edge,
- webkit,
- android,
- android23,
- androidStock,
- opera,
- chrome,
- gecko,
- safari,
- phantom,
- opera12,
- win,
- ie3d,
- webkit3d,
- gecko3d,
- any3d,
- mobile,
- mobileWebkit,
- mobileWebkit3d,
- msPointer,
- pointer,
- touch,
- touchNative,
- mobileOpera,
- mobileGecko,
- retina,
- passiveEvents,
- canvas: canvas$1,
- svg: svg$1,
- vml,
- inlineSvg,
- mac,
- linux
- };
- var POINTER_DOWN = Browser.msPointer ? "MSPointerDown" : "pointerdown";
- var POINTER_MOVE = Browser.msPointer ? "MSPointerMove" : "pointermove";
- var POINTER_UP = Browser.msPointer ? "MSPointerUp" : "pointerup";
- var POINTER_CANCEL = Browser.msPointer ? "MSPointerCancel" : "pointercancel";
- var pEvent = {
- touchstart: POINTER_DOWN,
- touchmove: POINTER_MOVE,
- touchend: POINTER_UP,
- touchcancel: POINTER_CANCEL
- };
- var handle = {
- touchstart: _onPointerStart,
- touchmove: _handlePointer,
- touchend: _handlePointer,
- touchcancel: _handlePointer
- };
- var _pointers = {};
- var _pointerDocListener = false;
- function addPointerListener(obj, type, handler) {
- if (type === "touchstart") {
- _addPointerDocListener();
- }
- if (!handle[type]) {
- console.warn("wrong event specified:", type);
- return falseFn;
- }
- handler = handle[type].bind(this, handler);
- obj.addEventListener(pEvent[type], handler, false);
- return handler;
- }
- function removePointerListener(obj, type, handler) {
- if (!pEvent[type]) {
- console.warn("wrong event specified:", type);
- return;
- }
- obj.removeEventListener(pEvent[type], handler, false);
- }
- function _globalPointerDown(e) {
- _pointers[e.pointerId] = e;
- }
- function _globalPointerMove(e) {
- if (_pointers[e.pointerId]) {
- _pointers[e.pointerId] = e;
- }
- }
- function _globalPointerUp(e) {
- delete _pointers[e.pointerId];
- }
- function _addPointerDocListener() {
- if (!_pointerDocListener) {
- document.addEventListener(POINTER_DOWN, _globalPointerDown, true);
- document.addEventListener(POINTER_MOVE, _globalPointerMove, true);
- document.addEventListener(POINTER_UP, _globalPointerUp, true);
- document.addEventListener(POINTER_CANCEL, _globalPointerUp, true);
- _pointerDocListener = true;
- }
- }
- function _handlePointer(handler, e) {
- if (e.pointerType === (e.MSPOINTER_TYPE_MOUSE || "mouse")) {
- return;
- }
- e.touches = [];
- for (var i in _pointers) {
- e.touches.push(_pointers[i]);
- }
- e.changedTouches = [e];
- handler(e);
- }
- function _onPointerStart(handler, e) {
- if (e.MSPOINTER_TYPE_TOUCH && e.pointerType === e.MSPOINTER_TYPE_TOUCH) {
- preventDefault(e);
- }
- _handlePointer(handler, e);
- }
- function makeDblclick(event) {
- var newEvent = {}, prop, i;
- for (i in event) {
- prop = event[i];
- newEvent[i] = prop && prop.bind ? prop.bind(event) : prop;
- }
- event = newEvent;
- newEvent.type = "dblclick";
- newEvent.detail = 2;
- newEvent.isTrusted = false;
- newEvent._simulated = true;
- return newEvent;
- }
- var delay = 200;
- function addDoubleTapListener(obj, handler) {
- obj.addEventListener("dblclick", handler);
- var last = 0, detail;
- function simDblclick(e) {
- if (e.detail !== 1) {
- detail = e.detail;
- return;
- }
- if (e.pointerType === "mouse" || e.sourceCapabilities && !e.sourceCapabilities.firesTouchEvents) {
- return;
- }
- var path = getPropagationPath(e);
- if (path.some(function(el) {
- return el instanceof HTMLLabelElement && el.attributes.for;
- }) && !path.some(function(el) {
- return el instanceof HTMLInputElement || el instanceof HTMLSelectElement;
- })) {
- return;
- }
- var now = Date.now();
- if (now - last <= delay) {
- detail++;
- if (detail === 2) {
- handler(makeDblclick(e));
- }
- } else {
- detail = 1;
- }
- last = now;
- }
- obj.addEventListener("click", simDblclick);
- return {
- dblclick: handler,
- simDblclick
- };
- }
- function removeDoubleTapListener(obj, handlers) {
- obj.removeEventListener("dblclick", handlers.dblclick);
- obj.removeEventListener("click", handlers.simDblclick);
- }
- var TRANSFORM = testProp(
- ["transform", "webkitTransform", "OTransform", "MozTransform", "msTransform"]
- );
- var TRANSITION = testProp(
- ["webkitTransition", "transition", "OTransition", "MozTransition", "msTransition"]
- );
- var TRANSITION_END = TRANSITION === "webkitTransition" || TRANSITION === "OTransition" ? TRANSITION + "End" : "transitionend";
- function get(id) {
- return typeof id === "string" ? document.getElementById(id) : id;
- }
- function getStyle(el, style2) {
- var value = el.style[style2] || el.currentStyle && el.currentStyle[style2];
- if ((!value || value === "auto") && document.defaultView) {
- var css = document.defaultView.getComputedStyle(el, null);
- value = css ? css[style2] : null;
- }
- return value === "auto" ? null : value;
- }
- function create$1(tagName, className, container) {
- var el = document.createElement(tagName);
- el.className = className || "";
- if (container) {
- container.appendChild(el);
- }
- return el;
- }
- function remove(el) {
- var parent = el.parentNode;
- if (parent) {
- parent.removeChild(el);
- }
- }
- function empty(el) {
- while (el.firstChild) {
- el.removeChild(el.firstChild);
- }
- }
- function toFront(el) {
- var parent = el.parentNode;
- if (parent && parent.lastChild !== el) {
- parent.appendChild(el);
- }
- }
- function toBack(el) {
- var parent = el.parentNode;
- if (parent && parent.firstChild !== el) {
- parent.insertBefore(el, parent.firstChild);
- }
- }
- function hasClass(el, name) {
- if (el.classList !== void 0) {
- return el.classList.contains(name);
- }
- var className = getClass(el);
- return className.length > 0 && new RegExp("(^|\\s)" + name + "(\\s|$)").test(className);
- }
- function addClass(el, name) {
- if (el.classList !== void 0) {
- var classes = splitWords(name);
- for (var i = 0, len = classes.length; i < len; i++) {
- el.classList.add(classes[i]);
- }
- } else if (!hasClass(el, name)) {
- var className = getClass(el);
- setClass(el, (className ? className + " " : "") + name);
- }
- }
- function removeClass(el, name) {
- if (el.classList !== void 0) {
- el.classList.remove(name);
- } else {
- setClass(el, trim((" " + getClass(el) + " ").replace(" " + name + " ", " ")));
- }
- }
- function setClass(el, name) {
- if (el.className.baseVal === void 0) {
- el.className = name;
- } else {
- el.className.baseVal = name;
- }
- }
- function getClass(el) {
- if (el.correspondingElement) {
- el = el.correspondingElement;
- }
- return el.className.baseVal === void 0 ? el.className : el.className.baseVal;
- }
- function setOpacity(el, value) {
- if ("opacity" in el.style) {
- el.style.opacity = value;
- } else if ("filter" in el.style) {
- _setOpacityIE(el, value);
- }
- }
- function _setOpacityIE(el, value) {
- var filter = false, filterName = "DXImageTransform.Microsoft.Alpha";
- try {
- filter = el.filters.item(filterName);
- } catch (e) {
- if (value === 1) {
- return;
- }
- }
- value = Math.round(value * 100);
- if (filter) {
- filter.Enabled = value !== 100;
- filter.Opacity = value;
- } else {
- el.style.filter += " progid:" + filterName + "(opacity=" + value + ")";
- }
- }
- function testProp(props) {
- var style2 = document.documentElement.style;
- for (var i = 0; i < props.length; i++) {
- if (props[i] in style2) {
- return props[i];
- }
- }
- return false;
- }
- function setTransform(el, offset, scale2) {
- var pos = offset || new Point(0, 0);
- el.style[TRANSFORM] = (Browser.ie3d ? "translate(" + pos.x + "px," + pos.y + "px)" : "translate3d(" + pos.x + "px," + pos.y + "px,0)") + (scale2 ? " scale(" + scale2 + ")" : "");
- }
- function setPosition(el, point) {
- el._leaflet_pos = point;
- if (Browser.any3d) {
- setTransform(el, point);
- } else {
- el.style.left = point.x + "px";
- el.style.top = point.y + "px";
- }
- }
- function getPosition(el) {
- return el._leaflet_pos || new Point(0, 0);
- }
- var disableTextSelection;
- var enableTextSelection;
- var _userSelect;
- if ("onselectstart" in document) {
- disableTextSelection = function() {
- on(window, "selectstart", preventDefault);
- };
- enableTextSelection = function() {
- off(window, "selectstart", preventDefault);
- };
- } else {
- var userSelectProperty = testProp(
- ["userSelect", "WebkitUserSelect", "OUserSelect", "MozUserSelect", "msUserSelect"]
- );
- disableTextSelection = function() {
- if (userSelectProperty) {
- var style2 = document.documentElement.style;
- _userSelect = style2[userSelectProperty];
- style2[userSelectProperty] = "none";
- }
- };
- enableTextSelection = function() {
- if (userSelectProperty) {
- document.documentElement.style[userSelectProperty] = _userSelect;
- _userSelect = void 0;
- }
- };
- }
- function disableImageDrag() {
- on(window, "dragstart", preventDefault);
- }
- function enableImageDrag() {
- off(window, "dragstart", preventDefault);
- }
- var _outlineElement, _outlineStyle;
- function preventOutline(element) {
- while (element.tabIndex === -1) {
- element = element.parentNode;
- }
- if (!element.style) {
- return;
- }
- restoreOutline();
- _outlineElement = element;
- _outlineStyle = element.style.outlineStyle;
- element.style.outlineStyle = "none";
- on(window, "keydown", restoreOutline);
- }
- function restoreOutline() {
- if (!_outlineElement) {
- return;
- }
- _outlineElement.style.outlineStyle = _outlineStyle;
- _outlineElement = void 0;
- _outlineStyle = void 0;
- off(window, "keydown", restoreOutline);
- }
- function getSizedParentNode(element) {
- do {
- element = element.parentNode;
- } while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);
- return element;
- }
- function getScale(element) {
- var rect = element.getBoundingClientRect();
- return {
- x: rect.width / element.offsetWidth || 1,
- y: rect.height / element.offsetHeight || 1,
- boundingClientRect: rect
- };
- }
- var DomUtil = {
- __proto__: null,
- TRANSFORM,
- TRANSITION,
- TRANSITION_END,
- get,
- getStyle,
- create: create$1,
- remove,
- empty,
- toFront,
- toBack,
- hasClass,
- addClass,
- removeClass,
- setClass,
- getClass,
- setOpacity,
- testProp,
- setTransform,
- setPosition,
- getPosition,
- get disableTextSelection() {
- return disableTextSelection;
- },
- get enableTextSelection() {
- return enableTextSelection;
- },
- disableImageDrag,
- enableImageDrag,
- preventOutline,
- restoreOutline,
- getSizedParentNode,
- getScale
- };
- function on(obj, types, fn, context) {
- if (types && typeof types === "object") {
- for (var type in types) {
- addOne(obj, type, types[type], fn);
- }
- } else {
- types = splitWords(types);
- for (var i = 0, len = types.length; i < len; i++) {
- addOne(obj, types[i], fn, context);
- }
- }
- return this;
- }
- var eventsKey = "_leaflet_events";
- function off(obj, types, fn, context) {
- if (arguments.length === 1) {
- batchRemove(obj);
- delete obj[eventsKey];
- } else if (types && typeof types === "object") {
- for (var type in types) {
- removeOne(obj, type, types[type], fn);
- }
- } else {
- types = splitWords(types);
- if (arguments.length === 2) {
- batchRemove(obj, function(type2) {
- return indexOf(types, type2) !== -1;
- });
- } else {
- for (var i = 0, len = types.length; i < len; i++) {
- removeOne(obj, types[i], fn, context);
- }
- }
- }
- return this;
- }
- function batchRemove(obj, filterFn) {
- for (var id in obj[eventsKey]) {
- var type = id.split(/\d/)[0];
- if (!filterFn || filterFn(type)) {
- removeOne(obj, type, null, null, id);
- }
- }
- }
- var mouseSubst = {
- mouseenter: "mouseover",
- mouseleave: "mouseout",
- wheel: !("onwheel" in window) && "mousewheel"
- };
- function addOne(obj, type, fn, context) {
- var id = type + stamp(fn) + (context ? "_" + stamp(context) : "");
- if (obj[eventsKey] && obj[eventsKey][id]) {
- return this;
- }
- var handler = function(e) {
- return fn.call(context || obj, e || window.event);
- };
- var originalHandler = handler;
- if (!Browser.touchNative && Browser.pointer && type.indexOf("touch") === 0) {
- handler = addPointerListener(obj, type, handler);
- } else if (Browser.touch && type === "dblclick") {
- handler = addDoubleTapListener(obj, handler);
- } else if ("addEventListener" in obj) {
- if (type === "touchstart" || type === "touchmove" || type === "wheel" || type === "mousewheel") {
- obj.addEventListener(mouseSubst[type] || type, handler, Browser.passiveEvents ? { passive: false } : false);
- } else if (type === "mouseenter" || type === "mouseleave") {
- handler = function(e) {
- e = e || window.event;
- if (isExternalTarget(obj, e)) {
- originalHandler(e);
- }
- };
- obj.addEventListener(mouseSubst[type], handler, false);
- } else {
- obj.addEventListener(type, originalHandler, false);
- }
- } else {
- obj.attachEvent("on" + type, handler);
- }
- obj[eventsKey] = obj[eventsKey] || {};
- obj[eventsKey][id] = handler;
- }
- function removeOne(obj, type, fn, context, id) {
- id = id || type + stamp(fn) + (context ? "_" + stamp(context) : "");
- var handler = obj[eventsKey] && obj[eventsKey][id];
- if (!handler) {
- return this;
- }
- if (!Browser.touchNative && Browser.pointer && type.indexOf("touch") === 0) {
- removePointerListener(obj, type, handler);
- } else if (Browser.touch && type === "dblclick") {
- removeDoubleTapListener(obj, handler);
- } else if ("removeEventListener" in obj) {
- obj.removeEventListener(mouseSubst[type] || type, handler, false);
- } else {
- obj.detachEvent("on" + type, handler);
- }
- obj[eventsKey][id] = null;
- }
- function stopPropagation(e) {
- if (e.stopPropagation) {
- e.stopPropagation();
- } else if (e.originalEvent) {
- e.originalEvent._stopped = true;
- } else {
- e.cancelBubble = true;
- }
- return this;
- }
- function disableScrollPropagation(el) {
- addOne(el, "wheel", stopPropagation);
- return this;
- }
- function disableClickPropagation(el) {
- on(el, "mousedown touchstart dblclick contextmenu", stopPropagation);
- el["_leaflet_disable_click"] = true;
- return this;
- }
- function preventDefault(e) {
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- return this;
- }
- function stop(e) {
- preventDefault(e);
- stopPropagation(e);
- return this;
- }
- function getPropagationPath(ev) {
- if (ev.composedPath) {
- return ev.composedPath();
- }
- var path = [];
- var el = ev.target;
- while (el) {
- path.push(el);
- el = el.parentNode;
- }
- return path;
- }
- function getMousePosition(e, container) {
- if (!container) {
- return new Point(e.clientX, e.clientY);
- }
- var scale2 = getScale(container), offset = scale2.boundingClientRect;
- return new Point(
- // offset.left/top values are in page scale (like clientX/Y),
- // whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).
- (e.clientX - offset.left) / scale2.x - container.clientLeft,
- (e.clientY - offset.top) / scale2.y - container.clientTop
- );
- }
- var wheelPxFactor = Browser.linux && Browser.chrome ? window.devicePixelRatio : Browser.mac ? window.devicePixelRatio * 3 : window.devicePixelRatio > 0 ? 2 * window.devicePixelRatio : 1;
- function getWheelDelta(e) {
- return Browser.edge ? e.wheelDeltaY / 2 : (
- // Don't trust window-geometry-based delta
- e.deltaY && e.deltaMode === 0 ? -e.deltaY / wheelPxFactor : (
- // Pixels
- e.deltaY && e.deltaMode === 1 ? -e.deltaY * 20 : (
- // Lines
- e.deltaY && e.deltaMode === 2 ? -e.deltaY * 60 : (
- // Pages
- e.deltaX || e.deltaZ ? 0 : (
- // Skip horizontal/depth wheel events
- e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : (
- // Legacy IE pixels
- e.detail && Math.abs(e.detail) < 32765 ? -e.detail * 20 : (
- // Legacy Moz lines
- e.detail ? e.detail / -32765 * 60 : (
- // Legacy Moz pages
- 0
- )
- )
- )
- )
- )
- )
- )
- );
- }
- function isExternalTarget(el, e) {
- var related = e.relatedTarget;
- if (!related) {
- return true;
- }
- try {
- while (related && related !== el) {
- related = related.parentNode;
- }
- } catch (err) {
- return false;
- }
- return related !== el;
- }
- var DomEvent = {
- __proto__: null,
- on,
- off,
- stopPropagation,
- disableScrollPropagation,
- disableClickPropagation,
- preventDefault,
- stop,
- getPropagationPath,
- getMousePosition,
- getWheelDelta,
- isExternalTarget,
- addListener: on,
- removeListener: off
- };
- var PosAnimation = Evented.extend({
- // @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)
- // Run an animation of a given element to a new position, optionally setting
- // duration in seconds (`0.25` by default) and easing linearity factor (3rd
- // argument of the [cubic bezier curve](https://cubic-bezier.com/#0,0,.5,1),
- // `0.5` by default).
- run: function(el, newPos, duration, easeLinearity) {
- this.stop();
- this._el = el;
- this._inProgress = true;
- this._duration = duration || 0.25;
- this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);
- this._startPos = getPosition(el);
- this._offset = newPos.subtract(this._startPos);
- this._startTime = +/* @__PURE__ */ new Date();
- this.fire("start");
- this._animate();
- },
- // @method stop()
- // Stops the animation (if currently running).
- stop: function() {
- if (!this._inProgress) {
- return;
- }
- this._step(true);
- this._complete();
- },
- _animate: function() {
- this._animId = requestAnimFrame(this._animate, this);
- this._step();
- },
- _step: function(round) {
- var elapsed = +/* @__PURE__ */ new Date() - this._startTime, duration = this._duration * 1e3;
- if (elapsed < duration) {
- this._runFrame(this._easeOut(elapsed / duration), round);
- } else {
- this._runFrame(1);
- this._complete();
- }
- },
- _runFrame: function(progress, round) {
- var pos = this._startPos.add(this._offset.multiplyBy(progress));
- if (round) {
- pos._round();
- }
- setPosition(this._el, pos);
- this.fire("step");
- },
- _complete: function() {
- cancelAnimFrame(this._animId);
- this._inProgress = false;
- this.fire("end");
- },
- _easeOut: function(t) {
- return 1 - Math.pow(1 - t, this._easeOutPower);
- }
- });
- var Map = Evented.extend({
- options: {
- // @section Map State Options
- // @option crs: CRS = L.CRS.EPSG3857
- // The [Coordinate Reference System](#crs) to use. Don't change this if you're not
- // sure what it means.
- crs: EPSG3857,
- // @option center: LatLng = undefined
- // Initial geographic center of the map
- center: void 0,
- // @option zoom: Number = undefined
- // Initial map zoom level
- zoom: void 0,
- // @option minZoom: Number = *
- // Minimum zoom level of the map.
- // If not specified and at least one `GridLayer` or `TileLayer` is in the map,
- // the lowest of their `minZoom` options will be used instead.
- minZoom: void 0,
- // @option maxZoom: Number = *
- // Maximum zoom level of the map.
- // If not specified and at least one `GridLayer` or `TileLayer` is in the map,
- // the highest of their `maxZoom` options will be used instead.
- maxZoom: void 0,
- // @option layers: Layer[] = []
- // Array of layers that will be added to the map initially
- layers: [],
- // @option maxBounds: LatLngBounds = null
- // When this option is set, the map restricts the view to the given
- // geographical bounds, bouncing the user back if the user tries to pan
- // outside the view. To set the restriction dynamically, use
- // [`setMaxBounds`](#map-setmaxbounds) method.
- maxBounds: void 0,
- // @option renderer: Renderer = *
- // The default method for drawing vector layers on the map. `L.SVG`
- // or `L.Canvas` by default depending on browser support.
- renderer: void 0,
- // @section Animation Options
- // @option zoomAnimation: Boolean = true
- // Whether the map zoom animation is enabled. By default it's enabled
- // in all browsers that support CSS3 Transitions except Android.
- zoomAnimation: true,
- // @option zoomAnimationThreshold: Number = 4
- // Won't animate zoom if the zoom difference exceeds this value.
- zoomAnimationThreshold: 4,
- // @option fadeAnimation: Boolean = true
- // Whether the tile fade animation is enabled. By default it's enabled
- // in all browsers that support CSS3 Transitions except Android.
- fadeAnimation: true,
- // @option markerZoomAnimation: Boolean = true
- // Whether markers animate their zoom with the zoom animation, if disabled
- // they will disappear for the length of the animation. By default it's
- // enabled in all browsers that support CSS3 Transitions except Android.
- markerZoomAnimation: true,
- // @option transform3DLimit: Number = 2^23
- // Defines the maximum size of a CSS translation transform. The default
- // value should not be changed unless a web browser positions layers in
- // the wrong place after doing a large `panBy`.
- transform3DLimit: 8388608,
- // Precision limit of a 32-bit float
- // @section Interaction Options
- // @option zoomSnap: Number = 1
- // Forces the map's zoom level to always be a multiple of this, particularly
- // right after a [`fitBounds()`](#map-fitbounds) or a pinch-zoom.
- // By default, the zoom level snaps to the nearest integer; lower values
- // (e.g. `0.5` or `0.1`) allow for greater granularity. A value of `0`
- // means the zoom level will not be snapped after `fitBounds` or a pinch-zoom.
- zoomSnap: 1,
- // @option zoomDelta: Number = 1
- // Controls how much the map's zoom level will change after a
- // [`zoomIn()`](#map-zoomin), [`zoomOut()`](#map-zoomout), pressing `+`
- // or `-` on the keyboard, or using the [zoom controls](#control-zoom).
- // Values smaller than `1` (e.g. `0.5`) allow for greater granularity.
- zoomDelta: 1,
- // @option trackResize: Boolean = true
- // Whether the map automatically handles browser window resize to update itself.
- trackResize: true
- },
- initialize: function(id, options) {
- options = setOptions(this, options);
- this._handlers = [];
- this._layers = {};
- this._zoomBoundLayers = {};
- this._sizeChanged = true;
- this._initContainer(id);
- this._initLayout();
- this._onResize = bind(this._onResize, this);
- this._initEvents();
- if (options.maxBounds) {
- this.setMaxBounds(options.maxBounds);
- }
- if (options.zoom !== void 0) {
- this._zoom = this._limitZoom(options.zoom);
- }
- if (options.center && options.zoom !== void 0) {
- this.setView(toLatLng(options.center), options.zoom, { reset: true });
- }
- this.callInitHooks();
- this._zoomAnimated = TRANSITION && Browser.any3d && !Browser.mobileOpera && this.options.zoomAnimation;
- if (this._zoomAnimated) {
- this._createAnimProxy();
- on(this._proxy, TRANSITION_END, this._catchTransitionEnd, this);
- }
- this._addLayers(this.options.layers);
- },
- // @section Methods for modifying map state
- // @method setView(center: LatLng, zoom: Number, options?: Zoom/pan options): this
- // Sets the view of the map (geographical center and zoom) with the given
- // animation options.
- setView: function(center, zoom2, options) {
- zoom2 = zoom2 === void 0 ? this._zoom : this._limitZoom(zoom2);
- center = this._limitCenter(toLatLng(center), zoom2, this.options.maxBounds);
- options = options || {};
- this._stop();
- if (this._loaded && !options.reset && options !== true) {
- if (options.animate !== void 0) {
- options.zoom = extend({ animate: options.animate }, options.zoom);
- options.pan = extend({ animate: options.animate, duration: options.duration }, options.pan);
- }
- var moved = this._zoom !== zoom2 ? this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom2, options.zoom) : this._tryAnimatedPan(center, options.pan);
- if (moved) {
- clearTimeout(this._sizeTimer);
- return this;
- }
- }
- this._resetView(center, zoom2, options.pan && options.pan.noMoveStart);
- return this;
- },
- // @method setZoom(zoom: Number, options?: Zoom/pan options): this
- // Sets the zoom of the map.
- setZoom: function(zoom2, options) {
- if (!this._loaded) {
- this._zoom = zoom2;
- return this;
- }
- return this.setView(this.getCenter(), zoom2, { zoom: options });
- },
- // @method zoomIn(delta?: Number, options?: Zoom options): this
- // Increases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).
- zoomIn: function(delta, options) {
- delta = delta || (Browser.any3d ? this.options.zoomDelta : 1);
- return this.setZoom(this._zoom + delta, options);
- },
- // @method zoomOut(delta?: Number, options?: Zoom options): this
- // Decreases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).
- zoomOut: function(delta, options) {
- delta = delta || (Browser.any3d ? this.options.zoomDelta : 1);
- return this.setZoom(this._zoom - delta, options);
- },
- // @method setZoomAround(latlng: LatLng, zoom: Number, options: Zoom options): this
- // Zooms the map while keeping a specified geographical point on the map
- // stationary (e.g. used internally for scroll zoom and double-click zoom).
- // @alternative
- // @method setZoomAround(offset: Point, zoom: Number, options: Zoom options): this
- // Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.
- setZoomAround: function(latlng, zoom2, options) {
- var scale2 = this.getZoomScale(zoom2), viewHalf = this.getSize().divideBy(2), containerPoint = latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng), centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale2), newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));
- return this.setView(newCenter, zoom2, { zoom: options });
- },
- _getBoundsCenterZoom: function(bounds, options) {
- options = options || {};
- bounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds);
- var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]), paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]), zoom2 = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
- zoom2 = typeof options.maxZoom === "number" ? Math.min(options.maxZoom, zoom2) : zoom2;
- if (zoom2 === Infinity) {
- return {
- center: bounds.getCenter(),
- zoom: zoom2
- };
- }
- var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), swPoint = this.project(bounds.getSouthWest(), zoom2), nePoint = this.project(bounds.getNorthEast(), zoom2), center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom2);
- return {
- center,
- zoom: zoom2
- };
- },
- // @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this
- // Sets a map view that contains the given geographical bounds with the
- // maximum zoom level possible.
- fitBounds: function(bounds, options) {
- bounds = toLatLngBounds(bounds);
- if (!bounds.isValid()) {
- throw new Error("Bounds are not valid.");
- }
- var target = this._getBoundsCenterZoom(bounds, options);
- return this.setView(target.center, target.zoom, options);
- },
- // @method fitWorld(options?: fitBounds options): this
- // Sets a map view that mostly contains the whole world with the maximum
- // zoom level possible.
- fitWorld: function(options) {
- return this.fitBounds([[-90, -180], [90, 180]], options);
- },
- // @method panTo(latlng: LatLng, options?: Pan options): this
- // Pans the map to a given center.
- panTo: function(center, options) {
- return this.setView(center, this._zoom, { pan: options });
- },
- // @method panBy(offset: Point, options?: Pan options): this
- // Pans the map by a given number of pixels (animated).
- panBy: function(offset, options) {
- offset = toPoint(offset).round();
- options = options || {};
- if (!offset.x && !offset.y) {
- return this.fire("moveend");
- }
- if (options.animate !== true && !this.getSize().contains(offset)) {
- this._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom());
- return this;
- }
- if (!this._panAnim) {
- this._panAnim = new PosAnimation();
- this._panAnim.on({
- "step": this._onPanTransitionStep,
- "end": this._onPanTransitionEnd
- }, this);
- }
- if (!options.noMoveStart) {
- this.fire("movestart");
- }
- if (options.animate !== false) {
- addClass(this._mapPane, "leaflet-pan-anim");
- var newPos = this._getMapPanePos().subtract(offset).round();
- this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);
- } else {
- this._rawPanBy(offset);
- this.fire("move").fire("moveend");
- }
- return this;
- },
- // @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this
- // Sets the view of the map (geographical center and zoom) performing a smooth
- // pan-zoom animation.
- flyTo: function(targetCenter, targetZoom, options) {
- options = options || {};
- if (options.animate === false || !Browser.any3d) {
- return this.setView(targetCenter, targetZoom, options);
- }
- this._stop();
- var from = this.project(this.getCenter()), to = this.project(targetCenter), size = this.getSize(), startZoom = this._zoom;
- targetCenter = toLatLng(targetCenter);
- targetZoom = targetZoom === void 0 ? startZoom : targetZoom;
- var w0 = Math.max(size.x, size.y), w1 = w0 * this.getZoomScale(startZoom, targetZoom), u1 = to.distanceTo(from) || 1, rho = 1.42, rho2 = rho * rho;
- function r(i) {
- var s1 = i ? -1 : 1, s2 = i ? w1 : w0, t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1, b1 = 2 * s2 * rho2 * u1, b = t1 / b1, sq = Math.sqrt(b * b + 1) - b;
- var log = sq < 1e-9 ? -18 : Math.log(sq);
- return log;
- }
- function sinh(n) {
- return (Math.exp(n) - Math.exp(-n)) / 2;
- }
- function cosh(n) {
- return (Math.exp(n) + Math.exp(-n)) / 2;
- }
- function tanh(n) {
- return sinh(n) / cosh(n);
- }
- var r0 = r(0);
- function w(s) {
- return w0 * (cosh(r0) / cosh(r0 + rho * s));
- }
- function u(s) {
- return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2;
- }
- function easeOut(t) {
- return 1 - Math.pow(1 - t, 1.5);
- }
- var start = Date.now(), S = (r(1) - r0) / rho, duration = options.duration ? 1e3 * options.duration : 1e3 * S * 0.8;
- function frame() {
- var t = (Date.now() - start) / duration, s = easeOut(t) * S;
- if (t <= 1) {
- this._flyToFrame = requestAnimFrame(frame, this);
- this._move(
- this.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom),
- this.getScaleZoom(w0 / w(s), startZoom),
- { flyTo: true }
- );
- } else {
- this._move(targetCenter, targetZoom)._moveEnd(true);
- }
- }
- this._moveStart(true, options.noMoveStart);
- frame.call(this);
- return this;
- },
- // @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this
- // Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto),
- // but takes a bounds parameter like [`fitBounds`](#map-fitbounds).
- flyToBounds: function(bounds, options) {
- var target = this._getBoundsCenterZoom(bounds, options);
- return this.flyTo(target.center, target.zoom, options);
- },
- // @method setMaxBounds(bounds: LatLngBounds): this
- // Restricts the map view to the given bounds (see the [maxBounds](#map-maxbounds) option).
- setMaxBounds: function(bounds) {
- bounds = toLatLngBounds(bounds);
- if (this.listens("moveend", this._panInsideMaxBounds)) {
- this.off("moveend", this._panInsideMaxBounds);
- }
- if (!bounds.isValid()) {
- this.options.maxBounds = null;
- return this;
- }
- this.options.maxBounds = bounds;
- if (this._loaded) {
- this._panInsideMaxBounds();
- }
- return this.on("moveend", this._panInsideMaxBounds);
- },
- // @method setMinZoom(zoom: Number): this
- // Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option).
- setMinZoom: function(zoom2) {
- var oldZoom = this.options.minZoom;
- this.options.minZoom = zoom2;
- if (this._loaded && oldZoom !== zoom2) {
- this.fire("zoomlevelschange");
- if (this.getZoom() < this.options.minZoom) {
- return this.setZoom(zoom2);
- }
- }
- return this;
- },
- // @method setMaxZoom(zoom: Number): this
- // Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option).
- setMaxZoom: function(zoom2) {
- var oldZoom = this.options.maxZoom;
- this.options.maxZoom = zoom2;
- if (this._loaded && oldZoom !== zoom2) {
- this.fire("zoomlevelschange");
- if (this.getZoom() > this.options.maxZoom) {
- return this.setZoom(zoom2);
- }
- }
- return this;
- },
- // @method panInsideBounds(bounds: LatLngBounds, options?: Pan options): this
- // Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.
- panInsideBounds: function(bounds, options) {
- this._enforcingBounds = true;
- var center = this.getCenter(), newCenter = this._limitCenter(center, this._zoom, toLatLngBounds(bounds));
- if (!center.equals(newCenter)) {
- this.panTo(newCenter, options);
- }
- this._enforcingBounds = false;
- return this;
- },
- // @method panInside(latlng: LatLng, options?: padding options): this
- // Pans the map the minimum amount to make the `latlng` visible. Use
- // padding options to fit the display to more restricted bounds.
- // If `latlng` is already within the (optionally padded) display bounds,
- // the map will not be panned.
- panInside: function(latlng, options) {
- options = options || {};
- var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]), paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]), pixelCenter = this.project(this.getCenter()), pixelPoint = this.project(latlng), pixelBounds = this.getPixelBounds(), paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]), paddedSize = paddedBounds.getSize();
- if (!paddedBounds.contains(pixelPoint)) {
- this._enforcingBounds = true;
- var centerOffset = pixelPoint.subtract(paddedBounds.getCenter());
- var offset = paddedBounds.extend(pixelPoint).getSize().subtract(paddedSize);
- pixelCenter.x += centerOffset.x < 0 ? -offset.x : offset.x;
- pixelCenter.y += centerOffset.y < 0 ? -offset.y : offset.y;
- this.panTo(this.unproject(pixelCenter), options);
- this._enforcingBounds = false;
- }
- return this;
- },
- // @method invalidateSize(options: Zoom/pan options): this
- // Checks if the map container size changed and updates the map if so —
- // call it after you've changed the map size dynamically, also animating
- // pan by default. If `options.pan` is `false`, panning will not occur.
- // If `options.debounceMoveend` is `true`, it will delay `moveend` event so
- // that it doesn't happen often even if the method is called many
- // times in a row.
- // @alternative
- // @method invalidateSize(animate: Boolean): this
- // Checks if the map container size changed and updates the map if so —
- // call it after you've changed the map size dynamically, also animating
- // pan by default.
- invalidateSize: function(options) {
- if (!this._loaded) {
- return this;
- }
- options = extend({
- animate: false,
- pan: true
- }, options === true ? { animate: true } : options);
- var oldSize = this.getSize();
- this._sizeChanged = true;
- this._lastCenter = null;
- var newSize = this.getSize(), oldCenter = oldSize.divideBy(2).round(), newCenter = newSize.divideBy(2).round(), offset = oldCenter.subtract(newCenter);
- if (!offset.x && !offset.y) {
- return this;
- }
- if (options.animate && options.pan) {
- this.panBy(offset);
- } else {
- if (options.pan) {
- this._rawPanBy(offset);
- }
- this.fire("move");
- if (options.debounceMoveend) {
- clearTimeout(this._sizeTimer);
- this._sizeTimer = setTimeout(bind(this.fire, this, "moveend"), 200);
- } else {
- this.fire("moveend");
- }
- }
- return this.fire("resize", {
- oldSize,
- newSize
- });
- },
- // @section Methods for modifying map state
- // @method stop(): this
- // Stops the currently running `panTo` or `flyTo` animation, if any.
- stop: function() {
- this.setZoom(this._limitZoom(this._zoom));
- if (!this.options.zoomSnap) {
- this.fire("viewreset");
- }
- return this._stop();
- },
- // @section Geolocation methods
- // @method locate(options?: Locate options): this
- // Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound)
- // event with location data on success or a [`locationerror`](#map-locationerror) event on failure,
- // and optionally sets the map view to the user's location with respect to
- // detection accuracy (or to the world view if geolocation failed).
- // Note that, if your page doesn't use HTTPS, this method will fail in
- // modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins))
- // See `Locate options` for more details.
- locate: function(options) {
- options = this._locateOptions = extend({
- timeout: 1e4,
- watch: false
- // setView: false
- // maxZoom: <Number>
- // maximumAge: 0
- // enableHighAccuracy: false
- }, options);
- if (!("geolocation" in navigator)) {
- this._handleGeolocationError({
- code: 0,
- message: "Geolocation not supported."
- });
- return this;
- }
- var onResponse = bind(this._handleGeolocationResponse, this), onError = bind(this._handleGeolocationError, this);
- if (options.watch) {
- this._locationWatchId = navigator.geolocation.watchPosition(onResponse, onError, options);
- } else {
- navigator.geolocation.getCurrentPosition(onResponse, onError, options);
- }
- return this;
- },
- // @method stopLocate(): this
- // Stops watching location previously initiated by `map.locate({watch: true})`
- // and aborts resetting the map view if map.locate was called with
- // `{setView: true}`.
- stopLocate: function() {
- if (navigator.geolocation && navigator.geolocation.clearWatch) {
- navigator.geolocation.clearWatch(this._locationWatchId);
- }
- if (this._locateOptions) {
- this._locateOptions.setView = false;
- }
- return this;
- },
- _handleGeolocationError: function(error) {
- if (!this._container._leaflet_id) {
- return;
- }
- var c = error.code, message = error.message || (c === 1 ? "permission denied" : c === 2 ? "position unavailable" : "timeout");
- if (this._locateOptions.setView && !this._loaded) {
- this.fitWorld();
- }
- this.fire("locationerror", {
- code: c,
- message: "Geolocation error: " + message + "."
- });
- },
- _handleGeolocationResponse: function(pos) {
- if (!this._container._leaflet_id) {
- return;
- }
- var lat = pos.coords.latitude, lng = pos.coords.longitude, latlng = new LatLng(lat, lng), bounds = latlng.toBounds(pos.coords.accuracy * 2), options = this._locateOptions;
- if (options.setView) {
- var zoom2 = this.getBoundsZoom(bounds);
- this.setView(latlng, options.maxZoom ? Math.min(zoom2, options.maxZoom) : zoom2);
- }
- var data = {
- latlng,
- bounds,
- timestamp: pos.timestamp
- };
- for (var i in pos.coords) {
- if (typeof pos.coords[i] === "number") {
- data[i] = pos.coords[i];
- }
- }
- this.fire("locationfound", data);
- },
- // TODO Appropriate docs section?
- // @section Other Methods
- // @method addHandler(name: String, HandlerClass: Function): this
- // Adds a new `Handler` to the map, given its name and constructor function.
- addHandler: function(name, HandlerClass) {
- if (!HandlerClass) {
- return this;
- }
- var handler = this[name] = new HandlerClass(this);
- this._handlers.push(handler);
- if (this.options[name]) {
- handler.enable();
- }
- return this;
- },
- // @method remove(): this
- // Destroys the map and clears all related event listeners.
- remove: function() {
- this._initEvents(true);
- if (this.options.maxBounds) {
- this.off("moveend", this._panInsideMaxBounds);
- }
- if (this._containerId !== this._container._leaflet_id) {
- throw new Error("Map container is being reused by another instance");
- }
- try {
- delete this._container._leaflet_id;
- delete this._containerId;
- } catch (e) {
- this._container._leaflet_id = void 0;
- this._containerId = void 0;
- }
- if (this._locationWatchId !== void 0) {
- this.stopLocate();
- }
- this._stop();
- remove(this._mapPane);
- if (this._clearControlPos) {
- this._clearControlPos();
- }
- if (this._resizeRequest) {
- cancelAnimFrame(this._resizeRequest);
- this._resizeRequest = null;
- }
- this._clearHandlers();
- if (this._loaded) {
- this.fire("unload");
- }
- var i;
- for (i in this._layers) {
- this._layers[i].remove();
- }
- for (i in this._panes) {
- remove(this._panes[i]);
- }
- this._layers = [];
- this._panes = [];
- delete this._mapPane;
- delete this._renderer;
- return this;
- },
- // @section Other Methods
- // @method createPane(name: String, container?: HTMLElement): HTMLElement
- // Creates a new [map pane](#map-pane) with the given name if it doesn't exist already,
- // then returns it. The pane is created as a child of `container`, or
- // as a child of the main map pane if not set.
- createPane: function(name, container) {
- var className = "leaflet-pane" + (name ? " leaflet-" + name.replace("Pane", "") + "-pane" : ""), pane = create$1("div", className, container || this._mapPane);
- if (name) {
- this._panes[name] = pane;
- }
- return pane;
- },
- // @section Methods for Getting Map State
- // @method getCenter(): LatLng
- // Returns the geographical center of the map view
- getCenter: function() {
- this._checkIfLoaded();
- if (this._lastCenter && !this._moved()) {
- return this._lastCenter.clone();
- }
- return this.layerPointToLatLng(this._getCenterLayerPoint());
- },
- // @method getZoom(): Number
- // Returns the current zoom level of the map view
- getZoom: function() {
- return this._zoom;
- },
- // @method getBounds(): LatLngBounds
- // Returns the geographical bounds visible in the current map view
- getBounds: function() {
- var bounds = this.getPixelBounds(), sw = this.unproject(bounds.getBottomLeft()), ne = this.unproject(bounds.getTopRight());
- return new LatLngBounds(sw, ne);
- },
- // @method getMinZoom(): Number
- // Returns the minimum zoom level of the map (if set in the `minZoom` option of the map or of any layers), or `0` by default.
- getMinZoom: function() {
- return this.options.minZoom === void 0 ? this._layersMinZoom || 0 : this.options.minZoom;
- },
- // @method getMaxZoom(): Number
- // Returns the maximum zoom level of the map (if set in the `maxZoom` option of the map or of any layers).
- getMaxZoom: function() {
- return this.options.maxZoom === void 0 ? this._layersMaxZoom === void 0 ? Infinity : this._layersMaxZoom : this.options.maxZoom;
- },
- // @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number
- // Returns the maximum zoom level on which the given bounds fit to the map
- // view in its entirety. If `inside` (optional) is set to `true`, the method
- // instead returns the minimum zoom level on which the map view fits into
- // the given bounds in its entirety.
- getBoundsZoom: function(bounds, inside, padding) {
- bounds = toLatLngBounds(bounds);
- padding = toPoint(padding || [0, 0]);
- var zoom2 = this.getZoom() || 0, min = this.getMinZoom(), max = this.getMaxZoom(), nw = bounds.getNorthWest(), se = bounds.getSouthEast(), size = this.getSize().subtract(padding), boundsSize = toBounds(this.project(se, zoom2), this.project(nw, zoom2)).getSize(), snap = Browser.any3d ? this.options.zoomSnap : 1, scalex = size.x / boundsSize.x, scaley = size.y / boundsSize.y, scale2 = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);
- zoom2 = this.getScaleZoom(scale2, zoom2);
- if (snap) {
- zoom2 = Math.round(zoom2 / (snap / 100)) * (snap / 100);
- zoom2 = inside ? Math.ceil(zoom2 / snap) * snap : Math.floor(zoom2 / snap) * snap;
- }
- return Math.max(min, Math.min(max, zoom2));
- },
- // @method getSize(): Point
- // Returns the current size of the map container (in pixels).
- getSize: function() {
- if (!this._size || this._sizeChanged) {
- this._size = new Point(
- this._container.clientWidth || 0,
- this._container.clientHeight || 0
- );
- this._sizeChanged = false;
- }
- return this._size.clone();
- },
- // @method getPixelBounds(): Bounds
- // Returns the bounds of the current map view in projected pixel
- // coordinates (sometimes useful in layer and overlay implementations).
- getPixelBounds: function(center, zoom2) {
- var topLeftPoint = this._getTopLeftPoint(center, zoom2);
- return new Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
- },
- // TODO: Check semantics - isn't the pixel origin the 0,0 coord relative to
- // the map pane? "left point of the map layer" can be confusing, specially
- // since there can be negative offsets.
- // @method getPixelOrigin(): Point
- // Returns the projected pixel coordinates of the top left point of
- // the map layer (useful in custom layer and overlay implementations).
- getPixelOrigin: function() {
- this._checkIfLoaded();
- return this._pixelOrigin;
- },
- // @method getPixelWorldBounds(zoom?: Number): Bounds
- // Returns the world's bounds in pixel coordinates for zoom level `zoom`.
- // If `zoom` is omitted, the map's current zoom level is used.
- getPixelWorldBounds: function(zoom2) {
- return this.options.crs.getProjectedBounds(zoom2 === void 0 ? this.getZoom() : zoom2);
- },
- // @section Other Methods
- // @method getPane(pane: String|HTMLElement): HTMLElement
- // Returns a [map pane](#map-pane), given its name or its HTML element (its identity).
- getPane: function(pane) {
- return typeof pane === "string" ? this._panes[pane] : pane;
- },
- // @method getPanes(): Object
- // Returns a plain object containing the names of all [panes](#map-pane) as keys and
- // the panes as values.
- getPanes: function() {
- return this._panes;
- },
- // @method getContainer: HTMLElement
- // Returns the HTML element that contains the map.
- getContainer: function() {
- return this._container;
- },
- // @section Conversion Methods
- // @method getZoomScale(toZoom: Number, fromZoom: Number): Number
- // Returns the scale factor to be applied to a map transition from zoom level
- // `fromZoom` to `toZoom`. Used internally to help with zoom animations.
- getZoomScale: function(toZoom, fromZoom) {
- var crs = this.options.crs;
- fromZoom = fromZoom === void 0 ? this._zoom : fromZoom;
- return crs.scale(toZoom) / crs.scale(fromZoom);
- },
- // @method getScaleZoom(scale: Number, fromZoom: Number): Number
- // Returns the zoom level that the map would end up at, if it is at `fromZoom`
- // level and everything is scaled by a factor of `scale`. Inverse of
- // [`getZoomScale`](#map-getZoomScale).
- getScaleZoom: function(scale2, fromZoom) {
- var crs = this.options.crs;
- fromZoom = fromZoom === void 0 ? this._zoom : fromZoom;
- var zoom2 = crs.zoom(scale2 * crs.scale(fromZoom));
- return isNaN(zoom2) ? Infinity : zoom2;
- },
- // @method project(latlng: LatLng, zoom: Number): Point
- // Projects a geographical coordinate `LatLng` according to the projection
- // of the map's CRS, then scales it according to `zoom` and the CRS's
- // `Transformation`. The result is pixel coordinate relative to
- // the CRS origin.
- project: function(latlng, zoom2) {
- zoom2 = zoom2 === void 0 ? this._zoom : zoom2;
- return this.options.crs.latLngToPoint(toLatLng(latlng), zoom2);
- },
- // @method unproject(point: Point, zoom: Number): LatLng
- // Inverse of [`project`](#map-project).
- unproject: function(point, zoom2) {
- zoom2 = zoom2 === void 0 ? this._zoom : zoom2;
- return this.options.crs.pointToLatLng(toPoint(point), zoom2);
- },
- // @method layerPointToLatLng(point: Point): LatLng
- // Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
- // returns the corresponding geographical coordinate (for the current zoom level).
- layerPointToLatLng: function(point) {
- var projectedPoint = toPoint(point).add(this.getPixelOrigin());
- return this.unproject(projectedPoint);
- },
- // @method latLngToLayerPoint(latlng: LatLng): Point
- // Given a geographical coordinate, returns the corresponding pixel coordinate
- // relative to the [origin pixel](#map-getpixelorigin).
- latLngToLayerPoint: function(latlng) {
- var projectedPoint = this.project(toLatLng(latlng))._round();
- return projectedPoint._subtract(this.getPixelOrigin());
- },
- // @method wrapLatLng(latlng: LatLng): LatLng
- // Returns a `LatLng` where `lat` and `lng` has been wrapped according to the
- // map's CRS's `wrapLat` and `wrapLng` properties, if they are outside the
- // CRS's bounds.
- // By default this means longitude is wrapped around the dateline so its
- // value is between -180 and +180 degrees.
- wrapLatLng: function(latlng) {
- return this.options.crs.wrapLatLng(toLatLng(latlng));
- },
- // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
- // Returns a `LatLngBounds` with the same size as the given one, ensuring that
- // its center is within the CRS's bounds.
- // By default this means the center longitude is wrapped around the dateline so its
- // value is between -180 and +180 degrees, and the majority of the bounds
- // overlaps the CRS's bounds.
- wrapLatLngBounds: function(latlng) {
- return this.options.crs.wrapLatLngBounds(toLatLngBounds(latlng));
- },
- // @method distance(latlng1: LatLng, latlng2: LatLng): Number
- // Returns the distance between two geographical coordinates according to
- // the map's CRS. By default this measures distance in meters.
- distance: function(latlng1, latlng2) {
- return this.options.crs.distance(toLatLng(latlng1), toLatLng(latlng2));
- },
- // @method containerPointToLayerPoint(point: Point): Point
- // Given a pixel coordinate relative to the map container, returns the corresponding
- // pixel coordinate relative to the [origin pixel](#map-getpixelorigin).
- containerPointToLayerPoint: function(point) {
- return toPoint(point).subtract(this._getMapPanePos());
- },
- // @method layerPointToContainerPoint(point: Point): Point
- // Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
- // returns the corresponding pixel coordinate relative to the map container.
- layerPointToContainerPoint: function(point) {
- return toPoint(point).add(this._getMapPanePos());
- },
- // @method containerPointToLatLng(point: Point): LatLng
- // Given a pixel coordinate relative to the map container, returns
- // the corresponding geographical coordinate (for the current zoom level).
- containerPointToLatLng: function(point) {
- var layerPoint = this.containerPointToLayerPoint(toPoint(point));
- return this.layerPointToLatLng(layerPoint);
- },
- // @method latLngToContainerPoint(latlng: LatLng): Point
- // Given a geographical coordinate, returns the corresponding pixel coordinate
- // relative to the map container.
- latLngToContainerPoint: function(latlng) {
- return this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng)));
- },
- // @method mouseEventToContainerPoint(ev: MouseEvent): Point
- // Given a MouseEvent object, returns the pixel coordinate relative to the
- // map container where the event took place.
- mouseEventToContainerPoint: function(e) {
- return getMousePosition(e, this._container);
- },
- // @method mouseEventToLayerPoint(ev: MouseEvent): Point
- // Given a MouseEvent object, returns the pixel coordinate relative to
- // the [origin pixel](#map-getpixelorigin) where the event took place.
- mouseEventToLayerPoint: function(e) {
- return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));
- },
- // @method mouseEventToLatLng(ev: MouseEvent): LatLng
- // Given a MouseEvent object, returns geographical coordinate where the
- // event took place.
- mouseEventToLatLng: function(e) {
- return this.layerPointToLatLng(this.mouseEventToLayerPoint(e));
- },
- // map initialization methods
- _initContainer: function(id) {
- var container = this._container = get(id);
- if (!container) {
- throw new Error("Map container not found.");
- } else if (container._leaflet_id) {
- throw new Error("Map container is already initialized.");
- }
- on(container, "scroll", this._onScroll, this);
- this._containerId = stamp(container);
- },
- _initLayout: function() {
- var container = this._container;
- this._fadeAnimated = this.options.fadeAnimation && Browser.any3d;
- addClass(container, "leaflet-container" + (Browser.touch ? " leaflet-touch" : "") + (Browser.retina ? " leaflet-retina" : "") + (Browser.ielt9 ? " leaflet-oldie" : "") + (Browser.safari ? " leaflet-safari" : "") + (this._fadeAnimated ? " leaflet-fade-anim" : ""));
- var position = getStyle(container, "position");
- if (position !== "absolute" && position !== "relative" && position !== "fixed" && position !== "sticky") {
- container.style.position = "relative";
- }
- this._initPanes();
- if (this._initControlPos) {
- this._initControlPos();
- }
- },
- _initPanes: function() {
- var panes = this._panes = {};
- this._paneRenderers = {};
- this._mapPane = this.createPane("mapPane", this._container);
- setPosition(this._mapPane, new Point(0, 0));
- this.createPane("tilePane");
- this.createPane("overlayPane");
- this.createPane("shadowPane");
- this.createPane("markerPane");
- this.createPane("tooltipPane");
- this.createPane("popupPane");
- if (!this.options.markerZoomAnimation) {
- addClass(panes.markerPane, "leaflet-zoom-hide");
- addClass(panes.shadowPane, "leaflet-zoom-hide");
- }
- },
- // private methods that modify map state
- // @section Map state change events
- _resetView: function(center, zoom2, noMoveStart) {
- setPosition(this._mapPane, new Point(0, 0));
- var loading = !this._loaded;
- this._loaded = true;
- zoom2 = this._limitZoom(zoom2);
- this.fire("viewprereset");
- var zoomChanged = this._zoom !== zoom2;
- this._moveStart(zoomChanged, noMoveStart)._move(center, zoom2)._moveEnd(zoomChanged);
- this.fire("viewreset");
- if (loading) {
- this.fire("load");
- }
- },
- _moveStart: function(zoomChanged, noMoveStart) {
- if (zoomChanged) {
- this.fire("zoomstart");
- }
- if (!noMoveStart) {
- this.fire("movestart");
- }
- return this;
- },
- _move: function(center, zoom2, data, supressEvent) {
- if (zoom2 === void 0) {
- zoom2 = this._zoom;
- }
- var zoomChanged = this._zoom !== zoom2;
- this._zoom = zoom2;
- this._lastCenter = center;
- this._pixelOrigin = this._getNewPixelOrigin(center);
- if (!supressEvent) {
- if (zoomChanged || data && data.pinch) {
- this.fire("zoom", data);
- }
- this.fire("move", data);
- } else if (data && data.pinch) {
- this.fire("zoom", data);
- }
- return this;
- },
- _moveEnd: function(zoomChanged) {
- if (zoomChanged) {
- this.fire("zoomend");
- }
- return this.fire("moveend");
- },
- _stop: function() {
- cancelAnimFrame(this._flyToFrame);
- if (this._panAnim) {
- this._panAnim.stop();
- }
- return this;
- },
- _rawPanBy: function(offset) {
- setPosition(this._mapPane, this._getMapPanePos().subtract(offset));
- },
- _getZoomSpan: function() {
- return this.getMaxZoom() - this.getMinZoom();
- },
- _panInsideMaxBounds: function() {
- if (!this._enforcingBounds) {
- this.panInsideBounds(this.options.maxBounds);
- }
- },
- _checkIfLoaded: function() {
- if (!this._loaded) {
- throw new Error("Set map center and zoom first.");
- }
- },
- // DOM event handling
- // @section Interaction events
- _initEvents: function(remove2) {
- this._targets = {};
- this._targets[stamp(this._container)] = this;
- var onOff = remove2 ? off : on;
- onOff(this._container, "click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress keydown keyup", this._handleDOMEvent, this);
- if (this.options.trackResize) {
- onOff(window, "resize", this._onResize, this);
- }
- if (Browser.any3d && this.options.transform3DLimit) {
- (remove2 ? this.off : this.on).call(this, "moveend", this._onMoveEnd);
- }
- },
- _onResize: function() {
- cancelAnimFrame(this._resizeRequest);
- this._resizeRequest = requestAnimFrame(
- function() {
- this.invalidateSize({ debounceMoveend: true });
- },
- this
- );
- },
- _onScroll: function() {
- this._container.scrollTop = 0;
- this._container.scrollLeft = 0;
- },
- _onMoveEnd: function() {
- var pos = this._getMapPanePos();
- if (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) {
- this._resetView(this.getCenter(), this.getZoom());
- }
- },
- _findEventTargets: function(e, type) {
- var targets = [], target, isHover = type === "mouseout" || type === "mouseover", src = e.target || e.srcElement, dragging = false;
- while (src) {
- target = this._targets[stamp(src)];
- if (target && (type === "click" || type === "preclick") && this._draggableMoved(target)) {
- dragging = true;
- break;
- }
- if (target && target.listens(type, true)) {
- if (isHover && !isExternalTarget(src, e)) {
- break;
- }
- targets.push(target);
- if (isHover) {
- break;
- }
- }
- if (src === this._container) {
- break;
- }
- src = src.parentNode;
- }
- if (!targets.length && !dragging && !isHover && this.listens(type, true)) {
- targets = [this];
- }
- return targets;
- },
- _isClickDisabled: function(el) {
- while (el && el !== this._container) {
- if (el["_leaflet_disable_click"]) {
- return true;
- }
- el = el.parentNode;
- }
- },
- _handleDOMEvent: function(e) {
- var el = e.target || e.srcElement;
- if (!this._loaded || el["_leaflet_disable_events"] || e.type === "click" && this._isClickDisabled(el)) {
- return;
- }
- var type = e.type;
- if (type === "mousedown") {
- preventOutline(el);
- }
- this._fireDOMEvent(e, type);
- },
- _mouseEvents: ["click", "dblclick", "mouseover", "mouseout", "contextmenu"],
- _fireDOMEvent: function(e, type, canvasTargets) {
- if (e.type === "click") {
- var synth = extend({}, e);
- synth.type = "preclick";
- this._fireDOMEvent(synth, synth.type, canvasTargets);
- }
- var targets = this._findEventTargets(e, type);
- if (canvasTargets) {
- var filtered = [];
- for (var i = 0; i < canvasTargets.length; i++) {
- if (canvasTargets[i].listens(type, true)) {
- filtered.push(canvasTargets[i]);
- }
- }
- targets = filtered.concat(targets);
- }
- if (!targets.length) {
- return;
- }
- if (type === "contextmenu") {
- preventDefault(e);
- }
- var target = targets[0];
- var data = {
- originalEvent: e
- };
- if (e.type !== "keypress" && e.type !== "keydown" && e.type !== "keyup") {
- var isMarker = target.getLatLng && (!target._radius || target._radius <= 10);
- data.containerPoint = isMarker ? this.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);
- data.layerPoint = this.containerPointToLayerPoint(data.containerPoint);
- data.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint);
- }
- for (i = 0; i < targets.length; i++) {
- targets[i].fire(type, data, true);
- if (data.originalEvent._stopped || targets[i].options.bubblingMouseEvents === false && indexOf(this._mouseEvents, type) !== -1) {
- return;
- }
- }
- },
- _draggableMoved: function(obj) {
- obj = obj.dragging && obj.dragging.enabled() ? obj : this;
- return obj.dragging && obj.dragging.moved() || this.boxZoom && this.boxZoom.moved();
- },
- _clearHandlers: function() {
- for (var i = 0, len = this._handlers.length; i < len; i++) {
- this._handlers[i].disable();
- }
- },
- // @section Other Methods
- // @method whenReady(fn: Function, context?: Object): this
- // Runs the given function `fn` when the map gets initialized with
- // a view (center and zoom) and at least one layer, or immediately
- // if it's already initialized, optionally passing a function context.
- whenReady: function(callback, context) {
- if (this._loaded) {
- callback.call(context || this, { target: this });
- } else {
- this.on("load", callback, context);
- }
- return this;
- },
- // private methods for getting map state
- _getMapPanePos: function() {
- return getPosition(this._mapPane) || new Point(0, 0);
- },
- _moved: function() {
- var pos = this._getMapPanePos();
- return pos && !pos.equals([0, 0]);
- },
- _getTopLeftPoint: function(center, zoom2) {
- var pixelOrigin = center && zoom2 !== void 0 ? this._getNewPixelOrigin(center, zoom2) : this.getPixelOrigin();
- return pixelOrigin.subtract(this._getMapPanePos());
- },
- _getNewPixelOrigin: function(center, zoom2) {
- var viewHalf = this.getSize()._divideBy(2);
- return this.project(center, zoom2)._subtract(viewHalf)._add(this._getMapPanePos())._round();
- },
- _latLngToNewLayerPoint: function(latlng, zoom2, center) {
- var topLeft = this._getNewPixelOrigin(center, zoom2);
- return this.project(latlng, zoom2)._subtract(topLeft);
- },
- _latLngBoundsToNewLayerBounds: function(latLngBounds, zoom2, center) {
- var topLeft = this._getNewPixelOrigin(center, zoom2);
- return toBounds([
- this.project(latLngBounds.getSouthWest(), zoom2)._subtract(topLeft),
- this.project(latLngBounds.getNorthWest(), zoom2)._subtract(topLeft),
- this.project(latLngBounds.getSouthEast(), zoom2)._subtract(topLeft),
- this.project(latLngBounds.getNorthEast(), zoom2)._subtract(topLeft)
- ]);
- },
- // layer point of the current center
- _getCenterLayerPoint: function() {
- return this.containerPointToLayerPoint(this.getSize()._divideBy(2));
- },
- // offset of the specified place to the current center in pixels
- _getCenterOffset: function(latlng) {
- return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint());
- },
- // adjust center for view to get inside bounds
- _limitCenter: function(center, zoom2, bounds) {
- if (!bounds) {
- return center;
- }
- var centerPoint = this.project(center, zoom2), viewHalf = this.getSize().divideBy(2), viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), offset = this._getBoundsOffset(viewBounds, bounds, zoom2);
- if (Math.abs(offset.x) <= 1 && Math.abs(offset.y) <= 1) {
- return center;
- }
- return this.unproject(centerPoint.add(offset), zoom2);
- },
- // adjust offset for view to get inside bounds
- _limitOffset: function(offset, bounds) {
- if (!bounds) {
- return offset;
- }
- var viewBounds = this.getPixelBounds(), newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset));
- return offset.add(this._getBoundsOffset(newBounds, bounds));
- },
- // returns offset needed for pxBounds to get inside maxBounds at a specified zoom
- _getBoundsOffset: function(pxBounds, maxBounds, zoom2) {
- var projectedMaxBounds = toBounds(
- this.project(maxBounds.getNorthEast(), zoom2),
- this.project(maxBounds.getSouthWest(), zoom2)
- ), minOffset = projectedMaxBounds.min.subtract(pxBounds.min), maxOffset = projectedMaxBounds.max.subtract(pxBounds.max), dx = this._rebound(minOffset.x, -maxOffset.x), dy = this._rebound(minOffset.y, -maxOffset.y);
- return new Point(dx, dy);
- },
- _rebound: function(left, right) {
- return left + right > 0 ? Math.round(left - right) / 2 : Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right));
- },
- _limitZoom: function(zoom2) {
- var min = this.getMinZoom(), max = this.getMaxZoom(), snap = Browser.any3d ? this.options.zoomSnap : 1;
- if (snap) {
- zoom2 = Math.round(zoom2 / snap) * snap;
- }
- return Math.max(min, Math.min(max, zoom2));
- },
- _onPanTransitionStep: function() {
- this.fire("move");
- },
- _onPanTransitionEnd: function() {
- removeClass(this._mapPane, "leaflet-pan-anim");
- this.fire("moveend");
- },
- _tryAnimatedPan: function(center, options) {
- var offset = this._getCenterOffset(center)._trunc();
- if ((options && options.animate) !== true && !this.getSize().contains(offset)) {
- return false;
- }
- this.panBy(offset, options);
- return true;
- },
- _createAnimProxy: function() {
- var proxy = this._proxy = create$1("div", "leaflet-proxy leaflet-zoom-animated");
- this._panes.mapPane.appendChild(proxy);
- this.on("zoomanim", function(e) {
- var prop = TRANSFORM, transform = this._proxy.style[prop];
- setTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));
- if (transform === this._proxy.style[prop] && this._animatingZoom) {
- this._onZoomTransitionEnd();
- }
- }, this);
- this.on("load moveend", this._animMoveEnd, this);
- this._on("unload", this._destroyAnimProxy, this);
- },
- _destroyAnimProxy: function() {
- remove(this._proxy);
- this.off("load moveend", this._animMoveEnd, this);
- delete this._proxy;
- },
- _animMoveEnd: function() {
- var c = this.getCenter(), z = this.getZoom();
- setTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1));
- },
- _catchTransitionEnd: function(e) {
- if (this._animatingZoom && e.propertyName.indexOf("transform") >= 0) {
- this._onZoomTransitionEnd();
- }
- },
- _nothingToAnimate: function() {
- return !this._container.getElementsByClassName("leaflet-zoom-animated").length;
- },
- _tryAnimatedZoom: function(center, zoom2, options) {
- if (this._animatingZoom) {
- return true;
- }
- options = options || {};
- if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || Math.abs(zoom2 - this._zoom) > this.options.zoomAnimationThreshold) {
- return false;
- }
- var scale2 = this.getZoomScale(zoom2), offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale2);
- if (options.animate !== true && !this.getSize().contains(offset)) {
- return false;
- }
- requestAnimFrame(function() {
- this._moveStart(true, options.noMoveStart || false)._animateZoom(center, zoom2, true);
- }, this);
- return true;
- },
- _animateZoom: function(center, zoom2, startAnim, noUpdate) {
- if (!this._mapPane) {
- return;
- }
- if (startAnim) {
- this._animatingZoom = true;
- this._animateToCenter = center;
- this._animateToZoom = zoom2;
- addClass(this._mapPane, "leaflet-zoom-anim");
- }
- this.fire("zoomanim", {
- center,
- zoom: zoom2,
- noUpdate
- });
- if (!this._tempFireZoomEvent) {
- this._tempFireZoomEvent = this._zoom !== this._animateToZoom;
- }
- this._move(this._animateToCenter, this._animateToZoom, void 0, true);
- setTimeout(bind(this._onZoomTransitionEnd, this), 250);
- },
- _onZoomTransitionEnd: function() {
- if (!this._animatingZoom) {
- return;
- }
- if (this._mapPane) {
- removeClass(this._mapPane, "leaflet-zoom-anim");
- }
- this._animatingZoom = false;
- this._move(this._animateToCenter, this._animateToZoom, void 0, true);
- if (this._tempFireZoomEvent) {
- this.fire("zoom");
- }
- delete this._tempFireZoomEvent;
- this.fire("move");
- this._moveEnd(true);
- }
- });
- function createMap(id, options) {
- return new Map(id, options);
- }
- var Control = Class.extend({
- // @section
- // @aka Control Options
- options: {
- // @option position: String = 'topright'
- // The position of the control (one of the map corners). Possible values are `'topleft'`,
- // `'topright'`, `'bottomleft'` or `'bottomright'`
- position: "topright"
- },
- initialize: function(options) {
- setOptions(this, options);
- },
- /* @section
- * Classes extending L.Control will inherit the following methods:
- *
- * @method getPosition: string
- * Returns the position of the control.
- */
- getPosition: function() {
- return this.options.position;
- },
- // @method setPosition(position: string): this
- // Sets the position of the control.
- setPosition: function(position) {
- var map = this._map;
- if (map) {
- map.removeControl(this);
- }
- this.options.position = position;
- if (map) {
- map.addControl(this);
- }
- return this;
- },
- // @method getContainer: HTMLElement
- // Returns the HTMLElement that contains the control.
- getContainer: function() {
- return this._container;
- },
- // @method addTo(map: Map): this
- // Adds the control to the given map.
- addTo: function(map) {
- this.remove();
- this._map = map;
- var container = this._container = this.onAdd(map), pos = this.getPosition(), corner = map._controlCorners[pos];
- addClass(container, "leaflet-control");
- if (pos.indexOf("bottom") !== -1) {
- corner.insertBefore(container, corner.firstChild);
- } else {
- corner.appendChild(container);
- }
- this._map.on("unload", this.remove, this);
- return this;
- },
- // @method remove: this
- // Removes the control from the map it is currently active on.
- remove: function() {
- if (!this._map) {
- return this;
- }
- remove(this._container);
- if (this.onRemove) {
- this.onRemove(this._map);
- }
- this._map.off("unload", this.remove, this);
- this._map = null;
- return this;
- },
- _refocusOnMap: function(e) {
- if (this._map && e && e.screenX > 0 && e.screenY > 0) {
- this._map.getContainer().focus();
- }
- }
- });
- var control = function(options) {
- return new Control(options);
- };
- Map.include({
- // @method addControl(control: Control): this
- // Adds the given control to the map
- addControl: function(control2) {
- control2.addTo(this);
- return this;
- },
- // @method removeControl(control: Control): this
- // Removes the given control from the map
- removeControl: function(control2) {
- control2.remove();
- return this;
- },
- _initControlPos: function() {
- var corners = this._controlCorners = {}, l = "leaflet-", container = this._controlContainer = create$1("div", l + "control-container", this._container);
- function createCorner(vSide, hSide) {
- var className = l + vSide + " " + l + hSide;
- corners[vSide + hSide] = create$1("div", className, container);
- }
- createCorner("top", "left");
- createCorner("top", "right");
- createCorner("bottom", "left");
- createCorner("bottom", "right");
- },
- _clearControlPos: function() {
- for (var i in this._controlCorners) {
- remove(this._controlCorners[i]);
- }
- remove(this._controlContainer);
- delete this._controlCorners;
- delete this._controlContainer;
- }
- });
- var Layers = Control.extend({
- // @section
- // @aka Control.Layers options
- options: {
- // @option collapsed: Boolean = true
- // If `true`, the control will be collapsed into an icon and expanded on mouse hover, touch, or keyboard activation.
- collapsed: true,
- position: "topright",
- // @option autoZIndex: Boolean = true
- // If `true`, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.
- autoZIndex: true,
- // @option hideSingleBase: Boolean = false
- // If `true`, the base layers in the control will be hidden when there is only one.
- hideSingleBase: false,
- // @option sortLayers: Boolean = false
- // Whether to sort the layers. When `false`, layers will keep the order
- // in which they were added to the control.
- sortLayers: false,
- // @option sortFunction: Function = *
- // A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
- // that will be used for sorting the layers, when `sortLayers` is `true`.
- // The function receives both the `L.Layer` instances and their names, as in
- // `sortFunction(layerA, layerB, nameA, nameB)`.
- // By default, it sorts layers alphabetically by their name.
- sortFunction: function(layerA, layerB, nameA, nameB) {
- return nameA < nameB ? -1 : nameB < nameA ? 1 : 0;
- }
- },
- initialize: function(baseLayers, overlays, options) {
- setOptions(this, options);
- this._layerControlInputs = [];
- this._layers = [];
- this._lastZIndex = 0;
- this._handlingClick = false;
- this._preventClick = false;
- for (var i in baseLayers) {
- this._addLayer(baseLayers[i], i);
- }
- for (i in overlays) {
- this._addLayer(overlays[i], i, true);
- }
- },
- onAdd: function(map) {
- this._initLayout();
- this._update();
- this._map = map;
- map.on("zoomend", this._checkDisabledLayers, this);
- for (var i = 0; i < this._layers.length; i++) {
- this._layers[i].layer.on("add remove", this._onLayerChange, this);
- }
- return this._container;
- },
- addTo: function(map) {
- Control.prototype.addTo.call(this, map);
- return this._expandIfNotCollapsed();
- },
- onRemove: function() {
- this._map.off("zoomend", this._checkDisabledLayers, this);
- for (var i = 0; i < this._layers.length; i++) {
- this._layers[i].layer.off("add remove", this._onLayerChange, this);
- }
- },
- // @method addBaseLayer(layer: Layer, name: String): this
- // Adds a base layer (radio button entry) with the given name to the control.
- addBaseLayer: function(layer, name) {
- this._addLayer(layer, name);
- return this._map ? this._update() : this;
- },
- // @method addOverlay(layer: Layer, name: String): this
- // Adds an overlay (checkbox entry) with the given name to the control.
- addOverlay: function(layer, name) {
- this._addLayer(layer, name, true);
- return this._map ? this._update() : this;
- },
- // @method removeLayer(layer: Layer): this
- // Remove the given layer from the control.
- removeLayer: function(layer) {
- layer.off("add remove", this._onLayerChange, this);
- var obj = this._getLayer(stamp(layer));
- if (obj) {
- this._layers.splice(this._layers.indexOf(obj), 1);
- }
- return this._map ? this._update() : this;
- },
- // @method expand(): this
- // Expand the control container if collapsed.
- expand: function() {
- addClass(this._container, "leaflet-control-layers-expanded");
- this._section.style.height = null;
- var acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);
- if (acceptableHeight < this._section.clientHeight) {
- addClass(this._section, "leaflet-control-layers-scrollbar");
- this._section.style.height = acceptableHeight + "px";
- } else {
- removeClass(this._section, "leaflet-control-layers-scrollbar");
- }
- this._checkDisabledLayers();
- return this;
- },
- // @method collapse(): this
- // Collapse the control container if expanded.
- collapse: function() {
- removeClass(this._container, "leaflet-control-layers-expanded");
- return this;
- },
- _initLayout: function() {
- var className = "leaflet-control-layers", container = this._container = create$1("div", className), collapsed = this.options.collapsed;
- container.setAttribute("aria-haspopup", true);
- disableClickPropagation(container);
- disableScrollPropagation(container);
- var section = this._section = create$1("section", className + "-list");
- if (collapsed) {
- this._map.on("click", this.collapse, this);
- on(container, {
- mouseenter: this._expandSafely,
- mouseleave: this.collapse
- }, this);
- }
- var link = this._layersLink = create$1("a", className + "-toggle", container);
- link.href = "#";
- link.title = "Layers";
- link.setAttribute("role", "button");
- on(link, {
- keydown: function(e) {
- if (e.keyCode === 13) {
- this._expandSafely();
- }
- },
- // Certain screen readers intercept the key event and instead send a click event
- click: function(e) {
- preventDefault(e);
- this._expandSafely();
- }
- }, this);
- if (!collapsed) {
- this.expand();
- }
- this._baseLayersList = create$1("div", className + "-base", section);
- this._separator = create$1("div", className + "-separator", section);
- this._overlaysList = create$1("div", className + "-overlays", section);
- container.appendChild(section);
- },
- _getLayer: function(id) {
- for (var i = 0; i < this._layers.length; i++) {
- if (this._layers[i] && stamp(this._layers[i].layer) === id) {
- return this._layers[i];
- }
- }
- },
- _addLayer: function(layer, name, overlay) {
- if (this._map) {
- layer.on("add remove", this._onLayerChange, this);
- }
- this._layers.push({
- layer,
- name,
- overlay
- });
- if (this.options.sortLayers) {
- this._layers.sort(bind(function(a, b) {
- return this.options.sortFunction(a.layer, b.layer, a.name, b.name);
- }, this));
- }
- if (this.options.autoZIndex && layer.setZIndex) {
- this._lastZIndex++;
- layer.setZIndex(this._lastZIndex);
- }
- this._expandIfNotCollapsed();
- },
- _update: function() {
- if (!this._container) {
- return this;
- }
- empty(this._baseLayersList);
- empty(this._overlaysList);
- this._layerControlInputs = [];
- var baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0;
- for (i = 0; i < this._layers.length; i++) {
- obj = this._layers[i];
- this._addItem(obj);
- overlaysPresent = overlaysPresent || obj.overlay;
- baseLayersPresent = baseLayersPresent || !obj.overlay;
- baseLayersCount += !obj.overlay ? 1 : 0;
- }
- if (this.options.hideSingleBase) {
- baseLayersPresent = baseLayersPresent && baseLayersCount > 1;
- this._baseLayersList.style.display = baseLayersPresent ? "" : "none";
- }
- this._separator.style.display = overlaysPresent && baseLayersPresent ? "" : "none";
- return this;
- },
- _onLayerChange: function(e) {
- if (!this._handlingClick) {
- this._update();
- }
- var obj = this._getLayer(stamp(e.target));
- var type = obj.overlay ? e.type === "add" ? "overlayadd" : "overlayremove" : e.type === "add" ? "baselayerchange" : null;
- if (type) {
- this._map.fire(type, obj);
- }
- },
- // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see https://stackoverflow.com/a/119079)
- _createRadioElement: function(name, checked) {
- var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"' + (checked ? ' checked="checked"' : "") + "/>";
- var radioFragment = document.createElement("div");
- radioFragment.innerHTML = radioHtml;
- return radioFragment.firstChild;
- },
- _addItem: function(obj) {
- var label = document.createElement("label"), checked = this._map.hasLayer(obj.layer), input;
- if (obj.overlay) {
- input = document.createElement("input");
- input.type = "checkbox";
- input.className = "leaflet-control-layers-selector";
- input.defaultChecked = checked;
- } else {
- input = this._createRadioElement("leaflet-base-layers_" + stamp(this), checked);
- }
- this._layerControlInputs.push(input);
- input.layerId = stamp(obj.layer);
- on(input, "click", this._onInputClick, this);
- var name = document.createElement("span");
- name.innerHTML = " " + obj.name;
- var holder = document.createElement("span");
- label.appendChild(holder);
- holder.appendChild(input);
- holder.appendChild(name);
- var container = obj.overlay ? this._overlaysList : this._baseLayersList;
- container.appendChild(label);
- this._checkDisabledLayers();
- return label;
- },
- _onInputClick: function() {
- if (this._preventClick) {
- return;
- }
- var inputs = this._layerControlInputs, input, layer;
- var addedLayers = [], removedLayers = [];
- this._handlingClick = true;
- for (var i = inputs.length - 1; i >= 0; i--) {
- input = inputs[i];
- layer = this._getLayer(input.layerId).layer;
- if (input.checked) {
- addedLayers.push(layer);
- } else if (!input.checked) {
- removedLayers.push(layer);
- }
- }
- for (i = 0; i < removedLayers.length; i++) {
- if (this._map.hasLayer(removedLayers[i])) {
- this._map.removeLayer(removedLayers[i]);
- }
- }
- for (i = 0; i < addedLayers.length; i++) {
- if (!this._map.hasLayer(addedLayers[i])) {
- this._map.addLayer(addedLayers[i]);
- }
- }
- this._handlingClick = false;
- this._refocusOnMap();
- },
- _checkDisabledLayers: function() {
- var inputs = this._layerControlInputs, input, layer, zoom2 = this._map.getZoom();
- for (var i = inputs.length - 1; i >= 0; i--) {
- input = inputs[i];
- layer = this._getLayer(input.layerId).layer;
- input.disabled = layer.options.minZoom !== void 0 && zoom2 < layer.options.minZoom || layer.options.maxZoom !== void 0 && zoom2 > layer.options.maxZoom;
- }
- },
- _expandIfNotCollapsed: function() {
- if (this._map && !this.options.collapsed) {
- this.expand();
- }
- return this;
- },
- _expandSafely: function() {
- var section = this._section;
- this._preventClick = true;
- on(section, "click", preventDefault);
- this.expand();
- var that = this;
- setTimeout(function() {
- off(section, "click", preventDefault);
- that._preventClick = false;
- });
- }
- });
- var layers = function(baseLayers, overlays, options) {
- return new Layers(baseLayers, overlays, options);
- };
- var Zoom = Control.extend({
- // @section
- // @aka Control.Zoom options
- options: {
- position: "topleft",
- // @option zoomInText: String = '<span aria-hidden="true">+</span>'
- // The text set on the 'zoom in' button.
- zoomInText: '<span aria-hidden="true">+</span>',
- // @option zoomInTitle: String = 'Zoom in'
- // The title set on the 'zoom in' button.
- zoomInTitle: "Zoom in",
- // @option zoomOutText: String = '<span aria-hidden="true">−</span>'
- // The text set on the 'zoom out' button.
- zoomOutText: '<span aria-hidden="true">−</span>',
- // @option zoomOutTitle: String = 'Zoom out'
- // The title set on the 'zoom out' button.
- zoomOutTitle: "Zoom out"
- },
- onAdd: function(map) {
- var zoomName = "leaflet-control-zoom", container = create$1("div", zoomName + " leaflet-bar"), options = this.options;
- this._zoomInButton = this._createButton(
- options.zoomInText,
- options.zoomInTitle,
- zoomName + "-in",
- container,
- this._zoomIn
- );
- this._zoomOutButton = this._createButton(
- options.zoomOutText,
- options.zoomOutTitle,
- zoomName + "-out",
- container,
- this._zoomOut
- );
- this._updateDisabled();
- map.on("zoomend zoomlevelschange", this._updateDisabled, this);
- return container;
- },
- onRemove: function(map) {
- map.off("zoomend zoomlevelschange", this._updateDisabled, this);
- },
- disable: function() {
- this._disabled = true;
- this._updateDisabled();
- return this;
- },
- enable: function() {
- this._disabled = false;
- this._updateDisabled();
- return this;
- },
- _zoomIn: function(e) {
- if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) {
- this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
- }
- },
- _zoomOut: function(e) {
- if (!this._disabled && this._map._zoom > this._map.getMinZoom()) {
- this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
- }
- },
- _createButton: function(html, title, className, container, fn) {
- var link = create$1("a", className, container);
- link.innerHTML = html;
- link.href = "#";
- link.title = title;
- link.setAttribute("role", "button");
- link.setAttribute("aria-label", title);
- disableClickPropagation(link);
- on(link, "click", stop);
- on(link, "click", fn, this);
- on(link, "click", this._refocusOnMap, this);
- return link;
- },
- _updateDisabled: function() {
- var map = this._map, className = "leaflet-disabled";
- removeClass(this._zoomInButton, className);
- removeClass(this._zoomOutButton, className);
- this._zoomInButton.setAttribute("aria-disabled", "false");
- this._zoomOutButton.setAttribute("aria-disabled", "false");
- if (this._disabled || map._zoom === map.getMinZoom()) {
- addClass(this._zoomOutButton, className);
- this._zoomOutButton.setAttribute("aria-disabled", "true");
- }
- if (this._disabled || map._zoom === map.getMaxZoom()) {
- addClass(this._zoomInButton, className);
- this._zoomInButton.setAttribute("aria-disabled", "true");
- }
- }
- });
- Map.mergeOptions({
- zoomControl: true
- });
- Map.addInitHook(function() {
- if (this.options.zoomControl) {
- this.zoomControl = new Zoom();
- this.addControl(this.zoomControl);
- }
- });
- var zoom = function(options) {
- return new Zoom(options);
- };
- var Scale = Control.extend({
- // @section
- // @aka Control.Scale options
- options: {
- position: "bottomleft",
- // @option maxWidth: Number = 100
- // Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
- maxWidth: 100,
- // @option metric: Boolean = True
- // Whether to show the metric scale line (m/km).
- metric: true,
- // @option imperial: Boolean = True
- // Whether to show the imperial scale line (mi/ft).
- imperial: true
- // @option updateWhenIdle: Boolean = false
- // If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)).
- },
- onAdd: function(map) {
- var className = "leaflet-control-scale", container = create$1("div", className), options = this.options;
- this._addScales(options, className + "-line", container);
- map.on(options.updateWhenIdle ? "moveend" : "move", this._update, this);
- map.whenReady(this._update, this);
- return container;
- },
- onRemove: function(map) {
- map.off(this.options.updateWhenIdle ? "moveend" : "move", this._update, this);
- },
- _addScales: function(options, className, container) {
- if (options.metric) {
- this._mScale = create$1("div", className, container);
- }
- if (options.imperial) {
- this._iScale = create$1("div", className, container);
- }
- },
- _update: function() {
- var map = this._map, y = map.getSize().y / 2;
- var maxMeters = map.distance(
- map.containerPointToLatLng([0, y]),
- map.containerPointToLatLng([this.options.maxWidth, y])
- );
- this._updateScales(maxMeters);
- },
- _updateScales: function(maxMeters) {
- if (this.options.metric && maxMeters) {
- this._updateMetric(maxMeters);
- }
- if (this.options.imperial && maxMeters) {
- this._updateImperial(maxMeters);
- }
- },
- _updateMetric: function(maxMeters) {
- var meters = this._getRoundNum(maxMeters), label = meters < 1e3 ? meters + " m" : meters / 1e3 + " km";
- this._updateScale(this._mScale, label, meters / maxMeters);
- },
- _updateImperial: function(maxMeters) {
- var maxFeet = maxMeters * 3.2808399, maxMiles, miles, feet;
- if (maxFeet > 5280) {
- maxMiles = maxFeet / 5280;
- miles = this._getRoundNum(maxMiles);
- this._updateScale(this._iScale, miles + " mi", miles / maxMiles);
- } else {
- feet = this._getRoundNum(maxFeet);
- this._updateScale(this._iScale, feet + " ft", feet / maxFeet);
- }
- },
- _updateScale: function(scale2, text, ratio) {
- scale2.style.width = Math.round(this.options.maxWidth * ratio) + "px";
- scale2.innerHTML = text;
- },
- _getRoundNum: function(num) {
- var pow10 = Math.pow(10, (Math.floor(num) + "").length - 1), d = num / pow10;
- d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1;
- return pow10 * d;
- }
- });
- var scale = function(options) {
- return new Scale(options);
- };
- var ukrainianFlag = '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="12" height="8" viewBox="0 0 12 8" class="leaflet-attribution-flag"><path fill="#4C7BE1" d="M0 0h12v4H0z"/><path fill="#FFD500" d="M0 4h12v3H0z"/><path fill="#E0BC00" d="M0 7h12v1H0z"/></svg>';
- var Attribution = Control.extend({
- // @section
- // @aka Control.Attribution options
- options: {
- position: "bottomright",
- // @option prefix: String|false = 'Leaflet'
- // The HTML text shown before the attributions. Pass `false` to disable.
- prefix: '<a href="https://leafletjs.com" title="A JavaScript library for interactive maps">' + (Browser.inlineSvg ? ukrainianFlag + " " : "") + "Leaflet</a>"
- },
- initialize: function(options) {
- setOptions(this, options);
- this._attributions = {};
- },
- onAdd: function(map) {
- map.attributionControl = this;
- this._container = create$1("div", "leaflet-control-attribution");
- disableClickPropagation(this._container);
- for (var i in map._layers) {
- if (map._layers[i].getAttribution) {
- this.addAttribution(map._layers[i].getAttribution());
- }
- }
- this._update();
- map.on("layeradd", this._addAttribution, this);
- return this._container;
- },
- onRemove: function(map) {
- map.off("layeradd", this._addAttribution, this);
- },
- _addAttribution: function(ev) {
- if (ev.layer.getAttribution) {
- this.addAttribution(ev.layer.getAttribution());
- ev.layer.once("remove", function() {
- this.removeAttribution(ev.layer.getAttribution());
- }, this);
- }
- },
- // @method setPrefix(prefix: String|false): this
- // The HTML text shown before the attributions. Pass `false` to disable.
- setPrefix: function(prefix) {
- this.options.prefix = prefix;
- this._update();
- return this;
- },
- // @method addAttribution(text: String): this
- // Adds an attribution text (e.g. `'© OpenStreetMap contributors'`).
- addAttribution: function(text) {
- if (!text) {
- return this;
- }
- if (!this._attributions[text]) {
- this._attributions[text] = 0;
- }
- this._attributions[text]++;
- this._update();
- return this;
- },
- // @method removeAttribution(text: String): this
- // Removes an attribution text.
- removeAttribution: function(text) {
- if (!text) {
- return this;
- }
- if (this._attributions[text]) {
- this._attributions[text]--;
- this._update();
- }
- return this;
- },
- _update: function() {
- if (!this._map) {
- return;
- }
- var attribs = [];
- for (var i in this._attributions) {
- if (this._attributions[i]) {
- attribs.push(i);
- }
- }
- var prefixAndAttribs = [];
- if (this.options.prefix) {
- prefixAndAttribs.push(this.options.prefix);
- }
- if (attribs.length) {
- prefixAndAttribs.push(attribs.join(", "));
- }
- this._container.innerHTML = prefixAndAttribs.join(' <span aria-hidden="true">|</span> ');
- }
- });
- Map.mergeOptions({
- attributionControl: true
- });
- Map.addInitHook(function() {
- if (this.options.attributionControl) {
- new Attribution().addTo(this);
- }
- });
- var attribution = function(options) {
- return new Attribution(options);
- };
- Control.Layers = Layers;
- Control.Zoom = Zoom;
- Control.Scale = Scale;
- Control.Attribution = Attribution;
- control.layers = layers;
- control.zoom = zoom;
- control.scale = scale;
- control.attribution = attribution;
- var Handler = Class.extend({
- initialize: function(map) {
- this._map = map;
- },
- // @method enable(): this
- // Enables the handler
- enable: function() {
- if (this._enabled) {
- return this;
- }
- this._enabled = true;
- this.addHooks();
- return this;
- },
- // @method disable(): this
- // Disables the handler
- disable: function() {
- if (!this._enabled) {
- return this;
- }
- this._enabled = false;
- this.removeHooks();
- return this;
- },
- // @method enabled(): Boolean
- // Returns `true` if the handler is enabled
- enabled: function() {
- return !!this._enabled;
- }
- // @section Extension methods
- // Classes inheriting from `Handler` must implement the two following methods:
- // @method addHooks()
- // Called when the handler is enabled, should add event hooks.
- // @method removeHooks()
- // Called when the handler is disabled, should remove the event hooks added previously.
- });
- Handler.addTo = function(map, name) {
- map.addHandler(name, this);
- return this;
- };
- var Mixin = { Events };
- var START = Browser.touch ? "touchstart mousedown" : "mousedown";
- var Draggable = Evented.extend({
- options: {
- // @section
- // @aka Draggable options
- // @option clickTolerance: Number = 3
- // The max number of pixels a user can shift the mouse pointer during a click
- // for it to be considered a valid click (as opposed to a mouse drag).
- clickTolerance: 3
- },
- // @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options)
- // Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default).
- initialize: function(element, dragStartTarget, preventOutline2, options) {
- setOptions(this, options);
- this._element = element;
- this._dragStartTarget = dragStartTarget || element;
- this._preventOutline = preventOutline2;
- },
- // @method enable()
- // Enables the dragging ability
- enable: function() {
- if (this._enabled) {
- return;
- }
- on(this._dragStartTarget, START, this._onDown, this);
- this._enabled = true;
- },
- // @method disable()
- // Disables the dragging ability
- disable: function() {
- if (!this._enabled) {
- return;
- }
- if (Draggable._dragging === this) {
- this.finishDrag(true);
- }
- off(this._dragStartTarget, START, this._onDown, this);
- this._enabled = false;
- this._moved = false;
- },
- _onDown: function(e) {
- if (!this._enabled) {
- return;
- }
- this._moved = false;
- if (hasClass(this._element, "leaflet-zoom-anim")) {
- return;
- }
- if (e.touches && e.touches.length !== 1) {
- if (Draggable._dragging === this) {
- this.finishDrag();
- }
- return;
- }
- if (Draggable._dragging || e.shiftKey || e.which !== 1 && e.button !== 1 && !e.touches) {
- return;
- }
- Draggable._dragging = this;
- if (this._preventOutline) {
- preventOutline(this._element);
- }
- disableImageDrag();
- disableTextSelection();
- if (this._moving) {
- return;
- }
- this.fire("down");
- var first = e.touches ? e.touches[0] : e, sizedParent = getSizedParentNode(this._element);
- this._startPoint = new Point(first.clientX, first.clientY);
- this._startPos = getPosition(this._element);
- this._parentScale = getScale(sizedParent);
- var mouseevent = e.type === "mousedown";
- on(document, mouseevent ? "mousemove" : "touchmove", this._onMove, this);
- on(document, mouseevent ? "mouseup" : "touchend touchcancel", this._onUp, this);
- },
- _onMove: function(e) {
- if (!this._enabled) {
- return;
- }
- if (e.touches && e.touches.length > 1) {
- this._moved = true;
- return;
- }
- var first = e.touches && e.touches.length === 1 ? e.touches[0] : e, offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);
- if (!offset.x && !offset.y) {
- return;
- }
- if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) {
- return;
- }
- offset.x /= this._parentScale.x;
- offset.y /= this._parentScale.y;
- preventDefault(e);
- if (!this._moved) {
- this.fire("dragstart");
- this._moved = true;
- addClass(document.body, "leaflet-dragging");
- this._lastTarget = e.target || e.srcElement;
- if (window.SVGElementInstance && this._lastTarget instanceof window.SVGElementInstance) {
- this._lastTarget = this._lastTarget.correspondingUseElement;
- }
- addClass(this._lastTarget, "leaflet-drag-target");
- }
- this._newPos = this._startPos.add(offset);
- this._moving = true;
- this._lastEvent = e;
- this._updatePosition();
- },
- _updatePosition: function() {
- var e = { originalEvent: this._lastEvent };
- this.fire("predrag", e);
- setPosition(this._element, this._newPos);
- this.fire("drag", e);
- },
- _onUp: function() {
- if (!this._enabled) {
- return;
- }
- this.finishDrag();
- },
- finishDrag: function(noInertia) {
- removeClass(document.body, "leaflet-dragging");
- if (this._lastTarget) {
- removeClass(this._lastTarget, "leaflet-drag-target");
- this._lastTarget = null;
- }
- off(document, "mousemove touchmove", this._onMove, this);
- off(document, "mouseup touchend touchcancel", this._onUp, this);
- enableImageDrag();
- enableTextSelection();
- var fireDragend = this._moved && this._moving;
- this._moving = false;
- Draggable._dragging = false;
- if (fireDragend) {
- this.fire("dragend", {
- noInertia,
- distance: this._newPos.distanceTo(this._startPos)
- });
- }
- }
- });
- function clipPolygon(points, bounds, round) {
- var clippedPoints, edges = [1, 4, 2, 8], i, j, k, a, b, len, edge2, p;
- for (i = 0, len = points.length; i < len; i++) {
- points[i]._code = _getBitCode(points[i], bounds);
- }
- for (k = 0; k < 4; k++) {
- edge2 = edges[k];
- clippedPoints = [];
- for (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
- a = points[i];
- b = points[j];
- if (!(a._code & edge2)) {
- if (b._code & edge2) {
- p = _getEdgeIntersection(b, a, edge2, bounds, round);
- p._code = _getBitCode(p, bounds);
- clippedPoints.push(p);
- }
- clippedPoints.push(a);
- } else if (!(b._code & edge2)) {
- p = _getEdgeIntersection(b, a, edge2, bounds, round);
- p._code = _getBitCode(p, bounds);
- clippedPoints.push(p);
- }
- }
- points = clippedPoints;
- }
- return points;
- }
- function polygonCenter(latlngs, crs) {
- var i, j, p1, p2, f, area, x, y, center;
- if (!latlngs || latlngs.length === 0) {
- throw new Error("latlngs not passed");
- }
- if (!isFlat(latlngs)) {
- console.warn("latlngs are not flat! Only the first ring will be used");
- latlngs = latlngs[0];
- }
- var centroidLatLng = toLatLng([0, 0]);
- var bounds = toLatLngBounds(latlngs);
- var areaBounds = bounds.getNorthWest().distanceTo(bounds.getSouthWest()) * bounds.getNorthEast().distanceTo(bounds.getNorthWest());
- if (areaBounds < 1700) {
- centroidLatLng = centroid(latlngs);
- }
- var len = latlngs.length;
- var points = [];
- for (i = 0; i < len; i++) {
- var latlng = toLatLng(latlngs[i]);
- points.push(crs.project(toLatLng([latlng.lat - centroidLatLng.lat, latlng.lng - centroidLatLng.lng])));
- }
- area = x = y = 0;
- for (i = 0, j = len - 1; i < len; j = i++) {
- p1 = points[i];
- p2 = points[j];
- f = p1.y * p2.x - p2.y * p1.x;
- x += (p1.x + p2.x) * f;
- y += (p1.y + p2.y) * f;
- area += f * 3;
- }
- if (area === 0) {
- center = points[0];
- } else {
- center = [x / area, y / area];
- }
- var latlngCenter = crs.unproject(toPoint(center));
- return toLatLng([latlngCenter.lat + centroidLatLng.lat, latlngCenter.lng + centroidLatLng.lng]);
- }
- function centroid(coords) {
- var latSum = 0;
- var lngSum = 0;
- var len = 0;
- for (var i = 0; i < coords.length; i++) {
- var latlng = toLatLng(coords[i]);
- latSum += latlng.lat;
- lngSum += latlng.lng;
- len++;
- }
- return toLatLng([latSum / len, lngSum / len]);
- }
- var PolyUtil = {
- __proto__: null,
- clipPolygon,
- polygonCenter,
- centroid
- };
- function simplify(points, tolerance) {
- if (!tolerance || !points.length) {
- return points.slice();
- }
- var sqTolerance = tolerance * tolerance;
- points = _reducePoints(points, sqTolerance);
- points = _simplifyDP(points, sqTolerance);
- return points;
- }
- function pointToSegmentDistance(p, p1, p2) {
- return Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true));
- }
- function closestPointOnSegment(p, p1, p2) {
- return _sqClosestPointOnSegment(p, p1, p2);
- }
- function _simplifyDP(points, sqTolerance) {
- var len = points.length, ArrayConstructor = typeof Uint8Array !== "undefined" ? Uint8Array : Array, markers = new ArrayConstructor(len);
- markers[0] = markers[len - 1] = 1;
- _simplifyDPStep(points, markers, sqTolerance, 0, len - 1);
- var i, newPoints = [];
- for (i = 0; i < len; i++) {
- if (markers[i]) {
- newPoints.push(points[i]);
- }
- }
- return newPoints;
- }
- function _simplifyDPStep(points, markers, sqTolerance, first, last) {
- var maxSqDist = 0, index2, i, sqDist;
- for (i = first + 1; i <= last - 1; i++) {
- sqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true);
- if (sqDist > maxSqDist) {
- index2 = i;
- maxSqDist = sqDist;
- }
- }
- if (maxSqDist > sqTolerance) {
- markers[index2] = 1;
- _simplifyDPStep(points, markers, sqTolerance, first, index2);
- _simplifyDPStep(points, markers, sqTolerance, index2, last);
- }
- }
- function _reducePoints(points, sqTolerance) {
- var reducedPoints = [points[0]];
- for (var i = 1, prev = 0, len = points.length; i < len; i++) {
- if (_sqDist(points[i], points[prev]) > sqTolerance) {
- reducedPoints.push(points[i]);
- prev = i;
- }
- }
- if (prev < len - 1) {
- reducedPoints.push(points[len - 1]);
- }
- return reducedPoints;
- }
- var _lastCode;
- function clipSegment(a, b, bounds, useLastCode, round) {
- var codeA = useLastCode ? _lastCode : _getBitCode(a, bounds), codeB = _getBitCode(b, bounds), codeOut, p, newCode;
- _lastCode = codeB;
- while (true) {
- if (!(codeA | codeB)) {
- return [a, b];
- }
- if (codeA & codeB) {
- return false;
- }
- codeOut = codeA || codeB;
- p = _getEdgeIntersection(a, b, codeOut, bounds, round);
- newCode = _getBitCode(p, bounds);
- if (codeOut === codeA) {
- a = p;
- codeA = newCode;
- } else {
- b = p;
- codeB = newCode;
- }
- }
- }
- function _getEdgeIntersection(a, b, code, bounds, round) {
- var dx = b.x - a.x, dy = b.y - a.y, min = bounds.min, max = bounds.max, x, y;
- if (code & 8) {
- x = a.x + dx * (max.y - a.y) / dy;
- y = max.y;
- } else if (code & 4) {
- x = a.x + dx * (min.y - a.y) / dy;
- y = min.y;
- } else if (code & 2) {
- x = max.x;
- y = a.y + dy * (max.x - a.x) / dx;
- } else if (code & 1) {
- x = min.x;
- y = a.y + dy * (min.x - a.x) / dx;
- }
- return new Point(x, y, round);
- }
- function _getBitCode(p, bounds) {
- var code = 0;
- if (p.x < bounds.min.x) {
- code |= 1;
- } else if (p.x > bounds.max.x) {
- code |= 2;
- }
- if (p.y < bounds.min.y) {
- code |= 4;
- } else if (p.y > bounds.max.y) {
- code |= 8;
- }
- return code;
- }
- function _sqDist(p1, p2) {
- var dx = p2.x - p1.x, dy = p2.y - p1.y;
- return dx * dx + dy * dy;
- }
- function _sqClosestPointOnSegment(p, p1, p2, sqDist) {
- var x = p1.x, y = p1.y, dx = p2.x - x, dy = p2.y - y, dot = dx * dx + dy * dy, t;
- if (dot > 0) {
- t = ((p.x - x) * dx + (p.y - y) * dy) / dot;
- if (t > 1) {
- x = p2.x;
- y = p2.y;
- } else if (t > 0) {
- x += dx * t;
- y += dy * t;
- }
- }
- dx = p.x - x;
- dy = p.y - y;
- return sqDist ? dx * dx + dy * dy : new Point(x, y);
- }
- function isFlat(latlngs) {
- return !isArray(latlngs[0]) || typeof latlngs[0][0] !== "object" && typeof latlngs[0][0] !== "undefined";
- }
- function _flat(latlngs) {
- console.warn("Deprecated use of _flat, please use L.LineUtil.isFlat instead.");
- return isFlat(latlngs);
- }
- function polylineCenter(latlngs, crs) {
- var i, halfDist, segDist, dist, p1, p2, ratio, center;
- if (!latlngs || latlngs.length === 0) {
- throw new Error("latlngs not passed");
- }
- if (!isFlat(latlngs)) {
- console.warn("latlngs are not flat! Only the first ring will be used");
- latlngs = latlngs[0];
- }
- var centroidLatLng = toLatLng([0, 0]);
- var bounds = toLatLngBounds(latlngs);
- var areaBounds = bounds.getNorthWest().distanceTo(bounds.getSouthWest()) * bounds.getNorthEast().distanceTo(bounds.getNorthWest());
- if (areaBounds < 1700) {
- centroidLatLng = centroid(latlngs);
- }
- var len = latlngs.length;
- var points = [];
- for (i = 0; i < len; i++) {
- var latlng = toLatLng(latlngs[i]);
- points.push(crs.project(toLatLng([latlng.lat - centroidLatLng.lat, latlng.lng - centroidLatLng.lng])));
- }
- for (i = 0, halfDist = 0; i < len - 1; i++) {
- halfDist += points[i].distanceTo(points[i + 1]) / 2;
- }
- if (halfDist === 0) {
- center = points[0];
- } else {
- for (i = 0, dist = 0; i < len - 1; i++) {
- p1 = points[i];
- p2 = points[i + 1];
- segDist = p1.distanceTo(p2);
- dist += segDist;
- if (dist > halfDist) {
- ratio = (dist - halfDist) / segDist;
- center = [
- p2.x - ratio * (p2.x - p1.x),
- p2.y - ratio * (p2.y - p1.y)
- ];
- break;
- }
- }
- }
- var latlngCenter = crs.unproject(toPoint(center));
- return toLatLng([latlngCenter.lat + centroidLatLng.lat, latlngCenter.lng + centroidLatLng.lng]);
- }
- var LineUtil = {
- __proto__: null,
- simplify,
- pointToSegmentDistance,
- closestPointOnSegment,
- clipSegment,
- _getEdgeIntersection,
- _getBitCode,
- _sqClosestPointOnSegment,
- isFlat,
- _flat,
- polylineCenter
- };
- var LonLat = {
- project: function(latlng) {
- return new Point(latlng.lng, latlng.lat);
- },
- unproject: function(point) {
- return new LatLng(point.y, point.x);
- },
- bounds: new Bounds([-180, -90], [180, 90])
- };
- var Mercator = {
- R: 6378137,
- R_MINOR: 6356752314245179e-9,
- bounds: new Bounds([-2003750834279e-5, -1549657073972e-5], [2003750834279e-5, 1876465623138e-5]),
- project: function(latlng) {
- var d = Math.PI / 180, r = this.R, y = latlng.lat * d, tmp = this.R_MINOR / r, e = Math.sqrt(1 - tmp * tmp), con = e * Math.sin(y);
- var ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2);
- y = -r * Math.log(Math.max(ts, 1e-10));
- return new Point(latlng.lng * d * r, y);
- },
- unproject: function(point) {
- var d = 180 / Math.PI, r = this.R, tmp = this.R_MINOR / r, e = Math.sqrt(1 - tmp * tmp), ts = Math.exp(-point.y / r), phi = Math.PI / 2 - 2 * Math.atan(ts);
- for (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) {
- con = e * Math.sin(phi);
- con = Math.pow((1 - con) / (1 + con), e / 2);
- dphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi;
- phi += dphi;
- }
- return new LatLng(phi * d, point.x * d / r);
- }
- };
- var index = {
- __proto__: null,
- LonLat,
- Mercator,
- SphericalMercator
- };
- var EPSG3395 = extend({}, Earth, {
- code: "EPSG:3395",
- projection: Mercator,
- transformation: function() {
- var scale2 = 0.5 / (Math.PI * Mercator.R);
- return toTransformation(scale2, 0.5, -scale2, 0.5);
- }()
- });
- var EPSG4326 = extend({}, Earth, {
- code: "EPSG:4326",
- projection: LonLat,
- transformation: toTransformation(1 / 180, 1, -1 / 180, 0.5)
- });
- var Simple = extend({}, CRS, {
- projection: LonLat,
- transformation: toTransformation(1, 0, -1, 0),
- scale: function(zoom2) {
- return Math.pow(2, zoom2);
- },
- zoom: function(scale2) {
- return Math.log(scale2) / Math.LN2;
- },
- distance: function(latlng1, latlng2) {
- var dx = latlng2.lng - latlng1.lng, dy = latlng2.lat - latlng1.lat;
- return Math.sqrt(dx * dx + dy * dy);
- },
- infinite: true
- });
- CRS.Earth = Earth;
- CRS.EPSG3395 = EPSG3395;
- CRS.EPSG3857 = EPSG3857;
- CRS.EPSG900913 = EPSG900913;
- CRS.EPSG4326 = EPSG4326;
- CRS.Simple = Simple;
- var Layer = Evented.extend({
- // Classes extending `L.Layer` will inherit the following options:
- options: {
- // @option pane: String = 'overlayPane'
- // By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default.
- pane: "overlayPane",
- // @option attribution: String = null
- // String to be shown in the attribution control, e.g. "© OpenStreetMap contributors". It describes the layer data and is often a legal obligation towards copyright holders and tile providers.
- attribution: null,
- bubblingMouseEvents: true
- },
- /* @section
- * Classes extending `L.Layer` will inherit the following methods:
- *
- * @method addTo(map: Map|LayerGroup): this
- * Adds the layer to the given map or layer group.
- */
- addTo: function(map) {
- map.addLayer(this);
- return this;
- },
- // @method remove: this
- // Removes the layer from the map it is currently active on.
- remove: function() {
- return this.removeFrom(this._map || this._mapToAdd);
- },
- // @method removeFrom(map: Map): this
- // Removes the layer from the given map
- //
- // @alternative
- // @method removeFrom(group: LayerGroup): this
- // Removes the layer from the given `LayerGroup`
- removeFrom: function(obj) {
- if (obj) {
- obj.removeLayer(this);
- }
- return this;
- },
- // @method getPane(name? : String): HTMLElement
- // Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer.
- getPane: function(name) {
- return this._map.getPane(name ? this.options[name] || name : this.options.pane);
- },
- addInteractiveTarget: function(targetEl) {
- this._map._targets[stamp(targetEl)] = this;
- return this;
- },
- removeInteractiveTarget: function(targetEl) {
- delete this._map._targets[stamp(targetEl)];
- return this;
- },
- // @method getAttribution: String
- // Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution).
- getAttribution: function() {
- return this.options.attribution;
- },
- _layerAdd: function(e) {
- var map = e.target;
- if (!map.hasLayer(this)) {
- return;
- }
- this._map = map;
- this._zoomAnimated = map._zoomAnimated;
- if (this.getEvents) {
- var events = this.getEvents();
- map.on(events, this);
- this.once("remove", function() {
- map.off(events, this);
- }, this);
- }
- this.onAdd(map);
- this.fire("add");
- map.fire("layeradd", { layer: this });
- }
- });
- Map.include({
- // @method addLayer(layer: Layer): this
- // Adds the given layer to the map
- addLayer: function(layer) {
- if (!layer._layerAdd) {
- throw new Error("The provided object is not a Layer.");
- }
- var id = stamp(layer);
- if (this._layers[id]) {
- return this;
- }
- this._layers[id] = layer;
- layer._mapToAdd = this;
- if (layer.beforeAdd) {
- layer.beforeAdd(this);
- }
- this.whenReady(layer._layerAdd, layer);
- return this;
- },
- // @method removeLayer(layer: Layer): this
- // Removes the given layer from the map.
- removeLayer: function(layer) {
- var id = stamp(layer);
- if (!this._layers[id]) {
- return this;
- }
- if (this._loaded) {
- layer.onRemove(this);
- }
- delete this._layers[id];
- if (this._loaded) {
- this.fire("layerremove", { layer });
- layer.fire("remove");
- }
- layer._map = layer._mapToAdd = null;
- return this;
- },
- // @method hasLayer(layer: Layer): Boolean
- // Returns `true` if the given layer is currently added to the map
- hasLayer: function(layer) {
- return stamp(layer) in this._layers;
- },
- /* @method eachLayer(fn: Function, context?: Object): this
- * Iterates over the layers of the map, optionally specifying context of the iterator function.
- * ```
- * map.eachLayer(function(layer){
- * layer.bindPopup('Hello');
- * });
- * ```
- */
- eachLayer: function(method, context) {
- for (var i in this._layers) {
- method.call(context, this._layers[i]);
- }
- return this;
- },
- _addLayers: function(layers2) {
- layers2 = layers2 ? isArray(layers2) ? layers2 : [layers2] : [];
- for (var i = 0, len = layers2.length; i < len; i++) {
- this.addLayer(layers2[i]);
- }
- },
- _addZoomLimit: function(layer) {
- if (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {
- this._zoomBoundLayers[stamp(layer)] = layer;
- this._updateZoomLevels();
- }
- },
- _removeZoomLimit: function(layer) {
- var id = stamp(layer);
- if (this._zoomBoundLayers[id]) {
- delete this._zoomBoundLayers[id];
- this._updateZoomLevels();
- }
- },
- _updateZoomLevels: function() {
- var minZoom = Infinity, maxZoom = -Infinity, oldZoomSpan = this._getZoomSpan();
- for (var i in this._zoomBoundLayers) {
- var options = this._zoomBoundLayers[i].options;
- minZoom = options.minZoom === void 0 ? minZoom : Math.min(minZoom, options.minZoom);
- maxZoom = options.maxZoom === void 0 ? maxZoom : Math.max(maxZoom, options.maxZoom);
- }
- this._layersMaxZoom = maxZoom === -Infinity ? void 0 : maxZoom;
- this._layersMinZoom = minZoom === Infinity ? void 0 : minZoom;
- if (oldZoomSpan !== this._getZoomSpan()) {
- this.fire("zoomlevelschange");
- }
- if (this.options.maxZoom === void 0 && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) {
- this.setZoom(this._layersMaxZoom);
- }
- if (this.options.minZoom === void 0 && this._layersMinZoom && this.getZoom() < this._layersMinZoom) {
- this.setZoom(this._layersMinZoom);
- }
- }
- });
- var LayerGroup = Layer.extend({
- initialize: function(layers2, options) {
- setOptions(this, options);
- this._layers = {};
- var i, len;
- if (layers2) {
- for (i = 0, len = layers2.length; i < len; i++) {
- this.addLayer(layers2[i]);
- }
- }
- },
- // @method addLayer(layer: Layer): this
- // Adds the given layer to the group.
- addLayer: function(layer) {
- var id = this.getLayerId(layer);
- this._layers[id] = layer;
- if (this._map) {
- this._map.addLayer(layer);
- }
- return this;
- },
- // @method removeLayer(layer: Layer): this
- // Removes the given layer from the group.
- // @alternative
- // @method removeLayer(id: Number): this
- // Removes the layer with the given internal ID from the group.
- removeLayer: function(layer) {
- var id = layer in this._layers ? layer : this.getLayerId(layer);
- if (this._map && this._layers[id]) {
- this._map.removeLayer(this._layers[id]);
- }
- delete this._layers[id];
- return this;
- },
- // @method hasLayer(layer: Layer): Boolean
- // Returns `true` if the given layer is currently added to the group.
- // @alternative
- // @method hasLayer(id: Number): Boolean
- // Returns `true` if the given internal ID is currently added to the group.
- hasLayer: function(layer) {
- var layerId = typeof layer === "number" ? layer : this.getLayerId(layer);
- return layerId in this._layers;
- },
- // @method clearLayers(): this
- // Removes all the layers from the group.
- clearLayers: function() {
- return this.eachLayer(this.removeLayer, this);
- },
- // @method invoke(methodName: String, …): this
- // Calls `methodName` on every layer contained in this group, passing any
- // additional parameters. Has no effect if the layers contained do not
- // implement `methodName`.
- invoke: function(methodName) {
- var args = Array.prototype.slice.call(arguments, 1), i, layer;
- for (i in this._layers) {
- layer = this._layers[i];
- if (layer[methodName]) {
- layer[methodName].apply(layer, args);
- }
- }
- return this;
- },
- onAdd: function(map) {
- this.eachLayer(map.addLayer, map);
- },
- onRemove: function(map) {
- this.eachLayer(map.removeLayer, map);
- },
- // @method eachLayer(fn: Function, context?: Object): this
- // Iterates over the layers of the group, optionally specifying context of the iterator function.
- // ```js
- // group.eachLayer(function (layer) {
- // layer.bindPopup('Hello');
- // });
- // ```
- eachLayer: function(method, context) {
- for (var i in this._layers) {
- method.call(context, this._layers[i]);
- }
- return this;
- },
- // @method getLayer(id: Number): Layer
- // Returns the layer with the given internal ID.
- getLayer: function(id) {
- return this._layers[id];
- },
- // @method getLayers(): Layer[]
- // Returns an array of all the layers added to the group.
- getLayers: function() {
- var layers2 = [];
- this.eachLayer(layers2.push, layers2);
- return layers2;
- },
- // @method setZIndex(zIndex: Number): this
- // Calls `setZIndex` on every layer contained in this group, passing the z-index.
- setZIndex: function(zIndex) {
- return this.invoke("setZIndex", zIndex);
- },
- // @method getLayerId(layer: Layer): Number
- // Returns the internal ID for a layer
- getLayerId: function(layer) {
- return stamp(layer);
- }
- });
- var layerGroup = function(layers2, options) {
- return new LayerGroup(layers2, options);
- };
- var FeatureGroup = LayerGroup.extend({
- addLayer: function(layer) {
- if (this.hasLayer(layer)) {
- return this;
- }
- layer.addEventParent(this);
- LayerGroup.prototype.addLayer.call(this, layer);
- return this.fire("layeradd", { layer });
- },
- removeLayer: function(layer) {
- if (!this.hasLayer(layer)) {
- return this;
- }
- if (layer in this._layers) {
- layer = this._layers[layer];
- }
- layer.removeEventParent(this);
- LayerGroup.prototype.removeLayer.call(this, layer);
- return this.fire("layerremove", { layer });
- },
- // @method setStyle(style: Path options): this
- // Sets the given path options to each layer of the group that has a `setStyle` method.
- setStyle: function(style2) {
- return this.invoke("setStyle", style2);
- },
- // @method bringToFront(): this
- // Brings the layer group to the top of all other layers
- bringToFront: function() {
- return this.invoke("bringToFront");
- },
- // @method bringToBack(): this
- // Brings the layer group to the back of all other layers
- bringToBack: function() {
- return this.invoke("bringToBack");
- },
- // @method getBounds(): LatLngBounds
- // Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).
- getBounds: function() {
- var bounds = new LatLngBounds();
- for (var id in this._layers) {
- var layer = this._layers[id];
- bounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng());
- }
- return bounds;
- }
- });
- var featureGroup = function(layers2, options) {
- return new FeatureGroup(layers2, options);
- };
- var Icon = Class.extend({
- /* @section
- * @aka Icon options
- *
- * @option iconUrl: String = null
- * **(required)** The URL to the icon image (absolute or relative to your script path).
- *
- * @option iconRetinaUrl: String = null
- * The URL to a retina sized version of the icon image (absolute or relative to your
- * script path). Used for Retina screen devices.
- *
- * @option iconSize: Point = null
- * Size of the icon image in pixels.
- *
- * @option iconAnchor: Point = null
- * The coordinates of the "tip" of the icon (relative to its top left corner). The icon
- * will be aligned so that this point is at the marker's geographical location. Centered
- * by default if size is specified, also can be set in CSS with negative margins.
- *
- * @option popupAnchor: Point = [0, 0]
- * The coordinates of the point from which popups will "open", relative to the icon anchor.
- *
- * @option tooltipAnchor: Point = [0, 0]
- * The coordinates of the point from which tooltips will "open", relative to the icon anchor.
- *
- * @option shadowUrl: String = null
- * The URL to the icon shadow image. If not specified, no shadow image will be created.
- *
- * @option shadowRetinaUrl: String = null
- *
- * @option shadowSize: Point = null
- * Size of the shadow image in pixels.
- *
- * @option shadowAnchor: Point = null
- * The coordinates of the "tip" of the shadow (relative to its top left corner) (the same
- * as iconAnchor if not specified).
- *
- * @option className: String = ''
- * A custom class name to assign to both icon and shadow images. Empty by default.
- */
- options: {
- popupAnchor: [0, 0],
- tooltipAnchor: [0, 0],
- // @option crossOrigin: Boolean|String = false
- // Whether the crossOrigin attribute will be added to the tiles.
- // If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.
- // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
- crossOrigin: false
- },
- initialize: function(options) {
- setOptions(this, options);
- },
- // @method createIcon(oldIcon?: HTMLElement): HTMLElement
- // Called internally when the icon has to be shown, returns a `<img>` HTML element
- // styled according to the options.
- createIcon: function(oldIcon) {
- return this._createIcon("icon", oldIcon);
- },
- // @method createShadow(oldIcon?: HTMLElement): HTMLElement
- // As `createIcon`, but for the shadow beneath it.
- createShadow: function(oldIcon) {
- return this._createIcon("shadow", oldIcon);
- },
- _createIcon: function(name, oldIcon) {
- var src = this._getIconUrl(name);
- if (!src) {
- if (name === "icon") {
- throw new Error("iconUrl not set in Icon options (see the docs).");
- }
- return null;
- }
- var img = this._createImg(src, oldIcon && oldIcon.tagName === "IMG" ? oldIcon : null);
- this._setIconStyles(img, name);
- if (this.options.crossOrigin || this.options.crossOrigin === "") {
- img.crossOrigin = this.options.crossOrigin === true ? "" : this.options.crossOrigin;
- }
- return img;
- },
- _setIconStyles: function(img, name) {
- var options = this.options;
- var sizeOption = options[name + "Size"];
- if (typeof sizeOption === "number") {
- sizeOption = [sizeOption, sizeOption];
- }
- var size = toPoint(sizeOption), anchor = toPoint(name === "shadow" && options.shadowAnchor || options.iconAnchor || size && size.divideBy(2, true));
- img.className = "leaflet-marker-" + name + " " + (options.className || "");
- if (anchor) {
- img.style.marginLeft = -anchor.x + "px";
- img.style.marginTop = -anchor.y + "px";
- }
- if (size) {
- img.style.width = size.x + "px";
- img.style.height = size.y + "px";
- }
- },
- _createImg: function(src, el) {
- el = el || document.createElement("img");
- el.src = src;
- return el;
- },
- _getIconUrl: function(name) {
- return Browser.retina && this.options[name + "RetinaUrl"] || this.options[name + "Url"];
- }
- });
- function icon(options) {
- return new Icon(options);
- }
- var IconDefault = Icon.extend({
- options: {
- iconUrl: "marker-icon.png",
- iconRetinaUrl: "marker-icon-2x.png",
- shadowUrl: "marker-shadow.png",
- iconSize: [25, 41],
- iconAnchor: [12, 41],
- popupAnchor: [1, -34],
- tooltipAnchor: [16, -28],
- shadowSize: [41, 41]
- },
- _getIconUrl: function(name) {
- if (typeof IconDefault.imagePath !== "string") {
- IconDefault.imagePath = this._detectIconPath();
- }
- return (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);
- },
- _stripUrl: function(path) {
- var strip = function(str, re, idx) {
- var match = re.exec(str);
- return match && match[idx];
- };
- path = strip(path, /^url\((['"])?(.+)\1\)$/, 2);
- return path && strip(path, /^(.*)marker-icon\.png$/, 1);
- },
- _detectIconPath: function() {
- var el = create$1("div", "leaflet-default-icon-path", document.body);
- var path = getStyle(el, "background-image") || getStyle(el, "backgroundImage");
- document.body.removeChild(el);
- path = this._stripUrl(path);
- if (path) {
- return path;
- }
- var link = document.querySelector('link[href$="leaflet.css"]');
- if (!link) {
- return "";
- }
- return link.href.substring(0, link.href.length - "leaflet.css".length - 1);
- }
- });
- var MarkerDrag = Handler.extend({
- initialize: function(marker2) {
- this._marker = marker2;
- },
- addHooks: function() {
- var icon2 = this._marker._icon;
- if (!this._draggable) {
- this._draggable = new Draggable(icon2, icon2, true);
- }
- this._draggable.on({
- dragstart: this._onDragStart,
- predrag: this._onPreDrag,
- drag: this._onDrag,
- dragend: this._onDragEnd
- }, this).enable();
- addClass(icon2, "leaflet-marker-draggable");
- },
- removeHooks: function() {
- this._draggable.off({
- dragstart: this._onDragStart,
- predrag: this._onPreDrag,
- drag: this._onDrag,
- dragend: this._onDragEnd
- }, this).disable();
- if (this._marker._icon) {
- removeClass(this._marker._icon, "leaflet-marker-draggable");
- }
- },
- moved: function() {
- return this._draggable && this._draggable._moved;
- },
- _adjustPan: function(e) {
- var marker2 = this._marker, map = marker2._map, speed = this._marker.options.autoPanSpeed, padding = this._marker.options.autoPanPadding, iconPos = getPosition(marker2._icon), bounds = map.getPixelBounds(), origin = map.getPixelOrigin();
- var panBounds = toBounds(
- bounds.min._subtract(origin).add(padding),
- bounds.max._subtract(origin).subtract(padding)
- );
- if (!panBounds.contains(iconPos)) {
- var movement = toPoint(
- (Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) - (Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),
- (Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) - (Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)
- ).multiplyBy(speed);
- map.panBy(movement, { animate: false });
- this._draggable._newPos._add(movement);
- this._draggable._startPos._add(movement);
- setPosition(marker2._icon, this._draggable._newPos);
- this._onDrag(e);
- this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
- }
- },
- _onDragStart: function() {
- this._oldLatLng = this._marker.getLatLng();
- this._marker.closePopup && this._marker.closePopup();
- this._marker.fire("movestart").fire("dragstart");
- },
- _onPreDrag: function(e) {
- if (this._marker.options.autoPan) {
- cancelAnimFrame(this._panRequest);
- this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
- }
- },
- _onDrag: function(e) {
- var marker2 = this._marker, shadow = marker2._shadow, iconPos = getPosition(marker2._icon), latlng = marker2._map.layerPointToLatLng(iconPos);
- if (shadow) {
- setPosition(shadow, iconPos);
- }
- marker2._latlng = latlng;
- e.latlng = latlng;
- e.oldLatLng = this._oldLatLng;
- marker2.fire("move", e).fire("drag", e);
- },
- _onDragEnd: function(e) {
- cancelAnimFrame(this._panRequest);
- delete this._oldLatLng;
- this._marker.fire("moveend").fire("dragend", e);
- }
- });
- var Marker = Layer.extend({
- // @section
- // @aka Marker options
- options: {
- // @option icon: Icon = *
- // Icon instance to use for rendering the marker.
- // See [Icon documentation](#L.Icon) for details on how to customize the marker icon.
- // If not specified, a common instance of `L.Icon.Default` is used.
- icon: new IconDefault(),
- // Option inherited from "Interactive layer" abstract class
- interactive: true,
- // @option keyboard: Boolean = true
- // Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
- keyboard: true,
- // @option title: String = ''
- // Text for the browser tooltip that appear on marker hover (no tooltip by default).
- // [Useful for accessibility](https://leafletjs.com/examples/accessibility/#markers-must-be-labelled).
- title: "",
- // @option alt: String = 'Marker'
- // Text for the `alt` attribute of the icon image.
- // [Useful for accessibility](https://leafletjs.com/examples/accessibility/#markers-must-be-labelled).
- alt: "Marker",
- // @option zIndexOffset: Number = 0
- // By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively).
- zIndexOffset: 0,
- // @option opacity: Number = 1.0
- // The opacity of the marker.
- opacity: 1,
- // @option riseOnHover: Boolean = false
- // If `true`, the marker will get on top of others when you hover the mouse over it.
- riseOnHover: false,
- // @option riseOffset: Number = 250
- // The z-index offset used for the `riseOnHover` feature.
- riseOffset: 250,
- // @option pane: String = 'markerPane'
- // `Map pane` where the markers icon will be added.
- pane: "markerPane",
- // @option shadowPane: String = 'shadowPane'
- // `Map pane` where the markers shadow will be added.
- shadowPane: "shadowPane",
- // @option bubblingMouseEvents: Boolean = false
- // When `true`, a mouse event on this marker will trigger the same event on the map
- // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
- bubblingMouseEvents: false,
- // @option autoPanOnFocus: Boolean = true
- // When `true`, the map will pan whenever the marker is focused (via
- // e.g. pressing `tab` on the keyboard) to ensure the marker is
- // visible within the map's bounds
- autoPanOnFocus: true,
- // @section Draggable marker options
- // @option draggable: Boolean = false
- // Whether the marker is draggable with mouse/touch or not.
- draggable: false,
- // @option autoPan: Boolean = false
- // Whether to pan the map when dragging this marker near its edge or not.
- autoPan: false,
- // @option autoPanPadding: Point = Point(50, 50)
- // Distance (in pixels to the left/right and to the top/bottom) of the
- // map edge to start panning the map.
- autoPanPadding: [50, 50],
- // @option autoPanSpeed: Number = 10
- // Number of pixels the map should pan by.
- autoPanSpeed: 10
- },
- /* @section
- *
- * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods:
- */
- initialize: function(latlng, options) {
- setOptions(this, options);
- this._latlng = toLatLng(latlng);
- },
- onAdd: function(map) {
- this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;
- if (this._zoomAnimated) {
- map.on("zoomanim", this._animateZoom, this);
- }
- this._initIcon();
- this.update();
- },
- onRemove: function(map) {
- if (this.dragging && this.dragging.enabled()) {
- this.options.draggable = true;
- this.dragging.removeHooks();
- }
- delete this.dragging;
- if (this._zoomAnimated) {
- map.off("zoomanim", this._animateZoom, this);
- }
- this._removeIcon();
- this._removeShadow();
- },
- getEvents: function() {
- return {
- zoom: this.update,
- viewreset: this.update
- };
- },
- // @method getLatLng: LatLng
- // Returns the current geographical position of the marker.
- getLatLng: function() {
- return this._latlng;
- },
- // @method setLatLng(latlng: LatLng): this
- // Changes the marker position to the given point.
- setLatLng: function(latlng) {
- var oldLatLng = this._latlng;
- this._latlng = toLatLng(latlng);
- this.update();
- return this.fire("move", { oldLatLng, latlng: this._latlng });
- },
- // @method setZIndexOffset(offset: Number): this
- // Changes the [zIndex offset](#marker-zindexoffset) of the marker.
- setZIndexOffset: function(offset) {
- this.options.zIndexOffset = offset;
- return this.update();
- },
- // @method getIcon: Icon
- // Returns the current icon used by the marker
- getIcon: function() {
- return this.options.icon;
- },
- // @method setIcon(icon: Icon): this
- // Changes the marker icon.
- setIcon: function(icon2) {
- this.options.icon = icon2;
- if (this._map) {
- this._initIcon();
- this.update();
- }
- if (this._popup) {
- this.bindPopup(this._popup, this._popup.options);
- }
- return this;
- },
- getElement: function() {
- return this._icon;
- },
- update: function() {
- if (this._icon && this._map) {
- var pos = this._map.latLngToLayerPoint(this._latlng).round();
- this._setPos(pos);
- }
- return this;
- },
- _initIcon: function() {
- var options = this.options, classToAdd = "leaflet-zoom-" + (this._zoomAnimated ? "animated" : "hide");
- var icon2 = options.icon.createIcon(this._icon), addIcon = false;
- if (icon2 !== this._icon) {
- if (this._icon) {
- this._removeIcon();
- }
- addIcon = true;
- if (options.title) {
- icon2.title = options.title;
- }
- if (icon2.tagName === "IMG") {
- icon2.alt = options.alt || "";
- }
- }
- addClass(icon2, classToAdd);
- if (options.keyboard) {
- icon2.tabIndex = "0";
- icon2.setAttribute("role", "button");
- }
- this._icon = icon2;
- if (options.riseOnHover) {
- this.on({
- mouseover: this._bringToFront,
- mouseout: this._resetZIndex
- });
- }
- if (this.options.autoPanOnFocus) {
- on(icon2, "focus", this._panOnFocus, this);
- }
- var newShadow = options.icon.createShadow(this._shadow), addShadow = false;
- if (newShadow !== this._shadow) {
- this._removeShadow();
- addShadow = true;
- }
- if (newShadow) {
- addClass(newShadow, classToAdd);
- newShadow.alt = "";
- }
- this._shadow = newShadow;
- if (options.opacity < 1) {
- this._updateOpacity();
- }
- if (addIcon) {
- this.getPane().appendChild(this._icon);
- }
- this._initInteraction();
- if (newShadow && addShadow) {
- this.getPane(options.shadowPane).appendChild(this._shadow);
- }
- },
- _removeIcon: function() {
- if (this.options.riseOnHover) {
- this.off({
- mouseover: this._bringToFront,
- mouseout: this._resetZIndex
- });
- }
- if (this.options.autoPanOnFocus) {
- off(this._icon, "focus", this._panOnFocus, this);
- }
- remove(this._icon);
- this.removeInteractiveTarget(this._icon);
- this._icon = null;
- },
- _removeShadow: function() {
- if (this._shadow) {
- remove(this._shadow);
- }
- this._shadow = null;
- },
- _setPos: function(pos) {
- if (this._icon) {
- setPosition(this._icon, pos);
- }
- if (this._shadow) {
- setPosition(this._shadow, pos);
- }
- this._zIndex = pos.y + this.options.zIndexOffset;
- this._resetZIndex();
- },
- _updateZIndex: function(offset) {
- if (this._icon) {
- this._icon.style.zIndex = this._zIndex + offset;
- }
- },
- _animateZoom: function(opt) {
- var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
- this._setPos(pos);
- },
- _initInteraction: function() {
- if (!this.options.interactive) {
- return;
- }
- addClass(this._icon, "leaflet-interactive");
- this.addInteractiveTarget(this._icon);
- if (MarkerDrag) {
- var draggable = this.options.draggable;
- if (this.dragging) {
- draggable = this.dragging.enabled();
- this.dragging.disable();
- }
- this.dragging = new MarkerDrag(this);
- if (draggable) {
- this.dragging.enable();
- }
- }
- },
- // @method setOpacity(opacity: Number): this
- // Changes the opacity of the marker.
- setOpacity: function(opacity) {
- this.options.opacity = opacity;
- if (this._map) {
- this._updateOpacity();
- }
- return this;
- },
- _updateOpacity: function() {
- var opacity = this.options.opacity;
- if (this._icon) {
- setOpacity(this._icon, opacity);
- }
- if (this._shadow) {
- setOpacity(this._shadow, opacity);
- }
- },
- _bringToFront: function() {
- this._updateZIndex(this.options.riseOffset);
- },
- _resetZIndex: function() {
- this._updateZIndex(0);
- },
- _panOnFocus: function() {
- var map = this._map;
- if (!map) {
- return;
- }
- var iconOpts = this.options.icon.options;
- var size = iconOpts.iconSize ? toPoint(iconOpts.iconSize) : toPoint(0, 0);
- var anchor = iconOpts.iconAnchor ? toPoint(iconOpts.iconAnchor) : toPoint(0, 0);
- map.panInside(this._latlng, {
- paddingTopLeft: anchor,
- paddingBottomRight: size.subtract(anchor)
- });
- },
- _getPopupAnchor: function() {
- return this.options.icon.options.popupAnchor;
- },
- _getTooltipAnchor: function() {
- return this.options.icon.options.tooltipAnchor;
- }
- });
- function marker(latlng, options) {
- return new Marker(latlng, options);
- }
- var Path = Layer.extend({
- // @section
- // @aka Path options
- options: {
- // @option stroke: Boolean = true
- // Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.
- stroke: true,
- // @option color: String = '#3388ff'
- // Stroke color
- color: "#3388ff",
- // @option weight: Number = 3
- // Stroke width in pixels
- weight: 3,
- // @option opacity: Number = 1.0
- // Stroke opacity
- opacity: 1,
- // @option lineCap: String= 'round'
- // A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.
- lineCap: "round",
- // @option lineJoin: String = 'round'
- // A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.
- lineJoin: "round",
- // @option dashArray: String = null
- // A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
- dashArray: null,
- // @option dashOffset: String = null
- // A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
- dashOffset: null,
- // @option fill: Boolean = depends
- // Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.
- fill: false,
- // @option fillColor: String = *
- // Fill color. Defaults to the value of the [`color`](#path-color) option
- fillColor: null,
- // @option fillOpacity: Number = 0.2
- // Fill opacity.
- fillOpacity: 0.2,
- // @option fillRule: String = 'evenodd'
- // A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.
- fillRule: "evenodd",
- // className: '',
- // Option inherited from "Interactive layer" abstract class
- interactive: true,
- // @option bubblingMouseEvents: Boolean = true
- // When `true`, a mouse event on this path will trigger the same event on the map
- // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
- bubblingMouseEvents: true
- },
- beforeAdd: function(map) {
- this._renderer = map.getRenderer(this);
- },
- onAdd: function() {
- this._renderer._initPath(this);
- this._reset();
- this._renderer._addPath(this);
- },
- onRemove: function() {
- this._renderer._removePath(this);
- },
- // @method redraw(): this
- // Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.
- redraw: function() {
- if (this._map) {
- this._renderer._updatePath(this);
- }
- return this;
- },
- // @method setStyle(style: Path options): this
- // Changes the appearance of a Path based on the options in the `Path options` object.
- setStyle: function(style2) {
- setOptions(this, style2);
- if (this._renderer) {
- this._renderer._updateStyle(this);
- if (this.options.stroke && style2 && Object.prototype.hasOwnProperty.call(style2, "weight")) {
- this._updateBounds();
- }
- }
- return this;
- },
- // @method bringToFront(): this
- // Brings the layer to the top of all path layers.
- bringToFront: function() {
- if (this._renderer) {
- this._renderer._bringToFront(this);
- }
- return this;
- },
- // @method bringToBack(): this
- // Brings the layer to the bottom of all path layers.
- bringToBack: function() {
- if (this._renderer) {
- this._renderer._bringToBack(this);
- }
- return this;
- },
- getElement: function() {
- return this._path;
- },
- _reset: function() {
- this._project();
- this._update();
- },
- _clickTolerance: function() {
- return (this.options.stroke ? this.options.weight / 2 : 0) + (this._renderer.options.tolerance || 0);
- }
- });
- var CircleMarker = Path.extend({
- // @section
- // @aka CircleMarker options
- options: {
- fill: true,
- // @option radius: Number = 10
- // Radius of the circle marker, in pixels
- radius: 10
- },
- initialize: function(latlng, options) {
- setOptions(this, options);
- this._latlng = toLatLng(latlng);
- this._radius = this.options.radius;
- },
- // @method setLatLng(latLng: LatLng): this
- // Sets the position of a circle marker to a new location.
- setLatLng: function(latlng) {
- var oldLatLng = this._latlng;
- this._latlng = toLatLng(latlng);
- this.redraw();
- return this.fire("move", { oldLatLng, latlng: this._latlng });
- },
- // @method getLatLng(): LatLng
- // Returns the current geographical position of the circle marker
- getLatLng: function() {
- return this._latlng;
- },
- // @method setRadius(radius: Number): this
- // Sets the radius of a circle marker. Units are in pixels.
- setRadius: function(radius) {
- this.options.radius = this._radius = radius;
- return this.redraw();
- },
- // @method getRadius(): Number
- // Returns the current radius of the circle
- getRadius: function() {
- return this._radius;
- },
- setStyle: function(options) {
- var radius = options && options.radius || this._radius;
- Path.prototype.setStyle.call(this, options);
- this.setRadius(radius);
- return this;
- },
- _project: function() {
- this._point = this._map.latLngToLayerPoint(this._latlng);
- this._updateBounds();
- },
- _updateBounds: function() {
- var r = this._radius, r2 = this._radiusY || r, w = this._clickTolerance(), p = [r + w, r2 + w];
- this._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));
- },
- _update: function() {
- if (this._map) {
- this._updatePath();
- }
- },
- _updatePath: function() {
- this._renderer._updateCircle(this);
- },
- _empty: function() {
- return this._radius && !this._renderer._bounds.intersects(this._pxBounds);
- },
- // Needed by the `Canvas` renderer for interactivity
- _containsPoint: function(p) {
- return p.distanceTo(this._point) <= this._radius + this._clickTolerance();
- }
- });
- function circleMarker(latlng, options) {
- return new CircleMarker(latlng, options);
- }
- var Circle = CircleMarker.extend({
- initialize: function(latlng, options, legacyOptions) {
- if (typeof options === "number") {
- options = extend({}, legacyOptions, { radius: options });
- }
- setOptions(this, options);
- this._latlng = toLatLng(latlng);
- if (isNaN(this.options.radius)) {
- throw new Error("Circle radius cannot be NaN");
- }
- this._mRadius = this.options.radius;
- },
- // @method setRadius(radius: Number): this
- // Sets the radius of a circle. Units are in meters.
- setRadius: function(radius) {
- this._mRadius = radius;
- return this.redraw();
- },
- // @method getRadius(): Number
- // Returns the current radius of a circle. Units are in meters.
- getRadius: function() {
- return this._mRadius;
- },
- // @method getBounds(): LatLngBounds
- // Returns the `LatLngBounds` of the path.
- getBounds: function() {
- var half = [this._radius, this._radiusY || this._radius];
- return new LatLngBounds(
- this._map.layerPointToLatLng(this._point.subtract(half)),
- this._map.layerPointToLatLng(this._point.add(half))
- );
- },
- setStyle: Path.prototype.setStyle,
- _project: function() {
- var lng = this._latlng.lng, lat = this._latlng.lat, map = this._map, crs = map.options.crs;
- if (crs.distance === Earth.distance) {
- var d = Math.PI / 180, latR = this._mRadius / Earth.R / d, top = map.project([lat + latR, lng]), bottom = map.project([lat - latR, lng]), p = top.add(bottom).divideBy(2), lat2 = map.unproject(p).lat, lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) / (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;
- if (isNaN(lngR) || lngR === 0) {
- lngR = latR / Math.cos(Math.PI / 180 * lat);
- }
- this._point = p.subtract(map.getPixelOrigin());
- this._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
- this._radiusY = p.y - top.y;
- } else {
- var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));
- this._point = map.latLngToLayerPoint(this._latlng);
- this._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;
- }
- this._updateBounds();
- }
- });
- function circle(latlng, options, legacyOptions) {
- return new Circle(latlng, options, legacyOptions);
- }
- var Polyline = Path.extend({
- // @section
- // @aka Polyline options
- options: {
- // @option smoothFactor: Number = 1.0
- // How much to simplify the polyline on each zoom level. More means
- // better performance and smoother look, and less means more accurate representation.
- smoothFactor: 1,
- // @option noClip: Boolean = false
- // Disable polyline clipping.
- noClip: false
- },
- initialize: function(latlngs, options) {
- setOptions(this, options);
- this._setLatLngs(latlngs);
- },
- // @method getLatLngs(): LatLng[]
- // Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.
- getLatLngs: function() {
- return this._latlngs;
- },
- // @method setLatLngs(latlngs: LatLng[]): this
- // Replaces all the points in the polyline with the given array of geographical points.
- setLatLngs: function(latlngs) {
- this._setLatLngs(latlngs);
- return this.redraw();
- },
- // @method isEmpty(): Boolean
- // Returns `true` if the Polyline has no LatLngs.
- isEmpty: function() {
- return !this._latlngs.length;
- },
- // @method closestLayerPoint(p: Point): Point
- // Returns the point closest to `p` on the Polyline.
- closestLayerPoint: function(p) {
- var minDistance = Infinity, minPoint = null, closest = _sqClosestPointOnSegment, p1, p2;
- for (var j = 0, jLen = this._parts.length; j < jLen; j++) {
- var points = this._parts[j];
- for (var i = 1, len = points.length; i < len; i++) {
- p1 = points[i - 1];
- p2 = points[i];
- var sqDist = closest(p, p1, p2, true);
- if (sqDist < minDistance) {
- minDistance = sqDist;
- minPoint = closest(p, p1, p2);
- }
- }
- }
- if (minPoint) {
- minPoint.distance = Math.sqrt(minDistance);
- }
- return minPoint;
- },
- // @method getCenter(): LatLng
- // Returns the center ([centroid](https://en.wikipedia.org/wiki/Centroid)) of the polyline.
- getCenter: function() {
- if (!this._map) {
- throw new Error("Must add layer to map before using getCenter()");
- }
- return polylineCenter(this._defaultShape(), this._map.options.crs);
- },
- // @method getBounds(): LatLngBounds
- // Returns the `LatLngBounds` of the path.
- getBounds: function() {
- return this._bounds;
- },
- // @method addLatLng(latlng: LatLng, latlngs?: LatLng[]): this
- // Adds a given point to the polyline. By default, adds to the first ring of
- // the polyline in case of a multi-polyline, but can be overridden by passing
- // a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).
- addLatLng: function(latlng, latlngs) {
- latlngs = latlngs || this._defaultShape();
- latlng = toLatLng(latlng);
- latlngs.push(latlng);
- this._bounds.extend(latlng);
- return this.redraw();
- },
- _setLatLngs: function(latlngs) {
- this._bounds = new LatLngBounds();
- this._latlngs = this._convertLatLngs(latlngs);
- },
- _defaultShape: function() {
- return isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];
- },
- // recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
- _convertLatLngs: function(latlngs) {
- var result = [], flat = isFlat(latlngs);
- for (var i = 0, len = latlngs.length; i < len; i++) {
- if (flat) {
- result[i] = toLatLng(latlngs[i]);
- this._bounds.extend(result[i]);
- } else {
- result[i] = this._convertLatLngs(latlngs[i]);
- }
- }
- return result;
- },
- _project: function() {
- var pxBounds = new Bounds();
- this._rings = [];
- this._projectLatlngs(this._latlngs, this._rings, pxBounds);
- if (this._bounds.isValid() && pxBounds.isValid()) {
- this._rawPxBounds = pxBounds;
- this._updateBounds();
- }
- },
- _updateBounds: function() {
- var w = this._clickTolerance(), p = new Point(w, w);
- if (!this._rawPxBounds) {
- return;
- }
- this._pxBounds = new Bounds([
- this._rawPxBounds.min.subtract(p),
- this._rawPxBounds.max.add(p)
- ]);
- },
- // recursively turns latlngs into a set of rings with projected coordinates
- _projectLatlngs: function(latlngs, result, projectedBounds) {
- var flat = latlngs[0] instanceof LatLng, len = latlngs.length, i, ring;
- if (flat) {
- ring = [];
- for (i = 0; i < len; i++) {
- ring[i] = this._map.latLngToLayerPoint(latlngs[i]);
- projectedBounds.extend(ring[i]);
- }
- result.push(ring);
- } else {
- for (i = 0; i < len; i++) {
- this._projectLatlngs(latlngs[i], result, projectedBounds);
- }
- }
- },
- // clip polyline by renderer bounds so that we have less to render for performance
- _clipPoints: function() {
- var bounds = this._renderer._bounds;
- this._parts = [];
- if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
- return;
- }
- if (this.options.noClip) {
- this._parts = this._rings;
- return;
- }
- var parts = this._parts, i, j, k, len, len2, segment, points;
- for (i = 0, k = 0, len = this._rings.length; i < len; i++) {
- points = this._rings[i];
- for (j = 0, len2 = points.length; j < len2 - 1; j++) {
- segment = clipSegment(points[j], points[j + 1], bounds, j, true);
- if (!segment) {
- continue;
- }
- parts[k] = parts[k] || [];
- parts[k].push(segment[0]);
- if (segment[1] !== points[j + 1] || j === len2 - 2) {
- parts[k].push(segment[1]);
- k++;
- }
- }
- }
- },
- // simplify each clipped part of the polyline for performance
- _simplifyPoints: function() {
- var parts = this._parts, tolerance = this.options.smoothFactor;
- for (var i = 0, len = parts.length; i < len; i++) {
- parts[i] = simplify(parts[i], tolerance);
- }
- },
- _update: function() {
- if (!this._map) {
- return;
- }
- this._clipPoints();
- this._simplifyPoints();
- this._updatePath();
- },
- _updatePath: function() {
- this._renderer._updatePoly(this);
- },
- // Needed by the `Canvas` renderer for interactivity
- _containsPoint: function(p, closed) {
- var i, j, k, len, len2, part, w = this._clickTolerance();
- if (!this._pxBounds || !this._pxBounds.contains(p)) {
- return false;
- }
- for (i = 0, len = this._parts.length; i < len; i++) {
- part = this._parts[i];
- for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
- if (!closed && j === 0) {
- continue;
- }
- if (pointToSegmentDistance(p, part[k], part[j]) <= w) {
- return true;
- }
- }
- }
- return false;
- }
- });
- function polyline(latlngs, options) {
- return new Polyline(latlngs, options);
- }
- Polyline._flat = _flat;
- var Polygon = Polyline.extend({
- options: {
- fill: true
- },
- isEmpty: function() {
- return !this._latlngs.length || !this._latlngs[0].length;
- },
- // @method getCenter(): LatLng
- // Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the Polygon.
- getCenter: function() {
- if (!this._map) {
- throw new Error("Must add layer to map before using getCenter()");
- }
- return polygonCenter(this._defaultShape(), this._map.options.crs);
- },
- _convertLatLngs: function(latlngs) {
- var result = Polyline.prototype._convertLatLngs.call(this, latlngs), len = result.length;
- if (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) {
- result.pop();
- }
- return result;
- },
- _setLatLngs: function(latlngs) {
- Polyline.prototype._setLatLngs.call(this, latlngs);
- if (isFlat(this._latlngs)) {
- this._latlngs = [this._latlngs];
- }
- },
- _defaultShape: function() {
- return isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];
- },
- _clipPoints: function() {
- var bounds = this._renderer._bounds, w = this.options.weight, p = new Point(w, w);
- bounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));
- this._parts = [];
- if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
- return;
- }
- if (this.options.noClip) {
- this._parts = this._rings;
- return;
- }
- for (var i = 0, len = this._rings.length, clipped; i < len; i++) {
- clipped = clipPolygon(this._rings[i], bounds, true);
- if (clipped.length) {
- this._parts.push(clipped);
- }
- }
- },
- _updatePath: function() {
- this._renderer._updatePoly(this, true);
- },
- // Needed by the `Canvas` renderer for interactivity
- _containsPoint: function(p) {
- var inside = false, part, p1, p2, i, j, k, len, len2;
- if (!this._pxBounds || !this._pxBounds.contains(p)) {
- return false;
- }
- for (i = 0, len = this._parts.length; i < len; i++) {
- part = this._parts[i];
- for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
- p1 = part[j];
- p2 = part[k];
- if (p1.y > p.y !== p2.y > p.y && p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x) {
- inside = !inside;
- }
- }
- }
- return inside || Polyline.prototype._containsPoint.call(this, p, true);
- }
- });
- function polygon(latlngs, options) {
- return new Polygon(latlngs, options);
- }
- var GeoJSON = FeatureGroup.extend({
- /* @section
- * @aka GeoJSON options
- *
- * @option pointToLayer: Function = *
- * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally
- * called when data is added, passing the GeoJSON point feature and its `LatLng`.
- * The default is to spawn a default `Marker`:
- * ```js
- * function(geoJsonPoint, latlng) {
- * return L.marker(latlng);
- * }
- * ```
- *
- * @option style: Function = *
- * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,
- * called internally when data is added.
- * The default value is to not override any defaults:
- * ```js
- * function (geoJsonFeature) {
- * return {}
- * }
- * ```
- *
- * @option onEachFeature: Function = *
- * A `Function` that will be called once for each created `Feature`, after it has
- * been created and styled. Useful for attaching events and popups to features.
- * The default is to do nothing with the newly created layers:
- * ```js
- * function (feature, layer) {}
- * ```
- *
- * @option filter: Function = *
- * A `Function` that will be used to decide whether to include a feature or not.
- * The default is to include all features:
- * ```js
- * function (geoJsonFeature) {
- * return true;
- * }
- * ```
- * Note: dynamically changing the `filter` option will have effect only on newly
- * added data. It will _not_ re-evaluate already included features.
- *
- * @option coordsToLatLng: Function = *
- * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s.
- * The default is the `coordsToLatLng` static method.
- *
- * @option markersInheritOptions: Boolean = false
- * Whether default Markers for "Point" type Features inherit from group options.
- */
- initialize: function(geojson, options) {
- setOptions(this, options);
- this._layers = {};
- if (geojson) {
- this.addData(geojson);
- }
- },
- // @method addData( <GeoJSON> data ): this
- // Adds a GeoJSON object to the layer.
- addData: function(geojson) {
- var features = isArray(geojson) ? geojson : geojson.features, i, len, feature;
- if (features) {
- for (i = 0, len = features.length; i < len; i++) {
- feature = features[i];
- if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
- this.addData(feature);
- }
- }
- return this;
- }
- var options = this.options;
- if (options.filter && !options.filter(geojson)) {
- return this;
- }
- var layer = geometryToLayer(geojson, options);
- if (!layer) {
- return this;
- }
- layer.feature = asFeature(geojson);
- layer.defaultOptions = layer.options;
- this.resetStyle(layer);
- if (options.onEachFeature) {
- options.onEachFeature(geojson, layer);
- }
- return this.addLayer(layer);
- },
- // @method resetStyle( <Path> layer? ): this
- // Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.
- // If `layer` is omitted, the style of all features in the current layer is reset.
- resetStyle: function(layer) {
- if (layer === void 0) {
- return this.eachLayer(this.resetStyle, this);
- }
- layer.options = extend({}, layer.defaultOptions);
- this._setLayerStyle(layer, this.options.style);
- return this;
- },
- // @method setStyle( <Function> style ): this
- // Changes styles of GeoJSON vector layers with the given style function.
- setStyle: function(style2) {
- return this.eachLayer(function(layer) {
- this._setLayerStyle(layer, style2);
- }, this);
- },
- _setLayerStyle: function(layer, style2) {
- if (layer.setStyle) {
- if (typeof style2 === "function") {
- style2 = style2(layer.feature);
- }
- layer.setStyle(style2);
- }
- }
- });
- function geometryToLayer(geojson, options) {
- var geometry = geojson.type === "Feature" ? geojson.geometry : geojson, coords = geometry ? geometry.coordinates : null, layers2 = [], pointToLayer = options && options.pointToLayer, _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng, latlng, latlngs, i, len;
- if (!coords && !geometry) {
- return null;
- }
- switch (geometry.type) {
- case "Point":
- latlng = _coordsToLatLng(coords);
- return _pointToLayer(pointToLayer, geojson, latlng, options);
- case "MultiPoint":
- for (i = 0, len = coords.length; i < len; i++) {
- latlng = _coordsToLatLng(coords[i]);
- layers2.push(_pointToLayer(pointToLayer, geojson, latlng, options));
- }
- return new FeatureGroup(layers2);
- case "LineString":
- case "MultiLineString":
- latlngs = coordsToLatLngs(coords, geometry.type === "LineString" ? 0 : 1, _coordsToLatLng);
- return new Polyline(latlngs, options);
- case "Polygon":
- case "MultiPolygon":
- latlngs = coordsToLatLngs(coords, geometry.type === "Polygon" ? 1 : 2, _coordsToLatLng);
- return new Polygon(latlngs, options);
- case "GeometryCollection":
- for (i = 0, len = geometry.geometries.length; i < len; i++) {
- var geoLayer = geometryToLayer({
- geometry: geometry.geometries[i],
- type: "Feature",
- properties: geojson.properties
- }, options);
- if (geoLayer) {
- layers2.push(geoLayer);
- }
- }
- return new FeatureGroup(layers2);
- case "FeatureCollection":
- for (i = 0, len = geometry.features.length; i < len; i++) {
- var featureLayer = geometryToLayer(geometry.features[i], options);
- if (featureLayer) {
- layers2.push(featureLayer);
- }
- }
- return new FeatureGroup(layers2);
- default:
- throw new Error("Invalid GeoJSON object.");
- }
- }
- function _pointToLayer(pointToLayerFn, geojson, latlng, options) {
- return pointToLayerFn ? pointToLayerFn(geojson, latlng) : new Marker(latlng, options && options.markersInheritOptions && options);
- }
- function coordsToLatLng(coords) {
- return new LatLng(coords[1], coords[0], coords[2]);
- }
- function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
- var latlngs = [];
- for (var i = 0, len = coords.length, latlng; i < len; i++) {
- latlng = levelsDeep ? coordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) : (_coordsToLatLng || coordsToLatLng)(coords[i]);
- latlngs.push(latlng);
- }
- return latlngs;
- }
- function latLngToCoords(latlng, precision) {
- latlng = toLatLng(latlng);
- return latlng.alt !== void 0 ? [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] : [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];
- }
- function latLngsToCoords(latlngs, levelsDeep, closed, precision) {
- var coords = [];
- for (var i = 0, len = latlngs.length; i < len; i++) {
- coords.push(levelsDeep ? latLngsToCoords(latlngs[i], isFlat(latlngs[i]) ? 0 : levelsDeep - 1, closed, precision) : latLngToCoords(latlngs[i], precision));
- }
- if (!levelsDeep && closed && coords.length > 0) {
- coords.push(coords[0].slice());
- }
- return coords;
- }
- function getFeature(layer, newGeometry) {
- return layer.feature ? extend({}, layer.feature, { geometry: newGeometry }) : asFeature(newGeometry);
- }
- function asFeature(geojson) {
- if (geojson.type === "Feature" || geojson.type === "FeatureCollection") {
- return geojson;
- }
- return {
- type: "Feature",
- properties: {},
- geometry: geojson
- };
- }
- var PointToGeoJSON = {
- toGeoJSON: function(precision) {
- return getFeature(this, {
- type: "Point",
- coordinates: latLngToCoords(this.getLatLng(), precision)
- });
- }
- };
- Marker.include(PointToGeoJSON);
- Circle.include(PointToGeoJSON);
- CircleMarker.include(PointToGeoJSON);
- Polyline.include({
- toGeoJSON: function(precision) {
- var multi = !isFlat(this._latlngs);
- var coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);
- return getFeature(this, {
- type: (multi ? "Multi" : "") + "LineString",
- coordinates: coords
- });
- }
- });
- Polygon.include({
- toGeoJSON: function(precision) {
- var holes = !isFlat(this._latlngs), multi = holes && !isFlat(this._latlngs[0]);
- var coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);
- if (!holes) {
- coords = [coords];
- }
- return getFeature(this, {
- type: (multi ? "Multi" : "") + "Polygon",
- coordinates: coords
- });
- }
- });
- LayerGroup.include({
- toMultiPoint: function(precision) {
- var coords = [];
- this.eachLayer(function(layer) {
- coords.push(layer.toGeoJSON(precision).geometry.coordinates);
- });
- return getFeature(this, {
- type: "MultiPoint",
- coordinates: coords
- });
- },
- // @method toGeoJSON(precision?: Number|false): Object
- // Coordinates values are rounded with [`formatNum`](#util-formatnum) function with given `precision`.
- // Returns a [`GeoJSON`](https://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`).
- toGeoJSON: function(precision) {
- var type = this.feature && this.feature.geometry && this.feature.geometry.type;
- if (type === "MultiPoint") {
- return this.toMultiPoint(precision);
- }
- var isGeometryCollection = type === "GeometryCollection", jsons = [];
- this.eachLayer(function(layer) {
- if (layer.toGeoJSON) {
- var json = layer.toGeoJSON(precision);
- if (isGeometryCollection) {
- jsons.push(json.geometry);
- } else {
- var feature = asFeature(json);
- if (feature.type === "FeatureCollection") {
- jsons.push.apply(jsons, feature.features);
- } else {
- jsons.push(feature);
- }
- }
- }
- });
- if (isGeometryCollection) {
- return getFeature(this, {
- geometries: jsons,
- type: "GeometryCollection"
- });
- }
- return {
- type: "FeatureCollection",
- features: jsons
- };
- }
- });
- function geoJSON(geojson, options) {
- return new GeoJSON(geojson, options);
- }
- var geoJson = geoJSON;
- var ImageOverlay = Layer.extend({
- // @section
- // @aka ImageOverlay options
- options: {
- // @option opacity: Number = 1.0
- // The opacity of the image overlay.
- opacity: 1,
- // @option alt: String = ''
- // Text for the `alt` attribute of the image (useful for accessibility).
- alt: "",
- // @option interactive: Boolean = false
- // If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered.
- interactive: false,
- // @option crossOrigin: Boolean|String = false
- // Whether the crossOrigin attribute will be added to the image.
- // If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data.
- // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
- crossOrigin: false,
- // @option errorOverlayUrl: String = ''
- // URL to the overlay image to show in place of the overlay that failed to load.
- errorOverlayUrl: "",
- // @option zIndex: Number = 1
- // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer.
- zIndex: 1,
- // @option className: String = ''
- // A custom class name to assign to the image. Empty by default.
- className: ""
- },
- initialize: function(url, bounds, options) {
- this._url = url;
- this._bounds = toLatLngBounds(bounds);
- setOptions(this, options);
- },
- onAdd: function() {
- if (!this._image) {
- this._initImage();
- if (this.options.opacity < 1) {
- this._updateOpacity();
- }
- }
- if (this.options.interactive) {
- addClass(this._image, "leaflet-interactive");
- this.addInteractiveTarget(this._image);
- }
- this.getPane().appendChild(this._image);
- this._reset();
- },
- onRemove: function() {
- remove(this._image);
- if (this.options.interactive) {
- this.removeInteractiveTarget(this._image);
- }
- },
- // @method setOpacity(opacity: Number): this
- // Sets the opacity of the overlay.
- setOpacity: function(opacity) {
- this.options.opacity = opacity;
- if (this._image) {
- this._updateOpacity();
- }
- return this;
- },
- setStyle: function(styleOpts) {
- if (styleOpts.opacity) {
- this.setOpacity(styleOpts.opacity);
- }
- return this;
- },
- // @method bringToFront(): this
- // Brings the layer to the top of all overlays.
- bringToFront: function() {
- if (this._map) {
- toFront(this._image);
- }
- return this;
- },
- // @method bringToBack(): this
- // Brings the layer to the bottom of all overlays.
- bringToBack: function() {
- if (this._map) {
- toBack(this._image);
- }
- return this;
- },
- // @method setUrl(url: String): this
- // Changes the URL of the image.
- setUrl: function(url) {
- this._url = url;
- if (this._image) {
- this._image.src = url;
- }
- return this;
- },
- // @method setBounds(bounds: LatLngBounds): this
- // Update the bounds that this ImageOverlay covers
- setBounds: function(bounds) {
- this._bounds = toLatLngBounds(bounds);
- if (this._map) {
- this._reset();
- }
- return this;
- },
- getEvents: function() {
- var events = {
- zoom: this._reset,
- viewreset: this._reset
- };
- if (this._zoomAnimated) {
- events.zoomanim = this._animateZoom;
- }
- return events;
- },
- // @method setZIndex(value: Number): this
- // Changes the [zIndex](#imageoverlay-zindex) of the image overlay.
- setZIndex: function(value) {
- this.options.zIndex = value;
- this._updateZIndex();
- return this;
- },
- // @method getBounds(): LatLngBounds
- // Get the bounds that this ImageOverlay covers
- getBounds: function() {
- return this._bounds;
- },
- // @method getElement(): HTMLElement
- // Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement)
- // used by this overlay.
- getElement: function() {
- return this._image;
- },
- _initImage: function() {
- var wasElementSupplied = this._url.tagName === "IMG";
- var img = this._image = wasElementSupplied ? this._url : create$1("img");
- addClass(img, "leaflet-image-layer");
- if (this._zoomAnimated) {
- addClass(img, "leaflet-zoom-animated");
- }
- if (this.options.className) {
- addClass(img, this.options.className);
- }
- img.onselectstart = falseFn;
- img.onmousemove = falseFn;
- img.onload = bind(this.fire, this, "load");
- img.onerror = bind(this._overlayOnError, this, "error");
- if (this.options.crossOrigin || this.options.crossOrigin === "") {
- img.crossOrigin = this.options.crossOrigin === true ? "" : this.options.crossOrigin;
- }
- if (this.options.zIndex) {
- this._updateZIndex();
- }
- if (wasElementSupplied) {
- this._url = img.src;
- return;
- }
- img.src = this._url;
- img.alt = this.options.alt;
- },
- _animateZoom: function(e) {
- var scale2 = this._map.getZoomScale(e.zoom), offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min;
- setTransform(this._image, offset, scale2);
- },
- _reset: function() {
- var image = this._image, bounds = new Bounds(
- this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
- this._map.latLngToLayerPoint(this._bounds.getSouthEast())
- ), size = bounds.getSize();
- setPosition(image, bounds.min);
- image.style.width = size.x + "px";
- image.style.height = size.y + "px";
- },
- _updateOpacity: function() {
- setOpacity(this._image, this.options.opacity);
- },
- _updateZIndex: function() {
- if (this._image && this.options.zIndex !== void 0 && this.options.zIndex !== null) {
- this._image.style.zIndex = this.options.zIndex;
- }
- },
- _overlayOnError: function() {
- this.fire("error");
- var errorUrl = this.options.errorOverlayUrl;
- if (errorUrl && this._url !== errorUrl) {
- this._url = errorUrl;
- this._image.src = errorUrl;
- }
- },
- // @method getCenter(): LatLng
- // Returns the center of the ImageOverlay.
- getCenter: function() {
- return this._bounds.getCenter();
- }
- });
- var imageOverlay = function(url, bounds, options) {
- return new ImageOverlay(url, bounds, options);
- };
- var VideoOverlay = ImageOverlay.extend({
- // @section
- // @aka VideoOverlay options
- options: {
- // @option autoplay: Boolean = true
- // Whether the video starts playing automatically when loaded.
- // On some browsers autoplay will only work with `muted: true`
- autoplay: true,
- // @option loop: Boolean = true
- // Whether the video will loop back to the beginning when played.
- loop: true,
- // @option keepAspectRatio: Boolean = true
- // Whether the video will save aspect ratio after the projection.
- // Relevant for supported browsers. See [browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)
- keepAspectRatio: true,
- // @option muted: Boolean = false
- // Whether the video starts on mute when loaded.
- muted: false,
- // @option playsInline: Boolean = true
- // Mobile browsers will play the video right where it is instead of open it up in fullscreen mode.
- playsInline: true
- },
- _initImage: function() {
- var wasElementSupplied = this._url.tagName === "VIDEO";
- var vid = this._image = wasElementSupplied ? this._url : create$1("video");
- addClass(vid, "leaflet-image-layer");
- if (this._zoomAnimated) {
- addClass(vid, "leaflet-zoom-animated");
- }
- if (this.options.className) {
- addClass(vid, this.options.className);
- }
- vid.onselectstart = falseFn;
- vid.onmousemove = falseFn;
- vid.onloadeddata = bind(this.fire, this, "load");
- if (wasElementSupplied) {
- var sourceElements = vid.getElementsByTagName("source");
- var sources = [];
- for (var j = 0; j < sourceElements.length; j++) {
- sources.push(sourceElements[j].src);
- }
- this._url = sourceElements.length > 0 ? sources : [vid.src];
- return;
- }
- if (!isArray(this._url)) {
- this._url = [this._url];
- }
- if (!this.options.keepAspectRatio && Object.prototype.hasOwnProperty.call(vid.style, "objectFit")) {
- vid.style["objectFit"] = "fill";
- }
- vid.autoplay = !!this.options.autoplay;
- vid.loop = !!this.options.loop;
- vid.muted = !!this.options.muted;
- vid.playsInline = !!this.options.playsInline;
- for (var i = 0; i < this._url.length; i++) {
- var source = create$1("source");
- source.src = this._url[i];
- vid.appendChild(source);
- }
- }
- // @method getElement(): HTMLVideoElement
- // Returns the instance of [`HTMLVideoElement`](https://developer.mozilla.org/docs/Web/API/HTMLVideoElement)
- // used by this overlay.
- });
- function videoOverlay(video, bounds, options) {
- return new VideoOverlay(video, bounds, options);
- }
- var SVGOverlay = ImageOverlay.extend({
- _initImage: function() {
- var el = this._image = this._url;
- addClass(el, "leaflet-image-layer");
- if (this._zoomAnimated) {
- addClass(el, "leaflet-zoom-animated");
- }
- if (this.options.className) {
- addClass(el, this.options.className);
- }
- el.onselectstart = falseFn;
- el.onmousemove = falseFn;
- }
- // @method getElement(): SVGElement
- // Returns the instance of [`SVGElement`](https://developer.mozilla.org/docs/Web/API/SVGElement)
- // used by this overlay.
- });
- function svgOverlay(el, bounds, options) {
- return new SVGOverlay(el, bounds, options);
- }
- var DivOverlay = Layer.extend({
- // @section
- // @aka DivOverlay options
- options: {
- // @option interactive: Boolean = false
- // If true, the popup/tooltip will listen to the mouse events.
- interactive: false,
- // @option offset: Point = Point(0, 0)
- // The offset of the overlay position.
- offset: [0, 0],
- // @option className: String = ''
- // A custom CSS class name to assign to the overlay.
- className: "",
- // @option pane: String = undefined
- // `Map pane` where the overlay will be added.
- pane: void 0,
- // @option content: String|HTMLElement|Function = ''
- // Sets the HTML content of the overlay while initializing. If a function is passed the source layer will be
- // passed to the function. The function should return a `String` or `HTMLElement` to be used in the overlay.
- content: ""
- },
- initialize: function(options, source) {
- if (options && (options instanceof LatLng || isArray(options))) {
- this._latlng = toLatLng(options);
- setOptions(this, source);
- } else {
- setOptions(this, options);
- this._source = source;
- }
- if (this.options.content) {
- this._content = this.options.content;
- }
- },
- // @method openOn(map: Map): this
- // Adds the overlay to the map.
- // Alternative to `map.openPopup(popup)`/`.openTooltip(tooltip)`.
- openOn: function(map) {
- map = arguments.length ? map : this._source._map;
- if (!map.hasLayer(this)) {
- map.addLayer(this);
- }
- return this;
- },
- // @method close(): this
- // Closes the overlay.
- // Alternative to `map.closePopup(popup)`/`.closeTooltip(tooltip)`
- // and `layer.closePopup()`/`.closeTooltip()`.
- close: function() {
- if (this._map) {
- this._map.removeLayer(this);
- }
- return this;
- },
- // @method toggle(layer?: Layer): this
- // Opens or closes the overlay bound to layer depending on its current state.
- // Argument may be omitted only for overlay bound to layer.
- // Alternative to `layer.togglePopup()`/`.toggleTooltip()`.
- toggle: function(layer) {
- if (this._map) {
- this.close();
- } else {
- if (arguments.length) {
- this._source = layer;
- } else {
- layer = this._source;
- }
- this._prepareOpen();
- this.openOn(layer._map);
- }
- return this;
- },
- onAdd: function(map) {
- this._zoomAnimated = map._zoomAnimated;
- if (!this._container) {
- this._initLayout();
- }
- if (map._fadeAnimated) {
- setOpacity(this._container, 0);
- }
- clearTimeout(this._removeTimeout);
- this.getPane().appendChild(this._container);
- this.update();
- if (map._fadeAnimated) {
- setOpacity(this._container, 1);
- }
- this.bringToFront();
- if (this.options.interactive) {
- addClass(this._container, "leaflet-interactive");
- this.addInteractiveTarget(this._container);
- }
- },
- onRemove: function(map) {
- if (map._fadeAnimated) {
- setOpacity(this._container, 0);
- this._removeTimeout = setTimeout(bind(remove, void 0, this._container), 200);
- } else {
- remove(this._container);
- }
- if (this.options.interactive) {
- removeClass(this._container, "leaflet-interactive");
- this.removeInteractiveTarget(this._container);
- }
- },
- // @namespace DivOverlay
- // @method getLatLng: LatLng
- // Returns the geographical point of the overlay.
- getLatLng: function() {
- return this._latlng;
- },
- // @method setLatLng(latlng: LatLng): this
- // Sets the geographical point where the overlay will open.
- setLatLng: function(latlng) {
- this._latlng = toLatLng(latlng);
- if (this._map) {
- this._updatePosition();
- this._adjustPan();
- }
- return this;
- },
- // @method getContent: String|HTMLElement
- // Returns the content of the overlay.
- getContent: function() {
- return this._content;
- },
- // @method setContent(htmlContent: String|HTMLElement|Function): this
- // Sets the HTML content of the overlay. If a function is passed the source layer will be passed to the function.
- // The function should return a `String` or `HTMLElement` to be used in the overlay.
- setContent: function(content) {
- this._content = content;
- this.update();
- return this;
- },
- // @method getElement: String|HTMLElement
- // Returns the HTML container of the overlay.
- getElement: function() {
- return this._container;
- },
- // @method update: null
- // Updates the overlay content, layout and position. Useful for updating the overlay after something inside changed, e.g. image loaded.
- update: function() {
- if (!this._map) {
- return;
- }
- this._container.style.visibility = "hidden";
- this._updateContent();
- this._updateLayout();
- this._updatePosition();
- this._container.style.visibility = "";
- this._adjustPan();
- },
- getEvents: function() {
- var events = {
- zoom: this._updatePosition,
- viewreset: this._updatePosition
- };
- if (this._zoomAnimated) {
- events.zoomanim = this._animateZoom;
- }
- return events;
- },
- // @method isOpen: Boolean
- // Returns `true` when the overlay is visible on the map.
- isOpen: function() {
- return !!this._map && this._map.hasLayer(this);
- },
- // @method bringToFront: this
- // Brings this overlay in front of other overlays (in the same map pane).
- bringToFront: function() {
- if (this._map) {
- toFront(this._container);
- }
- return this;
- },
- // @method bringToBack: this
- // Brings this overlay to the back of other overlays (in the same map pane).
- bringToBack: function() {
- if (this._map) {
- toBack(this._container);
- }
- return this;
- },
- // prepare bound overlay to open: update latlng pos / content source (for FeatureGroup)
- _prepareOpen: function(latlng) {
- var source = this._source;
- if (!source._map) {
- return false;
- }
- if (source instanceof FeatureGroup) {
- source = null;
- var layers2 = this._source._layers;
- for (var id in layers2) {
- if (layers2[id]._map) {
- source = layers2[id];
- break;
- }
- }
- if (!source) {
- return false;
- }
- this._source = source;
- }
- if (!latlng) {
- if (source.getCenter) {
- latlng = source.getCenter();
- } else if (source.getLatLng) {
- latlng = source.getLatLng();
- } else if (source.getBounds) {
- latlng = source.getBounds().getCenter();
- } else {
- throw new Error("Unable to get source layer LatLng.");
- }
- }
- this.setLatLng(latlng);
- if (this._map) {
- this.update();
- }
- return true;
- },
- _updateContent: function() {
- if (!this._content) {
- return;
- }
- var node = this._contentNode;
- var content = typeof this._content === "function" ? this._content(this._source || this) : this._content;
- if (typeof content === "string") {
- node.innerHTML = content;
- } else {
- while (node.hasChildNodes()) {
- node.removeChild(node.firstChild);
- }
- node.appendChild(content);
- }
- this.fire("contentupdate");
- },
- _updatePosition: function() {
- if (!this._map) {
- return;
- }
- var pos = this._map.latLngToLayerPoint(this._latlng), offset = toPoint(this.options.offset), anchor = this._getAnchor();
- if (this._zoomAnimated) {
- setPosition(this._container, pos.add(anchor));
- } else {
- offset = offset.add(pos).add(anchor);
- }
- var bottom = this._containerBottom = -offset.y, left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x;
- this._container.style.bottom = bottom + "px";
- this._container.style.left = left + "px";
- },
- _getAnchor: function() {
- return [0, 0];
- }
- });
- Map.include({
- _initOverlay: function(OverlayClass, content, latlng, options) {
- var overlay = content;
- if (!(overlay instanceof OverlayClass)) {
- overlay = new OverlayClass(options).setContent(content);
- }
- if (latlng) {
- overlay.setLatLng(latlng);
- }
- return overlay;
- }
- });
- Layer.include({
- _initOverlay: function(OverlayClass, old, content, options) {
- var overlay = content;
- if (overlay instanceof OverlayClass) {
- setOptions(overlay, options);
- overlay._source = this;
- } else {
- overlay = old && !options ? old : new OverlayClass(options, this);
- overlay.setContent(content);
- }
- return overlay;
- }
- });
- var Popup = DivOverlay.extend({
- // @section
- // @aka Popup options
- options: {
- // @option pane: String = 'popupPane'
- // `Map pane` where the popup will be added.
- pane: "popupPane",
- // @option offset: Point = Point(0, 7)
- // The offset of the popup position.
- offset: [0, 7],
- // @option maxWidth: Number = 300
- // Max width of the popup, in pixels.
- maxWidth: 300,
- // @option minWidth: Number = 50
- // Min width of the popup, in pixels.
- minWidth: 50,
- // @option maxHeight: Number = null
- // If set, creates a scrollable container of the given height
- // inside a popup if its content exceeds it.
- // The scrollable container can be styled using the
- // `leaflet-popup-scrolled` CSS class selector.
- maxHeight: null,
- // @option autoPan: Boolean = true
- // Set it to `false` if you don't want the map to do panning animation
- // to fit the opened popup.
- autoPan: true,
- // @option autoPanPaddingTopLeft: Point = null
- // The margin between the popup and the top left corner of the map
- // view after autopanning was performed.
- autoPanPaddingTopLeft: null,
- // @option autoPanPaddingBottomRight: Point = null
- // The margin between the popup and the bottom right corner of the map
- // view after autopanning was performed.
- autoPanPaddingBottomRight: null,
- // @option autoPanPadding: Point = Point(5, 5)
- // Equivalent of setting both top left and bottom right autopan padding to the same value.
- autoPanPadding: [5, 5],
- // @option keepInView: Boolean = false
- // Set it to `true` if you want to prevent users from panning the popup
- // off of the screen while it is open.
- keepInView: false,
- // @option closeButton: Boolean = true
- // Controls the presence of a close button in the popup.
- closeButton: true,
- // @option autoClose: Boolean = true
- // Set it to `false` if you want to override the default behavior of
- // the popup closing when another popup is opened.
- autoClose: true,
- // @option closeOnEscapeKey: Boolean = true
- // Set it to `false` if you want to override the default behavior of
- // the ESC key for closing of the popup.
- closeOnEscapeKey: true,
- // @option closeOnClick: Boolean = *
- // Set it if you want to override the default behavior of the popup closing when user clicks
- // on the map. Defaults to the map's [`closePopupOnClick`](#map-closepopuponclick) option.
- // @option className: String = ''
- // A custom CSS class name to assign to the popup.
- className: ""
- },
- // @namespace Popup
- // @method openOn(map: Map): this
- // Alternative to `map.openPopup(popup)`.
- // Adds the popup to the map and closes the previous one.
- openOn: function(map) {
- map = arguments.length ? map : this._source._map;
- if (!map.hasLayer(this) && map._popup && map._popup.options.autoClose) {
- map.removeLayer(map._popup);
- }
- map._popup = this;
- return DivOverlay.prototype.openOn.call(this, map);
- },
- onAdd: function(map) {
- DivOverlay.prototype.onAdd.call(this, map);
- map.fire("popupopen", { popup: this });
- if (this._source) {
- this._source.fire("popupopen", { popup: this }, true);
- if (!(this._source instanceof Path)) {
- this._source.on("preclick", stopPropagation);
- }
- }
- },
- onRemove: function(map) {
- DivOverlay.prototype.onRemove.call(this, map);
- map.fire("popupclose", { popup: this });
- if (this._source) {
- this._source.fire("popupclose", { popup: this }, true);
- if (!(this._source instanceof Path)) {
- this._source.off("preclick", stopPropagation);
- }
- }
- },
- getEvents: function() {
- var events = DivOverlay.prototype.getEvents.call(this);
- if (this.options.closeOnClick !== void 0 ? this.options.closeOnClick : this._map.options.closePopupOnClick) {
- events.preclick = this.close;
- }
- if (this.options.keepInView) {
- events.moveend = this._adjustPan;
- }
- return events;
- },
- _initLayout: function() {
- var prefix = "leaflet-popup", container = this._container = create$1(
- "div",
- prefix + " " + (this.options.className || "") + " leaflet-zoom-animated"
- );
- var wrapper = this._wrapper = create$1("div", prefix + "-content-wrapper", container);
- this._contentNode = create$1("div", prefix + "-content", wrapper);
- disableClickPropagation(container);
- disableScrollPropagation(this._contentNode);
- on(container, "contextmenu", stopPropagation);
- this._tipContainer = create$1("div", prefix + "-tip-container", container);
- this._tip = create$1("div", prefix + "-tip", this._tipContainer);
- if (this.options.closeButton) {
- var closeButton = this._closeButton = create$1("a", prefix + "-close-button", container);
- closeButton.setAttribute("role", "button");
- closeButton.setAttribute("aria-label", "Close popup");
- closeButton.href = "#close";
- closeButton.innerHTML = '<span aria-hidden="true">×</span>';
- on(closeButton, "click", function(ev) {
- preventDefault(ev);
- this.close();
- }, this);
- }
- },
- _updateLayout: function() {
- var container = this._contentNode, style2 = container.style;
- style2.width = "";
- style2.whiteSpace = "nowrap";
- var width = container.offsetWidth;
- width = Math.min(width, this.options.maxWidth);
- width = Math.max(width, this.options.minWidth);
- style2.width = width + 1 + "px";
- style2.whiteSpace = "";
- style2.height = "";
- var height = container.offsetHeight, maxHeight = this.options.maxHeight, scrolledClass = "leaflet-popup-scrolled";
- if (maxHeight && height > maxHeight) {
- style2.height = maxHeight + "px";
- addClass(container, scrolledClass);
- } else {
- removeClass(container, scrolledClass);
- }
- this._containerWidth = this._container.offsetWidth;
- },
- _animateZoom: function(e) {
- var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center), anchor = this._getAnchor();
- setPosition(this._container, pos.add(anchor));
- },
- _adjustPan: function() {
- if (!this.options.autoPan) {
- return;
- }
- if (this._map._panAnim) {
- this._map._panAnim.stop();
- }
- if (this._autopanning) {
- this._autopanning = false;
- return;
- }
- var map = this._map, marginBottom = parseInt(getStyle(this._container, "marginBottom"), 10) || 0, containerHeight = this._container.offsetHeight + marginBottom, containerWidth = this._containerWidth, layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom);
- layerPos._add(getPosition(this._container));
- var containerPos = map.layerPointToContainerPoint(layerPos), padding = toPoint(this.options.autoPanPadding), paddingTL = toPoint(this.options.autoPanPaddingTopLeft || padding), paddingBR = toPoint(this.options.autoPanPaddingBottomRight || padding), size = map.getSize(), dx = 0, dy = 0;
- if (containerPos.x + containerWidth + paddingBR.x > size.x) {
- dx = containerPos.x + containerWidth - size.x + paddingBR.x;
- }
- if (containerPos.x - dx - paddingTL.x < 0) {
- dx = containerPos.x - paddingTL.x;
- }
- if (containerPos.y + containerHeight + paddingBR.y > size.y) {
- dy = containerPos.y + containerHeight - size.y + paddingBR.y;
- }
- if (containerPos.y - dy - paddingTL.y < 0) {
- dy = containerPos.y - paddingTL.y;
- }
- if (dx || dy) {
- if (this.options.keepInView) {
- this._autopanning = true;
- }
- map.fire("autopanstart").panBy([dx, dy]);
- }
- },
- _getAnchor: function() {
- return toPoint(this._source && this._source._getPopupAnchor ? this._source._getPopupAnchor() : [0, 0]);
- }
- });
- var popup = function(options, source) {
- return new Popup(options, source);
- };
- Map.mergeOptions({
- closePopupOnClick: true
- });
- Map.include({
- // @method openPopup(popup: Popup): this
- // Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).
- // @alternative
- // @method openPopup(content: String|HTMLElement, latlng: LatLng, options?: Popup options): this
- // Creates a popup with the specified content and options and opens it in the given point on a map.
- openPopup: function(popup2, latlng, options) {
- this._initOverlay(Popup, popup2, latlng, options).openOn(this);
- return this;
- },
- // @method closePopup(popup?: Popup): this
- // Closes the popup previously opened with [openPopup](#map-openpopup) (or the given one).
- closePopup: function(popup2) {
- popup2 = arguments.length ? popup2 : this._popup;
- if (popup2) {
- popup2.close();
- }
- return this;
- }
- });
- Layer.include({
- // @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this
- // Binds a popup to the layer with the passed `content` and sets up the
- // necessary event listeners. If a `Function` is passed it will receive
- // the layer as the first argument and should return a `String` or `HTMLElement`.
- bindPopup: function(content, options) {
- this._popup = this._initOverlay(Popup, this._popup, content, options);
- if (!this._popupHandlersAdded) {
- this.on({
- click: this._openPopup,
- keypress: this._onKeyPress,
- remove: this.closePopup,
- move: this._movePopup
- });
- this._popupHandlersAdded = true;
- }
- return this;
- },
- // @method unbindPopup(): this
- // Removes the popup previously bound with `bindPopup`.
- unbindPopup: function() {
- if (this._popup) {
- this.off({
- click: this._openPopup,
- keypress: this._onKeyPress,
- remove: this.closePopup,
- move: this._movePopup
- });
- this._popupHandlersAdded = false;
- this._popup = null;
- }
- return this;
- },
- // @method openPopup(latlng?: LatLng): this
- // Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed.
- openPopup: function(latlng) {
- if (this._popup) {
- if (!(this instanceof FeatureGroup)) {
- this._popup._source = this;
- }
- if (this._popup._prepareOpen(latlng || this._latlng)) {
- this._popup.openOn(this._map);
- }
- }
- return this;
- },
- // @method closePopup(): this
- // Closes the popup bound to this layer if it is open.
- closePopup: function() {
- if (this._popup) {
- this._popup.close();
- }
- return this;
- },
- // @method togglePopup(): this
- // Opens or closes the popup bound to this layer depending on its current state.
- togglePopup: function() {
- if (this._popup) {
- this._popup.toggle(this);
- }
- return this;
- },
- // @method isPopupOpen(): boolean
- // Returns `true` if the popup bound to this layer is currently open.
- isPopupOpen: function() {
- return this._popup ? this._popup.isOpen() : false;
- },
- // @method setPopupContent(content: String|HTMLElement|Popup): this
- // Sets the content of the popup bound to this layer.
- setPopupContent: function(content) {
- if (this._popup) {
- this._popup.setContent(content);
- }
- return this;
- },
- // @method getPopup(): Popup
- // Returns the popup bound to this layer.
- getPopup: function() {
- return this._popup;
- },
- _openPopup: function(e) {
- if (!this._popup || !this._map) {
- return;
- }
- stop(e);
- var target = e.layer || e.target;
- if (this._popup._source === target && !(target instanceof Path)) {
- if (this._map.hasLayer(this._popup)) {
- this.closePopup();
- } else {
- this.openPopup(e.latlng);
- }
- return;
- }
- this._popup._source = target;
- this.openPopup(e.latlng);
- },
- _movePopup: function(e) {
- this._popup.setLatLng(e.latlng);
- },
- _onKeyPress: function(e) {
- if (e.originalEvent.keyCode === 13) {
- this._openPopup(e);
- }
- }
- });
- var Tooltip = DivOverlay.extend({
- // @section
- // @aka Tooltip options
- options: {
- // @option pane: String = 'tooltipPane'
- // `Map pane` where the tooltip will be added.
- pane: "tooltipPane",
- // @option offset: Point = Point(0, 0)
- // Optional offset of the tooltip position.
- offset: [0, 0],
- // @option direction: String = 'auto'
- // Direction where to open the tooltip. Possible values are: `right`, `left`,
- // `top`, `bottom`, `center`, `auto`.
- // `auto` will dynamically switch between `right` and `left` according to the tooltip
- // position on the map.
- direction: "auto",
- // @option permanent: Boolean = false
- // Whether to open the tooltip permanently or only on mouseover.
- permanent: false,
- // @option sticky: Boolean = false
- // If true, the tooltip will follow the mouse instead of being fixed at the feature center.
- sticky: false,
- // @option opacity: Number = 0.9
- // Tooltip container opacity.
- opacity: 0.9
- },
- onAdd: function(map) {
- DivOverlay.prototype.onAdd.call(this, map);
- this.setOpacity(this.options.opacity);
- map.fire("tooltipopen", { tooltip: this });
- if (this._source) {
- this.addEventParent(this._source);
- this._source.fire("tooltipopen", { tooltip: this }, true);
- }
- },
- onRemove: function(map) {
- DivOverlay.prototype.onRemove.call(this, map);
- map.fire("tooltipclose", { tooltip: this });
- if (this._source) {
- this.removeEventParent(this._source);
- this._source.fire("tooltipclose", { tooltip: this }, true);
- }
- },
- getEvents: function() {
- var events = DivOverlay.prototype.getEvents.call(this);
- if (!this.options.permanent) {
- events.preclick = this.close;
- }
- return events;
- },
- _initLayout: function() {
- var prefix = "leaflet-tooltip", className = prefix + " " + (this.options.className || "") + " leaflet-zoom-" + (this._zoomAnimated ? "animated" : "hide");
- this._contentNode = this._container = create$1("div", className);
- this._container.setAttribute("role", "tooltip");
- this._container.setAttribute("id", "leaflet-tooltip-" + stamp(this));
- },
- _updateLayout: function() {
- },
- _adjustPan: function() {
- },
- _setPosition: function(pos) {
- var subX, subY, map = this._map, container = this._container, centerPoint = map.latLngToContainerPoint(map.getCenter()), tooltipPoint = map.layerPointToContainerPoint(pos), direction = this.options.direction, tooltipWidth = container.offsetWidth, tooltipHeight = container.offsetHeight, offset = toPoint(this.options.offset), anchor = this._getAnchor();
- if (direction === "top") {
- subX = tooltipWidth / 2;
- subY = tooltipHeight;
- } else if (direction === "bottom") {
- subX = tooltipWidth / 2;
- subY = 0;
- } else if (direction === "center") {
- subX = tooltipWidth / 2;
- subY = tooltipHeight / 2;
- } else if (direction === "right") {
- subX = 0;
- subY = tooltipHeight / 2;
- } else if (direction === "left") {
- subX = tooltipWidth;
- subY = tooltipHeight / 2;
- } else if (tooltipPoint.x < centerPoint.x) {
- direction = "right";
- subX = 0;
- subY = tooltipHeight / 2;
- } else {
- direction = "left";
- subX = tooltipWidth + (offset.x + anchor.x) * 2;
- subY = tooltipHeight / 2;
- }
- pos = pos.subtract(toPoint(subX, subY, true)).add(offset).add(anchor);
- removeClass(container, "leaflet-tooltip-right");
- removeClass(container, "leaflet-tooltip-left");
- removeClass(container, "leaflet-tooltip-top");
- removeClass(container, "leaflet-tooltip-bottom");
- addClass(container, "leaflet-tooltip-" + direction);
- setPosition(container, pos);
- },
- _updatePosition: function() {
- var pos = this._map.latLngToLayerPoint(this._latlng);
- this._setPosition(pos);
- },
- setOpacity: function(opacity) {
- this.options.opacity = opacity;
- if (this._container) {
- setOpacity(this._container, opacity);
- }
- },
- _animateZoom: function(e) {
- var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
- this._setPosition(pos);
- },
- _getAnchor: function() {
- return toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
- }
- });
- var tooltip = function(options, source) {
- return new Tooltip(options, source);
- };
- Map.include({
- // @method openTooltip(tooltip: Tooltip): this
- // Opens the specified tooltip.
- // @alternative
- // @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this
- // Creates a tooltip with the specified content and options and open it.
- openTooltip: function(tooltip2, latlng, options) {
- this._initOverlay(Tooltip, tooltip2, latlng, options).openOn(this);
- return this;
- },
- // @method closeTooltip(tooltip: Tooltip): this
- // Closes the tooltip given as parameter.
- closeTooltip: function(tooltip2) {
- tooltip2.close();
- return this;
- }
- });
- Layer.include({
- // @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this
- // Binds a tooltip to the layer with the passed `content` and sets up the
- // necessary event listeners. If a `Function` is passed it will receive
- // the layer as the first argument and should return a `String` or `HTMLElement`.
- bindTooltip: function(content, options) {
- if (this._tooltip && this.isTooltipOpen()) {
- this.unbindTooltip();
- }
- this._tooltip = this._initOverlay(Tooltip, this._tooltip, content, options);
- this._initTooltipInteractions();
- if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) {
- this.openTooltip();
- }
- return this;
- },
- // @method unbindTooltip(): this
- // Removes the tooltip previously bound with `bindTooltip`.
- unbindTooltip: function() {
- if (this._tooltip) {
- this._initTooltipInteractions(true);
- this.closeTooltip();
- this._tooltip = null;
- }
- return this;
- },
- _initTooltipInteractions: function(remove2) {
- if (!remove2 && this._tooltipHandlersAdded) {
- return;
- }
- var onOff = remove2 ? "off" : "on", events = {
- remove: this.closeTooltip,
- move: this._moveTooltip
- };
- if (!this._tooltip.options.permanent) {
- events.mouseover = this._openTooltip;
- events.mouseout = this.closeTooltip;
- events.click = this._openTooltip;
- if (this._map) {
- this._addFocusListeners();
- } else {
- events.add = this._addFocusListeners;
- }
- } else {
- events.add = this._openTooltip;
- }
- if (this._tooltip.options.sticky) {
- events.mousemove = this._moveTooltip;
- }
- this[onOff](events);
- this._tooltipHandlersAdded = !remove2;
- },
- // @method openTooltip(latlng?: LatLng): this
- // Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed.
- openTooltip: function(latlng) {
- if (this._tooltip) {
- if (!(this instanceof FeatureGroup)) {
- this._tooltip._source = this;
- }
- if (this._tooltip._prepareOpen(latlng)) {
- this._tooltip.openOn(this._map);
- if (this.getElement) {
- this._setAriaDescribedByOnLayer(this);
- } else if (this.eachLayer) {
- this.eachLayer(this._setAriaDescribedByOnLayer, this);
- }
- }
- }
- return this;
- },
- // @method closeTooltip(): this
- // Closes the tooltip bound to this layer if it is open.
- closeTooltip: function() {
- if (this._tooltip) {
- return this._tooltip.close();
- }
- },
- // @method toggleTooltip(): this
- // Opens or closes the tooltip bound to this layer depending on its current state.
- toggleTooltip: function() {
- if (this._tooltip) {
- this._tooltip.toggle(this);
- }
- return this;
- },
- // @method isTooltipOpen(): boolean
- // Returns `true` if the tooltip bound to this layer is currently open.
- isTooltipOpen: function() {
- return this._tooltip.isOpen();
- },
- // @method setTooltipContent(content: String|HTMLElement|Tooltip): this
- // Sets the content of the tooltip bound to this layer.
- setTooltipContent: function(content) {
- if (this._tooltip) {
- this._tooltip.setContent(content);
- }
- return this;
- },
- // @method getTooltip(): Tooltip
- // Returns the tooltip bound to this layer.
- getTooltip: function() {
- return this._tooltip;
- },
- _addFocusListeners: function() {
- if (this.getElement) {
- this._addFocusListenersOnLayer(this);
- } else if (this.eachLayer) {
- this.eachLayer(this._addFocusListenersOnLayer, this);
- }
- },
- _addFocusListenersOnLayer: function(layer) {
- var el = typeof layer.getElement === "function" && layer.getElement();
- if (el) {
- on(el, "focus", function() {
- this._tooltip._source = layer;
- this.openTooltip();
- }, this);
- on(el, "blur", this.closeTooltip, this);
- }
- },
- _setAriaDescribedByOnLayer: function(layer) {
- var el = typeof layer.getElement === "function" && layer.getElement();
- if (el) {
- el.setAttribute("aria-describedby", this._tooltip._container.id);
- }
- },
- _openTooltip: function(e) {
- if (!this._tooltip || !this._map) {
- return;
- }
- if (this._map.dragging && this._map.dragging.moving() && !this._openOnceFlag) {
- this._openOnceFlag = true;
- var that = this;
- this._map.once("moveend", function() {
- that._openOnceFlag = false;
- that._openTooltip(e);
- });
- return;
- }
- this._tooltip._source = e.layer || e.target;
- this.openTooltip(this._tooltip.options.sticky ? e.latlng : void 0);
- },
- _moveTooltip: function(e) {
- var latlng = e.latlng, containerPoint, layerPoint;
- if (this._tooltip.options.sticky && e.originalEvent) {
- containerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);
- layerPoint = this._map.containerPointToLayerPoint(containerPoint);
- latlng = this._map.layerPointToLatLng(layerPoint);
- }
- this._tooltip.setLatLng(latlng);
- }
- });
- var DivIcon = Icon.extend({
- options: {
- // @section
- // @aka DivIcon options
- iconSize: [12, 12],
- // also can be set through CSS
- // iconAnchor: (Point),
- // popupAnchor: (Point),
- // @option html: String|HTMLElement = ''
- // Custom HTML code to put inside the div element, empty by default. Alternatively,
- // an instance of `HTMLElement`.
- html: false,
- // @option bgPos: Point = [0, 0]
- // Optional relative position of the background, in pixels
- bgPos: null,
- className: "leaflet-div-icon"
- },
- createIcon: function(oldIcon) {
- var div = oldIcon && oldIcon.tagName === "DIV" ? oldIcon : document.createElement("div"), options = this.options;
- if (options.html instanceof Element) {
- empty(div);
- div.appendChild(options.html);
- } else {
- div.innerHTML = options.html !== false ? options.html : "";
- }
- if (options.bgPos) {
- var bgPos = toPoint(options.bgPos);
- div.style.backgroundPosition = -bgPos.x + "px " + -bgPos.y + "px";
- }
- this._setIconStyles(div, "icon");
- return div;
- },
- createShadow: function() {
- return null;
- }
- });
- function divIcon(options) {
- return new DivIcon(options);
- }
- Icon.Default = IconDefault;
- var GridLayer = Layer.extend({
- // @section
- // @aka GridLayer options
- options: {
- // @option tileSize: Number|Point = 256
- // Width and height of tiles in the grid. Use a number if width and height are equal, or `L.point(width, height)` otherwise.
- tileSize: 256,
- // @option opacity: Number = 1.0
- // Opacity of the tiles. Can be used in the `createTile()` function.
- opacity: 1,
- // @option updateWhenIdle: Boolean = (depends)
- // Load new tiles only when panning ends.
- // `true` by default on mobile browsers, in order to avoid too many requests and keep smooth navigation.
- // `false` otherwise in order to display new tiles _during_ panning, since it is easy to pan outside the
- // [`keepBuffer`](#gridlayer-keepbuffer) option in desktop browsers.
- updateWhenIdle: Browser.mobile,
- // @option updateWhenZooming: Boolean = true
- // By default, a smooth zoom animation (during a [touch zoom](#map-touchzoom) or a [`flyTo()`](#map-flyto)) will update grid layers every integer zoom level. Setting this option to `false` will update the grid layer only when the smooth animation ends.
- updateWhenZooming: true,
- // @option updateInterval: Number = 200
- // Tiles will not update more than once every `updateInterval` milliseconds when panning.
- updateInterval: 200,
- // @option zIndex: Number = 1
- // The explicit zIndex of the tile layer.
- zIndex: 1,
- // @option bounds: LatLngBounds = undefined
- // If set, tiles will only be loaded inside the set `LatLngBounds`.
- bounds: null,
- // @option minZoom: Number = 0
- // The minimum zoom level down to which this layer will be displayed (inclusive).
- minZoom: 0,
- // @option maxZoom: Number = undefined
- // The maximum zoom level up to which this layer will be displayed (inclusive).
- maxZoom: void 0,
- // @option maxNativeZoom: Number = undefined
- // Maximum zoom number the tile source has available. If it is specified,
- // the tiles on all zoom levels higher than `maxNativeZoom` will be loaded
- // from `maxNativeZoom` level and auto-scaled.
- maxNativeZoom: void 0,
- // @option minNativeZoom: Number = undefined
- // Minimum zoom number the tile source has available. If it is specified,
- // the tiles on all zoom levels lower than `minNativeZoom` will be loaded
- // from `minNativeZoom` level and auto-scaled.
- minNativeZoom: void 0,
- // @option noWrap: Boolean = false
- // Whether the layer is wrapped around the antimeridian. If `true`, the
- // GridLayer will only be displayed once at low zoom levels. Has no
- // effect when the [map CRS](#map-crs) doesn't wrap around. Can be used
- // in combination with [`bounds`](#gridlayer-bounds) to prevent requesting
- // tiles outside the CRS limits.
- noWrap: false,
- // @option pane: String = 'tilePane'
- // `Map pane` where the grid layer will be added.
- pane: "tilePane",
- // @option className: String = ''
- // A custom class name to assign to the tile layer. Empty by default.
- className: "",
- // @option keepBuffer: Number = 2
- // When panning the map, keep this many rows and columns of tiles before unloading them.
- keepBuffer: 2
- },
- initialize: function(options) {
- setOptions(this, options);
- },
- onAdd: function() {
- this._initContainer();
- this._levels = {};
- this._tiles = {};
- this._resetView();
- },
- beforeAdd: function(map) {
- map._addZoomLimit(this);
- },
- onRemove: function(map) {
- this._removeAllTiles();
- remove(this._container);
- map._removeZoomLimit(this);
- this._container = null;
- this._tileZoom = void 0;
- },
- // @method bringToFront: this
- // Brings the tile layer to the top of all tile layers.
- bringToFront: function() {
- if (this._map) {
- toFront(this._container);
- this._setAutoZIndex(Math.max);
- }
- return this;
- },
- // @method bringToBack: this
- // Brings the tile layer to the bottom of all tile layers.
- bringToBack: function() {
- if (this._map) {
- toBack(this._container);
- this._setAutoZIndex(Math.min);
- }
- return this;
- },
- // @method getContainer: HTMLElement
- // Returns the HTML element that contains the tiles for this layer.
- getContainer: function() {
- return this._container;
- },
- // @method setOpacity(opacity: Number): this
- // Changes the [opacity](#gridlayer-opacity) of the grid layer.
- setOpacity: function(opacity) {
- this.options.opacity = opacity;
- this._updateOpacity();
- return this;
- },
- // @method setZIndex(zIndex: Number): this
- // Changes the [zIndex](#gridlayer-zindex) of the grid layer.
- setZIndex: function(zIndex) {
- this.options.zIndex = zIndex;
- this._updateZIndex();
- return this;
- },
- // @method isLoading: Boolean
- // Returns `true` if any tile in the grid layer has not finished loading.
- isLoading: function() {
- return this._loading;
- },
- // @method redraw: this
- // Causes the layer to clear all the tiles and request them again.
- redraw: function() {
- if (this._map) {
- this._removeAllTiles();
- var tileZoom = this._clampZoom(this._map.getZoom());
- if (tileZoom !== this._tileZoom) {
- this._tileZoom = tileZoom;
- this._updateLevels();
- }
- this._update();
- }
- return this;
- },
- getEvents: function() {
- var events = {
- viewprereset: this._invalidateAll,
- viewreset: this._resetView,
- zoom: this._resetView,
- moveend: this._onMoveEnd
- };
- if (!this.options.updateWhenIdle) {
- if (!this._onMove) {
- this._onMove = throttle(this._onMoveEnd, this.options.updateInterval, this);
- }
- events.move = this._onMove;
- }
- if (this._zoomAnimated) {
- events.zoomanim = this._animateZoom;
- }
- return events;
- },
- // @section Extension methods
- // Layers extending `GridLayer` shall reimplement the following method.
- // @method createTile(coords: Object, done?: Function): HTMLElement
- // Called only internally, must be overridden by classes extending `GridLayer`.
- // Returns the `HTMLElement` corresponding to the given `coords`. If the `done` callback
- // is specified, it must be called when the tile has finished loading and drawing.
- createTile: function() {
- return document.createElement("div");
- },
- // @section
- // @method getTileSize: Point
- // Normalizes the [tileSize option](#gridlayer-tilesize) into a point. Used by the `createTile()` method.
- getTileSize: function() {
- var s = this.options.tileSize;
- return s instanceof Point ? s : new Point(s, s);
- },
- _updateZIndex: function() {
- if (this._container && this.options.zIndex !== void 0 && this.options.zIndex !== null) {
- this._container.style.zIndex = this.options.zIndex;
- }
- },
- _setAutoZIndex: function(compare) {
- var layers2 = this.getPane().children, edgeZIndex = -compare(-Infinity, Infinity);
- for (var i = 0, len = layers2.length, zIndex; i < len; i++) {
- zIndex = layers2[i].style.zIndex;
- if (layers2[i] !== this._container && zIndex) {
- edgeZIndex = compare(edgeZIndex, +zIndex);
- }
- }
- if (isFinite(edgeZIndex)) {
- this.options.zIndex = edgeZIndex + compare(-1, 1);
- this._updateZIndex();
- }
- },
- _updateOpacity: function() {
- if (!this._map) {
- return;
- }
- if (Browser.ielt9) {
- return;
- }
- setOpacity(this._container, this.options.opacity);
- var now = +/* @__PURE__ */ new Date(), nextFrame = false, willPrune = false;
- for (var key in this._tiles) {
- var tile = this._tiles[key];
- if (!tile.current || !tile.loaded) {
- continue;
- }
- var fade = Math.min(1, (now - tile.loaded) / 200);
- setOpacity(tile.el, fade);
- if (fade < 1) {
- nextFrame = true;
- } else {
- if (tile.active) {
- willPrune = true;
- } else {
- this._onOpaqueTile(tile);
- }
- tile.active = true;
- }
- }
- if (willPrune && !this._noPrune) {
- this._pruneTiles();
- }
- if (nextFrame) {
- cancelAnimFrame(this._fadeFrame);
- this._fadeFrame = requestAnimFrame(this._updateOpacity, this);
- }
- },
- _onOpaqueTile: falseFn,
- _initContainer: function() {
- if (this._container) {
- return;
- }
- this._container = create$1("div", "leaflet-layer " + (this.options.className || ""));
- this._updateZIndex();
- if (this.options.opacity < 1) {
- this._updateOpacity();
- }
- this.getPane().appendChild(this._container);
- },
- _updateLevels: function() {
- var zoom2 = this._tileZoom, maxZoom = this.options.maxZoom;
- if (zoom2 === void 0) {
- return void 0;
- }
- for (var z in this._levels) {
- z = Number(z);
- if (this._levels[z].el.children.length || z === zoom2) {
- this._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom2 - z);
- this._onUpdateLevel(z);
- } else {
- remove(this._levels[z].el);
- this._removeTilesAtZoom(z);
- this._onRemoveLevel(z);
- delete this._levels[z];
- }
- }
- var level = this._levels[zoom2], map = this._map;
- if (!level) {
- level = this._levels[zoom2] = {};
- level.el = create$1("div", "leaflet-tile-container leaflet-zoom-animated", this._container);
- level.el.style.zIndex = maxZoom;
- level.origin = map.project(map.unproject(map.getPixelOrigin()), zoom2).round();
- level.zoom = zoom2;
- this._setZoomTransform(level, map.getCenter(), map.getZoom());
- falseFn(level.el.offsetWidth);
- this._onCreateLevel(level);
- }
- this._level = level;
- return level;
- },
- _onUpdateLevel: falseFn,
- _onRemoveLevel: falseFn,
- _onCreateLevel: falseFn,
- _pruneTiles: function() {
- if (!this._map) {
- return;
- }
- var key, tile;
- var zoom2 = this._map.getZoom();
- if (zoom2 > this.options.maxZoom || zoom2 < this.options.minZoom) {
- this._removeAllTiles();
- return;
- }
- for (key in this._tiles) {
- tile = this._tiles[key];
- tile.retain = tile.current;
- }
- for (key in this._tiles) {
- tile = this._tiles[key];
- if (tile.current && !tile.active) {
- var coords = tile.coords;
- if (!this._retainParent(coords.x, coords.y, coords.z, coords.z - 5)) {
- this._retainChildren(coords.x, coords.y, coords.z, coords.z + 2);
- }
- }
- }
- for (key in this._tiles) {
- if (!this._tiles[key].retain) {
- this._removeTile(key);
- }
- }
- },
- _removeTilesAtZoom: function(zoom2) {
- for (var key in this._tiles) {
- if (this._tiles[key].coords.z !== zoom2) {
- continue;
- }
- this._removeTile(key);
- }
- },
- _removeAllTiles: function() {
- for (var key in this._tiles) {
- this._removeTile(key);
- }
- },
- _invalidateAll: function() {
- for (var z in this._levels) {
- remove(this._levels[z].el);
- this._onRemoveLevel(Number(z));
- delete this._levels[z];
- }
- this._removeAllTiles();
- this._tileZoom = void 0;
- },
- _retainParent: function(x, y, z, minZoom) {
- var x2 = Math.floor(x / 2), y2 = Math.floor(y / 2), z2 = z - 1, coords2 = new Point(+x2, +y2);
- coords2.z = +z2;
- var key = this._tileCoordsToKey(coords2), tile = this._tiles[key];
- if (tile && tile.active) {
- tile.retain = true;
- return true;
- } else if (tile && tile.loaded) {
- tile.retain = true;
- }
- if (z2 > minZoom) {
- return this._retainParent(x2, y2, z2, minZoom);
- }
- return false;
- },
- _retainChildren: function(x, y, z, maxZoom) {
- for (var i = 2 * x; i < 2 * x + 2; i++) {
- for (var j = 2 * y; j < 2 * y + 2; j++) {
- var coords = new Point(i, j);
- coords.z = z + 1;
- var key = this._tileCoordsToKey(coords), tile = this._tiles[key];
- if (tile && tile.active) {
- tile.retain = true;
- continue;
- } else if (tile && tile.loaded) {
- tile.retain = true;
- }
- if (z + 1 < maxZoom) {
- this._retainChildren(i, j, z + 1, maxZoom);
- }
- }
- }
- },
- _resetView: function(e) {
- var animating = e && (e.pinch || e.flyTo);
- this._setView(this._map.getCenter(), this._map.getZoom(), animating, animating);
- },
- _animateZoom: function(e) {
- this._setView(e.center, e.zoom, true, e.noUpdate);
- },
- _clampZoom: function(zoom2) {
- var options = this.options;
- if (void 0 !== options.minNativeZoom && zoom2 < options.minNativeZoom) {
- return options.minNativeZoom;
- }
- if (void 0 !== options.maxNativeZoom && options.maxNativeZoom < zoom2) {
- return options.maxNativeZoom;
- }
- return zoom2;
- },
- _setView: function(center, zoom2, noPrune, noUpdate) {
- var tileZoom = Math.round(zoom2);
- if (this.options.maxZoom !== void 0 && tileZoom > this.options.maxZoom || this.options.minZoom !== void 0 && tileZoom < this.options.minZoom) {
- tileZoom = void 0;
- } else {
- tileZoom = this._clampZoom(tileZoom);
- }
- var tileZoomChanged = this.options.updateWhenZooming && tileZoom !== this._tileZoom;
- if (!noUpdate || tileZoomChanged) {
- this._tileZoom = tileZoom;
- if (this._abortLoading) {
- this._abortLoading();
- }
- this._updateLevels();
- this._resetGrid();
- if (tileZoom !== void 0) {
- this._update(center);
- }
- if (!noPrune) {
- this._pruneTiles();
- }
- this._noPrune = !!noPrune;
- }
- this._setZoomTransforms(center, zoom2);
- },
- _setZoomTransforms: function(center, zoom2) {
- for (var i in this._levels) {
- this._setZoomTransform(this._levels[i], center, zoom2);
- }
- },
- _setZoomTransform: function(level, center, zoom2) {
- var scale2 = this._map.getZoomScale(zoom2, level.zoom), translate = level.origin.multiplyBy(scale2).subtract(this._map._getNewPixelOrigin(center, zoom2)).round();
- if (Browser.any3d) {
- setTransform(level.el, translate, scale2);
- } else {
- setPosition(level.el, translate);
- }
- },
- _resetGrid: function() {
- var map = this._map, crs = map.options.crs, tileSize = this._tileSize = this.getTileSize(), tileZoom = this._tileZoom;
- var bounds = this._map.getPixelWorldBounds(this._tileZoom);
- if (bounds) {
- this._globalTileRange = this._pxBoundsToTileRange(bounds);
- }
- this._wrapX = crs.wrapLng && !this.options.noWrap && [
- Math.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x),
- Math.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y)
- ];
- this._wrapY = crs.wrapLat && !this.options.noWrap && [
- Math.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x),
- Math.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y)
- ];
- },
- _onMoveEnd: function() {
- if (!this._map || this._map._animatingZoom) {
- return;
- }
- this._update();
- },
- _getTiledPixelBounds: function(center) {
- var map = this._map, mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(), scale2 = map.getZoomScale(mapZoom, this._tileZoom), pixelCenter = map.project(center, this._tileZoom).floor(), halfSize = map.getSize().divideBy(scale2 * 2);
- return new Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
- },
- // Private method to load tiles in the grid's active zoom level according to map bounds
- _update: function(center) {
- var map = this._map;
- if (!map) {
- return;
- }
- var zoom2 = this._clampZoom(map.getZoom());
- if (center === void 0) {
- center = map.getCenter();
- }
- if (this._tileZoom === void 0) {
- return;
- }
- var pixelBounds = this._getTiledPixelBounds(center), tileRange = this._pxBoundsToTileRange(pixelBounds), tileCenter = tileRange.getCenter(), queue = [], margin = this.options.keepBuffer, noPruneRange = new Bounds(
- tileRange.getBottomLeft().subtract([margin, -margin]),
- tileRange.getTopRight().add([margin, -margin])
- );
- if (!(isFinite(tileRange.min.x) && isFinite(tileRange.min.y) && isFinite(tileRange.max.x) && isFinite(tileRange.max.y))) {
- throw new Error("Attempted to load an infinite number of tiles");
- }
- for (var key in this._tiles) {
- var c = this._tiles[key].coords;
- if (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) {
- this._tiles[key].current = false;
- }
- }
- if (Math.abs(zoom2 - this._tileZoom) > 1) {
- this._setView(center, zoom2);
- return;
- }
- for (var j = tileRange.min.y; j <= tileRange.max.y; j++) {
- for (var i = tileRange.min.x; i <= tileRange.max.x; i++) {
- var coords = new Point(i, j);
- coords.z = this._tileZoom;
- if (!this._isValidTile(coords)) {
- continue;
- }
- var tile = this._tiles[this._tileCoordsToKey(coords)];
- if (tile) {
- tile.current = true;
- } else {
- queue.push(coords);
- }
- }
- }
- queue.sort(function(a, b) {
- return a.distanceTo(tileCenter) - b.distanceTo(tileCenter);
- });
- if (queue.length !== 0) {
- if (!this._loading) {
- this._loading = true;
- this.fire("loading");
- }
- var fragment = document.createDocumentFragment();
- for (i = 0; i < queue.length; i++) {
- this._addTile(queue[i], fragment);
- }
- this._level.el.appendChild(fragment);
- }
- },
- _isValidTile: function(coords) {
- var crs = this._map.options.crs;
- if (!crs.infinite) {
- var bounds = this._globalTileRange;
- if (!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x) || !crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y)) {
- return false;
- }
- }
- if (!this.options.bounds) {
- return true;
- }
- var tileBounds = this._tileCoordsToBounds(coords);
- return toLatLngBounds(this.options.bounds).overlaps(tileBounds);
- },
- _keyToBounds: function(key) {
- return this._tileCoordsToBounds(this._keyToTileCoords(key));
- },
- _tileCoordsToNwSe: function(coords) {
- var map = this._map, tileSize = this.getTileSize(), nwPoint = coords.scaleBy(tileSize), sePoint = nwPoint.add(tileSize), nw = map.unproject(nwPoint, coords.z), se = map.unproject(sePoint, coords.z);
- return [nw, se];
- },
- // converts tile coordinates to its geographical bounds
- _tileCoordsToBounds: function(coords) {
- var bp = this._tileCoordsToNwSe(coords), bounds = new LatLngBounds(bp[0], bp[1]);
- if (!this.options.noWrap) {
- bounds = this._map.wrapLatLngBounds(bounds);
- }
- return bounds;
- },
- // converts tile coordinates to key for the tile cache
- _tileCoordsToKey: function(coords) {
- return coords.x + ":" + coords.y + ":" + coords.z;
- },
- // converts tile cache key to coordinates
- _keyToTileCoords: function(key) {
- var k = key.split(":"), coords = new Point(+k[0], +k[1]);
- coords.z = +k[2];
- return coords;
- },
- _removeTile: function(key) {
- var tile = this._tiles[key];
- if (!tile) {
- return;
- }
- remove(tile.el);
- delete this._tiles[key];
- this.fire("tileunload", {
- tile: tile.el,
- coords: this._keyToTileCoords(key)
- });
- },
- _initTile: function(tile) {
- addClass(tile, "leaflet-tile");
- var tileSize = this.getTileSize();
- tile.style.width = tileSize.x + "px";
- tile.style.height = tileSize.y + "px";
- tile.onselectstart = falseFn;
- tile.onmousemove = falseFn;
- if (Browser.ielt9 && this.options.opacity < 1) {
- setOpacity(tile, this.options.opacity);
- }
- },
- _addTile: function(coords, container) {
- var tilePos = this._getTilePos(coords), key = this._tileCoordsToKey(coords);
- var tile = this.createTile(this._wrapCoords(coords), bind(this._tileReady, this, coords));
- this._initTile(tile);
- if (this.createTile.length < 2) {
- requestAnimFrame(bind(this._tileReady, this, coords, null, tile));
- }
- setPosition(tile, tilePos);
- this._tiles[key] = {
- el: tile,
- coords,
- current: true
- };
- container.appendChild(tile);
- this.fire("tileloadstart", {
- tile,
- coords
- });
- },
- _tileReady: function(coords, err, tile) {
- if (err) {
- this.fire("tileerror", {
- error: err,
- tile,
- coords
- });
- }
- var key = this._tileCoordsToKey(coords);
- tile = this._tiles[key];
- if (!tile) {
- return;
- }
- tile.loaded = +/* @__PURE__ */ new Date();
- if (this._map._fadeAnimated) {
- setOpacity(tile.el, 0);
- cancelAnimFrame(this._fadeFrame);
- this._fadeFrame = requestAnimFrame(this._updateOpacity, this);
- } else {
- tile.active = true;
- this._pruneTiles();
- }
- if (!err) {
- addClass(tile.el, "leaflet-tile-loaded");
- this.fire("tileload", {
- tile: tile.el,
- coords
- });
- }
- if (this._noTilesToLoad()) {
- this._loading = false;
- this.fire("load");
- if (Browser.ielt9 || !this._map._fadeAnimated) {
- requestAnimFrame(this._pruneTiles, this);
- } else {
- setTimeout(bind(this._pruneTiles, this), 250);
- }
- }
- },
- _getTilePos: function(coords) {
- return coords.scaleBy(this.getTileSize()).subtract(this._level.origin);
- },
- _wrapCoords: function(coords) {
- var newCoords = new Point(
- this._wrapX ? wrapNum(coords.x, this._wrapX) : coords.x,
- this._wrapY ? wrapNum(coords.y, this._wrapY) : coords.y
- );
- newCoords.z = coords.z;
- return newCoords;
- },
- _pxBoundsToTileRange: function(bounds) {
- var tileSize = this.getTileSize();
- return new Bounds(
- bounds.min.unscaleBy(tileSize).floor(),
- bounds.max.unscaleBy(tileSize).ceil().subtract([1, 1])
- );
- },
- _noTilesToLoad: function() {
- for (var key in this._tiles) {
- if (!this._tiles[key].loaded) {
- return false;
- }
- }
- return true;
- }
- });
- function gridLayer(options) {
- return new GridLayer(options);
- }
- var TileLayer = GridLayer.extend({
- // @section
- // @aka TileLayer options
- options: {
- // @option minZoom: Number = 0
- // The minimum zoom level down to which this layer will be displayed (inclusive).
- minZoom: 0,
- // @option maxZoom: Number = 18
- // The maximum zoom level up to which this layer will be displayed (inclusive).
- maxZoom: 18,
- // @option subdomains: String|String[] = 'abc'
- // Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
- subdomains: "abc",
- // @option errorTileUrl: String = ''
- // URL to the tile image to show in place of the tile that failed to load.
- errorTileUrl: "",
- // @option zoomOffset: Number = 0
- // The zoom number used in tile URLs will be offset with this value.
- zoomOffset: 0,
- // @option tms: Boolean = false
- // If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).
- tms: false,
- // @option zoomReverse: Boolean = false
- // If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)
- zoomReverse: false,
- // @option detectRetina: Boolean = false
- // If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
- detectRetina: false,
- // @option crossOrigin: Boolean|String = false
- // Whether the crossOrigin attribute will be added to the tiles.
- // If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.
- // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
- crossOrigin: false,
- // @option referrerPolicy: Boolean|String = false
- // Whether the referrerPolicy attribute will be added to the tiles.
- // If a String is provided, all tiles will have their referrerPolicy attribute set to the String provided.
- // This may be needed if your map's rendering context has a strict default but your tile provider expects a valid referrer
- // (e.g. to validate an API token).
- // Refer to [HTMLImageElement.referrerPolicy](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/referrerPolicy) for valid String values.
- referrerPolicy: false
- },
- initialize: function(url, options) {
- this._url = url;
- options = setOptions(this, options);
- if (options.detectRetina && Browser.retina && options.maxZoom > 0) {
- options.tileSize = Math.floor(options.tileSize / 2);
- if (!options.zoomReverse) {
- options.zoomOffset++;
- options.maxZoom = Math.max(options.minZoom, options.maxZoom - 1);
- } else {
- options.zoomOffset--;
- options.minZoom = Math.min(options.maxZoom, options.minZoom + 1);
- }
- options.minZoom = Math.max(0, options.minZoom);
- } else if (!options.zoomReverse) {
- options.maxZoom = Math.max(options.minZoom, options.maxZoom);
- } else {
- options.minZoom = Math.min(options.maxZoom, options.minZoom);
- }
- if (typeof options.subdomains === "string") {
- options.subdomains = options.subdomains.split("");
- }
- this.on("tileunload", this._onTileRemove);
- },
- // @method setUrl(url: String, noRedraw?: Boolean): this
- // Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
- // If the URL does not change, the layer will not be redrawn unless
- // the noRedraw parameter is set to false.
- setUrl: function(url, noRedraw) {
- if (this._url === url && noRedraw === void 0) {
- noRedraw = true;
- }
- this._url = url;
- if (!noRedraw) {
- this.redraw();
- }
- return this;
- },
- // @method createTile(coords: Object, done?: Function): HTMLElement
- // Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
- // to return an `<img>` HTML element with the appropriate image URL given `coords`. The `done`
- // callback is called when the tile has been loaded.
- createTile: function(coords, done) {
- var tile = document.createElement("img");
- on(tile, "load", bind(this._tileOnLoad, this, done, tile));
- on(tile, "error", bind(this._tileOnError, this, done, tile));
- if (this.options.crossOrigin || this.options.crossOrigin === "") {
- tile.crossOrigin = this.options.crossOrigin === true ? "" : this.options.crossOrigin;
- }
- if (typeof this.options.referrerPolicy === "string") {
- tile.referrerPolicy = this.options.referrerPolicy;
- }
- tile.alt = "";
- tile.src = this.getTileUrl(coords);
- return tile;
- },
- // @section Extension methods
- // @uninheritable
- // Layers extending `TileLayer` might reimplement the following method.
- // @method getTileUrl(coords: Object): String
- // Called only internally, returns the URL for a tile given its coordinates.
- // Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.
- getTileUrl: function(coords) {
- var data = {
- r: Browser.retina ? "@2x" : "",
- s: this._getSubdomain(coords),
- x: coords.x,
- y: coords.y,
- z: this._getZoomForUrl()
- };
- if (this._map && !this._map.options.crs.infinite) {
- var invertedY = this._globalTileRange.max.y - coords.y;
- if (this.options.tms) {
- data["y"] = invertedY;
- }
- data["-y"] = invertedY;
- }
- return template(this._url, extend(data, this.options));
- },
- _tileOnLoad: function(done, tile) {
- if (Browser.ielt9) {
- setTimeout(bind(done, this, null, tile), 0);
- } else {
- done(null, tile);
- }
- },
- _tileOnError: function(done, tile, e) {
- var errorUrl = this.options.errorTileUrl;
- if (errorUrl && tile.getAttribute("src") !== errorUrl) {
- tile.src = errorUrl;
- }
- done(e, tile);
- },
- _onTileRemove: function(e) {
- e.tile.onload = null;
- },
- _getZoomForUrl: function() {
- var zoom2 = this._tileZoom, maxZoom = this.options.maxZoom, zoomReverse = this.options.zoomReverse, zoomOffset = this.options.zoomOffset;
- if (zoomReverse) {
- zoom2 = maxZoom - zoom2;
- }
- return zoom2 + zoomOffset;
- },
- _getSubdomain: function(tilePoint) {
- var index2 = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;
- return this.options.subdomains[index2];
- },
- // stops loading all tiles in the background layer
- _abortLoading: function() {
- var i, tile;
- for (i in this._tiles) {
- if (this._tiles[i].coords.z !== this._tileZoom) {
- tile = this._tiles[i].el;
- tile.onload = falseFn;
- tile.onerror = falseFn;
- if (!tile.complete) {
- tile.src = emptyImageUrl;
- var coords = this._tiles[i].coords;
- remove(tile);
- delete this._tiles[i];
- this.fire("tileabort", {
- tile,
- coords
- });
- }
- }
- }
- },
- _removeTile: function(key) {
- var tile = this._tiles[key];
- if (!tile) {
- return;
- }
- tile.el.setAttribute("src", emptyImageUrl);
- return GridLayer.prototype._removeTile.call(this, key);
- },
- _tileReady: function(coords, err, tile) {
- if (!this._map || tile && tile.getAttribute("src") === emptyImageUrl) {
- return;
- }
- return GridLayer.prototype._tileReady.call(this, coords, err, tile);
- }
- });
- function tileLayer(url, options) {
- return new TileLayer(url, options);
- }
- var TileLayerWMS = TileLayer.extend({
- // @section
- // @aka TileLayer.WMS options
- // If any custom options not documented here are used, they will be sent to the
- // WMS server as extra parameters in each request URL. This can be useful for
- // [non-standard vendor WMS parameters](https://docs.geoserver.org/stable/en/user/services/wms/vendor.html).
- defaultWmsParams: {
- service: "WMS",
- request: "GetMap",
- // @option layers: String = ''
- // **(required)** Comma-separated list of WMS layers to show.
- layers: "",
- // @option styles: String = ''
- // Comma-separated list of WMS styles.
- styles: "",
- // @option format: String = 'image/jpeg'
- // WMS image format (use `'image/png'` for layers with transparency).
- format: "image/jpeg",
- // @option transparent: Boolean = false
- // If `true`, the WMS service will return images with transparency.
- transparent: false,
- // @option version: String = '1.1.1'
- // Version of the WMS service to use
- version: "1.1.1"
- },
- options: {
- // @option crs: CRS = null
- // Coordinate Reference System to use for the WMS requests, defaults to
- // map CRS. Don't change this if you're not sure what it means.
- crs: null,
- // @option uppercase: Boolean = false
- // If `true`, WMS request parameter keys will be uppercase.
- uppercase: false
- },
- initialize: function(url, options) {
- this._url = url;
- var wmsParams = extend({}, this.defaultWmsParams);
- for (var i in options) {
- if (!(i in this.options)) {
- wmsParams[i] = options[i];
- }
- }
- options = setOptions(this, options);
- var realRetina = options.detectRetina && Browser.retina ? 2 : 1;
- var tileSize = this.getTileSize();
- wmsParams.width = tileSize.x * realRetina;
- wmsParams.height = tileSize.y * realRetina;
- this.wmsParams = wmsParams;
- },
- onAdd: function(map) {
- this._crs = this.options.crs || map.options.crs;
- this._wmsVersion = parseFloat(this.wmsParams.version);
- var projectionKey = this._wmsVersion >= 1.3 ? "crs" : "srs";
- this.wmsParams[projectionKey] = this._crs.code;
- TileLayer.prototype.onAdd.call(this, map);
- },
- getTileUrl: function(coords) {
- var tileBounds = this._tileCoordsToNwSe(coords), crs = this._crs, bounds = toBounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])), min = bounds.min, max = bounds.max, bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ? [min.y, min.x, max.y, max.x] : [min.x, min.y, max.x, max.y]).join(","), url = TileLayer.prototype.getTileUrl.call(this, coords);
- return url + getParamString(this.wmsParams, url, this.options.uppercase) + (this.options.uppercase ? "&BBOX=" : "&bbox=") + bbox;
- },
- // @method setParams(params: Object, noRedraw?: Boolean): this
- // Merges an object with the new parameters and re-requests tiles on the current screen (unless `noRedraw` was set to true).
- setParams: function(params, noRedraw) {
- extend(this.wmsParams, params);
- if (!noRedraw) {
- this.redraw();
- }
- return this;
- }
- });
- function tileLayerWMS(url, options) {
- return new TileLayerWMS(url, options);
- }
- TileLayer.WMS = TileLayerWMS;
- tileLayer.wms = tileLayerWMS;
- var Renderer = Layer.extend({
- // @section
- // @aka Renderer options
- options: {
- // @option padding: Number = 0.1
- // How much to extend the clip area around the map view (relative to its size)
- // e.g. 0.1 would be 10% of map view in each direction
- padding: 0.1
- },
- initialize: function(options) {
- setOptions(this, options);
- stamp(this);
- this._layers = this._layers || {};
- },
- onAdd: function() {
- if (!this._container) {
- this._initContainer();
- addClass(this._container, "leaflet-zoom-animated");
- }
- this.getPane().appendChild(this._container);
- this._update();
- this.on("update", this._updatePaths, this);
- },
- onRemove: function() {
- this.off("update", this._updatePaths, this);
- this._destroyContainer();
- },
- getEvents: function() {
- var events = {
- viewreset: this._reset,
- zoom: this._onZoom,
- moveend: this._update,
- zoomend: this._onZoomEnd
- };
- if (this._zoomAnimated) {
- events.zoomanim = this._onAnimZoom;
- }
- return events;
- },
- _onAnimZoom: function(ev) {
- this._updateTransform(ev.center, ev.zoom);
- },
- _onZoom: function() {
- this._updateTransform(this._map.getCenter(), this._map.getZoom());
- },
- _updateTransform: function(center, zoom2) {
- var scale2 = this._map.getZoomScale(zoom2, this._zoom), viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding), currentCenterPoint = this._map.project(this._center, zoom2), topLeftOffset = viewHalf.multiplyBy(-scale2).add(currentCenterPoint).subtract(this._map._getNewPixelOrigin(center, zoom2));
- if (Browser.any3d) {
- setTransform(this._container, topLeftOffset, scale2);
- } else {
- setPosition(this._container, topLeftOffset);
- }
- },
- _reset: function() {
- this._update();
- this._updateTransform(this._center, this._zoom);
- for (var id in this._layers) {
- this._layers[id]._reset();
- }
- },
- _onZoomEnd: function() {
- for (var id in this._layers) {
- this._layers[id]._project();
- }
- },
- _updatePaths: function() {
- for (var id in this._layers) {
- this._layers[id]._update();
- }
- },
- _update: function() {
- var p = this.options.padding, size = this._map.getSize(), min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();
- this._bounds = new Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round());
- this._center = this._map.getCenter();
- this._zoom = this._map.getZoom();
- }
- });
- var Canvas = Renderer.extend({
- // @section
- // @aka Canvas options
- options: {
- // @option tolerance: Number = 0
- // How much to extend the click tolerance around a path/object on the map.
- tolerance: 0
- },
- getEvents: function() {
- var events = Renderer.prototype.getEvents.call(this);
- events.viewprereset = this._onViewPreReset;
- return events;
- },
- _onViewPreReset: function() {
- this._postponeUpdatePaths = true;
- },
- onAdd: function() {
- Renderer.prototype.onAdd.call(this);
- this._draw();
- },
- _initContainer: function() {
- var container = this._container = document.createElement("canvas");
- on(container, "mousemove", this._onMouseMove, this);
- on(container, "click dblclick mousedown mouseup contextmenu", this._onClick, this);
- on(container, "mouseout", this._handleMouseOut, this);
- container["_leaflet_disable_events"] = true;
- this._ctx = container.getContext("2d");
- },
- _destroyContainer: function() {
- cancelAnimFrame(this._redrawRequest);
- delete this._ctx;
- remove(this._container);
- off(this._container);
- delete this._container;
- },
- _updatePaths: function() {
- if (this._postponeUpdatePaths) {
- return;
- }
- var layer;
- this._redrawBounds = null;
- for (var id in this._layers) {
- layer = this._layers[id];
- layer._update();
- }
- this._redraw();
- },
- _update: function() {
- if (this._map._animatingZoom && this._bounds) {
- return;
- }
- Renderer.prototype._update.call(this);
- var b = this._bounds, container = this._container, size = b.getSize(), m = Browser.retina ? 2 : 1;
- setPosition(container, b.min);
- container.width = m * size.x;
- container.height = m * size.y;
- container.style.width = size.x + "px";
- container.style.height = size.y + "px";
- if (Browser.retina) {
- this._ctx.scale(2, 2);
- }
- this._ctx.translate(-b.min.x, -b.min.y);
- this.fire("update");
- },
- _reset: function() {
- Renderer.prototype._reset.call(this);
- if (this._postponeUpdatePaths) {
- this._postponeUpdatePaths = false;
- this._updatePaths();
- }
- },
- _initPath: function(layer) {
- this._updateDashArray(layer);
- this._layers[stamp(layer)] = layer;
- var order = layer._order = {
- layer,
- prev: this._drawLast,
- next: null
- };
- if (this._drawLast) {
- this._drawLast.next = order;
- }
- this._drawLast = order;
- this._drawFirst = this._drawFirst || this._drawLast;
- },
- _addPath: function(layer) {
- this._requestRedraw(layer);
- },
- _removePath: function(layer) {
- var order = layer._order;
- var next = order.next;
- var prev = order.prev;
- if (next) {
- next.prev = prev;
- } else {
- this._drawLast = prev;
- }
- if (prev) {
- prev.next = next;
- } else {
- this._drawFirst = next;
- }
- delete layer._order;
- delete this._layers[stamp(layer)];
- this._requestRedraw(layer);
- },
- _updatePath: function(layer) {
- this._extendRedrawBounds(layer);
- layer._project();
- layer._update();
- this._requestRedraw(layer);
- },
- _updateStyle: function(layer) {
- this._updateDashArray(layer);
- this._requestRedraw(layer);
- },
- _updateDashArray: function(layer) {
- if (typeof layer.options.dashArray === "string") {
- var parts = layer.options.dashArray.split(/[, ]+/), dashArray = [], dashValue, i;
- for (i = 0; i < parts.length; i++) {
- dashValue = Number(parts[i]);
- if (isNaN(dashValue)) {
- return;
- }
- dashArray.push(dashValue);
- }
- layer.options._dashArray = dashArray;
- } else {
- layer.options._dashArray = layer.options.dashArray;
- }
- },
- _requestRedraw: function(layer) {
- if (!this._map) {
- return;
- }
- this._extendRedrawBounds(layer);
- this._redrawRequest = this._redrawRequest || requestAnimFrame(this._redraw, this);
- },
- _extendRedrawBounds: function(layer) {
- if (layer._pxBounds) {
- var padding = (layer.options.weight || 0) + 1;
- this._redrawBounds = this._redrawBounds || new Bounds();
- this._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding]));
- this._redrawBounds.extend(layer._pxBounds.max.add([padding, padding]));
- }
- },
- _redraw: function() {
- this._redrawRequest = null;
- if (this._redrawBounds) {
- this._redrawBounds.min._floor();
- this._redrawBounds.max._ceil();
- }
- this._clear();
- this._draw();
- this._redrawBounds = null;
- },
- _clear: function() {
- var bounds = this._redrawBounds;
- if (bounds) {
- var size = bounds.getSize();
- this._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y);
- } else {
- this._ctx.save();
- this._ctx.setTransform(1, 0, 0, 1, 0, 0);
- this._ctx.clearRect(0, 0, this._container.width, this._container.height);
- this._ctx.restore();
- }
- },
- _draw: function() {
- var layer, bounds = this._redrawBounds;
- this._ctx.save();
- if (bounds) {
- var size = bounds.getSize();
- this._ctx.beginPath();
- this._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y);
- this._ctx.clip();
- }
- this._drawing = true;
- for (var order = this._drawFirst; order; order = order.next) {
- layer = order.layer;
- if (!bounds || layer._pxBounds && layer._pxBounds.intersects(bounds)) {
- layer._updatePath();
- }
- }
- this._drawing = false;
- this._ctx.restore();
- },
- _updatePoly: function(layer, closed) {
- if (!this._drawing) {
- return;
- }
- var i, j, len2, p, parts = layer._parts, len = parts.length, ctx = this._ctx;
- if (!len) {
- return;
- }
- ctx.beginPath();
- for (i = 0; i < len; i++) {
- for (j = 0, len2 = parts[i].length; j < len2; j++) {
- p = parts[i][j];
- ctx[j ? "lineTo" : "moveTo"](p.x, p.y);
- }
- if (closed) {
- ctx.closePath();
- }
- }
- this._fillStroke(ctx, layer);
- },
- _updateCircle: function(layer) {
- if (!this._drawing || layer._empty()) {
- return;
- }
- var p = layer._point, ctx = this._ctx, r = Math.max(Math.round(layer._radius), 1), s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;
- if (s !== 1) {
- ctx.save();
- ctx.scale(1, s);
- }
- ctx.beginPath();
- ctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false);
- if (s !== 1) {
- ctx.restore();
- }
- this._fillStroke(ctx, layer);
- },
- _fillStroke: function(ctx, layer) {
- var options = layer.options;
- if (options.fill) {
- ctx.globalAlpha = options.fillOpacity;
- ctx.fillStyle = options.fillColor || options.color;
- ctx.fill(options.fillRule || "evenodd");
- }
- if (options.stroke && options.weight !== 0) {
- if (ctx.setLineDash) {
- ctx.setLineDash(layer.options && layer.options._dashArray || []);
- }
- ctx.globalAlpha = options.opacity;
- ctx.lineWidth = options.weight;
- ctx.strokeStyle = options.color;
- ctx.lineCap = options.lineCap;
- ctx.lineJoin = options.lineJoin;
- ctx.stroke();
- }
- },
- // Canvas obviously doesn't have mouse events for individual drawn objects,
- // so we emulate that by calculating what's under the mouse on mousemove/click manually
- _onClick: function(e) {
- var point = this._map.mouseEventToLayerPoint(e), layer, clickedLayer;
- for (var order = this._drawFirst; order; order = order.next) {
- layer = order.layer;
- if (layer.options.interactive && layer._containsPoint(point)) {
- if (!(e.type === "click" || e.type === "preclick") || !this._map._draggableMoved(layer)) {
- clickedLayer = layer;
- }
- }
- }
- this._fireEvent(clickedLayer ? [clickedLayer] : false, e);
- },
- _onMouseMove: function(e) {
- if (!this._map || this._map.dragging.moving() || this._map._animatingZoom) {
- return;
- }
- var point = this._map.mouseEventToLayerPoint(e);
- this._handleMouseHover(e, point);
- },
- _handleMouseOut: function(e) {
- var layer = this._hoveredLayer;
- if (layer) {
- removeClass(this._container, "leaflet-interactive");
- this._fireEvent([layer], e, "mouseout");
- this._hoveredLayer = null;
- this._mouseHoverThrottled = false;
- }
- },
- _handleMouseHover: function(e, point) {
- if (this._mouseHoverThrottled) {
- return;
- }
- var layer, candidateHoveredLayer;
- for (var order = this._drawFirst; order; order = order.next) {
- layer = order.layer;
- if (layer.options.interactive && layer._containsPoint(point)) {
- candidateHoveredLayer = layer;
- }
- }
- if (candidateHoveredLayer !== this._hoveredLayer) {
- this._handleMouseOut(e);
- if (candidateHoveredLayer) {
- addClass(this._container, "leaflet-interactive");
- this._fireEvent([candidateHoveredLayer], e, "mouseover");
- this._hoveredLayer = candidateHoveredLayer;
- }
- }
- this._fireEvent(this._hoveredLayer ? [this._hoveredLayer] : false, e);
- this._mouseHoverThrottled = true;
- setTimeout(bind(function() {
- this._mouseHoverThrottled = false;
- }, this), 32);
- },
- _fireEvent: function(layers2, e, type) {
- this._map._fireDOMEvent(e, type || e.type, layers2);
- },
- _bringToFront: function(layer) {
- var order = layer._order;
- if (!order) {
- return;
- }
- var next = order.next;
- var prev = order.prev;
- if (next) {
- next.prev = prev;
- } else {
- return;
- }
- if (prev) {
- prev.next = next;
- } else if (next) {
- this._drawFirst = next;
- }
- order.prev = this._drawLast;
- this._drawLast.next = order;
- order.next = null;
- this._drawLast = order;
- this._requestRedraw(layer);
- },
- _bringToBack: function(layer) {
- var order = layer._order;
- if (!order) {
- return;
- }
- var next = order.next;
- var prev = order.prev;
- if (prev) {
- prev.next = next;
- } else {
- return;
- }
- if (next) {
- next.prev = prev;
- } else if (prev) {
- this._drawLast = prev;
- }
- order.prev = null;
- order.next = this._drawFirst;
- this._drawFirst.prev = order;
- this._drawFirst = order;
- this._requestRedraw(layer);
- }
- });
- function canvas(options) {
- return Browser.canvas ? new Canvas(options) : null;
- }
- var vmlCreate = function() {
- try {
- document.namespaces.add("lvml", "urn:schemas-microsoft-com:vml");
- return function(name) {
- return document.createElement("<lvml:" + name + ' class="lvml">');
- };
- } catch (e) {
- }
- return function(name) {
- return document.createElement("<" + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">');
- };
- }();
- var vmlMixin = {
- _initContainer: function() {
- this._container = create$1("div", "leaflet-vml-container");
- },
- _update: function() {
- if (this._map._animatingZoom) {
- return;
- }
- Renderer.prototype._update.call(this);
- this.fire("update");
- },
- _initPath: function(layer) {
- var container = layer._container = vmlCreate("shape");
- addClass(container, "leaflet-vml-shape " + (this.options.className || ""));
- container.coordsize = "1 1";
- layer._path = vmlCreate("path");
- container.appendChild(layer._path);
- this._updateStyle(layer);
- this._layers[stamp(layer)] = layer;
- },
- _addPath: function(layer) {
- var container = layer._container;
- this._container.appendChild(container);
- if (layer.options.interactive) {
- layer.addInteractiveTarget(container);
- }
- },
- _removePath: function(layer) {
- var container = layer._container;
- remove(container);
- layer.removeInteractiveTarget(container);
- delete this._layers[stamp(layer)];
- },
- _updateStyle: function(layer) {
- var stroke = layer._stroke, fill = layer._fill, options = layer.options, container = layer._container;
- container.stroked = !!options.stroke;
- container.filled = !!options.fill;
- if (options.stroke) {
- if (!stroke) {
- stroke = layer._stroke = vmlCreate("stroke");
- }
- container.appendChild(stroke);
- stroke.weight = options.weight + "px";
- stroke.color = options.color;
- stroke.opacity = options.opacity;
- if (options.dashArray) {
- stroke.dashStyle = isArray(options.dashArray) ? options.dashArray.join(" ") : options.dashArray.replace(/( *, *)/g, " ");
- } else {
- stroke.dashStyle = "";
- }
- stroke.endcap = options.lineCap.replace("butt", "flat");
- stroke.joinstyle = options.lineJoin;
- } else if (stroke) {
- container.removeChild(stroke);
- layer._stroke = null;
- }
- if (options.fill) {
- if (!fill) {
- fill = layer._fill = vmlCreate("fill");
- }
- container.appendChild(fill);
- fill.color = options.fillColor || options.color;
- fill.opacity = options.fillOpacity;
- } else if (fill) {
- container.removeChild(fill);
- layer._fill = null;
- }
- },
- _updateCircle: function(layer) {
- var p = layer._point.round(), r = Math.round(layer._radius), r2 = Math.round(layer._radiusY || r);
- this._setPath(layer, layer._empty() ? "M0 0" : "AL " + p.x + "," + p.y + " " + r + "," + r2 + " 0," + 65535 * 360);
- },
- _setPath: function(layer, path) {
- layer._path.v = path;
- },
- _bringToFront: function(layer) {
- toFront(layer._container);
- },
- _bringToBack: function(layer) {
- toBack(layer._container);
- }
- };
- var create = Browser.vml ? vmlCreate : svgCreate;
- var SVG = Renderer.extend({
- _initContainer: function() {
- this._container = create("svg");
- this._container.setAttribute("pointer-events", "none");
- this._rootGroup = create("g");
- this._container.appendChild(this._rootGroup);
- },
- _destroyContainer: function() {
- remove(this._container);
- off(this._container);
- delete this._container;
- delete this._rootGroup;
- delete this._svgSize;
- },
- _update: function() {
- if (this._map._animatingZoom && this._bounds) {
- return;
- }
- Renderer.prototype._update.call(this);
- var b = this._bounds, size = b.getSize(), container = this._container;
- if (!this._svgSize || !this._svgSize.equals(size)) {
- this._svgSize = size;
- container.setAttribute("width", size.x);
- container.setAttribute("height", size.y);
- }
- setPosition(container, b.min);
- container.setAttribute("viewBox", [b.min.x, b.min.y, size.x, size.y].join(" "));
- this.fire("update");
- },
- // methods below are called by vector layers implementations
- _initPath: function(layer) {
- var path = layer._path = create("path");
- if (layer.options.className) {
- addClass(path, layer.options.className);
- }
- if (layer.options.interactive) {
- addClass(path, "leaflet-interactive");
- }
- this._updateStyle(layer);
- this._layers[stamp(layer)] = layer;
- },
- _addPath: function(layer) {
- if (!this._rootGroup) {
- this._initContainer();
- }
- this._rootGroup.appendChild(layer._path);
- layer.addInteractiveTarget(layer._path);
- },
- _removePath: function(layer) {
- remove(layer._path);
- layer.removeInteractiveTarget(layer._path);
- delete this._layers[stamp(layer)];
- },
- _updatePath: function(layer) {
- layer._project();
- layer._update();
- },
- _updateStyle: function(layer) {
- var path = layer._path, options = layer.options;
- if (!path) {
- return;
- }
- if (options.stroke) {
- path.setAttribute("stroke", options.color);
- path.setAttribute("stroke-opacity", options.opacity);
- path.setAttribute("stroke-width", options.weight);
- path.setAttribute("stroke-linecap", options.lineCap);
- path.setAttribute("stroke-linejoin", options.lineJoin);
- if (options.dashArray) {
- path.setAttribute("stroke-dasharray", options.dashArray);
- } else {
- path.removeAttribute("stroke-dasharray");
- }
- if (options.dashOffset) {
- path.setAttribute("stroke-dashoffset", options.dashOffset);
- } else {
- path.removeAttribute("stroke-dashoffset");
- }
- } else {
- path.setAttribute("stroke", "none");
- }
- if (options.fill) {
- path.setAttribute("fill", options.fillColor || options.color);
- path.setAttribute("fill-opacity", options.fillOpacity);
- path.setAttribute("fill-rule", options.fillRule || "evenodd");
- } else {
- path.setAttribute("fill", "none");
- }
- },
- _updatePoly: function(layer, closed) {
- this._setPath(layer, pointsToPath(layer._parts, closed));
- },
- _updateCircle: function(layer) {
- var p = layer._point, r = Math.max(Math.round(layer._radius), 1), r2 = Math.max(Math.round(layer._radiusY), 1) || r, arc = "a" + r + "," + r2 + " 0 1,0 ";
- var d = layer._empty() ? "M0 0" : "M" + (p.x - r) + "," + p.y + arc + r * 2 + ",0 " + arc + -r * 2 + ",0 ";
- this._setPath(layer, d);
- },
- _setPath: function(layer, path) {
- layer._path.setAttribute("d", path);
- },
- // SVG does not have the concept of zIndex so we resort to changing the DOM order of elements
- _bringToFront: function(layer) {
- toFront(layer._path);
- },
- _bringToBack: function(layer) {
- toBack(layer._path);
- }
- });
- if (Browser.vml) {
- SVG.include(vmlMixin);
- }
- function svg(options) {
- return Browser.svg || Browser.vml ? new SVG(options) : null;
- }
- Map.include({
- // @namespace Map; @method getRenderer(layer: Path): Renderer
- // Returns the instance of `Renderer` that should be used to render the given
- // `Path`. It will ensure that the `renderer` options of the map and paths
- // are respected, and that the renderers do exist on the map.
- getRenderer: function(layer) {
- var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;
- if (!renderer) {
- renderer = this._renderer = this._createRenderer();
- }
- if (!this.hasLayer(renderer)) {
- this.addLayer(renderer);
- }
- return renderer;
- },
- _getPaneRenderer: function(name) {
- if (name === "overlayPane" || name === void 0) {
- return false;
- }
- var renderer = this._paneRenderers[name];
- if (renderer === void 0) {
- renderer = this._createRenderer({ pane: name });
- this._paneRenderers[name] = renderer;
- }
- return renderer;
- },
- _createRenderer: function(options) {
- return this.options.preferCanvas && canvas(options) || svg(options);
- }
- });
- var Rectangle = Polygon.extend({
- initialize: function(latLngBounds, options) {
- Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options);
- },
- // @method setBounds(latLngBounds: LatLngBounds): this
- // Redraws the rectangle with the passed bounds.
- setBounds: function(latLngBounds) {
- return this.setLatLngs(this._boundsToLatLngs(latLngBounds));
- },
- _boundsToLatLngs: function(latLngBounds) {
- latLngBounds = toLatLngBounds(latLngBounds);
- return [
- latLngBounds.getSouthWest(),
- latLngBounds.getNorthWest(),
- latLngBounds.getNorthEast(),
- latLngBounds.getSouthEast()
- ];
- }
- });
- function rectangle(latLngBounds, options) {
- return new Rectangle(latLngBounds, options);
- }
- SVG.create = create;
- SVG.pointsToPath = pointsToPath;
- GeoJSON.geometryToLayer = geometryToLayer;
- GeoJSON.coordsToLatLng = coordsToLatLng;
- GeoJSON.coordsToLatLngs = coordsToLatLngs;
- GeoJSON.latLngToCoords = latLngToCoords;
- GeoJSON.latLngsToCoords = latLngsToCoords;
- GeoJSON.getFeature = getFeature;
- GeoJSON.asFeature = asFeature;
- Map.mergeOptions({
- // @option boxZoom: Boolean = true
- // Whether the map can be zoomed to a rectangular area specified by
- // dragging the mouse while pressing the shift key.
- boxZoom: true
- });
- var BoxZoom = Handler.extend({
- initialize: function(map) {
- this._map = map;
- this._container = map._container;
- this._pane = map._panes.overlayPane;
- this._resetStateTimeout = 0;
- map.on("unload", this._destroy, this);
- },
- addHooks: function() {
- on(this._container, "mousedown", this._onMouseDown, this);
- },
- removeHooks: function() {
- off(this._container, "mousedown", this._onMouseDown, this);
- },
- moved: function() {
- return this._moved;
- },
- _destroy: function() {
- remove(this._pane);
- delete this._pane;
- },
- _resetState: function() {
- this._resetStateTimeout = 0;
- this._moved = false;
- },
- _clearDeferredResetState: function() {
- if (this._resetStateTimeout !== 0) {
- clearTimeout(this._resetStateTimeout);
- this._resetStateTimeout = 0;
- }
- },
- _onMouseDown: function(e) {
- if (!e.shiftKey || e.which !== 1 && e.button !== 1) {
- return false;
- }
- this._clearDeferredResetState();
- this._resetState();
- disableTextSelection();
- disableImageDrag();
- this._startPoint = this._map.mouseEventToContainerPoint(e);
- on(document, {
- contextmenu: stop,
- mousemove: this._onMouseMove,
- mouseup: this._onMouseUp,
- keydown: this._onKeyDown
- }, this);
- },
- _onMouseMove: function(e) {
- if (!this._moved) {
- this._moved = true;
- this._box = create$1("div", "leaflet-zoom-box", this._container);
- addClass(this._container, "leaflet-crosshair");
- this._map.fire("boxzoomstart");
- }
- this._point = this._map.mouseEventToContainerPoint(e);
- var bounds = new Bounds(this._point, this._startPoint), size = bounds.getSize();
- setPosition(this._box, bounds.min);
- this._box.style.width = size.x + "px";
- this._box.style.height = size.y + "px";
- },
- _finish: function() {
- if (this._moved) {
- remove(this._box);
- removeClass(this._container, "leaflet-crosshair");
- }
- enableTextSelection();
- enableImageDrag();
- off(document, {
- contextmenu: stop,
- mousemove: this._onMouseMove,
- mouseup: this._onMouseUp,
- keydown: this._onKeyDown
- }, this);
- },
- _onMouseUp: function(e) {
- if (e.which !== 1 && e.button !== 1) {
- return;
- }
- this._finish();
- if (!this._moved) {
- return;
- }
- this._clearDeferredResetState();
- this._resetStateTimeout = setTimeout(bind(this._resetState, this), 0);
- var bounds = new LatLngBounds(
- this._map.containerPointToLatLng(this._startPoint),
- this._map.containerPointToLatLng(this._point)
- );
- this._map.fitBounds(bounds).fire("boxzoomend", { boxZoomBounds: bounds });
- },
- _onKeyDown: function(e) {
- if (e.keyCode === 27) {
- this._finish();
- this._clearDeferredResetState();
- this._resetState();
- }
- }
- });
- Map.addInitHook("addHandler", "boxZoom", BoxZoom);
- Map.mergeOptions({
- // @option doubleClickZoom: Boolean|String = true
- // Whether the map can be zoomed in by double clicking on it and
- // zoomed out by double clicking while holding shift. If passed
- // `'center'`, double-click zoom will zoom to the center of the
- // view regardless of where the mouse was.
- doubleClickZoom: true
- });
- var DoubleClickZoom = Handler.extend({
- addHooks: function() {
- this._map.on("dblclick", this._onDoubleClick, this);
- },
- removeHooks: function() {
- this._map.off("dblclick", this._onDoubleClick, this);
- },
- _onDoubleClick: function(e) {
- var map = this._map, oldZoom = map.getZoom(), delta = map.options.zoomDelta, zoom2 = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta;
- if (map.options.doubleClickZoom === "center") {
- map.setZoom(zoom2);
- } else {
- map.setZoomAround(e.containerPoint, zoom2);
- }
- }
- });
- Map.addInitHook("addHandler", "doubleClickZoom", DoubleClickZoom);
- Map.mergeOptions({
- // @option dragging: Boolean = true
- // Whether the map is draggable with mouse/touch or not.
- dragging: true,
- // @section Panning Inertia Options
- // @option inertia: Boolean = *
- // If enabled, panning of the map will have an inertia effect where
- // the map builds momentum while dragging and continues moving in
- // the same direction for some time. Feels especially nice on touch
- // devices. Enabled by default.
- inertia: true,
- // @option inertiaDeceleration: Number = 3000
- // The rate with which the inertial movement slows down, in pixels/second².
- inertiaDeceleration: 3400,
- // px/s^2
- // @option inertiaMaxSpeed: Number = Infinity
- // Max speed of the inertial movement, in pixels/second.
- inertiaMaxSpeed: Infinity,
- // px/s
- // @option easeLinearity: Number = 0.2
- easeLinearity: 0.2,
- // TODO refactor, move to CRS
- // @option worldCopyJump: Boolean = false
- // With this option enabled, the map tracks when you pan to another "copy"
- // of the world and seamlessly jumps to the original one so that all overlays
- // like markers and vector layers are still visible.
- worldCopyJump: false,
- // @option maxBoundsViscosity: Number = 0.0
- // If `maxBounds` is set, this option will control how solid the bounds
- // are when dragging the map around. The default value of `0.0` allows the
- // user to drag outside the bounds at normal speed, higher values will
- // slow down map dragging outside bounds, and `1.0` makes the bounds fully
- // solid, preventing the user from dragging outside the bounds.
- maxBoundsViscosity: 0
- });
- var Drag = Handler.extend({
- addHooks: function() {
- if (!this._draggable) {
- var map = this._map;
- this._draggable = new Draggable(map._mapPane, map._container);
- this._draggable.on({
- dragstart: this._onDragStart,
- drag: this._onDrag,
- dragend: this._onDragEnd
- }, this);
- this._draggable.on("predrag", this._onPreDragLimit, this);
- if (map.options.worldCopyJump) {
- this._draggable.on("predrag", this._onPreDragWrap, this);
- map.on("zoomend", this._onZoomEnd, this);
- map.whenReady(this._onZoomEnd, this);
- }
- }
- addClass(this._map._container, "leaflet-grab leaflet-touch-drag");
- this._draggable.enable();
- this._positions = [];
- this._times = [];
- },
- removeHooks: function() {
- removeClass(this._map._container, "leaflet-grab");
- removeClass(this._map._container, "leaflet-touch-drag");
- this._draggable.disable();
- },
- moved: function() {
- return this._draggable && this._draggable._moved;
- },
- moving: function() {
- return this._draggable && this._draggable._moving;
- },
- _onDragStart: function() {
- var map = this._map;
- map._stop();
- if (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) {
- var bounds = toLatLngBounds(this._map.options.maxBounds);
- this._offsetLimit = toBounds(
- this._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1),
- this._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1).add(this._map.getSize())
- );
- this._viscosity = Math.min(1, Math.max(0, this._map.options.maxBoundsViscosity));
- } else {
- this._offsetLimit = null;
- }
- map.fire("movestart").fire("dragstart");
- if (map.options.inertia) {
- this._positions = [];
- this._times = [];
- }
- },
- _onDrag: function(e) {
- if (this._map.options.inertia) {
- var time = this._lastTime = +/* @__PURE__ */ new Date(), pos = this._lastPos = this._draggable._absPos || this._draggable._newPos;
- this._positions.push(pos);
- this._times.push(time);
- this._prunePositions(time);
- }
- this._map.fire("move", e).fire("drag", e);
- },
- _prunePositions: function(time) {
- while (this._positions.length > 1 && time - this._times[0] > 50) {
- this._positions.shift();
- this._times.shift();
- }
- },
- _onZoomEnd: function() {
- var pxCenter = this._map.getSize().divideBy(2), pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);
- this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;
- this._worldWidth = this._map.getPixelWorldBounds().getSize().x;
- },
- _viscousLimit: function(value, threshold) {
- return value - (value - threshold) * this._viscosity;
- },
- _onPreDragLimit: function() {
- if (!this._viscosity || !this._offsetLimit) {
- return;
- }
- var offset = this._draggable._newPos.subtract(this._draggable._startPos);
- var limit = this._offsetLimit;
- if (offset.x < limit.min.x) {
- offset.x = this._viscousLimit(offset.x, limit.min.x);
- }
- if (offset.y < limit.min.y) {
- offset.y = this._viscousLimit(offset.y, limit.min.y);
- }
- if (offset.x > limit.max.x) {
- offset.x = this._viscousLimit(offset.x, limit.max.x);
- }
- if (offset.y > limit.max.y) {
- offset.y = this._viscousLimit(offset.y, limit.max.y);
- }
- this._draggable._newPos = this._draggable._startPos.add(offset);
- },
- _onPreDragWrap: function() {
- var worldWidth = this._worldWidth, halfWidth = Math.round(worldWidth / 2), dx = this._initialWorldOffset, x = this._draggable._newPos.x, newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;
- this._draggable._absPos = this._draggable._newPos.clone();
- this._draggable._newPos.x = newX;
- },
- _onDragEnd: function(e) {
- var map = this._map, options = map.options, noInertia = !options.inertia || e.noInertia || this._times.length < 2;
- map.fire("dragend", e);
- if (noInertia) {
- map.fire("moveend");
- } else {
- this._prunePositions(+/* @__PURE__ */ new Date());
- var direction = this._lastPos.subtract(this._positions[0]), duration = (this._lastTime - this._times[0]) / 1e3, ease = options.easeLinearity, speedVector = direction.multiplyBy(ease / duration), speed = speedVector.distanceTo([0, 0]), limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease), offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();
- if (!offset.x && !offset.y) {
- map.fire("moveend");
- } else {
- offset = map._limitOffset(offset, map.options.maxBounds);
- requestAnimFrame(function() {
- map.panBy(offset, {
- duration: decelerationDuration,
- easeLinearity: ease,
- noMoveStart: true,
- animate: true
- });
- });
- }
- }
- }
- });
- Map.addInitHook("addHandler", "dragging", Drag);
- Map.mergeOptions({
- // @option keyboard: Boolean = true
- // Makes the map focusable and allows users to navigate the map with keyboard
- // arrows and `+`/`-` keys.
- keyboard: true,
- // @option keyboardPanDelta: Number = 80
- // Amount of pixels to pan when pressing an arrow key.
- keyboardPanDelta: 80
- });
- var Keyboard = Handler.extend({
- keyCodes: {
- left: [37],
- right: [39],
- down: [40],
- up: [38],
- zoomIn: [187, 107, 61, 171],
- zoomOut: [189, 109, 54, 173]
- },
- initialize: function(map) {
- this._map = map;
- this._setPanDelta(map.options.keyboardPanDelta);
- this._setZoomDelta(map.options.zoomDelta);
- },
- addHooks: function() {
- var container = this._map._container;
- if (container.tabIndex <= 0) {
- container.tabIndex = "0";
- }
- on(container, {
- focus: this._onFocus,
- blur: this._onBlur,
- mousedown: this._onMouseDown
- }, this);
- this._map.on({
- focus: this._addHooks,
- blur: this._removeHooks
- }, this);
- },
- removeHooks: function() {
- this._removeHooks();
- off(this._map._container, {
- focus: this._onFocus,
- blur: this._onBlur,
- mousedown: this._onMouseDown
- }, this);
- this._map.off({
- focus: this._addHooks,
- blur: this._removeHooks
- }, this);
- },
- _onMouseDown: function() {
- if (this._focused) {
- return;
- }
- var body = document.body, docEl = document.documentElement, top = body.scrollTop || docEl.scrollTop, left = body.scrollLeft || docEl.scrollLeft;
- this._map._container.focus();
- window.scrollTo(left, top);
- },
- _onFocus: function() {
- this._focused = true;
- this._map.fire("focus");
- },
- _onBlur: function() {
- this._focused = false;
- this._map.fire("blur");
- },
- _setPanDelta: function(panDelta) {
- var keys = this._panKeys = {}, codes = this.keyCodes, i, len;
- for (i = 0, len = codes.left.length; i < len; i++) {
- keys[codes.left[i]] = [-1 * panDelta, 0];
- }
- for (i = 0, len = codes.right.length; i < len; i++) {
- keys[codes.right[i]] = [panDelta, 0];
- }
- for (i = 0, len = codes.down.length; i < len; i++) {
- keys[codes.down[i]] = [0, panDelta];
- }
- for (i = 0, len = codes.up.length; i < len; i++) {
- keys[codes.up[i]] = [0, -1 * panDelta];
- }
- },
- _setZoomDelta: function(zoomDelta) {
- var keys = this._zoomKeys = {}, codes = this.keyCodes, i, len;
- for (i = 0, len = codes.zoomIn.length; i < len; i++) {
- keys[codes.zoomIn[i]] = zoomDelta;
- }
- for (i = 0, len = codes.zoomOut.length; i < len; i++) {
- keys[codes.zoomOut[i]] = -zoomDelta;
- }
- },
- _addHooks: function() {
- on(document, "keydown", this._onKeyDown, this);
- },
- _removeHooks: function() {
- off(document, "keydown", this._onKeyDown, this);
- },
- _onKeyDown: function(e) {
- if (e.altKey || e.ctrlKey || e.metaKey) {
- return;
- }
- var key = e.keyCode, map = this._map, offset;
- if (key in this._panKeys) {
- if (!map._panAnim || !map._panAnim._inProgress) {
- offset = this._panKeys[key];
- if (e.shiftKey) {
- offset = toPoint(offset).multiplyBy(3);
- }
- if (map.options.maxBounds) {
- offset = map._limitOffset(toPoint(offset), map.options.maxBounds);
- }
- if (map.options.worldCopyJump) {
- var newLatLng = map.wrapLatLng(map.unproject(map.project(map.getCenter()).add(offset)));
- map.panTo(newLatLng);
- } else {
- map.panBy(offset);
- }
- }
- } else if (key in this._zoomKeys) {
- map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);
- } else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) {
- map.closePopup();
- } else {
- return;
- }
- stop(e);
- }
- });
- Map.addInitHook("addHandler", "keyboard", Keyboard);
- Map.mergeOptions({
- // @section Mouse wheel options
- // @option scrollWheelZoom: Boolean|String = true
- // Whether the map can be zoomed by using the mouse wheel. If passed `'center'`,
- // it will zoom to the center of the view regardless of where the mouse was.
- scrollWheelZoom: true,
- // @option wheelDebounceTime: Number = 40
- // Limits the rate at which a wheel can fire (in milliseconds). By default
- // user can't zoom via wheel more often than once per 40 ms.
- wheelDebounceTime: 40,
- // @option wheelPxPerZoomLevel: Number = 60
- // How many scroll pixels (as reported by [L.DomEvent.getWheelDelta](#domevent-getwheeldelta))
- // mean a change of one full zoom level. Smaller values will make wheel-zooming
- // faster (and vice versa).
- wheelPxPerZoomLevel: 60
- });
- var ScrollWheelZoom = Handler.extend({
- addHooks: function() {
- on(this._map._container, "wheel", this._onWheelScroll, this);
- this._delta = 0;
- },
- removeHooks: function() {
- off(this._map._container, "wheel", this._onWheelScroll, this);
- },
- _onWheelScroll: function(e) {
- var delta = getWheelDelta(e);
- var debounce = this._map.options.wheelDebounceTime;
- this._delta += delta;
- this._lastMousePos = this._map.mouseEventToContainerPoint(e);
- if (!this._startTime) {
- this._startTime = +/* @__PURE__ */ new Date();
- }
- var left = Math.max(debounce - (+/* @__PURE__ */ new Date() - this._startTime), 0);
- clearTimeout(this._timer);
- this._timer = setTimeout(bind(this._performZoom, this), left);
- stop(e);
- },
- _performZoom: function() {
- var map = this._map, zoom2 = map.getZoom(), snap = this._map.options.zoomSnap || 0;
- map._stop();
- var d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4), d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2, d4 = snap ? Math.ceil(d3 / snap) * snap : d3, delta = map._limitZoom(zoom2 + (this._delta > 0 ? d4 : -d4)) - zoom2;
- this._delta = 0;
- this._startTime = null;
- if (!delta) {
- return;
- }
- if (map.options.scrollWheelZoom === "center") {
- map.setZoom(zoom2 + delta);
- } else {
- map.setZoomAround(this._lastMousePos, zoom2 + delta);
- }
- }
- });
- Map.addInitHook("addHandler", "scrollWheelZoom", ScrollWheelZoom);
- var tapHoldDelay = 600;
- Map.mergeOptions({
- // @section Touch interaction options
- // @option tapHold: Boolean
- // Enables simulation of `contextmenu` event, default is `true` for mobile Safari.
- tapHold: Browser.touchNative && Browser.safari && Browser.mobile,
- // @option tapTolerance: Number = 15
- // The max number of pixels a user can shift his finger during touch
- // for it to be considered a valid tap.
- tapTolerance: 15
- });
- var TapHold = Handler.extend({
- addHooks: function() {
- on(this._map._container, "touchstart", this._onDown, this);
- },
- removeHooks: function() {
- off(this._map._container, "touchstart", this._onDown, this);
- },
- _onDown: function(e) {
- clearTimeout(this._holdTimeout);
- if (e.touches.length !== 1) {
- return;
- }
- var first = e.touches[0];
- this._startPos = this._newPos = new Point(first.clientX, first.clientY);
- this._holdTimeout = setTimeout(bind(function() {
- this._cancel();
- if (!this._isTapValid()) {
- return;
- }
- on(document, "touchend", preventDefault);
- on(document, "touchend touchcancel", this._cancelClickPrevent);
- this._simulateEvent("contextmenu", first);
- }, this), tapHoldDelay);
- on(document, "touchend touchcancel contextmenu", this._cancel, this);
- on(document, "touchmove", this._onMove, this);
- },
- _cancelClickPrevent: function cancelClickPrevent() {
- off(document, "touchend", preventDefault);
- off(document, "touchend touchcancel", cancelClickPrevent);
- },
- _cancel: function() {
- clearTimeout(this._holdTimeout);
- off(document, "touchend touchcancel contextmenu", this._cancel, this);
- off(document, "touchmove", this._onMove, this);
- },
- _onMove: function(e) {
- var first = e.touches[0];
- this._newPos = new Point(first.clientX, first.clientY);
- },
- _isTapValid: function() {
- return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance;
- },
- _simulateEvent: function(type, e) {
- var simulatedEvent = new MouseEvent(type, {
- bubbles: true,
- cancelable: true,
- view: window,
- // detail: 1,
- screenX: e.screenX,
- screenY: e.screenY,
- clientX: e.clientX,
- clientY: e.clientY
- // button: 2,
- // buttons: 2
- });
- simulatedEvent._simulated = true;
- e.target.dispatchEvent(simulatedEvent);
- }
- });
- Map.addInitHook("addHandler", "tapHold", TapHold);
- Map.mergeOptions({
- // @section Touch interaction options
- // @option touchZoom: Boolean|String = *
- // Whether the map can be zoomed by touch-dragging with two fingers. If
- // passed `'center'`, it will zoom to the center of the view regardless of
- // where the touch events (fingers) were. Enabled for touch-capable web
- // browsers.
- touchZoom: Browser.touch,
- // @option bounceAtZoomLimits: Boolean = true
- // Set it to false if you don't want the map to zoom beyond min/max zoom
- // and then bounce back when pinch-zooming.
- bounceAtZoomLimits: true
- });
- var TouchZoom = Handler.extend({
- addHooks: function() {
- addClass(this._map._container, "leaflet-touch-zoom");
- on(this._map._container, "touchstart", this._onTouchStart, this);
- },
- removeHooks: function() {
- removeClass(this._map._container, "leaflet-touch-zoom");
- off(this._map._container, "touchstart", this._onTouchStart, this);
- },
- _onTouchStart: function(e) {
- var map = this._map;
- if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) {
- return;
- }
- var p1 = map.mouseEventToContainerPoint(e.touches[0]), p2 = map.mouseEventToContainerPoint(e.touches[1]);
- this._centerPoint = map.getSize()._divideBy(2);
- this._startLatLng = map.containerPointToLatLng(this._centerPoint);
- if (map.options.touchZoom !== "center") {
- this._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2));
- }
- this._startDist = p1.distanceTo(p2);
- this._startZoom = map.getZoom();
- this._moved = false;
- this._zooming = true;
- map._stop();
- on(document, "touchmove", this._onTouchMove, this);
- on(document, "touchend touchcancel", this._onTouchEnd, this);
- preventDefault(e);
- },
- _onTouchMove: function(e) {
- if (!e.touches || e.touches.length !== 2 || !this._zooming) {
- return;
- }
- var map = this._map, p1 = map.mouseEventToContainerPoint(e.touches[0]), p2 = map.mouseEventToContainerPoint(e.touches[1]), scale2 = p1.distanceTo(p2) / this._startDist;
- this._zoom = map.getScaleZoom(scale2, this._startZoom);
- if (!map.options.bounceAtZoomLimits && (this._zoom < map.getMinZoom() && scale2 < 1 || this._zoom > map.getMaxZoom() && scale2 > 1)) {
- this._zoom = map._limitZoom(this._zoom);
- }
- if (map.options.touchZoom === "center") {
- this._center = this._startLatLng;
- if (scale2 === 1) {
- return;
- }
- } else {
- var delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint);
- if (scale2 === 1 && delta.x === 0 && delta.y === 0) {
- return;
- }
- this._center = map.unproject(map.project(this._pinchStartLatLng, this._zoom).subtract(delta), this._zoom);
- }
- if (!this._moved) {
- map._moveStart(true, false);
- this._moved = true;
- }
- cancelAnimFrame(this._animRequest);
- var moveFn = bind(map._move, map, this._center, this._zoom, { pinch: true, round: false }, void 0);
- this._animRequest = requestAnimFrame(moveFn, this, true);
- preventDefault(e);
- },
- _onTouchEnd: function() {
- if (!this._moved || !this._zooming) {
- this._zooming = false;
- return;
- }
- this._zooming = false;
- cancelAnimFrame(this._animRequest);
- off(document, "touchmove", this._onTouchMove, this);
- off(document, "touchend touchcancel", this._onTouchEnd, this);
- if (this._map.options.zoomAnimation) {
- this._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap);
- } else {
- this._map._resetView(this._center, this._map._limitZoom(this._zoom));
- }
- }
- });
- Map.addInitHook("addHandler", "touchZoom", TouchZoom);
- Map.BoxZoom = BoxZoom;
- Map.DoubleClickZoom = DoubleClickZoom;
- Map.Drag = Drag;
- Map.Keyboard = Keyboard;
- Map.ScrollWheelZoom = ScrollWheelZoom;
- Map.TapHold = TapHold;
- Map.TouchZoom = TouchZoom;
- exports2.Bounds = Bounds;
- exports2.Browser = Browser;
- exports2.CRS = CRS;
- exports2.Canvas = Canvas;
- exports2.Circle = Circle;
- exports2.CircleMarker = CircleMarker;
- exports2.Class = Class;
- exports2.Control = Control;
- exports2.DivIcon = DivIcon;
- exports2.DivOverlay = DivOverlay;
- exports2.DomEvent = DomEvent;
- exports2.DomUtil = DomUtil;
- exports2.Draggable = Draggable;
- exports2.Evented = Evented;
- exports2.FeatureGroup = FeatureGroup;
- exports2.GeoJSON = GeoJSON;
- exports2.GridLayer = GridLayer;
- exports2.Handler = Handler;
- exports2.Icon = Icon;
- exports2.ImageOverlay = ImageOverlay;
- exports2.LatLng = LatLng;
- exports2.LatLngBounds = LatLngBounds;
- exports2.Layer = Layer;
- exports2.LayerGroup = LayerGroup;
- exports2.LineUtil = LineUtil;
- exports2.Map = Map;
- exports2.Marker = Marker;
- exports2.Mixin = Mixin;
- exports2.Path = Path;
- exports2.Point = Point;
- exports2.PolyUtil = PolyUtil;
- exports2.Polygon = Polygon;
- exports2.Polyline = Polyline;
- exports2.Popup = Popup;
- exports2.PosAnimation = PosAnimation;
- exports2.Projection = index;
- exports2.Rectangle = Rectangle;
- exports2.Renderer = Renderer;
- exports2.SVG = SVG;
- exports2.SVGOverlay = SVGOverlay;
- exports2.TileLayer = TileLayer;
- exports2.Tooltip = Tooltip;
- exports2.Transformation = Transformation;
- exports2.Util = Util;
- exports2.VideoOverlay = VideoOverlay;
- exports2.bind = bind;
- exports2.bounds = toBounds;
- exports2.canvas = canvas;
- exports2.circle = circle;
- exports2.circleMarker = circleMarker;
- exports2.control = control;
- exports2.divIcon = divIcon;
- exports2.extend = extend;
- exports2.featureGroup = featureGroup;
- exports2.geoJSON = geoJSON;
- exports2.geoJson = geoJson;
- exports2.gridLayer = gridLayer;
- exports2.icon = icon;
- exports2.imageOverlay = imageOverlay;
- exports2.latLng = toLatLng;
- exports2.latLngBounds = toLatLngBounds;
- exports2.layerGroup = layerGroup;
- exports2.map = createMap;
- exports2.marker = marker;
- exports2.point = toPoint;
- exports2.polygon = polygon;
- exports2.polyline = polyline;
- exports2.popup = popup;
- exports2.rectangle = rectangle;
- exports2.setOptions = setOptions;
- exports2.stamp = stamp;
- exports2.svg = svg;
- exports2.svgOverlay = svgOverlay;
- exports2.tileLayer = tileLayer;
- exports2.tooltip = tooltip;
- exports2.transformation = toTransformation;
- exports2.version = version;
- exports2.videoOverlay = videoOverlay;
- var oldL = window.L;
- exports2.noConflict = function() {
- window.L = oldL;
- return this;
- };
- window.L = exports2;
- });
- }
- });
- export default require_leaflet_src();
- /*! Bundled license information:
- leaflet/dist/leaflet-src.js:
- (* @preserve
- * Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
- * (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
- *)
- */
- //# sourceMappingURL=leaflet.js.map
|