highcharts-more.src.js 256 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817
  1. /**
  2. * @license Highcharts JS v7.0.2 (2019-01-17)
  3. *
  4. * (c) 2009-2018 Torstein Honsi
  5. *
  6. * License: www.highcharts.com/license
  7. */
  8. 'use strict';
  9. (function (factory) {
  10. if (typeof module === 'object' && module.exports) {
  11. factory['default'] = factory;
  12. module.exports = factory;
  13. } else if (typeof define === 'function' && define.amd) {
  14. define(function () {
  15. return factory;
  16. });
  17. } else {
  18. factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
  19. }
  20. }(function (Highcharts) {
  21. (function (H) {
  22. /* *
  23. * (c) 2010-2019 Torstein Honsi
  24. *
  25. * License: www.highcharts.com/license
  26. */
  27. var CenteredSeriesMixin = H.CenteredSeriesMixin,
  28. extend = H.extend,
  29. merge = H.merge,
  30. splat = H.splat;
  31. /**
  32. * The Pane object allows options that are common to a set of X and Y axes.
  33. *
  34. * In the future, this can be extended to basic Highcharts and Highstock.
  35. *
  36. * @private
  37. * @class
  38. * @name Highcharts.Pane
  39. *
  40. * @param {Highcharts.PaneOptions} options
  41. *
  42. * @param {Highcharts.Chart} chart
  43. */
  44. function Pane(options, chart) {
  45. this.init(options, chart);
  46. }
  47. // Extend the Pane prototype
  48. extend(Pane.prototype, {
  49. coll: 'pane', // Member of chart.pane
  50. /**
  51. * Initiate the Pane object
  52. *
  53. * @private
  54. * @function Highcharts.Pane#init
  55. *
  56. * @param {Highcharts.PaneOptions} options
  57. *
  58. * @param {Highcharts.Chart} chart
  59. */
  60. init: function (options, chart) {
  61. this.chart = chart;
  62. this.background = [];
  63. chart.pane.push(this);
  64. this.setOptions(options);
  65. },
  66. /**
  67. * @private
  68. * @function Highcharts.Pane#setOptions
  69. *
  70. * @param {Highcharts.PaneOptions} options
  71. */
  72. setOptions: function (options) {
  73. // Set options. Angular charts have a default background (#3318)
  74. this.options = options = merge(
  75. this.defaultOptions,
  76. this.chart.angular ? { background: {} } : undefined,
  77. options
  78. );
  79. },
  80. /**
  81. * Render the pane with its backgrounds.
  82. *
  83. * @private
  84. * @function Highcharts.Pane#render
  85. */
  86. render: function () {
  87. var options = this.options,
  88. backgroundOption = this.options.background,
  89. renderer = this.chart.renderer,
  90. len,
  91. i;
  92. if (!this.group) {
  93. this.group = renderer.g('pane-group')
  94. .attr({ zIndex: options.zIndex || 0 })
  95. .add();
  96. }
  97. this.updateCenter();
  98. // Render the backgrounds
  99. if (backgroundOption) {
  100. backgroundOption = splat(backgroundOption);
  101. len = Math.max(
  102. backgroundOption.length,
  103. this.background.length || 0
  104. );
  105. for (i = 0; i < len; i++) {
  106. // #6641 - if axis exists, chart is circular and apply
  107. // background
  108. if (backgroundOption[i] && this.axis) {
  109. this.renderBackground(
  110. merge(
  111. this.defaultBackgroundOptions,
  112. backgroundOption[i]
  113. ),
  114. i
  115. );
  116. } else if (this.background[i]) {
  117. this.background[i] = this.background[i].destroy();
  118. this.background.splice(i, 1);
  119. }
  120. }
  121. }
  122. },
  123. /**
  124. * Render an individual pane background.
  125. *
  126. * @private
  127. * @function Highcharts.Pane#renderBackground
  128. *
  129. * @param {Highcharts.PaneBackgroundOptions} backgroundOptions
  130. * Background options
  131. *
  132. * @param {number} i
  133. * The index of the background in this.backgrounds
  134. */
  135. renderBackground: function (backgroundOptions, i) {
  136. var method = 'animate',
  137. attribs = {
  138. 'class':
  139. 'highcharts-pane ' + (backgroundOptions.className || '')
  140. };
  141. if (!this.chart.styledMode) {
  142. extend(attribs, {
  143. 'fill': backgroundOptions.backgroundColor,
  144. 'stroke': backgroundOptions.borderColor,
  145. 'stroke-width': backgroundOptions.borderWidth
  146. });
  147. }
  148. if (!this.background[i]) {
  149. this.background[i] = this.chart.renderer.path()
  150. .add(this.group);
  151. method = 'attr';
  152. }
  153. this.background[i][method]({
  154. 'd': this.axis.getPlotBandPath(
  155. backgroundOptions.from,
  156. backgroundOptions.to,
  157. backgroundOptions
  158. )
  159. }).attr(attribs);
  160. },
  161. /**
  162. * The pane serves as a container for axes and backgrounds for circular
  163. * gauges and polar charts.
  164. *
  165. * @since 2.3.0
  166. * @product highcharts
  167. * @optionparent pane
  168. */
  169. defaultOptions: {
  170. /**
  171. * The end angle of the polar X axis or gauge value axis, given in
  172. * degrees where 0 is north. Defaults to [startAngle](#pane.startAngle)
  173. * + 360.
  174. *
  175. * @sample {highcharts} highcharts/demo/gauge-vu-meter/
  176. * VU-meter with custom start and end angle
  177. *
  178. * @type {number}
  179. * @since 2.3.0
  180. * @product highcharts
  181. * @apioption pane.endAngle
  182. */
  183. /**
  184. * The center of a polar chart or angular gauge, given as an array
  185. * of [x, y] positions. Positions can be given as integers that
  186. * transform to pixels, or as percentages of the plot area size.
  187. *
  188. * @sample {highcharts} highcharts/demo/gauge-vu-meter/
  189. * Two gauges with different center
  190. *
  191. * @type {Array<string|number>}
  192. * @default ["50%", "50%"]
  193. * @since 2.3.0
  194. * @product highcharts
  195. */
  196. center: ['50%', '50%'],
  197. /**
  198. * The size of the pane, either as a number defining pixels, or a
  199. * percentage defining a percentage of the plot are.
  200. *
  201. * @sample {highcharts} highcharts/demo/gauge-vu-meter/
  202. * Smaller size
  203. *
  204. * @type {number|string}
  205. * @product highcharts
  206. */
  207. size: '85%',
  208. /**
  209. * The start angle of the polar X axis or gauge axis, given in degrees
  210. * where 0 is north. Defaults to 0.
  211. *
  212. * @sample {highcharts} highcharts/demo/gauge-vu-meter/
  213. * VU-meter with custom start and end angle
  214. *
  215. * @since 2.3.0
  216. * @product highcharts
  217. */
  218. startAngle: 0
  219. },
  220. /**
  221. * An array of background items for the pane.
  222. *
  223. * @sample {highcharts} highcharts/demo/gauge-speedometer/
  224. * Speedometer gauge with multiple backgrounds
  225. *
  226. * @type {Array<*>}
  227. * @optionparent pane.background
  228. */
  229. defaultBackgroundOptions: {
  230. /**
  231. * The class name for this background.
  232. *
  233. * @sample {highcharts} highcharts/css/pane/
  234. * Panes styled by CSS
  235. * @sample {highstock} highcharts/css/pane/
  236. * Panes styled by CSS
  237. * @sample {highmaps} highcharts/css/pane/
  238. * Panes styled by CSS
  239. *
  240. * @type {string}
  241. * @default highcharts-pane
  242. * @since 5.0.0
  243. * @apioption pane.background.className
  244. */
  245. /**
  246. * The shape of the pane background. When `solid`, the background
  247. * is circular. When `arc`, the background extends only from the min
  248. * to the max of the value axis.
  249. *
  250. * @type {string}
  251. * @since 2.3.0
  252. * @validvalue ["arc", "circle", "solid"]
  253. * @product highcharts
  254. */
  255. shape: 'circle',
  256. /**
  257. * The pixel border width of the pane background.
  258. *
  259. * @since 2.3.0
  260. * @product highcharts
  261. */
  262. borderWidth: 1,
  263. /**
  264. * The pane background border color.
  265. *
  266. * @type {Highcharts.ColorString}
  267. * @since 2.3.0
  268. * @product highcharts
  269. */
  270. borderColor: '#cccccc',
  271. /**
  272. * The background color or gradient for the pane.
  273. *
  274. * @type {Highcharts.GradientColorObject}
  275. * @default { linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, stops: [[0, #ffffff], [1, #e6e6e6]] }
  276. * @since 2.3.0
  277. * @product highcharts
  278. */
  279. backgroundColor: {
  280. /**
  281. * @ignore
  282. */
  283. linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
  284. /**
  285. * @ignore
  286. */
  287. stops: [
  288. [0, '#ffffff'],
  289. [1, '#e6e6e6']
  290. ]
  291. },
  292. /** @ignore-option */
  293. from: -Number.MAX_VALUE, // corrected to axis min
  294. /**
  295. * The inner radius of the pane background. Can be either numeric
  296. * (pixels) or a percentage string.
  297. *
  298. * @type {number|string}
  299. * @since 2.3.0
  300. * @product highcharts
  301. */
  302. innerRadius: 0,
  303. /**
  304. * @ignore-option
  305. */
  306. to: Number.MAX_VALUE, // corrected to axis max
  307. /**
  308. * The outer radius of the circular pane background. Can be either
  309. * numeric (pixels) or a percentage string.
  310. *
  311. * @type {number|string}
  312. * @since 2.3.0
  313. * @product highcharts
  314. */
  315. outerRadius: '105%'
  316. },
  317. /**
  318. * Gets the center for the pane and its axis.
  319. *
  320. * @private
  321. * @function Highcharts.Pane#updateCenter
  322. *
  323. * @param {Highcharts.RadialAxis} axis
  324. */
  325. updateCenter: function (axis) {
  326. this.center = (axis || this.axis || {}).center =
  327. CenteredSeriesMixin.getCenter.call(this);
  328. },
  329. /**
  330. * Destroy the pane item
  331. *
  332. * @ignore
  333. * @private
  334. * @function Highcharts.Pane#destroy
  335. * /
  336. destroy: function () {
  337. H.erase(this.chart.pane, this);
  338. this.background.forEach(function (background) {
  339. background.destroy();
  340. });
  341. this.background.length = 0;
  342. this.group = this.group.destroy();
  343. },
  344. */
  345. /**
  346. * Update the pane item with new options
  347. *
  348. * @private
  349. * @function Highcharts.Pane#update
  350. *
  351. * @param {Highcharts.PaneOptions} options
  352. * New pane options
  353. *
  354. * @param {boolean} redraw
  355. */
  356. update: function (options, redraw) {
  357. merge(true, this.options, options);
  358. this.setOptions(this.options);
  359. this.render();
  360. this.chart.axes.forEach(function (axis) {
  361. if (axis.pane === this) {
  362. axis.pane = null;
  363. axis.update({}, redraw);
  364. }
  365. }, this);
  366. }
  367. });
  368. H.Pane = Pane;
  369. }(Highcharts));
  370. (function (H) {
  371. /* *
  372. * (c) 2010-2019 Torstein Honsi
  373. *
  374. * License: www.highcharts.com/license
  375. */
  376. var addEvent = H.addEvent,
  377. Axis = H.Axis,
  378. extend = H.extend,
  379. merge = H.merge,
  380. noop = H.noop,
  381. pick = H.pick,
  382. pInt = H.pInt,
  383. Tick = H.Tick,
  384. wrap = H.wrap,
  385. correctFloat = H.correctFloat,
  386. hiddenAxisMixin, // @todo Extract this to a new file
  387. radialAxisMixin, // @todo Extract this to a new file
  388. axisProto = Axis.prototype,
  389. tickProto = Tick.prototype;
  390. if (!H.radialAxisExtended) {
  391. H.radialAxisExtended = true;
  392. // Augmented methods for the x axis in order to hide it completely, used for
  393. // the X axis in gauges
  394. hiddenAxisMixin = {
  395. getOffset: noop,
  396. redraw: function () {
  397. this.isDirty = false; // prevent setting Y axis dirty
  398. },
  399. render: function () {
  400. this.isDirty = false; // prevent setting Y axis dirty
  401. },
  402. setScale: noop,
  403. setCategories: noop,
  404. setTitle: noop
  405. };
  406. // Augmented methods for the value axis
  407. radialAxisMixin = {
  408. // The default options extend defaultYAxisOptions
  409. defaultRadialGaugeOptions: {
  410. labels: {
  411. align: 'center',
  412. x: 0,
  413. y: null // auto
  414. },
  415. minorGridLineWidth: 0,
  416. minorTickInterval: 'auto',
  417. minorTickLength: 10,
  418. minorTickPosition: 'inside',
  419. minorTickWidth: 1,
  420. tickLength: 10,
  421. tickPosition: 'inside',
  422. tickWidth: 2,
  423. title: {
  424. rotation: 0
  425. },
  426. zIndex: 2 // behind dials, points in the series group
  427. },
  428. // Circular axis around the perimeter of a polar chart
  429. defaultRadialXOptions: {
  430. gridLineWidth: 1, // spokes
  431. labels: {
  432. align: null, // auto
  433. distance: 15,
  434. x: 0,
  435. y: null, // auto
  436. style: {
  437. textOverflow: 'none' // wrap lines by default (#7248)
  438. }
  439. },
  440. maxPadding: 0,
  441. minPadding: 0,
  442. showLastLabel: false,
  443. tickLength: 0
  444. },
  445. // Radial axis, like a spoke in a polar chart
  446. defaultRadialYOptions: {
  447. gridLineInterpolation: 'circle',
  448. labels: {
  449. align: 'right',
  450. x: -3,
  451. y: -2
  452. },
  453. showLastLabel: false,
  454. title: {
  455. x: 4,
  456. text: null,
  457. rotation: 90
  458. }
  459. },
  460. // Merge and set options
  461. setOptions: function (userOptions) {
  462. var options = this.options = merge(
  463. this.defaultOptions,
  464. this.defaultRadialOptions,
  465. userOptions
  466. );
  467. // Make sure the plotBands array is instanciated for each Axis
  468. // (#2649)
  469. if (!options.plotBands) {
  470. options.plotBands = [];
  471. }
  472. H.fireEvent(this, 'afterSetOptions');
  473. },
  474. // Wrap the getOffset method to return zero offset for title or labels
  475. // in a radial axis
  476. getOffset: function () {
  477. // Call the Axis prototype method (the method we're in now is on the
  478. // instance)
  479. axisProto.getOffset.call(this);
  480. // Title or label offsets are not counted
  481. this.chart.axisOffset[this.side] = 0;
  482. },
  483. // Get the path for the axis line. This method is also referenced in the
  484. // getPlotLinePath method.
  485. getLinePath: function (lineWidth, radius) {
  486. var center = this.center,
  487. end,
  488. chart = this.chart,
  489. r = pick(radius, center[2] / 2 - this.offset),
  490. path;
  491. if (this.isCircular || radius !== undefined) {
  492. path = this.chart.renderer.symbols.arc(
  493. this.left + center[0],
  494. this.top + center[1],
  495. r,
  496. r,
  497. {
  498. start: this.startAngleRad,
  499. end: this.endAngleRad,
  500. open: true,
  501. innerR: 0
  502. }
  503. );
  504. // Bounds used to position the plotLine label next to the line
  505. // (#7117)
  506. path.xBounds = [this.left + center[0]];
  507. path.yBounds = [this.top + center[1] - r];
  508. } else {
  509. end = this.postTranslate(this.angleRad, r);
  510. path = [
  511. 'M',
  512. center[0] + chart.plotLeft,
  513. center[1] + chart.plotTop,
  514. 'L',
  515. end.x,
  516. end.y
  517. ];
  518. }
  519. return path;
  520. },
  521. /* *
  522. * Override setAxisTranslation by setting the translation to the
  523. * difference in rotation. This allows the translate method to return
  524. * angle for any given value.
  525. */
  526. setAxisTranslation: function () {
  527. // Call uber method
  528. axisProto.setAxisTranslation.call(this);
  529. // Set transA and minPixelPadding
  530. if (this.center) { // it's not defined the first time
  531. if (this.isCircular) {
  532. this.transA = (this.endAngleRad - this.startAngleRad) /
  533. ((this.max - this.min) || 1);
  534. } else {
  535. this.transA = (
  536. (this.center[2] / 2) /
  537. ((this.max - this.min) || 1)
  538. );
  539. }
  540. if (this.isXAxis) {
  541. this.minPixelPadding = this.transA * this.minPointOffset;
  542. } else {
  543. // This is a workaround for regression #2593, but categories
  544. // still don't position correctly.
  545. this.minPixelPadding = 0;
  546. }
  547. }
  548. },
  549. /* *
  550. * In case of auto connect, add one closestPointRange to the max value
  551. * right before tickPositions are computed, so that ticks will extend
  552. * passed the real max.
  553. */
  554. beforeSetTickPositions: function () {
  555. // If autoConnect is true, polygonal grid lines are connected, and
  556. // one closestPointRange is added to the X axis to prevent the last
  557. // point from overlapping the first.
  558. this.autoConnect = (
  559. this.isCircular &&
  560. pick(this.userMax, this.options.max) === undefined &&
  561. correctFloat(this.endAngleRad - this.startAngleRad) ===
  562. correctFloat(2 * Math.PI)
  563. );
  564. if (this.autoConnect) {
  565. this.max += (
  566. (this.categories && 1) ||
  567. this.pointRange ||
  568. this.closestPointRange ||
  569. 0
  570. ); // #1197, #2260
  571. }
  572. },
  573. /* *
  574. * Override the setAxisSize method to use the arc's circumference as
  575. * length. This allows tickPixelInterval to apply to pixel lengths along
  576. * the perimeter
  577. */
  578. setAxisSize: function () {
  579. axisProto.setAxisSize.call(this);
  580. if (this.isRadial) {
  581. // Set the center array
  582. this.pane.updateCenter(this);
  583. // The sector is used in Axis.translate to compute the
  584. // translation of reversed axis points (#2570)
  585. if (this.isCircular) {
  586. this.sector = this.endAngleRad - this.startAngleRad;
  587. }
  588. // Axis len is used to lay out the ticks
  589. this.len = this.width = this.height =
  590. this.center[2] * pick(this.sector, 1) / 2;
  591. }
  592. },
  593. /* *
  594. * Returns the x, y coordinate of a point given by a value and a pixel
  595. * distance from center
  596. */
  597. getPosition: function (value, length) {
  598. return this.postTranslate(
  599. this.isCircular ?
  600. this.translate(value) :
  601. this.angleRad, // #2848
  602. pick(
  603. this.isCircular ? length : this.translate(value),
  604. this.center[2] / 2
  605. ) - this.offset
  606. );
  607. },
  608. /* *
  609. * Translate from intermediate plotX (angle), plotY (axis.len - radius)
  610. * to final chart coordinates.
  611. */
  612. postTranslate: function (angle, radius) {
  613. var chart = this.chart,
  614. center = this.center;
  615. angle = this.startAngleRad + angle;
  616. return {
  617. x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
  618. y: chart.plotTop + center[1] + Math.sin(angle) * radius
  619. };
  620. },
  621. /* *
  622. * Find the path for plot bands along the radial axis
  623. */
  624. getPlotBandPath: function (from, to, options) {
  625. var center = this.center,
  626. startAngleRad = this.startAngleRad,
  627. fullRadius = center[2] / 2,
  628. radii = [
  629. pick(options.outerRadius, '100%'),
  630. options.innerRadius,
  631. pick(options.thickness, 10)
  632. ],
  633. offset = Math.min(this.offset, 0),
  634. percentRegex = /%$/,
  635. start,
  636. end,
  637. open,
  638. isCircular = this.isCircular, // X axis in a polar chart
  639. ret;
  640. // Polygonal plot bands
  641. if (this.options.gridLineInterpolation === 'polygon') {
  642. ret = this.getPlotLinePath(from).concat(
  643. this.getPlotLinePath(to, true)
  644. );
  645. // Circular grid bands
  646. } else {
  647. // Keep within bounds
  648. from = Math.max(from, this.min);
  649. to = Math.min(to, this.max);
  650. // Plot bands on Y axis (radial axis) - inner and outer radius
  651. // depend on to and from
  652. if (!isCircular) {
  653. radii[0] = this.translate(from);
  654. radii[1] = this.translate(to);
  655. }
  656. // Convert percentages to pixel values
  657. radii = radii.map(function (radius) {
  658. if (percentRegex.test(radius)) {
  659. radius = (pInt(radius, 10) * fullRadius) / 100;
  660. }
  661. return radius;
  662. });
  663. // Handle full circle
  664. if (options.shape === 'circle' || !isCircular) {
  665. start = -Math.PI / 2;
  666. end = Math.PI * 1.5;
  667. open = true;
  668. } else {
  669. start = startAngleRad + this.translate(from);
  670. end = startAngleRad + this.translate(to);
  671. }
  672. radii[0] -= offset; // #5283
  673. radii[2] -= offset; // #5283
  674. ret = this.chart.renderer.symbols.arc(
  675. this.left + center[0],
  676. this.top + center[1],
  677. radii[0],
  678. radii[0],
  679. {
  680. // Math is for reversed yAxis (#3606)
  681. start: Math.min(start, end),
  682. end: Math.max(start, end),
  683. innerR: pick(radii[1], radii[0] - radii[2]),
  684. open: open
  685. }
  686. );
  687. }
  688. return ret;
  689. },
  690. /* *
  691. * Find the path for plot lines perpendicular to the radial axis.
  692. */
  693. getPlotLinePath: function (value, reverse) {
  694. var axis = this,
  695. center = axis.center,
  696. chart = axis.chart,
  697. end = axis.getPosition(value),
  698. xAxis,
  699. xy,
  700. tickPositions,
  701. ret;
  702. // Spokes
  703. if (axis.isCircular) {
  704. ret = [
  705. 'M',
  706. center[0] + chart.plotLeft,
  707. center[1] + chart.plotTop,
  708. 'L',
  709. end.x,
  710. end.y
  711. ];
  712. // Concentric circles
  713. } else if (axis.options.gridLineInterpolation === 'circle') {
  714. value = axis.translate(value);
  715. // a value of 0 is in the center, so it won't be visible,
  716. // but draw it anyway for update and animation (#2366)
  717. ret = axis.getLinePath(0, value);
  718. // Concentric polygons
  719. } else {
  720. // Find the X axis in the same pane
  721. chart.xAxis.forEach(function (a) {
  722. if (a.pane === axis.pane) {
  723. xAxis = a;
  724. }
  725. });
  726. ret = [];
  727. value = axis.translate(value);
  728. tickPositions = xAxis.tickPositions;
  729. if (xAxis.autoConnect) {
  730. tickPositions = tickPositions.concat([tickPositions[0]]);
  731. }
  732. // Reverse the positions for concatenation of polygonal plot
  733. // bands
  734. if (reverse) {
  735. tickPositions = [].concat(tickPositions).reverse();
  736. }
  737. tickPositions.forEach(function (pos, i) {
  738. xy = xAxis.getPosition(pos, value);
  739. ret.push(i ? 'L' : 'M', xy.x, xy.y);
  740. });
  741. }
  742. return ret;
  743. },
  744. /* *
  745. * Find the position for the axis title, by default inside the gauge
  746. */
  747. getTitlePosition: function () {
  748. var center = this.center,
  749. chart = this.chart,
  750. titleOptions = this.options.title;
  751. return {
  752. x: chart.plotLeft + center[0] + (titleOptions.x || 0),
  753. y: (
  754. chart.plotTop +
  755. center[1] -
  756. (
  757. {
  758. high: 0.5,
  759. middle: 0.25,
  760. low: 0
  761. }[titleOptions.align] * center[2]
  762. ) +
  763. (titleOptions.y || 0)
  764. )
  765. };
  766. }
  767. };
  768. // Actions before axis init.
  769. addEvent(Axis, 'init', function (e) {
  770. var axis = this,
  771. chart = this.chart,
  772. angular = chart.angular,
  773. polar = chart.polar,
  774. isX = this.isXAxis,
  775. isHidden = angular && isX,
  776. isCircular,
  777. chartOptions = chart.options,
  778. paneIndex = e.userOptions.pane || 0,
  779. pane = this.pane = chart.pane && chart.pane[paneIndex];
  780. // Before prototype.init
  781. if (angular) {
  782. extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
  783. isCircular = !isX;
  784. if (isCircular) {
  785. this.defaultRadialOptions = this.defaultRadialGaugeOptions;
  786. }
  787. } else if (polar) {
  788. extend(this, radialAxisMixin);
  789. isCircular = isX;
  790. this.defaultRadialOptions = isX ?
  791. this.defaultRadialXOptions :
  792. merge(this.defaultYAxisOptions, this.defaultRadialYOptions);
  793. }
  794. // Disable certain features on angular and polar axes
  795. if (angular || polar) {
  796. this.isRadial = true;
  797. chart.inverted = false;
  798. chartOptions.chart.zoomType = null;
  799. // Prevent overlapping axis labels (#9761)
  800. chart.labelCollectors.push(function () {
  801. if (
  802. axis.isRadial &&
  803. axis.tickPositions &&
  804. // undocumented option for now, but working
  805. axis.options.labels.allowOverlap !== true
  806. ) {
  807. return axis.tickPositions
  808. .map(function (pos) {
  809. return axis.ticks[pos] && axis.ticks[pos].label;
  810. })
  811. .filter(function (label) {
  812. return Boolean(label);
  813. });
  814. }
  815. });
  816. } else {
  817. this.isRadial = false;
  818. }
  819. // A pointer back to this axis to borrow geometry
  820. if (pane && isCircular) {
  821. pane.axis = this;
  822. }
  823. this.isCircular = isCircular;
  824. });
  825. addEvent(Axis, 'afterInit', function () {
  826. var chart = this.chart,
  827. options = this.options,
  828. isHidden = chart.angular && this.isXAxis,
  829. pane = this.pane,
  830. paneOptions = pane && pane.options;
  831. if (!isHidden && pane && (chart.angular || chart.polar)) {
  832. // Start and end angle options are
  833. // given in degrees relative to top, while internal computations are
  834. // in radians relative to right (like SVG).
  835. // Y axis in polar charts
  836. this.angleRad = (options.angle || 0) * Math.PI / 180;
  837. // Gauges
  838. this.startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180;
  839. this.endAngleRad = (
  840. pick(paneOptions.endAngle, paneOptions.startAngle + 360) - 90
  841. ) * Math.PI / 180; // Gauges
  842. this.offset = options.offset || 0;
  843. }
  844. });
  845. // Wrap auto label align to avoid setting axis-wide rotation on radial axes
  846. // (#4920)
  847. addEvent(Axis, 'autoLabelAlign', function (e) {
  848. if (this.isRadial) {
  849. e.align = undefined;
  850. e.preventDefault();
  851. }
  852. });
  853. // Add special cases within the Tick class' methods for radial axes.
  854. addEvent(Tick, 'afterGetPosition', function (e) {
  855. if (this.axis.getPosition) {
  856. extend(e.pos, this.axis.getPosition(this.pos));
  857. }
  858. });
  859. // Find the center position of the label based on the distance option.
  860. addEvent(Tick, 'afterGetLabelPosition', function (e) {
  861. var axis = this.axis,
  862. label = this.label,
  863. labelOptions = axis.options.labels,
  864. optionsY = labelOptions.y,
  865. ret,
  866. centerSlot = 20, // 20 degrees to each side at the top and bottom
  867. align = labelOptions.align,
  868. angle = (
  869. (axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) /
  870. Math.PI * 180
  871. ) % 360;
  872. if (axis.isRadial) { // Both X and Y axes in a polar chart
  873. ret = axis.getPosition(this.pos, (axis.center[2] / 2) +
  874. pick(labelOptions.distance, -25));
  875. // Automatically rotated
  876. if (labelOptions.rotation === 'auto') {
  877. label.attr({
  878. rotation: angle
  879. });
  880. // Vertically centered
  881. } else if (optionsY === null) {
  882. optionsY = (
  883. axis.chart.renderer
  884. .fontMetrics(label.styles && label.styles.fontSize).b -
  885. label.getBBox().height / 2
  886. );
  887. }
  888. // Automatic alignment
  889. if (align === null) {
  890. if (axis.isCircular) { // Y axis
  891. if (
  892. this.label.getBBox().width >
  893. axis.len * axis.tickInterval / (axis.max - axis.min)
  894. ) { // #3506
  895. centerSlot = 0;
  896. }
  897. if (angle > centerSlot && angle < 180 - centerSlot) {
  898. align = 'left'; // right hemisphere
  899. } else if (
  900. angle > 180 + centerSlot &&
  901. angle < 360 - centerSlot
  902. ) {
  903. align = 'right'; // left hemisphere
  904. } else {
  905. align = 'center'; // top or bottom
  906. }
  907. } else {
  908. align = 'center';
  909. }
  910. label.attr({
  911. align: align
  912. });
  913. }
  914. e.pos.x = ret.x + labelOptions.x;
  915. e.pos.y = ret.y + optionsY;
  916. }
  917. });
  918. // Wrap the getMarkPath function to return the path of the radial marker
  919. wrap(tickProto, 'getMarkPath', function (
  920. proceed,
  921. x,
  922. y,
  923. tickLength,
  924. tickWidth,
  925. horiz,
  926. renderer
  927. ) {
  928. var axis = this.axis,
  929. endPoint,
  930. ret;
  931. if (axis.isRadial) {
  932. endPoint = axis.getPosition(
  933. this.pos,
  934. axis.center[2] / 2 + tickLength
  935. );
  936. ret = [
  937. 'M',
  938. x,
  939. y,
  940. 'L',
  941. endPoint.x,
  942. endPoint.y
  943. ];
  944. } else {
  945. ret = proceed.call(
  946. this,
  947. x,
  948. y,
  949. tickLength,
  950. tickWidth,
  951. horiz,
  952. renderer
  953. );
  954. }
  955. return ret;
  956. });
  957. }
  958. }(Highcharts));
  959. (function (H) {
  960. /* *
  961. * (c) 2010-2019 Torstein Honsi
  962. *
  963. * License: www.highcharts.com/license
  964. */
  965. var noop = H.noop,
  966. pick = H.pick,
  967. extend = H.extend,
  968. isArray = H.isArray,
  969. defined = H.defined,
  970. Series = H.Series,
  971. seriesType = H.seriesType,
  972. seriesTypes = H.seriesTypes,
  973. seriesProto = Series.prototype,
  974. pointProto = H.Point.prototype;
  975. /**
  976. * The area range series is a carteseian series with higher and lower values for
  977. * each point along an X axis, where the area between the values is shaded.
  978. * Requires `highcharts-more.js`.
  979. *
  980. * @sample {highcharts} highcharts/demo/arearange/
  981. * Area range chart
  982. * @sample {highstock} stock/demo/arearange/
  983. * Area range chart
  984. *
  985. * @extends plotOptions.area
  986. * @product highcharts highstock
  987. * @excluding stack, stacking
  988. * @optionparent plotOptions.arearange
  989. */
  990. seriesType('arearange', 'area', {
  991. /**
  992. * Whether to apply a drop shadow to the graph line. Since 2.3 the shadow
  993. * can be an object configuration containing `color`, `offsetX`, `offsetY`,
  994. * `opacity` and `width`.
  995. *
  996. * @type {boolean|Highcharts.ShadowOptionsObject}
  997. * @product highcharts
  998. * @apioption plotOptions.arearange.shadow
  999. */
  1000. /**
  1001. * Pixel width of the arearange graph line.
  1002. *
  1003. * @since 2.3.0
  1004. * @product highcharts highstock
  1005. */
  1006. lineWidth: 1,
  1007. threshold: null,
  1008. tooltip: {
  1009. pointFormat: '<span style="color:{series.color}">\u25CF</span> ' +
  1010. '{series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'
  1011. },
  1012. /**
  1013. * Whether the whole area or just the line should respond to mouseover
  1014. * tooltips and other mouse or touch events.
  1015. *
  1016. * @since 2.3.0
  1017. * @product highcharts highstock
  1018. */
  1019. trackByArea: true,
  1020. /**
  1021. * Extended data labels for range series types. Range series data labels
  1022. * have no `x` and `y` options. Instead, they have `xLow`, `xHigh`, `yLow`
  1023. * and `yHigh` options to allow the higher and lower data label sets
  1024. * individually.
  1025. *
  1026. * @extends plotOptions.series.dataLabels
  1027. * @since 2.3.0
  1028. * @excluding x, y
  1029. * @product highcharts highstock
  1030. */
  1031. dataLabels: {
  1032. /**
  1033. * @type {Highcharts.AlignType|null}
  1034. */
  1035. align: null,
  1036. /**
  1037. * @type {Highcharts.VerticalAlignType|null}
  1038. */
  1039. verticalAlign: null,
  1040. /**
  1041. * X offset of the lower data labels relative to the point value.
  1042. *
  1043. * @sample {highcharts} highcharts/plotoptions/arearange-datalabels/
  1044. * Data labels on range series
  1045. * @sample {highstock} highcharts/plotoptions/arearange-datalabels/
  1046. * Data labels on range series
  1047. *
  1048. * @since 2.3.0
  1049. * @product highcharts highstock
  1050. */
  1051. xLow: 0,
  1052. /**
  1053. * X offset of the higher data labels relative to the point value.
  1054. *
  1055. * @sample {highcharts|highstock} highcharts/plotoptions/arearange-datalabels/
  1056. * Data labels on range series
  1057. *
  1058. * @since 2.3.0
  1059. * @product highcharts highstock
  1060. */
  1061. xHigh: 0,
  1062. /**
  1063. * Y offset of the lower data labels relative to the point value.
  1064. *
  1065. * @sample {highcharts|highstock} highcharts/plotoptions/arearange-datalabels/
  1066. * Data labels on range series
  1067. *
  1068. * @since 2.3.0
  1069. * @product highcharts highstock
  1070. */
  1071. yLow: 0,
  1072. /**
  1073. * Y offset of the higher data labels relative to the point value.
  1074. *
  1075. * @sample {highcharts|highstock} highcharts/plotoptions/arearange-datalabels/
  1076. * Data labels on range series
  1077. *
  1078. * @since 2.3.0
  1079. * @product highcharts highstock
  1080. */
  1081. yHigh: 0
  1082. }
  1083. // Prototype members
  1084. }, {
  1085. pointArrayMap: ['low', 'high'],
  1086. toYData: function (point) {
  1087. return [point.low, point.high];
  1088. },
  1089. pointValKey: 'low',
  1090. deferTranslatePolar: true,
  1091. // Translate a point's plotHigh from the internal angle and radius measures
  1092. // to true plotHigh coordinates. This is an addition of the toXY method
  1093. // found in Polar.js, because it runs too early for arearanges to be
  1094. // considered (#3419).
  1095. highToXY: function (point) {
  1096. // Find the polar plotX and plotY
  1097. var chart = this.chart,
  1098. xy = this.xAxis.postTranslate(
  1099. point.rectPlotX,
  1100. this.yAxis.len - point.plotHigh
  1101. );
  1102. point.plotHighX = xy.x - chart.plotLeft;
  1103. point.plotHigh = xy.y - chart.plotTop;
  1104. point.plotLowX = point.plotX;
  1105. },
  1106. // Translate data points from raw values x and y to plotX and plotY.
  1107. translate: function () {
  1108. var series = this,
  1109. yAxis = series.yAxis,
  1110. hasModifyValue = !!series.modifyValue;
  1111. seriesTypes.area.prototype.translate.apply(series);
  1112. // Set plotLow and plotHigh
  1113. series.points.forEach(function (point) {
  1114. var low = point.low,
  1115. high = point.high,
  1116. plotY = point.plotY;
  1117. if (high === null || low === null) {
  1118. point.isNull = true;
  1119. point.plotY = null;
  1120. } else {
  1121. point.plotLow = plotY;
  1122. point.plotHigh = yAxis.translate(
  1123. hasModifyValue ? series.modifyValue(high, point) : high,
  1124. 0,
  1125. 1,
  1126. 0,
  1127. 1
  1128. );
  1129. if (hasModifyValue) {
  1130. point.yBottom = point.plotHigh;
  1131. }
  1132. }
  1133. });
  1134. // Postprocess plotHigh
  1135. if (this.chart.polar) {
  1136. this.points.forEach(function (point) {
  1137. series.highToXY(point);
  1138. point.tooltipPos = [
  1139. (point.plotHighX + point.plotLowX) / 2,
  1140. (point.plotHigh + point.plotLow) / 2
  1141. ];
  1142. });
  1143. }
  1144. },
  1145. // Extend the line series' getSegmentPath method by applying the segment
  1146. // path to both lower and higher values of the range.
  1147. getGraphPath: function (points) {
  1148. var highPoints = [],
  1149. highAreaPoints = [],
  1150. i,
  1151. getGraphPath = seriesTypes.area.prototype.getGraphPath,
  1152. point,
  1153. pointShim,
  1154. linePath,
  1155. lowerPath,
  1156. options = this.options,
  1157. connectEnds = this.chart.polar && options.connectEnds !== false,
  1158. connectNulls = options.connectNulls,
  1159. step = options.step,
  1160. higherPath,
  1161. higherAreaPath;
  1162. points = points || this.points;
  1163. i = points.length;
  1164. // Create the top line and the top part of the area fill. The area fill
  1165. // compensates for null points by drawing down to the lower graph,
  1166. // moving across the null gap and starting again at the lower graph.
  1167. i = points.length;
  1168. while (i--) {
  1169. point = points[i];
  1170. if (
  1171. !point.isNull &&
  1172. !connectEnds &&
  1173. !connectNulls &&
  1174. (!points[i + 1] || points[i + 1].isNull)
  1175. ) {
  1176. highAreaPoints.push({
  1177. plotX: point.plotX,
  1178. plotY: point.plotY,
  1179. doCurve: false // #5186, gaps in areasplinerange fill
  1180. });
  1181. }
  1182. pointShim = {
  1183. polarPlotY: point.polarPlotY,
  1184. rectPlotX: point.rectPlotX,
  1185. yBottom: point.yBottom,
  1186. // plotHighX is for polar charts
  1187. plotX: pick(point.plotHighX, point.plotX),
  1188. plotY: point.plotHigh,
  1189. isNull: point.isNull
  1190. };
  1191. highAreaPoints.push(pointShim);
  1192. highPoints.push(pointShim);
  1193. if (
  1194. !point.isNull &&
  1195. !connectEnds &&
  1196. !connectNulls &&
  1197. (!points[i - 1] || points[i - 1].isNull)
  1198. ) {
  1199. highAreaPoints.push({
  1200. plotX: point.plotX,
  1201. plotY: point.plotY,
  1202. doCurve: false // #5186, gaps in areasplinerange fill
  1203. });
  1204. }
  1205. }
  1206. // Get the paths
  1207. lowerPath = getGraphPath.call(this, points);
  1208. if (step) {
  1209. if (step === true) {
  1210. step = 'left';
  1211. }
  1212. options.step = {
  1213. left: 'right',
  1214. center: 'center',
  1215. right: 'left'
  1216. }[step]; // swap for reading in getGraphPath
  1217. }
  1218. higherPath = getGraphPath.call(this, highPoints);
  1219. higherAreaPath = getGraphPath.call(this, highAreaPoints);
  1220. options.step = step;
  1221. // Create a line on both top and bottom of the range
  1222. linePath = [].concat(lowerPath, higherPath);
  1223. // For the area path, we need to change the 'move' statement
  1224. // into 'lineTo' or 'curveTo'
  1225. if (!this.chart.polar && higherAreaPath[0] === 'M') {
  1226. higherAreaPath[0] = 'L'; // this probably doesn't work for spline
  1227. }
  1228. this.graphPath = linePath;
  1229. this.areaPath = lowerPath.concat(higherAreaPath);
  1230. // Prepare for sideways animation
  1231. linePath.isArea = true;
  1232. linePath.xMap = lowerPath.xMap;
  1233. this.areaPath.xMap = lowerPath.xMap;
  1234. return linePath;
  1235. },
  1236. // Extend the basic drawDataLabels method by running it for both lower and
  1237. // higher values.
  1238. drawDataLabels: function () {
  1239. var data = this.points,
  1240. length = data.length,
  1241. i,
  1242. originalDataLabels = [],
  1243. dataLabelOptions = this.options.dataLabels,
  1244. point,
  1245. up,
  1246. inverted = this.chart.inverted,
  1247. upperDataLabelOptions,
  1248. lowerDataLabelOptions;
  1249. // Split into upper and lower options. If data labels is an array, the
  1250. // first element is the upper label, the second is the lower.
  1251. //
  1252. // TODO: We want to change this and allow multiple labels for both upper
  1253. // and lower values in the future - introducing some options for which
  1254. // point value to use as Y for the dataLabel, so that this could be
  1255. // handled in Series.drawDataLabels. This would also improve performance
  1256. // since we now have to loop over all the points multiple times to work
  1257. // around the data label logic.
  1258. if (isArray(dataLabelOptions)) {
  1259. if (dataLabelOptions.length > 1) {
  1260. upperDataLabelOptions = dataLabelOptions[0];
  1261. lowerDataLabelOptions = dataLabelOptions[1];
  1262. } else {
  1263. upperDataLabelOptions = dataLabelOptions[0];
  1264. lowerDataLabelOptions = { enabled: false };
  1265. }
  1266. } else {
  1267. upperDataLabelOptions = extend({}, dataLabelOptions); // Make copy;
  1268. upperDataLabelOptions.x = dataLabelOptions.xHigh;
  1269. upperDataLabelOptions.y = dataLabelOptions.yHigh;
  1270. lowerDataLabelOptions = extend({}, dataLabelOptions); // Make copy
  1271. lowerDataLabelOptions.x = dataLabelOptions.xLow;
  1272. lowerDataLabelOptions.y = dataLabelOptions.yLow;
  1273. }
  1274. // Draw upper labels
  1275. if (upperDataLabelOptions.enabled || this._hasPointLabels) {
  1276. // Set preliminary values for plotY and dataLabel
  1277. // and draw the upper labels
  1278. i = length;
  1279. while (i--) {
  1280. point = data[i];
  1281. if (point) {
  1282. up = upperDataLabelOptions.inside ?
  1283. point.plotHigh < point.plotLow :
  1284. point.plotHigh > point.plotLow;
  1285. point.y = point.high;
  1286. point._plotY = point.plotY;
  1287. point.plotY = point.plotHigh;
  1288. // Store original data labels and set preliminary label
  1289. // objects to be picked up in the uber method
  1290. originalDataLabels[i] = point.dataLabel;
  1291. point.dataLabel = point.dataLabelUpper;
  1292. // Set the default offset
  1293. point.below = up;
  1294. if (inverted) {
  1295. if (!upperDataLabelOptions.align) {
  1296. upperDataLabelOptions.align = up ? 'right' : 'left';
  1297. }
  1298. } else {
  1299. if (!upperDataLabelOptions.verticalAlign) {
  1300. upperDataLabelOptions.verticalAlign = up ?
  1301. 'top' :
  1302. 'bottom';
  1303. }
  1304. }
  1305. }
  1306. }
  1307. this.options.dataLabels = upperDataLabelOptions;
  1308. if (seriesProto.drawDataLabels) {
  1309. seriesProto.drawDataLabels.apply(this, arguments); // #1209
  1310. }
  1311. // Reset state after the upper labels were created. Move
  1312. // it to point.dataLabelUpper and reassign the originals.
  1313. // We do this here to support not drawing a lower label.
  1314. i = length;
  1315. while (i--) {
  1316. point = data[i];
  1317. if (point) {
  1318. point.dataLabelUpper = point.dataLabel;
  1319. point.dataLabel = originalDataLabels[i];
  1320. delete point.dataLabels;
  1321. point.y = point.low;
  1322. point.plotY = point._plotY;
  1323. }
  1324. }
  1325. }
  1326. // Draw lower labels
  1327. if (lowerDataLabelOptions.enabled || this._hasPointLabels) {
  1328. i = length;
  1329. while (i--) {
  1330. point = data[i];
  1331. if (point) {
  1332. up = lowerDataLabelOptions.inside ?
  1333. point.plotHigh < point.plotLow :
  1334. point.plotHigh > point.plotLow;
  1335. // Set the default offset
  1336. point.below = !up;
  1337. if (inverted) {
  1338. if (!lowerDataLabelOptions.align) {
  1339. lowerDataLabelOptions.align = up ? 'left' : 'right';
  1340. }
  1341. } else {
  1342. if (!lowerDataLabelOptions.verticalAlign) {
  1343. lowerDataLabelOptions.verticalAlign = up ?
  1344. 'bottom' :
  1345. 'top';
  1346. }
  1347. }
  1348. }
  1349. }
  1350. this.options.dataLabels = lowerDataLabelOptions;
  1351. if (seriesProto.drawDataLabels) {
  1352. seriesProto.drawDataLabels.apply(this, arguments);
  1353. }
  1354. }
  1355. // Merge upper and lower into point.dataLabels for later destroying
  1356. if (upperDataLabelOptions.enabled) {
  1357. i = length;
  1358. while (i--) {
  1359. point = data[i];
  1360. if (point) {
  1361. point.dataLabels = [point.dataLabelUpper, point.dataLabel]
  1362. .filter(function (label) {
  1363. return !!label;
  1364. });
  1365. }
  1366. }
  1367. }
  1368. // Reset options
  1369. this.options.dataLabels = dataLabelOptions;
  1370. },
  1371. alignDataLabel: function () {
  1372. seriesTypes.column.prototype.alignDataLabel.apply(this, arguments);
  1373. },
  1374. drawPoints: function () {
  1375. var series = this,
  1376. pointLength = series.points.length,
  1377. point,
  1378. i;
  1379. // Draw bottom points
  1380. seriesProto.drawPoints.apply(series, arguments);
  1381. // Prepare drawing top points
  1382. i = 0;
  1383. while (i < pointLength) {
  1384. point = series.points[i];
  1385. // Save original props to be overridden by temporary props for top
  1386. // points
  1387. point.origProps = {
  1388. plotY: point.plotY,
  1389. plotX: point.plotX,
  1390. isInside: point.isInside,
  1391. negative: point.negative,
  1392. zone: point.zone,
  1393. y: point.y
  1394. };
  1395. point.lowerGraphic = point.graphic;
  1396. point.graphic = point.upperGraphic;
  1397. point.plotY = point.plotHigh;
  1398. if (defined(point.plotHighX)) {
  1399. point.plotX = point.plotHighX;
  1400. }
  1401. point.y = point.high;
  1402. point.negative = point.high < (series.options.threshold || 0);
  1403. point.zone = series.zones.length && point.getZone();
  1404. if (!series.chart.polar) {
  1405. point.isInside = point.isTopInside = (
  1406. point.plotY !== undefined &&
  1407. point.plotY >= 0 &&
  1408. point.plotY <= series.yAxis.len && // #3519
  1409. point.plotX >= 0 &&
  1410. point.plotX <= series.xAxis.len
  1411. );
  1412. }
  1413. i++;
  1414. }
  1415. // Draw top points
  1416. seriesProto.drawPoints.apply(series, arguments);
  1417. // Reset top points preliminary modifications
  1418. i = 0;
  1419. while (i < pointLength) {
  1420. point = series.points[i];
  1421. point.upperGraphic = point.graphic;
  1422. point.graphic = point.lowerGraphic;
  1423. H.extend(point, point.origProps);
  1424. delete point.origProps;
  1425. i++;
  1426. }
  1427. },
  1428. setStackedPoints: noop
  1429. }, {
  1430. setState: function () {
  1431. var prevState = this.state,
  1432. series = this.series,
  1433. isPolar = series.chart.polar;
  1434. if (!defined(this.plotHigh)) {
  1435. // Boost doesn't calculate plotHigh
  1436. this.plotHigh = series.yAxis.toPixels(this.high, true);
  1437. }
  1438. if (!defined(this.plotLow)) {
  1439. // Boost doesn't calculate plotLow
  1440. this.plotLow = this.plotY = series.yAxis.toPixels(this.low, true);
  1441. }
  1442. if (series.stateMarkerGraphic) {
  1443. series.lowerStateMarkerGraphic = series.stateMarkerGraphic;
  1444. series.stateMarkerGraphic = series.upperStateMarkerGraphic;
  1445. }
  1446. // Change state also for the top marker
  1447. this.graphic = this.upperGraphic;
  1448. this.plotY = this.plotHigh;
  1449. if (isPolar) {
  1450. this.plotX = this.plotHighX;
  1451. }
  1452. // Top state:
  1453. pointProto.setState.apply(this, arguments);
  1454. this.state = prevState;
  1455. // Now restore defaults
  1456. this.plotY = this.plotLow;
  1457. this.graphic = this.lowerGraphic;
  1458. if (isPolar) {
  1459. this.plotX = this.plotLowX;
  1460. }
  1461. if (series.stateMarkerGraphic) {
  1462. series.upperStateMarkerGraphic = series.stateMarkerGraphic;
  1463. series.stateMarkerGraphic = series.lowerStateMarkerGraphic;
  1464. // Lower marker is stored at stateMarkerGraphic
  1465. // to avoid reference duplication (#7021)
  1466. series.lowerStateMarkerGraphic = undefined;
  1467. }
  1468. pointProto.setState.apply(this, arguments);
  1469. },
  1470. haloPath: function () {
  1471. var isPolar = this.series.chart.polar,
  1472. path = [];
  1473. // Bottom halo
  1474. this.plotY = this.plotLow;
  1475. if (isPolar) {
  1476. this.plotX = this.plotLowX;
  1477. }
  1478. if (this.isInside) {
  1479. path = pointProto.haloPath.apply(this, arguments);
  1480. }
  1481. // Top halo
  1482. this.plotY = this.plotHigh;
  1483. if (isPolar) {
  1484. this.plotX = this.plotHighX;
  1485. }
  1486. if (this.isTopInside) {
  1487. path = path.concat(
  1488. pointProto.haloPath.apply(this, arguments)
  1489. );
  1490. }
  1491. return path;
  1492. },
  1493. destroyElements: function () {
  1494. var graphics = ['lowerGraphic', 'upperGraphic'];
  1495. graphics.forEach(function (graphicName) {
  1496. if (this[graphicName]) {
  1497. this[graphicName] = this[graphicName].destroy();
  1498. }
  1499. }, this);
  1500. // Clear graphic for states, removed in the above each:
  1501. this.graphic = null;
  1502. return pointProto.destroyElements.apply(this, arguments);
  1503. }
  1504. });
  1505. /**
  1506. * A `arearange` series. If the [type](#series.arearange.type) option is not
  1507. * specified, it is inherited from [chart.type](#chart.type).
  1508. *
  1509. *
  1510. * @extends series,plotOptions.arearange
  1511. * @excluding dataParser, dataURL, stack, stacking
  1512. * @product highcharts highstock
  1513. * @apioption series.arearange
  1514. */
  1515. /**
  1516. * An array of data points for the series. For the `arearange` series type,
  1517. * points can be given in the following ways:
  1518. *
  1519. * 1. An array of arrays with 3 or 2 values. In this case, the values
  1520. * correspond to `x,low,high`. If the first value is a string, it is
  1521. * applied as the name of the point, and the `x` value is inferred.
  1522. * The `x` value can also be omitted, in which case the inner arrays
  1523. * should be of length 2\. Then the `x` value is automatically calculated,
  1524. * either starting at 0 and incremented by 1, or from `pointStart`
  1525. * and `pointInterval` given in the series options.
  1526. * ```js
  1527. * data: [
  1528. * [0, 8, 3],
  1529. * [1, 1, 1],
  1530. * [2, 6, 8]
  1531. * ]
  1532. * ```
  1533. *
  1534. * 2. An array of objects with named values. The following snippet shows only a
  1535. * few settings, see the complete options set below. If the total number of
  1536. * data points exceeds the series'
  1537. * [turboThreshold](#series.arearange.turboThreshold),
  1538. * this option is not available.
  1539. * ```js
  1540. * data: [{
  1541. * x: 1,
  1542. * low: 9,
  1543. * high: 0,
  1544. * name: "Point2",
  1545. * color: "#00FF00"
  1546. * }, {
  1547. * x: 1,
  1548. * low: 3,
  1549. * high: 4,
  1550. * name: "Point1",
  1551. * color: "#FF00FF"
  1552. * }]
  1553. * ```
  1554. *
  1555. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1556. * Arrays of numeric x and y
  1557. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1558. * Arrays of datetime x and y
  1559. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1560. * Arrays of point.name and y
  1561. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1562. * Config objects
  1563. *
  1564. * @type {Array<Array<(number|string),number>|Array<(number|string),number,number>|*>}
  1565. * @extends series.line.data
  1566. * @excluding marker, y
  1567. * @product highcharts highstock
  1568. * @apioption series.arearange.data
  1569. */
  1570. /**
  1571. * The high or maximum value for each data point.
  1572. *
  1573. * @type {number}
  1574. * @product highcharts highstock
  1575. * @apioption series.arearange.data.high
  1576. */
  1577. /**
  1578. * The low or minimum value for each data point.
  1579. *
  1580. * @type {number}
  1581. * @product highcharts highstock
  1582. * @apioption series.arearange.data.low
  1583. */
  1584. /**
  1585. * @excluding x, y
  1586. * @product highcharts highstock
  1587. * @apioption series.arearange.dataLabels
  1588. */
  1589. }(Highcharts));
  1590. (function (H) {
  1591. /* *
  1592. * (c) 2010-2019 Torstein Honsi
  1593. *
  1594. * License: www.highcharts.com/license
  1595. */
  1596. var seriesType = H.seriesType,
  1597. seriesTypes = H.seriesTypes;
  1598. /**
  1599. * The area spline range is a cartesian series type with higher and
  1600. * lower Y values along an X axis. The area inside the range is colored, and
  1601. * the graph outlining the area is a smoothed spline. Requires
  1602. * `highcharts-more.js`.
  1603. *
  1604. * @sample {highstock|highstock} stock/demo/areasplinerange/
  1605. * Area spline range
  1606. *
  1607. * @extends plotOptions.arearange
  1608. * @since 2.3.0
  1609. * @excluding step
  1610. * @product highcharts highstock
  1611. * @apioption plotOptions.areasplinerange
  1612. */
  1613. seriesType('areasplinerange', 'arearange', null, {
  1614. getPointSpline: seriesTypes.spline.prototype.getPointSpline
  1615. });
  1616. /**
  1617. * A `areasplinerange` series. If the [type](#series.areasplinerange.type)
  1618. * option is not specified, it is inherited from [chart.type](#chart.type).
  1619. *
  1620. * @extends series,plotOptions.areasplinerange
  1621. * @excluding dataParser, dataURL, stack
  1622. * @product highcharts highstock
  1623. * @apioption series.areasplinerange
  1624. */
  1625. /**
  1626. * An array of data points for the series. For the `areasplinerange`
  1627. * series type, points can be given in the following ways:
  1628. *
  1629. * 1. An array of arrays with 3 or 2 values. In this case, the values correspond
  1630. * to `x,low,high`. If the first value is a string, it is applied as the name
  1631. * of the point, and the `x` value is inferred. The `x` value can also be
  1632. * omitted, in which case the inner arrays should be of length 2\. Then the
  1633. * `x` value is automatically calculated, either starting at 0 and
  1634. * incremented by 1, or from `pointStart` and `pointInterval` given in the
  1635. * series options.
  1636. * ```js
  1637. * data: [
  1638. * [0, 0, 5],
  1639. * [1, 9, 1],
  1640. * [2, 5, 2]
  1641. * ]
  1642. * ```
  1643. *
  1644. * 2. An array of objects with named values. The following snippet shows only a
  1645. * few settings, see the complete options set below. If the total number of
  1646. * data points exceeds the series'
  1647. * [turboThreshold](#series.areasplinerange.turboThreshold), this option is
  1648. * not available.
  1649. * ```js
  1650. * data: [{
  1651. * x: 1,
  1652. * low: 5,
  1653. * high: 0,
  1654. * name: "Point2",
  1655. * color: "#00FF00"
  1656. * }, {
  1657. * x: 1,
  1658. * low: 4,
  1659. * high: 1,
  1660. * name: "Point1",
  1661. * color: "#FF00FF"
  1662. * }]
  1663. * ```
  1664. *
  1665. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1666. * Arrays of numeric x and y
  1667. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1668. * Arrays of datetime x and y
  1669. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1670. * Arrays of point.name and y
  1671. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1672. * Config objects
  1673. *
  1674. * @type {Array<Array<(number|string),number>|Array<(number|string),number,number>|*>}
  1675. * @extends series.arearange.data
  1676. * @product highcharts highstock
  1677. * @apioption series.areasplinerange.data
  1678. */
  1679. }(Highcharts));
  1680. (function (H) {
  1681. /* *
  1682. * (c) 2010-2019 Torstein Honsi
  1683. *
  1684. * License: www.highcharts.com/license
  1685. */
  1686. var defaultPlotOptions = H.defaultPlotOptions,
  1687. merge = H.merge,
  1688. noop = H.noop,
  1689. pick = H.pick,
  1690. seriesType = H.seriesType,
  1691. seriesTypes = H.seriesTypes;
  1692. var colProto = seriesTypes.column.prototype;
  1693. /**
  1694. * The column range is a cartesian series type with higher and lower
  1695. * Y values along an X axis. Requires `highcharts-more.js`. To display
  1696. * horizontal bars, set [chart.inverted](#chart.inverted) to `true`.
  1697. *
  1698. * @sample {highcharts|highstock} highcharts/demo/columnrange/
  1699. * Inverted column range
  1700. *
  1701. * @extends plotOptions.column
  1702. * @since 2.3.0
  1703. * @excluding negativeColor, stacking, softThreshold, threshold
  1704. * @product highcharts highstock
  1705. * @optionparent plotOptions.columnrange
  1706. */
  1707. var columnRangeOptions = {
  1708. /**
  1709. * Extended data labels for range series types. Range series data labels
  1710. * have no `x` and `y` options. Instead, they have `xLow`, `xHigh`,
  1711. * `yLow` and `yHigh` options to allow the higher and lower data label
  1712. * sets individually.
  1713. *
  1714. * @extends plotOptions.arearange.dataLabels
  1715. * @since 2.3.0
  1716. * @excluding x, y
  1717. * @product highcharts highstock
  1718. * @apioption plotOptions.columnrange.dataLabels
  1719. */
  1720. pointRange: null,
  1721. /** @ignore-option */
  1722. marker: null,
  1723. states: {
  1724. hover: {
  1725. /** @ignore-option */
  1726. halo: false
  1727. }
  1728. }
  1729. };
  1730. /**
  1731. * The ColumnRangeSeries class
  1732. *
  1733. * @private
  1734. * @class
  1735. * @name Highcharts.seriesTypes.columnrange
  1736. *
  1737. * @augments Highcharts.Series
  1738. */
  1739. seriesType('columnrange', 'arearange', merge(
  1740. defaultPlotOptions.column,
  1741. defaultPlotOptions.arearange,
  1742. columnRangeOptions
  1743. ), {
  1744. // Translate data points from raw values x and y to plotX and plotY
  1745. translate: function () {
  1746. var series = this,
  1747. yAxis = series.yAxis,
  1748. xAxis = series.xAxis,
  1749. startAngleRad = xAxis.startAngleRad,
  1750. start,
  1751. chart = series.chart,
  1752. isRadial = series.xAxis.isRadial,
  1753. safeDistance = Math.max(chart.chartWidth, chart.chartHeight) + 999,
  1754. plotHigh;
  1755. // Don't draw too far outside plot area (#6835)
  1756. function safeBounds(pixelPos) {
  1757. return Math.min(Math.max(
  1758. -safeDistance,
  1759. pixelPos
  1760. ), safeDistance);
  1761. }
  1762. colProto.translate.apply(series);
  1763. // Set plotLow and plotHigh
  1764. series.points.forEach(function (point) {
  1765. var shapeArgs = point.shapeArgs,
  1766. minPointLength = series.options.minPointLength,
  1767. heightDifference,
  1768. height,
  1769. y;
  1770. point.plotHigh = plotHigh = safeBounds(
  1771. yAxis.translate(point.high, 0, 1, 0, 1)
  1772. );
  1773. point.plotLow = safeBounds(point.plotY);
  1774. // adjust shape
  1775. y = plotHigh;
  1776. height = pick(point.rectPlotY, point.plotY) - plotHigh;
  1777. // Adjust for minPointLength
  1778. if (Math.abs(height) < minPointLength) {
  1779. heightDifference = (minPointLength - height);
  1780. height += heightDifference;
  1781. y -= heightDifference / 2;
  1782. // Adjust for negative ranges or reversed Y axis (#1457)
  1783. } else if (height < 0) {
  1784. height *= -1;
  1785. y -= height;
  1786. }
  1787. if (isRadial) {
  1788. start = point.barX + startAngleRad;
  1789. point.shapeType = 'path';
  1790. point.shapeArgs = {
  1791. d: series.polarArc(
  1792. y + height,
  1793. y,
  1794. start,
  1795. start + point.pointWidth
  1796. )
  1797. };
  1798. } else {
  1799. shapeArgs.height = height;
  1800. shapeArgs.y = y;
  1801. point.tooltipPos = chart.inverted ?
  1802. [
  1803. yAxis.len + yAxis.pos - chart.plotLeft - y - height / 2,
  1804. xAxis.len + xAxis.pos - chart.plotTop - shapeArgs.x -
  1805. shapeArgs.width / 2,
  1806. height
  1807. ] : [
  1808. xAxis.left - chart.plotLeft + shapeArgs.x +
  1809. shapeArgs.width / 2,
  1810. yAxis.pos - chart.plotTop + y + height / 2,
  1811. height
  1812. ]; // don't inherit from column tooltip position - #3372
  1813. }
  1814. });
  1815. },
  1816. directTouch: true,
  1817. trackerGroups: ['group', 'dataLabelsGroup'],
  1818. drawGraph: noop,
  1819. getSymbol: noop,
  1820. // Overrides from modules that may be loaded after this module
  1821. crispCol: function () {
  1822. return colProto.crispCol.apply(this, arguments);
  1823. },
  1824. drawPoints: function () {
  1825. return colProto.drawPoints.apply(this, arguments);
  1826. },
  1827. drawTracker: function () {
  1828. return colProto.drawTracker.apply(this, arguments);
  1829. },
  1830. getColumnMetrics: function () {
  1831. return colProto.getColumnMetrics.apply(this, arguments);
  1832. },
  1833. pointAttribs: function () {
  1834. return colProto.pointAttribs.apply(this, arguments);
  1835. },
  1836. animate: function () {
  1837. return colProto.animate.apply(this, arguments);
  1838. },
  1839. polarArc: function () {
  1840. return colProto.polarArc.apply(this, arguments);
  1841. },
  1842. translate3dPoints: function () {
  1843. return colProto.translate3dPoints.apply(this, arguments);
  1844. },
  1845. translate3dShapes: function () {
  1846. return colProto.translate3dShapes.apply(this, arguments);
  1847. }
  1848. }, {
  1849. setState: colProto.pointClass.prototype.setState
  1850. });
  1851. /**
  1852. * A `columnrange` series. If the [type](#series.columnrange.type)
  1853. * option is not specified, it is inherited from
  1854. * [chart.type](#chart.type).
  1855. *
  1856. * @extends series,plotOptions.columnrange
  1857. * @excluding dataParser, dataURL, stack, stacking
  1858. * @product highcharts highstock
  1859. * @apioption series.columnrange
  1860. */
  1861. /**
  1862. * An array of data points for the series. For the `columnrange` series
  1863. * type, points can be given in the following ways:
  1864. *
  1865. * 1. An array of arrays with 3 or 2 values. In this case, the values correspond
  1866. * to `x,low,high`. If the first value is a string, it is applied as the name
  1867. * of the point, and the `x` value is inferred. The `x` value can also be
  1868. * omitted, in which case the inner arrays should be of length 2\. Then the
  1869. * `x` value is automatically calculated, either starting at 0 and
  1870. * incremented by 1, or from `pointStart` and `pointInterval` given in the
  1871. * series options.
  1872. * ```js
  1873. * data: [
  1874. * [0, 4, 2],
  1875. * [1, 2, 1],
  1876. * [2, 9, 10]
  1877. * ]
  1878. * ```
  1879. *
  1880. * 2. An array of objects with named values. The following snippet shows only a
  1881. * few settings, see the complete options set below. If the total number of
  1882. * data points exceeds the series'
  1883. * [turboThreshold](#series.columnrange.turboThreshold), this option is not
  1884. * available.
  1885. * ```js
  1886. * data: [{
  1887. * x: 1,
  1888. * low: 0,
  1889. * high: 4,
  1890. * name: "Point2",
  1891. * color: "#00FF00"
  1892. * }, {
  1893. * x: 1,
  1894. * low: 5,
  1895. * high: 3,
  1896. * name: "Point1",
  1897. * color: "#FF00FF"
  1898. * }]
  1899. * ```
  1900. *
  1901. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1902. * Arrays of numeric x and y
  1903. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1904. * Arrays of datetime x and y
  1905. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1906. * Arrays of point.name and y
  1907. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1908. * Config objects
  1909. *
  1910. * @type {Array<Array<(number|string),number>|Array<(number|string),number,number>|*>}
  1911. * @extends series.arearange.data
  1912. * @excluding marker
  1913. * @product highcharts highstock
  1914. * @apioption series.columnrange.data
  1915. */
  1916. /**
  1917. * @excluding halo, lineWidth, lineWidthPlus, marker
  1918. * @product highcharts highstock
  1919. * @apioption series.columnrange.states.hover
  1920. */
  1921. /**
  1922. * @excluding halo, lineWidth, lineWidthPlus, marker
  1923. * @product highcharts highstock
  1924. * @apioption series.columnrange.states.select
  1925. */
  1926. }(Highcharts));
  1927. (function (H) {
  1928. /* *
  1929. * (c) 2010-2019 Sebastian Bochan
  1930. *
  1931. * License: www.highcharts.com/license
  1932. */
  1933. var pick = H.pick,
  1934. seriesType = H.seriesType,
  1935. seriesTypes = H.seriesTypes;
  1936. var colProto = seriesTypes.column.prototype;
  1937. /**
  1938. * The ColumnPyramidSeries class
  1939. *
  1940. * @private
  1941. * @class
  1942. * @name Highcharts.seriesTypes.columnpyramid
  1943. *
  1944. * @augments Highcharts.Series
  1945. */
  1946. seriesType('columnpyramid', 'column'
  1947. /**
  1948. * Column pyramid series display one pyramid per value along an X axis.
  1949. * Requires `highcharts-more.js`. To display horizontal pyramids,
  1950. * set [chart.inverted](#chart.inverted) to `true`.
  1951. *
  1952. * @sample {highcharts|highstock} highcharts/demo/column-pyramid/
  1953. * Column pyramid
  1954. * @sample {highcharts|highstock} highcharts/plotoptions/columnpyramid-stacked/
  1955. * Column pyramid stacked
  1956. * @sample {highcharts|highstock} highcharts/plotoptions/columnpyramid-inverted/
  1957. * Column pyramid inverted
  1958. *
  1959. * @extends plotOptions.column
  1960. * @since 7.0.0
  1961. * @product highcharts highstock
  1962. * @excluding boostThreshold, borderRadius, crisp, depth, edgeColor,
  1963. * edgeWidth, groupZPadding, negativeColor, softThreshold,
  1964. * threshold, zoneAxis, zones
  1965. * @optionparent plotOptions.columnpyramid
  1966. */
  1967. , {}, {
  1968. // Overrides the column translate method
  1969. translate: function () {
  1970. var series = this,
  1971. chart = series.chart,
  1972. options = series.options,
  1973. dense = series.dense =
  1974. series.closestPointRange * series.xAxis.transA < 2,
  1975. borderWidth = series.borderWidth = pick(
  1976. options.borderWidth,
  1977. dense ? 0 : 1 // #3635
  1978. ),
  1979. yAxis = series.yAxis,
  1980. threshold = options.threshold,
  1981. translatedThreshold = series.translatedThreshold =
  1982. yAxis.getThreshold(threshold),
  1983. minPointLength = pick(options.minPointLength, 5),
  1984. metrics = series.getColumnMetrics(),
  1985. pointWidth = metrics.width,
  1986. // postprocessed for border width
  1987. seriesBarW = series.barW =
  1988. Math.max(pointWidth, 1 + 2 * borderWidth),
  1989. pointXOffset = series.pointXOffset = metrics.offset;
  1990. if (chart.inverted) {
  1991. translatedThreshold -= 0.5; // #3355
  1992. }
  1993. // When the pointPadding is 0,
  1994. // we want the pyramids to be packed tightly,
  1995. // so we allow individual pyramids to have individual sizes.
  1996. // When pointPadding is greater,
  1997. // we strive for equal-width columns (#2694).
  1998. if (options.pointPadding) {
  1999. seriesBarW = Math.ceil(seriesBarW);
  2000. }
  2001. colProto.translate.apply(series);
  2002. // Record the new values
  2003. series.points.forEach(function (point) {
  2004. var yBottom = pick(point.yBottom, translatedThreshold),
  2005. safeDistance = 999 + Math.abs(yBottom),
  2006. plotY = Math.min(
  2007. Math.max(-safeDistance, point.plotY),
  2008. yAxis.len + safeDistance
  2009. ),
  2010. // Don't draw too far outside plot area
  2011. // (#1303, #2241, #4264)
  2012. barX = point.plotX + pointXOffset,
  2013. barW = seriesBarW / 2,
  2014. barY = Math.min(plotY, yBottom),
  2015. barH = Math.max(plotY, yBottom) - barY,
  2016. stackTotal, stackHeight, topPointY, topXwidth, bottomXwidth,
  2017. invBarPos,
  2018. x1, x2, x3, x4, y1, y2;
  2019. point.barX = barX;
  2020. point.pointWidth = pointWidth;
  2021. // Fix the tooltip on center of grouped pyramids
  2022. // (#1216, #424, #3648)
  2023. point.tooltipPos = chart.inverted ? [
  2024. yAxis.len + yAxis.pos - chart.plotLeft - plotY,
  2025. series.xAxis.len - barX - barW, barH
  2026. ] : [barX + barW, plotY + yAxis.pos - chart.plotTop, barH];
  2027. stackTotal = threshold + (point.total || point.y);
  2028. // overwrite stacktotal (always 100 / -100)
  2029. if (options.stacking === 'percent') {
  2030. stackTotal = threshold + (point.y < 0) ? -100 : 100;
  2031. }
  2032. // get the highest point (if stack, extract from total)
  2033. topPointY = yAxis.toPixels((stackTotal), true);
  2034. // calculate height of stack (in pixels)
  2035. stackHeight = chart.plotHeight - topPointY -
  2036. (chart.plotHeight - translatedThreshold);
  2037. // topXwidth and bottomXwidth = width of lines from the center
  2038. // calculated from tanges proportion.
  2039. topXwidth = (barW * (barY - topPointY)) / stackHeight;
  2040. // like topXwidth, but with height of point
  2041. bottomXwidth = (barW * (barY + barH - topPointY)) / stackHeight;
  2042. /*
  2043. /\
  2044. / \
  2045. x1,y1,------ x2,y1
  2046. / \
  2047. ----------
  2048. x4,y2 x3,y2
  2049. */
  2050. x1 = barX - topXwidth + barW;
  2051. x2 = barX + topXwidth + barW;
  2052. x3 = barX + bottomXwidth + barW;
  2053. x4 = barX - bottomXwidth + barW;
  2054. y1 = barY - minPointLength;
  2055. y2 = barY + barH;
  2056. if (point.y < 0) {
  2057. y1 = barY;
  2058. y2 = barY + barH + minPointLength;
  2059. }
  2060. // inverted chart
  2061. if (chart.inverted) {
  2062. invBarPos = chart.plotWidth - barY;
  2063. stackHeight = (topPointY -
  2064. (chart.plotWidth - translatedThreshold));
  2065. // proportion tanges
  2066. topXwidth = (barW *
  2067. (topPointY - invBarPos)) / stackHeight;
  2068. bottomXwidth = (barW *
  2069. (topPointY - (invBarPos - barH))) / stackHeight;
  2070. x1 = barX + barW + topXwidth; // top bottom
  2071. x2 = x1 - 2 * topXwidth; // top top
  2072. x3 = barX - bottomXwidth + barW; // bottom top
  2073. x4 = barX + bottomXwidth + barW; // bottom bottom
  2074. y1 = barY;
  2075. y2 = barY + barH - minPointLength;
  2076. if (point.y < 0) {
  2077. y2 = barY + barH + minPointLength;
  2078. }
  2079. }
  2080. // Register shape type and arguments to be used in drawPoints
  2081. point.shapeType = 'path';
  2082. point.shapeArgs = {
  2083. // args for datalabels positioning
  2084. x: x1,
  2085. y: y1,
  2086. width: x2 - x1,
  2087. height: barH,
  2088. // path of pyramid
  2089. d: ['M',
  2090. x1, y1,
  2091. 'L',
  2092. x2, y1,
  2093. x3, y2,
  2094. x4, y2,
  2095. 'Z'
  2096. ]
  2097. };
  2098. });
  2099. }
  2100. });
  2101. /**
  2102. * A `columnpyramid` series. If the [type](#series.columnpyramid.type) option is
  2103. * not specified, it is inherited from [chart.type](#chart.type).
  2104. *
  2105. * @extends series,plotOptions.columnpyramid
  2106. * @excluding connectEnds, connectNulls, dashStyle, dataParser, dataURL,
  2107. * gapSize, gapUnit, linecap, lineWidth, marker, step
  2108. * @product highcharts highstock
  2109. * @apioption series.columnpyramid
  2110. */
  2111. /**
  2112. * @excluding halo, lineWidth, lineWidthPlus, marker
  2113. * @product highcharts highstock
  2114. * @apioption series.columnpyramid.states.hover
  2115. */
  2116. /**
  2117. * @excluding halo, lineWidth, lineWidthPlus, marker
  2118. * @product highcharts highstock
  2119. * @apioption series.columnpyramid.states.select
  2120. */
  2121. /**
  2122. * An array of data points for the series. For the `columnpyramid` series type,
  2123. * points can be given in the following ways:
  2124. *
  2125. * 1. An array of numerical values. In this case, the numerical values will be
  2126. * interpreted as `y` options. The `x` values will be automatically
  2127. * calculated, either starting at 0 and incremented by 1, or from
  2128. * `pointStart` and `pointInterval` given in the series options. If the axis
  2129. * has categories, these will be used. Example:
  2130. * ```js
  2131. * data: [0, 5, 3, 5]
  2132. * ```
  2133. *
  2134. * 2. An array of arrays with 2 values. In this case, the values correspond to
  2135. * `x,y`. If the first value is a string, it is applied as the name of the
  2136. * point, and the `x` value is inferred.
  2137. * ```js
  2138. * data: [
  2139. * [0, 6],
  2140. * [1, 2],
  2141. * [2, 6]
  2142. * ]
  2143. * ```
  2144. *
  2145. * 3. An array of objects with named values. The objects are point configuration
  2146. * objects as seen below. If the total number of data points exceeds the
  2147. * series' [turboThreshold](#series.columnpyramid.turboThreshold), this
  2148. * option is not available.
  2149. * ```js
  2150. * data: [{
  2151. * x: 1,
  2152. * y: 9,
  2153. * name: "Point2",
  2154. * color: "#00FF00"
  2155. * }, {
  2156. * x: 1,
  2157. * y: 6,
  2158. * name: "Point1",
  2159. * color: "#FF00FF"
  2160. * }]
  2161. * ```
  2162. *
  2163. * @sample {highcharts} highcharts/chart/reflow-true/
  2164. * Numerical values
  2165. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  2166. * Arrays of numeric x and y
  2167. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  2168. * Arrays of datetime x and y
  2169. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  2170. * Arrays of point.name and y
  2171. * @sample {highcharts} highcharts/series/data-array-of-objects/
  2172. * Config objects
  2173. *
  2174. * @type {Array<number|Array<(number|string),number>|*>}
  2175. * @extends series.line.data
  2176. * @excluding marker
  2177. * @product highcharts highstock
  2178. * @apioption series.columnpyramid.data
  2179. */
  2180. }(Highcharts));
  2181. (function (H) {
  2182. /* *
  2183. * (c) 2010-2019 Torstein Honsi
  2184. *
  2185. * License: www.highcharts.com/license
  2186. */
  2187. var isNumber = H.isNumber,
  2188. merge = H.merge,
  2189. noop = H.noop,
  2190. pick = H.pick,
  2191. pInt = H.pInt,
  2192. Series = H.Series,
  2193. seriesType = H.seriesType,
  2194. TrackerMixin = H.TrackerMixin;
  2195. /**
  2196. * Gauges are circular plots displaying one or more values with a dial pointing
  2197. * to values along the perimeter.
  2198. *
  2199. * @sample highcharts/demo/gauge-speedometer/
  2200. * Gauge chart
  2201. *
  2202. * @extends plotOptions.line
  2203. * @excluding animationLimit, boostThreshold, connectEnds, connectNulls,
  2204. * cropThreshold, dashStyle, findNearestPointBy,
  2205. * getExtremesFromAll, marker, negativeColor, pointPlacement,
  2206. * shadow, softThreshold, stacking, states, step, threshold,
  2207. * turboThreshold, xAxis, zoneAxis, zones
  2208. * @product highcharts
  2209. * @optionparent plotOptions.gauge
  2210. */
  2211. seriesType('gauge', 'line', {
  2212. /**
  2213. * When this option is `true`, the dial will wrap around the axes. For
  2214. * instance, in a full-range gauge going from 0 to 360, a value of 400
  2215. * will point to 40\. When `wrap` is `false`, the dial stops at 360.
  2216. *
  2217. * @see [overshoot](#plotOptions.gauge.overshoot)
  2218. *
  2219. * @type {boolean}
  2220. * @default true
  2221. * @since 3.0
  2222. * @product highcharts
  2223. * @apioption plotOptions.gauge.wrap
  2224. */
  2225. /**
  2226. * Data labels for the gauge. For gauges, the data labels are enabled
  2227. * by default and shown in a bordered box below the point.
  2228. *
  2229. * @extends plotOptions.series.dataLabels
  2230. * @since 2.3.0
  2231. * @product highcharts
  2232. */
  2233. dataLabels: {
  2234. /**
  2235. * Enable or disable the data labels.
  2236. *
  2237. * @since 2.3.0
  2238. * @product highcharts highmaps
  2239. */
  2240. enabled: true,
  2241. defer: false,
  2242. /**
  2243. * The y position offset of the label relative to the center of the
  2244. * gauge.
  2245. *
  2246. * @since 2.3.0
  2247. * @product highcharts highmaps
  2248. */
  2249. y: 15,
  2250. /**
  2251. * The border radius in pixels for the gauge's data label.
  2252. *
  2253. * @since 2.3.0
  2254. * @product highcharts highmaps
  2255. */
  2256. borderRadius: 3,
  2257. crop: false,
  2258. /**
  2259. * The vertical alignment of the data label.
  2260. *
  2261. * @product highcharts highmaps
  2262. */
  2263. verticalAlign: 'top',
  2264. /**
  2265. * The Z index of the data labels. A value of 2 display them behind
  2266. * the dial.
  2267. *
  2268. * @since 2.1.5
  2269. * @product highcharts highmaps
  2270. */
  2271. zIndex: 2,
  2272. /**
  2273. * The border width in pixels for the gauge data label.
  2274. *
  2275. * @since 2.3.0
  2276. * @product highcharts highmaps
  2277. */
  2278. borderWidth: 1,
  2279. /**
  2280. * The border color for the data label.
  2281. *
  2282. * @type {Highcharts.ColorString}
  2283. * @default #cccccc
  2284. * @since 2.3.0
  2285. * @product highcharts highmaps
  2286. */
  2287. borderColor: '#cccccc'
  2288. },
  2289. /**
  2290. * Options for the dial or arrow pointer of the gauge.
  2291. *
  2292. * In styled mode, the dial is styled with the
  2293. * `.highcharts-gauge-series .highcharts-dial` rule.
  2294. *
  2295. * @sample {highcharts} highcharts/css/gauge/
  2296. * Styled mode
  2297. *
  2298. * @since 2.3.0
  2299. * @product highcharts
  2300. */
  2301. dial: {},
  2302. /**
  2303. * The length of the dial's base part, relative to the total radius
  2304. * or length of the dial.
  2305. *
  2306. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2307. * Dial options demonstrated
  2308. *
  2309. * @type {string}
  2310. * @default 70%
  2311. * @since 2.3.0
  2312. * @product highcharts
  2313. * @apioption plotOptions.gauge.dial.baseLength
  2314. */
  2315. /**
  2316. * The pixel width of the base of the gauge dial. The base is the part
  2317. * closest to the pivot, defined by baseLength.
  2318. *
  2319. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2320. * Dial options demonstrated
  2321. *
  2322. * @type {number}
  2323. * @default 3
  2324. * @since 2.3.0
  2325. * @product highcharts
  2326. * @apioption plotOptions.gauge.dial.baseWidth
  2327. */
  2328. /**
  2329. * The radius or length of the dial, in percentages relative to the
  2330. * radius of the gauge itself.
  2331. *
  2332. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2333. * Dial options demonstrated
  2334. *
  2335. * @type {string}
  2336. * @default 80%
  2337. * @since 2.3.0
  2338. * @product highcharts
  2339. * @apioption plotOptions.gauge.dial.radius
  2340. */
  2341. /**
  2342. * The length of the dial's rear end, the part that extends out on the
  2343. * other side of the pivot. Relative to the dial's length.
  2344. *
  2345. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2346. * Dial options demonstrated
  2347. *
  2348. * @type {string}
  2349. * @default 10%
  2350. * @since 2.3.0
  2351. * @product highcharts
  2352. * @apioption plotOptions.gauge.dial.rearLength
  2353. */
  2354. /**
  2355. * The width of the top of the dial, closest to the perimeter. The pivot
  2356. * narrows in from the base to the top.
  2357. *
  2358. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2359. * Dial options demonstrated
  2360. *
  2361. * @type {number}
  2362. * @default 1
  2363. * @since 2.3.0
  2364. * @product highcharts
  2365. * @apioption plotOptions.gauge.dial.topWidth
  2366. */
  2367. /**
  2368. * The background or fill color of the gauge's dial.
  2369. *
  2370. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2371. * Dial options demonstrated
  2372. *
  2373. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  2374. * @default #000000
  2375. * @since 2.3.0
  2376. * @product highcharts
  2377. * @apioption plotOptions.gauge.dial.backgroundColor
  2378. */
  2379. /**
  2380. * The border color or stroke of the gauge's dial. By default, the
  2381. * borderWidth is 0, so this must be set in addition to a custom border
  2382. * color.
  2383. *
  2384. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2385. * Dial options demonstrated
  2386. *
  2387. * @type {Highcharts.ColorString}
  2388. * @default #cccccc
  2389. * @since 2.3.0
  2390. * @product highcharts
  2391. * @apioption plotOptions.gauge.dial.borderColor
  2392. */
  2393. /**
  2394. * The width of the gauge dial border in pixels.
  2395. *
  2396. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2397. * Dial options demonstrated
  2398. *
  2399. * @type {number}
  2400. * @default 0
  2401. * @since 2.3.0
  2402. * @product highcharts
  2403. * @apioption plotOptions.gauge.dial.borderWidth
  2404. */
  2405. /**
  2406. * Allow the dial to overshoot the end of the perimeter axis by this
  2407. * many degrees. Say if the gauge axis goes from 0 to 60, a value of
  2408. * 100, or 1000, will show 5 degrees beyond the end of the axis when this
  2409. * option is set to 5.
  2410. *
  2411. * @see [wrap](#plotOptions.gauge.wrap)
  2412. *
  2413. * @sample {highcharts} highcharts/plotoptions/gauge-overshoot/
  2414. * Allow 5 degrees overshoot
  2415. *
  2416. * @type {number}
  2417. * @default 0
  2418. * @since 3.0.10
  2419. * @product highcharts
  2420. * @apioption plotOptions.gauge.overshoot
  2421. */
  2422. /**
  2423. * Options for the pivot or the center point of the gauge.
  2424. *
  2425. * In styled mode, the pivot is styled with the
  2426. * `.highcharts-gauge-series .highcharts-pivot` rule.
  2427. *
  2428. * @sample {highcharts} highcharts/css/gauge/
  2429. * Styled mode
  2430. *
  2431. * @since 2.3.0
  2432. * @product highcharts
  2433. */
  2434. pivot: {},
  2435. /**
  2436. * The pixel radius of the pivot.
  2437. *
  2438. * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
  2439. * Pivot options demonstrated
  2440. *
  2441. * @type {number}
  2442. * @default 5
  2443. * @since 2.3.0
  2444. * @product highcharts
  2445. * @apioption plotOptions.gauge.pivot.radius
  2446. */
  2447. /**
  2448. * The border or stroke width of the pivot.
  2449. *
  2450. * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
  2451. * Pivot options demonstrated
  2452. *
  2453. * @type {number}
  2454. * @default 0
  2455. * @since 2.3.0
  2456. * @product highcharts
  2457. * @apioption plotOptions.gauge.pivot.borderWidth
  2458. */
  2459. /**
  2460. * The border or stroke color of the pivot. In able to change this,
  2461. * the borderWidth must also be set to something other than the default
  2462. * 0.
  2463. *
  2464. * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
  2465. * Pivot options demonstrated
  2466. *
  2467. * @type {Highcharts.ColorString}
  2468. * @default #cccccc
  2469. * @since 2.3.0
  2470. * @product highcharts
  2471. * @apioption plotOptions.gauge.pivot.borderColor
  2472. */
  2473. /**
  2474. * The background color or fill of the pivot.
  2475. *
  2476. * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
  2477. * Pivot options demonstrated
  2478. *
  2479. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  2480. * @default #000000
  2481. * @since 2.3.0
  2482. * @product highcharts
  2483. * @apioption plotOptions.gauge.pivot.backgroundColor
  2484. */
  2485. tooltip: {
  2486. headerFormat: ''
  2487. },
  2488. /**
  2489. * Whether to display this particular series or series type in the
  2490. * legend. Defaults to false for gauge series.
  2491. *
  2492. * @since 2.3.0
  2493. * @product highcharts
  2494. */
  2495. showInLegend: false
  2496. // Prototype members
  2497. }, {
  2498. // chart.angular will be set to true when a gauge series is present,
  2499. // and this will be used on the axes
  2500. angular: true,
  2501. directTouch: true, // #5063
  2502. drawGraph: noop,
  2503. fixedBox: true,
  2504. forceDL: true,
  2505. noSharedTooltip: true,
  2506. trackerGroups: ['group', 'dataLabelsGroup'],
  2507. // Calculate paths etc
  2508. translate: function () {
  2509. var series = this,
  2510. yAxis = series.yAxis,
  2511. options = series.options,
  2512. center = yAxis.center;
  2513. series.generatePoints();
  2514. series.points.forEach(function (point) {
  2515. var dialOptions = merge(options.dial, point.dial),
  2516. radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) /
  2517. 200,
  2518. baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) /
  2519. 100,
  2520. rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) /
  2521. 100,
  2522. baseWidth = dialOptions.baseWidth || 3,
  2523. topWidth = dialOptions.topWidth || 1,
  2524. overshoot = options.overshoot,
  2525. rotation = yAxis.startAngleRad +
  2526. yAxis.translate(point.y, null, null, null, true);
  2527. // Handle the wrap and overshoot options
  2528. if (isNumber(overshoot)) {
  2529. overshoot = overshoot / 180 * Math.PI;
  2530. rotation = Math.max(
  2531. yAxis.startAngleRad - overshoot,
  2532. Math.min(yAxis.endAngleRad + overshoot, rotation)
  2533. );
  2534. } else if (options.wrap === false) {
  2535. rotation = Math.max(
  2536. yAxis.startAngleRad,
  2537. Math.min(yAxis.endAngleRad, rotation)
  2538. );
  2539. }
  2540. rotation = rotation * 180 / Math.PI;
  2541. point.shapeType = 'path';
  2542. point.shapeArgs = {
  2543. d: dialOptions.path || [
  2544. 'M',
  2545. -rearLength, -baseWidth / 2,
  2546. 'L',
  2547. baseLength, -baseWidth / 2,
  2548. radius, -topWidth / 2,
  2549. radius, topWidth / 2,
  2550. baseLength, baseWidth / 2,
  2551. -rearLength, baseWidth / 2,
  2552. 'z'
  2553. ],
  2554. translateX: center[0],
  2555. translateY: center[1],
  2556. rotation: rotation
  2557. };
  2558. // Positions for data label
  2559. point.plotX = center[0];
  2560. point.plotY = center[1];
  2561. });
  2562. },
  2563. // Draw the points where each point is one needle
  2564. drawPoints: function () {
  2565. var series = this,
  2566. chart = series.chart,
  2567. center = series.yAxis.center,
  2568. pivot = series.pivot,
  2569. options = series.options,
  2570. pivotOptions = options.pivot,
  2571. renderer = chart.renderer;
  2572. series.points.forEach(function (point) {
  2573. var graphic = point.graphic,
  2574. shapeArgs = point.shapeArgs,
  2575. d = shapeArgs.d,
  2576. dialOptions = merge(options.dial, point.dial); // #1233
  2577. if (graphic) {
  2578. graphic.animate(shapeArgs);
  2579. shapeArgs.d = d; // animate alters it
  2580. } else {
  2581. point.graphic = renderer[point.shapeType](shapeArgs)
  2582. .attr({
  2583. // required by VML when animation is false
  2584. rotation: shapeArgs.rotation,
  2585. zIndex: 1
  2586. })
  2587. .addClass('highcharts-dial')
  2588. .add(series.group);
  2589. // Presentational attributes
  2590. if (!chart.styledMode) {
  2591. point.graphic.attr({
  2592. stroke: dialOptions.borderColor || 'none',
  2593. 'stroke-width': dialOptions.borderWidth || 0,
  2594. fill: dialOptions.backgroundColor ||
  2595. '#000000'
  2596. });
  2597. }
  2598. }
  2599. });
  2600. // Add or move the pivot
  2601. if (pivot) {
  2602. pivot.animate({ // #1235
  2603. translateX: center[0],
  2604. translateY: center[1]
  2605. });
  2606. } else {
  2607. series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
  2608. .attr({
  2609. zIndex: 2
  2610. })
  2611. .addClass('highcharts-pivot')
  2612. .translate(center[0], center[1])
  2613. .add(series.group);
  2614. // Presentational attributes
  2615. if (!chart.styledMode) {
  2616. series.pivot.attr({
  2617. 'stroke-width': pivotOptions.borderWidth || 0,
  2618. stroke: pivotOptions.borderColor ||
  2619. '#cccccc',
  2620. fill: pivotOptions.backgroundColor ||
  2621. '#000000'
  2622. });
  2623. }
  2624. }
  2625. },
  2626. // Animate the arrow up from startAngle
  2627. animate: function (init) {
  2628. var series = this;
  2629. if (!init) {
  2630. series.points.forEach(function (point) {
  2631. var graphic = point.graphic;
  2632. if (graphic) {
  2633. // start value
  2634. graphic.attr({
  2635. rotation: series.yAxis.startAngleRad * 180 / Math.PI
  2636. });
  2637. // animate
  2638. graphic.animate({
  2639. rotation: point.shapeArgs.rotation
  2640. }, series.options.animation);
  2641. }
  2642. });
  2643. // delete this function to allow it only once
  2644. series.animate = null;
  2645. }
  2646. },
  2647. render: function () {
  2648. this.group = this.plotGroup(
  2649. 'group',
  2650. 'series',
  2651. this.visible ? 'visible' : 'hidden',
  2652. this.options.zIndex,
  2653. this.chart.seriesGroup
  2654. );
  2655. Series.prototype.render.call(this);
  2656. this.group.clip(this.chart.clipRect);
  2657. },
  2658. // Extend the basic setData method by running processData and generatePoints
  2659. // immediately, in order to access the points from the legend.
  2660. setData: function (data, redraw) {
  2661. Series.prototype.setData.call(this, data, false);
  2662. this.processData();
  2663. this.generatePoints();
  2664. if (pick(redraw, true)) {
  2665. this.chart.redraw();
  2666. }
  2667. },
  2668. // If the tracking module is loaded, add the point tracker
  2669. drawTracker: TrackerMixin && TrackerMixin.drawTrackerPoint
  2670. // Point members
  2671. }, {
  2672. // Don't do any hover colors or anything
  2673. setState: function (state) {
  2674. this.state = state;
  2675. }
  2676. });
  2677. /**
  2678. * A `gauge` series. If the [type](#series.gauge.type) option is not
  2679. * specified, it is inherited from [chart.type](#chart.type).
  2680. *
  2681. * @extends series,plotOptions.gauge
  2682. * @excluding animationLimit, boostThreshold, connectEnds, connectNulls,
  2683. * cropThreshold, dashStyle, dataParser, dataURL, findNearestPointBy,
  2684. * getExtremesFromAll, marker, negativeColor, pointPlacement, shadow,
  2685. * softThreshold, stack, stacking, states, step, threshold,
  2686. * turboThreshold, zoneAxis, zones
  2687. * @product highcharts
  2688. * @apioption series.gauge
  2689. */
  2690. /**
  2691. * An array of data points for the series. For the `gauge` series type,
  2692. * points can be given in the following ways:
  2693. *
  2694. * 1. An array of numerical values. In this case, the numerical values will be
  2695. * interpreted as `y` options. Example:
  2696. * ```js
  2697. * data: [0, 5, 3, 5]
  2698. * ```
  2699. *
  2700. * 2. An array of objects with named values. The following snippet shows only a
  2701. * few settings, see the complete options set below. If the total number of
  2702. * data points exceeds the series'
  2703. * [turboThreshold](#series.gauge.turboThreshold), this option is not
  2704. * available.
  2705. * ```js
  2706. * data: [{
  2707. * y: 6,
  2708. * name: "Point2",
  2709. * color: "#00FF00"
  2710. * }, {
  2711. * y: 8,
  2712. * name: "Point1",
  2713. * color: "#FF00FF"
  2714. * }]
  2715. * ```
  2716. *
  2717. * The typical gauge only contains a single data value.
  2718. *
  2719. * @sample {highcharts} highcharts/chart/reflow-true/
  2720. * Numerical values
  2721. * @sample {highcharts} highcharts/series/data-array-of-objects/
  2722. * Config objects
  2723. *
  2724. * @type {Array<number|*>}
  2725. * @extends series.line.data
  2726. * @excluding drilldown, marker, x
  2727. * @product highcharts
  2728. * @apioption series.gauge.data
  2729. */
  2730. }(Highcharts));
  2731. (function (H) {
  2732. /* *
  2733. * (c) 2010-2019 Torstein Honsi
  2734. *
  2735. * License: www.highcharts.com/license
  2736. */
  2737. var noop = H.noop,
  2738. pick = H.pick,
  2739. seriesType = H.seriesType,
  2740. seriesTypes = H.seriesTypes;
  2741. /**
  2742. * The boxplot series type.
  2743. *
  2744. * @private
  2745. * @class
  2746. * @name Highcharts.seriesTypes#boxplot
  2747. *
  2748. * @augments Highcharts.Series
  2749. */
  2750. /**
  2751. * A box plot is a convenient way of depicting groups of data through their
  2752. * five-number summaries: the smallest observation (sample minimum), lower
  2753. * quartile (Q1), median (Q2), upper quartile (Q3), and largest observation
  2754. * (sample maximum).
  2755. *
  2756. * @sample highcharts/demo/box-plot/
  2757. * Box plot
  2758. *
  2759. * @extends plotOptions.column
  2760. * @excluding borderColor, borderRadius, borderWidth, groupZPadding, states
  2761. * @product highcharts
  2762. * @optionparent plotOptions.boxplot
  2763. */
  2764. seriesType('boxplot', 'column', {
  2765. threshold: null,
  2766. tooltip: {
  2767. pointFormat:
  2768. '<span style="color:{point.color}">\u25CF</span> <b> ' +
  2769. '{series.name}</b><br/>' +
  2770. 'Maximum: {point.high}<br/>' +
  2771. 'Upper quartile: {point.q3}<br/>' +
  2772. 'Median: {point.median}<br/>' +
  2773. 'Lower quartile: {point.q1}<br/>' +
  2774. 'Minimum: {point.low}<br/>'
  2775. },
  2776. /**
  2777. * The length of the whiskers, the horizontal lines marking low and
  2778. * high values. It can be a numerical pixel value, or a percentage
  2779. * value of the box width. Set `0` to disable whiskers.
  2780. *
  2781. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2782. * True by default
  2783. *
  2784. * @type {number|string}
  2785. * @since 3.0
  2786. * @product highcharts
  2787. */
  2788. whiskerLength: '50%',
  2789. /**
  2790. * The fill color of the box.
  2791. *
  2792. * In styled mode, the fill color can be set with the
  2793. * `.highcharts-boxplot-box` class.
  2794. *
  2795. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2796. * Box plot styling
  2797. *
  2798. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  2799. * @default #ffffff
  2800. * @since 3.0
  2801. * @product highcharts
  2802. */
  2803. fillColor: '#ffffff',
  2804. /**
  2805. * The width of the line surrounding the box. If any of
  2806. * [stemWidth](#plotOptions.boxplot.stemWidth),
  2807. * [medianWidth](#plotOptions.boxplot.medianWidth)
  2808. * or [whiskerWidth](#plotOptions.boxplot.whiskerWidth) are `null`,
  2809. * the lineWidth also applies to these lines.
  2810. *
  2811. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2812. * Box plot styling
  2813. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2814. * Error bar styling
  2815. *
  2816. * @since 3.0
  2817. * @product highcharts
  2818. */
  2819. lineWidth: 1,
  2820. /**
  2821. * The color of the median line. If `undefined`, the general series color
  2822. * applies.
  2823. *
  2824. * In styled mode, the median stroke width can be set with the
  2825. * `.highcharts-boxplot-median` class.
  2826. *
  2827. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2828. * Box plot styling
  2829. * @sample {highcharts} highcharts/css/boxplot/
  2830. * Box plot in styled mode
  2831. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2832. * Error bar styling
  2833. *
  2834. * @type {Highcharts.ColorString|Highcharts.GradientColorObject}
  2835. * @since 3.0
  2836. * @product highcharts
  2837. * @apioption plotOptions.boxplot.medianColor
  2838. */
  2839. /**
  2840. * The pixel width of the median line. If `null`, the
  2841. * [lineWidth](#plotOptions.boxplot.lineWidth) is used.
  2842. *
  2843. * In styled mode, the median stroke width can be set with the
  2844. * `.highcharts-boxplot-median` class.
  2845. *
  2846. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2847. * Box plot styling
  2848. * @sample {highcharts} highcharts/css/boxplot/
  2849. * Box plot in styled mode
  2850. *
  2851. * @since 3.0
  2852. * @product highcharts
  2853. */
  2854. medianWidth: 2,
  2855. /*
  2856. // States are not working and are removed from docs.
  2857. // Refer to: #2340
  2858. states: {
  2859. hover: {
  2860. brightness: -0.3
  2861. }
  2862. },
  2863. /**
  2864. * The color of the stem, the vertical line extending from the box to
  2865. * the whiskers. If `undefined`, the series color is used.
  2866. *
  2867. * In styled mode, the stem stroke can be set with the
  2868. * `.highcharts-boxplot-stem` class.
  2869. *
  2870. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2871. * Box plot styling
  2872. * @sample {highcharts} highcharts/css/boxplot/
  2873. * Box plot in styled mode
  2874. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2875. * Error bar styling
  2876. *
  2877. * @type {Highcharts.ColorString}
  2878. * @since 3.0
  2879. * @product highcharts
  2880. * @apioption plotOptions.boxplot.stemColor
  2881. */
  2882. /**
  2883. * The dash style of the stem, the vertical line extending from the
  2884. * box to the whiskers.
  2885. *
  2886. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2887. * Box plot styling
  2888. * @sample {highcharts} highcharts/css/boxplot/
  2889. * Box plot in styled mode
  2890. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2891. * Error bar styling
  2892. *
  2893. * @type {Highcharts.DashStyleType}
  2894. * @default Solid
  2895. * @since 3.0
  2896. * @product highcharts
  2897. * @apioption plotOptions.boxplot.stemDashStyle
  2898. */
  2899. /**
  2900. * The width of the stem, the vertical line extending from the box to
  2901. * the whiskers. If `undefined`, the width is inherited from the
  2902. * [lineWidth](#plotOptions.boxplot.lineWidth) option.
  2903. *
  2904. * In styled mode, the stem stroke width can be set with the
  2905. * `.highcharts-boxplot-stem` class.
  2906. *
  2907. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2908. * Box plot styling
  2909. * @sample {highcharts} highcharts/css/boxplot/
  2910. * Box plot in styled mode
  2911. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2912. * Error bar styling
  2913. *
  2914. * @type {number}
  2915. * @since 3.0
  2916. * @product highcharts
  2917. * @apioption plotOptions.boxplot.stemWidth
  2918. */
  2919. /**
  2920. * The color of the whiskers, the horizontal lines marking low and high
  2921. * values. When `undefined`, the general series color is used.
  2922. *
  2923. * In styled mode, the whisker stroke can be set with the
  2924. * `.highcharts-boxplot-whisker` class .
  2925. *
  2926. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2927. * Box plot styling
  2928. * @sample {highcharts} highcharts/css/boxplot/
  2929. * Box plot in styled mode
  2930. *
  2931. * @type {Highcharts.ColorString}
  2932. * @since 3.0
  2933. * @product highcharts
  2934. * @apioption plotOptions.boxplot.whiskerColor
  2935. */
  2936. /**
  2937. * The line width of the whiskers, the horizontal lines marking low and
  2938. * high values. When `undefined`, the general
  2939. * [lineWidth](#plotOptions.boxplot.lineWidth) applies.
  2940. *
  2941. * In styled mode, the whisker stroke width can be set with the
  2942. * `.highcharts-boxplot-whisker` class.
  2943. *
  2944. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2945. * Box plot styling
  2946. * @sample {highcharts} highcharts/css/boxplot/
  2947. * Box plot in styled mode
  2948. *
  2949. * @since 3.0
  2950. * @product highcharts
  2951. */
  2952. whiskerWidth: 2
  2953. }, /** @lends Highcharts.seriesTypes.boxplot */ {
  2954. // array point configs are mapped to this
  2955. pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'],
  2956. toYData: function (point) { // return a plain array for speedy calculation
  2957. return [point.low, point.q1, point.median, point.q3, point.high];
  2958. },
  2959. // defines the top of the tracker
  2960. pointValKey: 'high',
  2961. // Get presentational attributes
  2962. pointAttribs: function () {
  2963. // No attributes should be set on point.graphic which is the group
  2964. return {};
  2965. },
  2966. // Disable data labels for box plot
  2967. drawDataLabels: noop,
  2968. // Translate data points from raw values x and y to plotX and plotY
  2969. translate: function () {
  2970. var series = this,
  2971. yAxis = series.yAxis,
  2972. pointArrayMap = series.pointArrayMap;
  2973. seriesTypes.column.prototype.translate.apply(series);
  2974. // do the translation on each point dimension
  2975. series.points.forEach(function (point) {
  2976. pointArrayMap.forEach(function (key) {
  2977. if (point[key] !== null) {
  2978. point[key + 'Plot'] = yAxis.translate(
  2979. point[key], 0, 1, 0, 1
  2980. );
  2981. }
  2982. });
  2983. });
  2984. },
  2985. // Draw the data points
  2986. drawPoints: function () {
  2987. var series = this,
  2988. points = series.points,
  2989. options = series.options,
  2990. chart = series.chart,
  2991. renderer = chart.renderer,
  2992. q1Plot,
  2993. q3Plot,
  2994. highPlot,
  2995. lowPlot,
  2996. medianPlot,
  2997. medianPath,
  2998. crispCorr,
  2999. crispX = 0,
  3000. boxPath,
  3001. width,
  3002. left,
  3003. right,
  3004. halfWidth,
  3005. // error bar inherits this series type but doesn't do quartiles
  3006. doQuartiles = series.doQuartiles !== false,
  3007. pointWiskerLength,
  3008. whiskerLength = series.options.whiskerLength;
  3009. points.forEach(function (point) {
  3010. var graphic = point.graphic,
  3011. verb = graphic ? 'animate' : 'attr',
  3012. shapeArgs = point.shapeArgs,
  3013. boxAttr = {},
  3014. stemAttr = {},
  3015. whiskersAttr = {},
  3016. medianAttr = {},
  3017. color = point.color || series.color;
  3018. if (point.plotY !== undefined) {
  3019. // crisp vector coordinates
  3020. width = shapeArgs.width;
  3021. left = Math.floor(shapeArgs.x);
  3022. right = left + width;
  3023. halfWidth = Math.round(width / 2);
  3024. q1Plot = Math.floor(doQuartiles ? point.q1Plot : point.lowPlot);
  3025. q3Plot = Math.floor(doQuartiles ? point.q3Plot : point.lowPlot);
  3026. highPlot = Math.floor(point.highPlot);
  3027. lowPlot = Math.floor(point.lowPlot);
  3028. if (!graphic) {
  3029. point.graphic = graphic = renderer.g('point')
  3030. .add(series.group);
  3031. point.stem = renderer.path()
  3032. .addClass('highcharts-boxplot-stem')
  3033. .add(graphic);
  3034. if (whiskerLength) {
  3035. point.whiskers = renderer.path()
  3036. .addClass('highcharts-boxplot-whisker')
  3037. .add(graphic);
  3038. }
  3039. if (doQuartiles) {
  3040. point.box = renderer.path(boxPath)
  3041. .addClass('highcharts-boxplot-box')
  3042. .add(graphic);
  3043. }
  3044. point.medianShape = renderer.path(medianPath)
  3045. .addClass('highcharts-boxplot-median')
  3046. .add(graphic);
  3047. }
  3048. if (!chart.styledMode) {
  3049. // Stem attributes
  3050. stemAttr.stroke =
  3051. point.stemColor || options.stemColor || color;
  3052. stemAttr['stroke-width'] = pick(
  3053. point.stemWidth,
  3054. options.stemWidth,
  3055. options.lineWidth
  3056. );
  3057. stemAttr.dashstyle =
  3058. point.stemDashStyle || options.stemDashStyle;
  3059. point.stem.attr(stemAttr);
  3060. // Whiskers attributes
  3061. if (whiskerLength) {
  3062. whiskersAttr.stroke =
  3063. point.whiskerColor || options.whiskerColor || color;
  3064. whiskersAttr['stroke-width'] = pick(
  3065. point.whiskerWidth,
  3066. options.whiskerWidth,
  3067. options.lineWidth
  3068. );
  3069. point.whiskers.attr(whiskersAttr);
  3070. }
  3071. if (doQuartiles) {
  3072. boxAttr.fill = (
  3073. point.fillColor ||
  3074. options.fillColor ||
  3075. color
  3076. );
  3077. boxAttr.stroke = options.lineColor || color;
  3078. boxAttr['stroke-width'] = options.lineWidth || 0;
  3079. point.box.attr(boxAttr);
  3080. }
  3081. // Median attributes
  3082. medianAttr.stroke =
  3083. point.medianColor || options.medianColor || color;
  3084. medianAttr['stroke-width'] = pick(
  3085. point.medianWidth,
  3086. options.medianWidth,
  3087. options.lineWidth
  3088. );
  3089. point.medianShape.attr(medianAttr);
  3090. }
  3091. // The stem
  3092. crispCorr = (point.stem.strokeWidth() % 2) / 2;
  3093. crispX = left + halfWidth + crispCorr;
  3094. point.stem[verb]({
  3095. d: [
  3096. // stem up
  3097. 'M',
  3098. crispX, q3Plot,
  3099. 'L',
  3100. crispX, highPlot,
  3101. // stem down
  3102. 'M',
  3103. crispX, q1Plot,
  3104. 'L',
  3105. crispX, lowPlot
  3106. ]
  3107. });
  3108. // The box
  3109. if (doQuartiles) {
  3110. crispCorr = (point.box.strokeWidth() % 2) / 2;
  3111. q1Plot = Math.floor(q1Plot) + crispCorr;
  3112. q3Plot = Math.floor(q3Plot) + crispCorr;
  3113. left += crispCorr;
  3114. right += crispCorr;
  3115. point.box[verb]({
  3116. d: [
  3117. 'M',
  3118. left, q3Plot,
  3119. 'L',
  3120. left, q1Plot,
  3121. 'L',
  3122. right, q1Plot,
  3123. 'L',
  3124. right, q3Plot,
  3125. 'L',
  3126. left, q3Plot,
  3127. 'z'
  3128. ]
  3129. });
  3130. }
  3131. // The whiskers
  3132. if (whiskerLength) {
  3133. crispCorr = (point.whiskers.strokeWidth() % 2) / 2;
  3134. highPlot = highPlot + crispCorr;
  3135. lowPlot = lowPlot + crispCorr;
  3136. pointWiskerLength = (/%$/).test(whiskerLength) ?
  3137. halfWidth * parseFloat(whiskerLength) / 100 :
  3138. whiskerLength / 2;
  3139. point.whiskers[verb]({
  3140. d: [
  3141. // High whisker
  3142. 'M',
  3143. crispX - pointWiskerLength,
  3144. highPlot,
  3145. 'L',
  3146. crispX + pointWiskerLength,
  3147. highPlot,
  3148. // Low whisker
  3149. 'M',
  3150. crispX - pointWiskerLength,
  3151. lowPlot,
  3152. 'L',
  3153. crispX + pointWiskerLength,
  3154. lowPlot
  3155. ]
  3156. });
  3157. }
  3158. // The median
  3159. medianPlot = Math.round(point.medianPlot);
  3160. crispCorr = (point.medianShape.strokeWidth() % 2) / 2;
  3161. medianPlot = medianPlot + crispCorr;
  3162. point.medianShape[verb]({
  3163. d: [
  3164. 'M',
  3165. left,
  3166. medianPlot,
  3167. 'L',
  3168. right,
  3169. medianPlot
  3170. ]
  3171. });
  3172. }
  3173. });
  3174. },
  3175. setStackedPoints: noop // #3890
  3176. });
  3177. /**
  3178. * A `boxplot` series. If the [type](#series.boxplot.type) option is
  3179. * not specified, it is inherited from [chart.type](#chart.type).
  3180. *
  3181. * @extends series,plotOptions.boxplot
  3182. * @excluding dataParser, dataURL, marker, stack, stacking, states
  3183. * @product highcharts
  3184. * @apioption series.boxplot
  3185. */
  3186. /**
  3187. * An array of data points for the series. For the `boxplot` series
  3188. * type, points can be given in the following ways:
  3189. *
  3190. * 1. An array of arrays with 6 or 5 values. In this case, the values correspond
  3191. * to `x,low,q1,median,q3,high`. If the first value is a string, it is
  3192. * applied as the name of the point, and the `x` value is inferred. The `x`
  3193. * value can also be omitted, in which case the inner arrays should be of
  3194. * length 5. Then the `x` value is automatically calculated, either starting
  3195. * at 0 and incremented by 1, or from `pointStart` and `pointInterval` given
  3196. * in the series options.
  3197. * ```js
  3198. * data: [
  3199. * [0, 3, 0, 10, 3, 5],
  3200. * [1, 7, 8, 7, 2, 9],
  3201. * [2, 6, 9, 5, 1, 3]
  3202. * ]
  3203. * ```
  3204. *
  3205. * 2. An array of objects with named values. The following snippet shows only a
  3206. * few settings, see the complete options set below. If the total number of
  3207. * data points exceeds the series'
  3208. * [turboThreshold](#series.boxplot.turboThreshold), this option is not
  3209. * available.
  3210. * ```js
  3211. * data: [{
  3212. * x: 1,
  3213. * low: 4,
  3214. * q1: 9,
  3215. * median: 9,
  3216. * q3: 1,
  3217. * high: 10,
  3218. * name: "Point2",
  3219. * color: "#00FF00"
  3220. * }, {
  3221. * x: 1,
  3222. * low: 5,
  3223. * q1: 7,
  3224. * median: 3,
  3225. * q3: 6,
  3226. * high: 2,
  3227. * name: "Point1",
  3228. * color: "#FF00FF"
  3229. * }]
  3230. * ```
  3231. *
  3232. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  3233. * Arrays of numeric x and y
  3234. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  3235. * Arrays of datetime x and y
  3236. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  3237. * Arrays of point.name and y
  3238. * @sample {highcharts} highcharts/series/data-array-of-objects/
  3239. * Config objects
  3240. *
  3241. * @type {Array<Array<(number|string),number,number,number,number>|Array<(number|string),number,number,number,number,number>|*>}
  3242. * @extends series.line.data
  3243. * @excluding marker
  3244. * @product highcharts
  3245. * @apioption series.boxplot.data
  3246. */
  3247. /**
  3248. * The `high` value for each data point, signifying the highest value
  3249. * in the sample set. The top whisker is drawn here.
  3250. *
  3251. * @type {number}
  3252. * @product highcharts
  3253. * @apioption series.boxplot.data.high
  3254. */
  3255. /**
  3256. * The `low` value for each data point, signifying the lowest value
  3257. * in the sample set. The bottom whisker is drawn here.
  3258. *
  3259. * @type {number}
  3260. * @product highcharts
  3261. * @apioption series.boxplot.data.low
  3262. */
  3263. /**
  3264. * The median for each data point. This is drawn as a line through the
  3265. * middle area of the box.
  3266. *
  3267. * @type {number}
  3268. * @product highcharts
  3269. * @apioption series.boxplot.data.median
  3270. */
  3271. /**
  3272. * The lower quartile for each data point. This is the bottom of the
  3273. * box.
  3274. *
  3275. * @type {number}
  3276. * @product highcharts
  3277. * @apioption series.boxplot.data.q1
  3278. */
  3279. /**
  3280. * The higher quartile for each data point. This is the top of the box.
  3281. *
  3282. * @type {number}
  3283. * @product highcharts
  3284. * @apioption series.boxplot.data.q3
  3285. */
  3286. }(Highcharts));
  3287. (function (H) {
  3288. /* *
  3289. * (c) 2010-2019 Torstein Honsi
  3290. *
  3291. * License: www.highcharts.com/license
  3292. */
  3293. var noop = H.noop,
  3294. seriesType = H.seriesType,
  3295. seriesTypes = H.seriesTypes;
  3296. /**
  3297. * Error bars are a graphical representation of the variability of data and are
  3298. * used on graphs to indicate the error, or uncertainty in a reported
  3299. * measurement.
  3300. *
  3301. * @sample highcharts/demo/error-bar/
  3302. * Error bars on a column series
  3303. * @sample highcharts/series-errorbar/on-scatter/
  3304. * Error bars on a scatter series
  3305. *
  3306. * @extends plotOptions.boxplot
  3307. * @product highcharts highstock
  3308. * @optionparent plotOptions.errorbar
  3309. */
  3310. seriesType('errorbar', 'boxplot', {
  3311. /**
  3312. * The main color of the bars. This can be overridden by
  3313. * [stemColor](#plotOptions.errorbar.stemColor) and
  3314. * [whiskerColor](#plotOptions.errorbar.whiskerColor) individually.
  3315. *
  3316. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  3317. * Error bar styling
  3318. *
  3319. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  3320. * @default #000000
  3321. * @since 3.0
  3322. * @product highcharts
  3323. */
  3324. color: '#000000',
  3325. grouping: false,
  3326. /**
  3327. * The parent series of the error bar. The default value links it to
  3328. * the previous series. Otherwise, use the id of the parent series.
  3329. *
  3330. * @since 3.0
  3331. * @product highcharts
  3332. */
  3333. linkedTo: ':previous',
  3334. tooltip: {
  3335. pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'
  3336. },
  3337. /**
  3338. * The line width of the whiskers, the horizontal lines marking low
  3339. * and high values. When `null`, the general
  3340. * [lineWidth](#plotOptions.errorbar.lineWidth) applies.
  3341. *
  3342. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  3343. * Error bar styling
  3344. *
  3345. * @type {number}
  3346. * @since 3.0
  3347. * @product highcharts
  3348. */
  3349. whiskerWidth: null
  3350. // Prototype members
  3351. }, {
  3352. type: 'errorbar',
  3353. pointArrayMap: ['low', 'high'], // array point configs are mapped to this
  3354. toYData: function (point) { // return a plain array for speedy calculation
  3355. return [point.low, point.high];
  3356. },
  3357. pointValKey: 'high', // defines the top of the tracker
  3358. doQuartiles: false,
  3359. drawDataLabels: seriesTypes.arearange ?
  3360. function () {
  3361. var valKey = this.pointValKey;
  3362. seriesTypes.arearange.prototype.drawDataLabels.call(this);
  3363. // Arearange drawDataLabels does not reset point.y to high,
  3364. // but to low after drawing (#4133)
  3365. this.data.forEach(function (point) {
  3366. point.y = point[valKey];
  3367. });
  3368. } :
  3369. noop,
  3370. // Get the width and X offset, either on top of the linked series column or
  3371. // standalone
  3372. getColumnMetrics: function () {
  3373. return (this.linkedParent && this.linkedParent.columnMetrics) ||
  3374. seriesTypes.column.prototype.getColumnMetrics.call(this);
  3375. }
  3376. });
  3377. /**
  3378. * A `errorbar` series. If the [type](#series.errorbar.type) option
  3379. * is not specified, it is inherited from [chart.type](#chart.type).
  3380. *
  3381. * @extends series,plotOptions.errorbar
  3382. * @excluding dataParser, dataURL, stack, stacking
  3383. * @product highcharts
  3384. * @apioption series.errorbar
  3385. */
  3386. /**
  3387. * An array of data points for the series. For the `errorbar` series
  3388. * type, points can be given in the following ways:
  3389. *
  3390. * 1. An array of arrays with 3 or 2 values. In this case, the values correspond
  3391. * to `x,low,high`. If the first value is a string, it is applied as the name
  3392. * of the point, and the `x` value is inferred. The `x` value can also be
  3393. * omitted, in which case the inner arrays should be of length 2\. Then the
  3394. * `x` value is automatically calculated, either starting at 0 and
  3395. * incremented by 1, or from `pointStart` and `pointInterval` given in the
  3396. * series options.
  3397. * ```js
  3398. * data: [
  3399. * [0, 10, 2],
  3400. * [1, 1, 8],
  3401. * [2, 4, 5]
  3402. * ]
  3403. * ```
  3404. *
  3405. * 2. An array of objects with named values. The following snippet shows only a
  3406. * few settings, see the complete options set below. If the total number of
  3407. * data points exceeds the series'
  3408. * [turboThreshold](#series.errorbar.turboThreshold), this option is not
  3409. * available.
  3410. * ```js
  3411. * data: [{
  3412. * x: 1,
  3413. * low: 0,
  3414. * high: 0,
  3415. * name: "Point2",
  3416. * color: "#00FF00"
  3417. * }, {
  3418. * x: 1,
  3419. * low: 5,
  3420. * high: 5,
  3421. * name: "Point1",
  3422. * color: "#FF00FF"
  3423. * }]
  3424. * ```
  3425. *
  3426. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  3427. * Arrays of numeric x and y
  3428. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  3429. * Arrays of datetime x and y
  3430. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  3431. * Arrays of point.name and y
  3432. * @sample {highcharts} highcharts/series/data-array-of-objects/
  3433. * Config objects
  3434. *
  3435. * @type {Array<Array<(number|string),number>|Array<(number|string),number,number>|*>}
  3436. * @extends series.arearange.data
  3437. * @excluding dataLabels, drilldown, marker, states
  3438. * @product highcharts
  3439. * @apioption series.errorbar.data
  3440. */
  3441. }(Highcharts));
  3442. (function (H) {
  3443. /* *
  3444. * (c) 2010-2019 Torstein Honsi
  3445. *
  3446. * License: www.highcharts.com/license
  3447. */
  3448. var correctFloat = H.correctFloat,
  3449. isNumber = H.isNumber,
  3450. pick = H.pick,
  3451. objectEach = H.objectEach,
  3452. arrayMin = H.arrayMin,
  3453. arrayMax = H.arrayMax,
  3454. addEvent = H.addEvent,
  3455. Axis = H.Axis,
  3456. Chart = H.Chart,
  3457. Point = H.Point,
  3458. Series = H.Series,
  3459. seriesType = H.seriesType,
  3460. seriesTypes = H.seriesTypes;
  3461. addEvent(Axis, 'afterInit', function () {
  3462. if (!this.isXAxis) {
  3463. this.waterfallStacks = {};
  3464. }
  3465. });
  3466. addEvent(Chart, 'beforeRedraw', function () {
  3467. var axes = this.axes,
  3468. series = this.series,
  3469. i = series.length;
  3470. while (i--) {
  3471. if (series[i].options.stacking) {
  3472. axes.forEach(function (axis) {
  3473. if (!axis.isXAxis) {
  3474. axis.waterfallStacks = {};
  3475. }
  3476. });
  3477. i = 0;
  3478. }
  3479. }
  3480. });
  3481. /**
  3482. * A waterfall chart displays sequentially introduced positive or negative
  3483. * values in cumulative columns.
  3484. *
  3485. * @sample highcharts/demo/waterfall/
  3486. * Waterfall chart
  3487. * @sample highcharts/plotoptions/waterfall-inverted/
  3488. * Horizontal (inverted) waterfall
  3489. * @sample highcharts/plotoptions/waterfall-stacked/
  3490. * Stacked waterfall chart
  3491. *
  3492. * @extends plotOptions.column
  3493. * @product highcharts
  3494. * @optionparent plotOptions.waterfall
  3495. */
  3496. seriesType('waterfall', 'column', {
  3497. /**
  3498. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  3499. * @apioption plotOptions.waterfall.color
  3500. */
  3501. /**
  3502. * The color used specifically for positive point columns. When not
  3503. * specified, the general series color is used.
  3504. *
  3505. * In styled mode, the waterfall colors can be set with the
  3506. * `.highcharts-point-negative`, `.highcharts-sum` and
  3507. * `.highcharts-intermediate-sum` classes.
  3508. *
  3509. * @sample {highcharts} highcharts/demo/waterfall/
  3510. * Waterfall
  3511. *
  3512. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  3513. * @product highcharts
  3514. * @apioption plotOptions.waterfall.upColor
  3515. */
  3516. dataLabels: {
  3517. inside: true
  3518. },
  3519. /**
  3520. * The width of the line connecting waterfall columns.
  3521. *
  3522. * @product highcharts
  3523. */
  3524. lineWidth: 1,
  3525. /**
  3526. * The color of the line that connects columns in a waterfall series.
  3527. *
  3528. * In styled mode, the stroke can be set with the `.highcharts-graph` class.
  3529. *
  3530. * @type {Highcharts.ColorString}
  3531. * @since 3.0
  3532. * @product highcharts
  3533. */
  3534. lineColor: '#333333',
  3535. /**
  3536. * A name for the dash style to use for the line connecting the columns
  3537. * of the waterfall series. Possible values: Dash, DashDot, Dot, LongDash,
  3538. * LongDashDot, LongDashDotDot, ShortDash, ShortDashDot, ShortDashDotDot,
  3539. * ShortDot, Solid
  3540. *
  3541. * In styled mode, the stroke dash-array can be set with the
  3542. * `.highcharts-graph` class.
  3543. *
  3544. * @type {Highcharts.DashStyleType}
  3545. * @since 3.0
  3546. * @product highcharts
  3547. */
  3548. dashStyle: 'Dot',
  3549. /**
  3550. * The color of the border of each waterfall column.
  3551. *
  3552. * In styled mode, the border stroke can be set with the
  3553. * `.highcharts-point` class.
  3554. *
  3555. * @type {Highcharts.ColorString}
  3556. * @since 3.0
  3557. * @product highcharts
  3558. */
  3559. borderColor: '#333333',
  3560. states: {
  3561. hover: {
  3562. lineWidthPlus: 0 // #3126
  3563. }
  3564. }
  3565. // Prototype members
  3566. }, {
  3567. pointValKey: 'y',
  3568. // Property needed to prevent lines between the columns from disappearing
  3569. // when negativeColor is used.
  3570. showLine: true,
  3571. // After generating points, set y-values for all sums.
  3572. generatePoints: function () {
  3573. var point,
  3574. len,
  3575. i,
  3576. y;
  3577. // Parent call:
  3578. seriesTypes.column.prototype.generatePoints.apply(this);
  3579. for (i = 0, len = this.points.length; i < len; i++) {
  3580. point = this.points[i];
  3581. y = this.processedYData[i];
  3582. // override point value for sums
  3583. // #3710 Update point does not propagate to sum
  3584. if (point.isIntermediateSum || point.isSum) {
  3585. point.y = correctFloat(y);
  3586. }
  3587. }
  3588. },
  3589. // Translate data points from raw values
  3590. translate: function () {
  3591. var series = this,
  3592. options = series.options,
  3593. yAxis = series.yAxis,
  3594. len,
  3595. i,
  3596. points,
  3597. point,
  3598. shapeArgs,
  3599. y,
  3600. yValue,
  3601. previousY,
  3602. previousIntermediate,
  3603. range,
  3604. minPointLength = pick(options.minPointLength, 5),
  3605. halfMinPointLength = minPointLength / 2,
  3606. threshold = options.threshold,
  3607. stacking = options.stacking,
  3608. tooltipY,
  3609. actualStack = yAxis.waterfallStacks[series.stackKey],
  3610. actualStackX,
  3611. total,
  3612. pointY,
  3613. yPos,
  3614. hPos;
  3615. // run column series translate
  3616. seriesTypes.column.prototype.translate.apply(series);
  3617. previousY = previousIntermediate = threshold;
  3618. points = series.points;
  3619. for (i = 0, len = points.length; i < len; i++) {
  3620. // cache current point object
  3621. point = points[i];
  3622. yValue = series.processedYData[i];
  3623. shapeArgs = point.shapeArgs;
  3624. range = [0, yValue];
  3625. pointY = point.y;
  3626. // code responsible for correct positions of stacked points
  3627. // starts here
  3628. if (stacking) {
  3629. if (actualStack) {
  3630. actualStackX = actualStack[i];
  3631. if (stacking === 'overlap') {
  3632. total = actualStackX.threshold + actualStackX.total;
  3633. actualStackX.total -= pointY;
  3634. y = pointY >= 0 ? total : total - pointY;
  3635. } else {
  3636. if (pointY >= 0) {
  3637. total = actualStackX.threshold +
  3638. actualStackX.posTotal;
  3639. actualStackX.posTotal -= pointY;
  3640. y = total;
  3641. } else {
  3642. total = actualStackX.threshold +
  3643. actualStackX.negTotal;
  3644. actualStackX.negTotal -= pointY;
  3645. y = total - pointY;
  3646. }
  3647. }
  3648. if (!point.isSum) {
  3649. // the connectorThreshold property is later used in
  3650. // getCrispPath function to draw a connector line in a
  3651. // correct place
  3652. actualStackX.connectorThreshold =
  3653. actualStackX.threshold + actualStackX.stackTotal;
  3654. }
  3655. if (yAxis.reversed) {
  3656. yPos = (pointY >= 0) ? (y - pointY) : (y + pointY);
  3657. hPos = y;
  3658. } else {
  3659. yPos = y;
  3660. hPos = y - pointY;
  3661. }
  3662. point.below = yPos <= pick(threshold, 0);
  3663. shapeArgs.y = yAxis.translate(yPos, 0, 1, 0, 1);
  3664. shapeArgs.height = Math.abs(shapeArgs.y -
  3665. yAxis.translate(hPos, 0, 1, 0, 1));
  3666. }
  3667. } else {
  3668. // up points
  3669. y = Math.max(previousY, previousY + pointY) + range[0];
  3670. shapeArgs.y = yAxis.translate(y, 0, 1, 0, 1);
  3671. // sum points
  3672. if (point.isSum) {
  3673. shapeArgs.y = yAxis.translate(range[1], 0, 1, 0, 1);
  3674. shapeArgs.height = Math.min(
  3675. yAxis.translate(range[0], 0, 1, 0, 1),
  3676. yAxis.len
  3677. ) - shapeArgs.y; // #4256
  3678. } else if (point.isIntermediateSum) {
  3679. if (pointY >= 0) {
  3680. yPos = range[1] + previousIntermediate;
  3681. hPos = previousIntermediate;
  3682. } else {
  3683. yPos = previousIntermediate;
  3684. hPos = range[1] + previousIntermediate;
  3685. }
  3686. if (yAxis.reversed) {
  3687. // swapping values
  3688. yPos ^= hPos;
  3689. hPos ^= yPos;
  3690. yPos ^= hPos;
  3691. }
  3692. shapeArgs.y = yAxis.translate(yPos, 0, 1, 0, 1);
  3693. shapeArgs.height = Math.abs(shapeArgs.y - Math.min(
  3694. yAxis.translate(hPos, 0, 1, 0, 1),
  3695. yAxis.len
  3696. ));
  3697. previousIntermediate += range[1];
  3698. // If it's not the sum point, update previous stack end position
  3699. // and get shape height (#3886)
  3700. } else {
  3701. shapeArgs.height = yValue > 0 ?
  3702. yAxis.translate(previousY, 0, 1, 0, 1) - shapeArgs.y :
  3703. yAxis.translate(previousY, 0, 1, 0, 1) -
  3704. yAxis.translate(previousY - yValue, 0, 1, 0, 1);
  3705. previousY += yValue;
  3706. point.below = previousY < pick(threshold, 0);
  3707. }
  3708. // #3952 Negative sum or intermediate sum not rendered correctly
  3709. if (shapeArgs.height < 0) {
  3710. shapeArgs.y += shapeArgs.height;
  3711. shapeArgs.height *= -1;
  3712. }
  3713. }
  3714. point.plotY = shapeArgs.y = Math.round(shapeArgs.y) -
  3715. (series.borderWidth % 2) / 2;
  3716. // #3151
  3717. shapeArgs.height = Math.max(Math.round(shapeArgs.height), 0.001);
  3718. point.yBottom = shapeArgs.y + shapeArgs.height;
  3719. if (shapeArgs.height <= minPointLength && !point.isNull) {
  3720. shapeArgs.height = minPointLength;
  3721. shapeArgs.y -= halfMinPointLength;
  3722. point.plotY = shapeArgs.y;
  3723. if (point.y < 0) {
  3724. point.minPointLengthOffset = -halfMinPointLength;
  3725. } else {
  3726. point.minPointLengthOffset = halfMinPointLength;
  3727. }
  3728. } else {
  3729. if (point.isNull) {
  3730. shapeArgs.width = 0;
  3731. }
  3732. point.minPointLengthOffset = 0;
  3733. }
  3734. // Correct tooltip placement (#3014)
  3735. tooltipY = point.plotY + (point.negative ? shapeArgs.height : 0);
  3736. if (series.chart.inverted) {
  3737. point.tooltipPos[0] = yAxis.len - tooltipY;
  3738. } else {
  3739. point.tooltipPos[1] = tooltipY;
  3740. }
  3741. }
  3742. },
  3743. // Call default processData then override yData to reflect waterfall's
  3744. // extremes on yAxis
  3745. processData: function (force) {
  3746. var series = this,
  3747. options = series.options,
  3748. yData = series.yData,
  3749. // #3710 Update point does not propagate to sum
  3750. points = options.data,
  3751. point,
  3752. dataLength = yData.length,
  3753. threshold = options.threshold || 0,
  3754. subSum,
  3755. sum,
  3756. dataMin,
  3757. dataMax,
  3758. y,
  3759. i;
  3760. sum = subSum = dataMin = dataMax = 0;
  3761. for (i = 0; i < dataLength; i++) {
  3762. y = yData[i];
  3763. point = points && points[i] ? points[i] : {};
  3764. if (y === 'sum' || point.isSum) {
  3765. yData[i] = correctFloat(sum);
  3766. } else if (y === 'intermediateSum' || point.isIntermediateSum) {
  3767. yData[i] = correctFloat(subSum);
  3768. subSum = 0;
  3769. } else {
  3770. sum += y;
  3771. subSum += y;
  3772. }
  3773. dataMin = Math.min(sum, dataMin);
  3774. dataMax = Math.max(sum, dataMax);
  3775. }
  3776. Series.prototype.processData.call(this, force);
  3777. // Record extremes only if stacking was not set:
  3778. if (!options.stacking) {
  3779. series.dataMin = dataMin + threshold;
  3780. series.dataMax = dataMax;
  3781. }
  3782. },
  3783. // Return y value or string if point is sum
  3784. toYData: function (pt) {
  3785. if (pt.isSum) {
  3786. // #3245 Error when first element is Sum or Intermediate Sum
  3787. return (pt.x === 0 ? null : 'sum');
  3788. }
  3789. if (pt.isIntermediateSum) {
  3790. return (pt.x === 0 ? null : 'intermediateSum'); // #3245
  3791. }
  3792. return pt.y;
  3793. },
  3794. // Postprocess mapping between options and SVG attributes
  3795. pointAttribs: function (point, state) {
  3796. var upColor = this.options.upColor,
  3797. attr;
  3798. // Set or reset up color (#3710, update to negative)
  3799. if (upColor && !point.options.color) {
  3800. point.color = point.y > 0 ? upColor : null;
  3801. }
  3802. attr = seriesTypes.column.prototype.pointAttribs.call(
  3803. this,
  3804. point,
  3805. state
  3806. );
  3807. // The dashStyle option in waterfall applies to the graph, not
  3808. // the points
  3809. delete attr.dashstyle;
  3810. return attr;
  3811. },
  3812. // Return an empty path initially, because we need to know the stroke-width
  3813. // in order to set the final path.
  3814. getGraphPath: function () {
  3815. return ['M', 0, 0];
  3816. },
  3817. // Draw columns' connector lines
  3818. getCrispPath: function () {
  3819. var data = this.data,
  3820. yAxis = this.yAxis,
  3821. length = data.length,
  3822. graphNormalizer = Math.round(this.graph.strokeWidth()) % 2 / 2,
  3823. borderNormalizer = Math.round(this.borderWidth) % 2 / 2,
  3824. reversedXAxis = this.xAxis.reversed,
  3825. reversedYAxis = this.yAxis.reversed,
  3826. stacking = this.options.stacking,
  3827. path = [],
  3828. connectorThreshold,
  3829. prevStack,
  3830. prevStackX,
  3831. prevPoint,
  3832. yPos,
  3833. isPos,
  3834. prevArgs,
  3835. pointArgs,
  3836. i,
  3837. d;
  3838. for (i = 1; i < length; i++) {
  3839. pointArgs = data[i].shapeArgs;
  3840. prevPoint = data[i - 1];
  3841. prevArgs = data[i - 1].shapeArgs;
  3842. prevStack = yAxis.waterfallStacks[this.stackKey];
  3843. isPos = prevPoint.y > 0 ? -prevArgs.height : 0;
  3844. if (prevStack) {
  3845. prevStackX = prevStack[i - 1];
  3846. // y position of the connector is different when series are
  3847. // stacked, yAxis is reversed and it also depends on point's
  3848. // value
  3849. if (stacking) {
  3850. connectorThreshold = prevStackX.connectorThreshold;
  3851. yPos = Math.round(
  3852. (yAxis.translate(connectorThreshold, 0, 1, 0, 1) +
  3853. (reversedYAxis ? isPos : 0))
  3854. ) - graphNormalizer;
  3855. } else {
  3856. yPos = prevArgs.y + prevPoint.minPointLengthOffset +
  3857. borderNormalizer - graphNormalizer;
  3858. }
  3859. d = [
  3860. 'M',
  3861. prevArgs.x + (reversedXAxis ? 0 : prevArgs.width),
  3862. yPos,
  3863. 'L',
  3864. pointArgs.x + (reversedXAxis ? pointArgs.width : 0),
  3865. yPos
  3866. ];
  3867. }
  3868. if (
  3869. !stacking &&
  3870. (prevPoint.y < 0 && !reversedYAxis) ||
  3871. (prevPoint.y > 0 && reversedYAxis)
  3872. ) {
  3873. d[2] += prevArgs.height;
  3874. d[5] += prevArgs.height;
  3875. }
  3876. path = path.concat(d);
  3877. }
  3878. return path;
  3879. },
  3880. // The graph is initially drawn with an empty definition, then updated with
  3881. // crisp rendering.
  3882. drawGraph: function () {
  3883. Series.prototype.drawGraph.call(this);
  3884. this.graph.attr({
  3885. d: this.getCrispPath()
  3886. });
  3887. },
  3888. // Waterfall has stacking along the x-values too.
  3889. setStackedPoints: function () {
  3890. var series = this,
  3891. options = series.options,
  3892. waterfallStacks = series.yAxis.waterfallStacks,
  3893. seriesThreshold = options.threshold,
  3894. stackThreshold = seriesThreshold || 0,
  3895. interSum = seriesThreshold || 0,
  3896. stackKey = series.stackKey,
  3897. xData = series.xData,
  3898. xLength = xData.length,
  3899. actualStack,
  3900. actualStackX,
  3901. posTotal,
  3902. negTotal,
  3903. xPoint,
  3904. yVal,
  3905. x;
  3906. // code responsible for creating stacks for waterfall series
  3907. if (series.visible || !series.chart.options.chart.ignoreHiddenSeries) {
  3908. if (!waterfallStacks[stackKey]) {
  3909. waterfallStacks[stackKey] = {};
  3910. }
  3911. actualStack = waterfallStacks[stackKey];
  3912. for (var i = 0; i < xLength; i++) {
  3913. x = xData[i];
  3914. if (!actualStack[x]) {
  3915. actualStack[x] = {
  3916. negTotal: 0,
  3917. posTotal: 0,
  3918. total: 0,
  3919. stackTotal: 0,
  3920. threshold: 0,
  3921. stackState: [stackThreshold]
  3922. };
  3923. }
  3924. actualStackX = actualStack[x];
  3925. yVal = series.yData[i];
  3926. if (yVal >= 0) {
  3927. actualStackX.posTotal += yVal;
  3928. } else {
  3929. actualStackX.negTotal += yVal;
  3930. }
  3931. // points do not exist yet, so raw data is used
  3932. xPoint = options.data[i];
  3933. posTotal = actualStackX.posTotal;
  3934. negTotal = actualStackX.negTotal;
  3935. if (xPoint && xPoint.isIntermediateSum) {
  3936. // swapping values
  3937. stackThreshold ^= interSum;
  3938. interSum ^= stackThreshold;
  3939. stackThreshold ^= interSum;
  3940. } else if (xPoint && xPoint.isSum) {
  3941. stackThreshold = seriesThreshold;
  3942. }
  3943. actualStackX.stackTotal = posTotal + negTotal;
  3944. actualStackX.total = actualStackX.stackTotal;
  3945. actualStackX.threshold = stackThreshold;
  3946. actualStackX.stackState[0] = stackThreshold;
  3947. actualStackX.stackState.push(actualStackX.stackTotal);
  3948. stackThreshold += actualStackX.stackTotal;
  3949. }
  3950. }
  3951. },
  3952. // Extremes for a non-stacked series are recorded in processData.
  3953. // In case of stacking, use Series.stackedYData to calculate extremes.
  3954. getExtremes: function () {
  3955. var stacking = this.options.stacking,
  3956. yAxis,
  3957. waterfallStacks,
  3958. stackedYNeg,
  3959. stackedYPos,
  3960. states,
  3961. firstState;
  3962. if (stacking) {
  3963. yAxis = this.yAxis;
  3964. waterfallStacks = yAxis.waterfallStacks;
  3965. stackedYNeg = this.stackedYNeg = [];
  3966. stackedYPos = this.stackedYPos = [];
  3967. // the visible y range can be different when stacking is set to
  3968. // overlap and different when it's set to normal
  3969. if (stacking === 'overlap') {
  3970. objectEach(waterfallStacks[this.stackKey], function (stackX) {
  3971. states = [];
  3972. stackX.stackState.forEach(function (state, stateIndex) {
  3973. firstState = stackX.stackState[0];
  3974. if (stateIndex) {
  3975. states.push(state + firstState);
  3976. } else {
  3977. states.push(firstState);
  3978. }
  3979. });
  3980. stackedYNeg.push(arrayMin(states));
  3981. stackedYPos.push(arrayMax(states));
  3982. });
  3983. } else {
  3984. objectEach(waterfallStacks[this.stackKey], function (stackX) {
  3985. stackedYNeg.push(stackX.negTotal + stackX.threshold);
  3986. stackedYPos.push(stackX.posTotal + stackX.threshold);
  3987. });
  3988. }
  3989. this.dataMin = arrayMin(stackedYNeg);
  3990. this.dataMax = arrayMax(stackedYPos);
  3991. }
  3992. }
  3993. // Point members
  3994. }, {
  3995. getClassName: function () {
  3996. var className = Point.prototype.getClassName.call(this);
  3997. if (this.isSum) {
  3998. className += ' highcharts-sum';
  3999. } else if (this.isIntermediateSum) {
  4000. className += ' highcharts-intermediate-sum';
  4001. }
  4002. return className;
  4003. },
  4004. // Pass the null test in ColumnSeries.translate.
  4005. isValid: function () {
  4006. return isNumber(this.y, true) || this.isSum || this.isIntermediateSum;
  4007. }
  4008. });
  4009. /**
  4010. * A `waterfall` series. If the [type](#series.waterfall.type) option
  4011. * is not specified, it is inherited from [chart.type](#chart.type).
  4012. *
  4013. * @extends series,plotOptions.waterfall
  4014. * @excluding dataParser, dataURL
  4015. * @product highcharts
  4016. * @apioption series.waterfall
  4017. */
  4018. /**
  4019. * An array of data points for the series. For the `waterfall` series
  4020. * type, points can be given in the following ways:
  4021. *
  4022. * 1. An array of numerical values. In this case, the numerical values will be
  4023. * interpreted as `y` options. The `x` values will be automatically
  4024. * calculated, either starting at 0 and incremented by 1, or from
  4025. * `pointStart` and `pointInterval` given in the series options. If the axis
  4026. * has categories, these will be used. Example:
  4027. * ```js
  4028. * data: [0, 5, 3, 5]
  4029. * ```
  4030. *
  4031. * 2. An array of arrays with 2 values. In this case, the values correspond to
  4032. * `x,y`. If the first value is a string, it is applied as the name of the
  4033. * point, and the `x` value is inferred.
  4034. * ```js
  4035. * data: [
  4036. * [0, 7],
  4037. * [1, 8],
  4038. * [2, 3]
  4039. * ]
  4040. * ```
  4041. *
  4042. * 3. An array of objects with named values. The following snippet shows only a
  4043. * few settings, see the complete options set below. If the total number of
  4044. * data points exceeds the series'
  4045. * [turboThreshold](#series.waterfall.turboThreshold), this option is not
  4046. * available.
  4047. * ```js
  4048. * data: [{
  4049. * x: 1,
  4050. * y: 8,
  4051. * name: "Point2",
  4052. * color: "#00FF00"
  4053. * }, {
  4054. * x: 1,
  4055. * y: 8,
  4056. * name: "Point1",
  4057. * color: "#FF00FF"
  4058. * }]
  4059. * ```
  4060. *
  4061. * @sample {highcharts} highcharts/chart/reflow-true/
  4062. * Numerical values
  4063. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  4064. * Arrays of numeric x and y
  4065. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  4066. * Arrays of datetime x and y
  4067. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  4068. * Arrays of point.name and y
  4069. * @sample {highcharts} highcharts/series/data-array-of-objects/
  4070. * Config objects
  4071. *
  4072. * @type {Array<number|Array<(number|string),number>|*>}
  4073. * @extends series.line.data
  4074. * @excluding marker
  4075. * @product highcharts
  4076. * @apioption series.waterfall.data
  4077. */
  4078. /**
  4079. * When this property is true, the points acts as a summary column for
  4080. * the values added or substracted since the last intermediate sum,
  4081. * or since the start of the series. The `y` value is ignored.
  4082. *
  4083. * @sample {highcharts} highcharts/demo/waterfall/
  4084. * Waterfall
  4085. *
  4086. * @type {boolean}
  4087. * @default false
  4088. * @product highcharts
  4089. * @apioption series.waterfall.data.isIntermediateSum
  4090. */
  4091. /**
  4092. * When this property is true, the point display the total sum across
  4093. * the entire series. The `y` value is ignored.
  4094. *
  4095. * @sample {highcharts} highcharts/demo/waterfall/
  4096. * Waterfall
  4097. *
  4098. * @type {boolean}
  4099. * @default false
  4100. * @product highcharts
  4101. * @apioption series.waterfall.data.isSum
  4102. */
  4103. }(Highcharts));
  4104. (function (H) {
  4105. /* *
  4106. * (c) 2010-2019 Torstein Honsi
  4107. *
  4108. * License: www.highcharts.com/license
  4109. */
  4110. var LegendSymbolMixin = H.LegendSymbolMixin,
  4111. noop = H.noop,
  4112. Series = H.Series,
  4113. seriesType = H.seriesType,
  4114. seriesTypes = H.seriesTypes;
  4115. /**
  4116. * A polygon series can be used to draw any freeform shape in the cartesian
  4117. * coordinate system. A fill is applied with the `color` option, and
  4118. * stroke is applied through `lineWidth` and `lineColor` options. Requires
  4119. * the `highcharts-more.js` file.
  4120. *
  4121. * @sample {highcharts} highcharts/demo/polygon/
  4122. * Polygon
  4123. * @sample {highstock} highcharts/demo/polygon/
  4124. * Polygon
  4125. *
  4126. * @extends plotOptions.scatter
  4127. * @since 4.1.0
  4128. * @excluding jitter, softThreshold, threshold
  4129. * @product highcharts highstock
  4130. * @optionparent plotOptions.polygon
  4131. */
  4132. seriesType('polygon', 'scatter', {
  4133. marker: {
  4134. enabled: false,
  4135. states: {
  4136. hover: {
  4137. enabled: false
  4138. }
  4139. }
  4140. },
  4141. stickyTracking: false,
  4142. tooltip: {
  4143. followPointer: true,
  4144. pointFormat: ''
  4145. },
  4146. trackByArea: true
  4147. // Prototype members
  4148. }, {
  4149. type: 'polygon',
  4150. getGraphPath: function () {
  4151. var graphPath = Series.prototype.getGraphPath.call(this),
  4152. i = graphPath.length + 1;
  4153. // Close all segments
  4154. while (i--) {
  4155. if ((i === graphPath.length || graphPath[i] === 'M') && i > 0) {
  4156. graphPath.splice(i, 0, 'z');
  4157. }
  4158. }
  4159. this.areaPath = graphPath;
  4160. return graphPath;
  4161. },
  4162. drawGraph: function () {
  4163. // Hack into the fill logic in area.drawGraph
  4164. this.options.fillColor = this.color;
  4165. seriesTypes.area.prototype.drawGraph.call(this);
  4166. },
  4167. drawLegendSymbol: LegendSymbolMixin.drawRectangle,
  4168. drawTracker: Series.prototype.drawTracker,
  4169. setStackedPoints: noop // No stacking points on polygons (#5310)
  4170. });
  4171. /**
  4172. * A `polygon` series. If the [type](#series.polygon.type) option is
  4173. * not specified, it is inherited from [chart.type](#chart.type).
  4174. *
  4175. * @extends series,plotOptions.polygon
  4176. * @excluding dataParser, dataURL, stack
  4177. * @product highcharts highstock
  4178. * @apioption series.polygon
  4179. */
  4180. /**
  4181. * An array of data points for the series. For the `polygon` series
  4182. * type, points can be given in the following ways:
  4183. *
  4184. * 1. An array of numerical values. In this case, the numerical values will be
  4185. * interpreted as `y` options. The `x` values will be automatically
  4186. * calculated, either starting at 0 and incremented by 1, or from
  4187. * `pointStart` and `pointInterval` given in the series options. If the axis
  4188. * has categories, these will be used. Example:
  4189. * ```js
  4190. * data: [0, 5, 3, 5]
  4191. * ```
  4192. *
  4193. * 2. An array of arrays with 2 values. In this case, the values correspond to
  4194. * `x,y`. If the first value is a string, it is applied as the name of the
  4195. * point, and the `x` value is inferred.
  4196. * ```js
  4197. * data: [
  4198. * [0, 10],
  4199. * [1, 3],
  4200. * [2, 1]
  4201. * ]
  4202. * ```
  4203. *
  4204. * 3. An array of objects with named values. The following snippet shows only a
  4205. * few settings, see the complete options set below. If the total number of
  4206. * data points exceeds the series'
  4207. * [turboThreshold](#series.polygon.turboThreshold), this option is not
  4208. * available.
  4209. * ```js
  4210. * data: [{
  4211. * x: 1,
  4212. * y: 1,
  4213. * name: "Point2",
  4214. * color: "#00FF00"
  4215. * }, {
  4216. * x: 1,
  4217. * y: 8,
  4218. * name: "Point1",
  4219. * color: "#FF00FF"
  4220. * }]
  4221. * ```
  4222. *
  4223. * @sample {highcharts} highcharts/chart/reflow-true/
  4224. * Numerical values
  4225. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  4226. * Arrays of numeric x and y
  4227. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  4228. * Arrays of datetime x and y
  4229. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  4230. * Arrays of point.name and y
  4231. * @sample {highcharts} highcharts/series/data-array-of-objects/
  4232. * Config objects
  4233. *
  4234. * @type {Array<number|Array<(number|string),number>|*>}
  4235. * @extends series.line.data
  4236. * @product highcharts highstock
  4237. * @apioption series.polygon.data
  4238. */
  4239. }(Highcharts));
  4240. (function (H) {
  4241. /* *
  4242. * (c) 2010-2019 Highsoft AS
  4243. *
  4244. * Author: Paweł Potaczek
  4245. *
  4246. * License: www.highcharts.com/license
  4247. */
  4248. /**
  4249. * @interface Highcharts.LegendBubbleLegendFormatterContextObject
  4250. *//**
  4251. * The center y position of the range.
  4252. * @name Highcharts.LegendBubbleLegendFormatterContextObject#center
  4253. * @type {number}
  4254. *//**
  4255. * The radius of the bubble range.
  4256. * @name Highcharts.LegendBubbleLegendFormatterContextObject#radius
  4257. * @type {number}
  4258. *//**
  4259. * The bubble value.
  4260. * @name Highcharts.LegendBubbleLegendFormatterContextObject#value
  4261. * @type {number}
  4262. */
  4263. var Series = H.Series,
  4264. Legend = H.Legend,
  4265. Chart = H.Chart,
  4266. addEvent = H.addEvent,
  4267. wrap = H.wrap,
  4268. color = H.color,
  4269. isNumber = H.isNumber,
  4270. numberFormat = H.numberFormat,
  4271. objectEach = H.objectEach,
  4272. merge = H.merge,
  4273. noop = H.noop,
  4274. pick = H.pick,
  4275. stableSort = H.stableSort,
  4276. setOptions = H.setOptions,
  4277. arrayMin = H.arrayMin,
  4278. arrayMax = H.arrayMax;
  4279. setOptions({ // Set default bubble legend options
  4280. legend: {
  4281. /**
  4282. * The bubble legend is an additional element in legend which presents
  4283. * the scale of the bubble series. Individual bubble ranges can be
  4284. * defined by user or calculated from series. In the case of
  4285. * automatically calculated ranges, a 1px margin of error is permitted.
  4286. * Requires `highcharts-more.js`.
  4287. *
  4288. * @since 7.0.0
  4289. * @product highcharts highstock highmaps
  4290. * @optionparent legend.bubbleLegend
  4291. */
  4292. bubbleLegend: {
  4293. /**
  4294. * The color of the ranges borders, can be also defined for an
  4295. * individual range.
  4296. *
  4297. * @sample highcharts/bubble-legend/similartoseries/
  4298. * Similat look to the bubble series
  4299. * @sample highcharts/bubble-legend/bordercolor/
  4300. * Individual bubble border color
  4301. *
  4302. * @type {Highcharts.ColorString}
  4303. */
  4304. borderColor: undefined,
  4305. /**
  4306. * The width of the ranges borders in pixels, can be also defined
  4307. * for an individual range.
  4308. */
  4309. borderWidth: 2,
  4310. /**
  4311. * An additional class name to apply to the bubble legend' circle
  4312. * graphical elements. This option does not replace default class
  4313. * names of the graphical element.
  4314. *
  4315. * @sample {highcharts} highcharts/css/bubble-legend/
  4316. * Styling by CSS
  4317. *
  4318. * @type {string}
  4319. */
  4320. className: undefined,
  4321. /**
  4322. * The main color of the bubble legend. Applies to ranges, if
  4323. * individual color is not defined.
  4324. *
  4325. * @sample highcharts/bubble-legend/similartoseries/
  4326. * Similat look to the bubble series
  4327. * @sample highcharts/bubble-legend/color/
  4328. * Individual bubble color
  4329. *
  4330. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  4331. */
  4332. color: undefined,
  4333. /**
  4334. * An additional class name to apply to the bubble legend's
  4335. * connector graphical elements. This option does not replace
  4336. * default class names of the graphical element.
  4337. *
  4338. * @sample {highcharts} highcharts/css/bubble-legend/
  4339. * Styling by CSS
  4340. *
  4341. * @type {string}
  4342. */
  4343. connectorClassName: undefined,
  4344. /**
  4345. * The color of the connector, can be also defined
  4346. * for an individual range.
  4347. *
  4348. * @type {Highcharts.ColorString}
  4349. */
  4350. connectorColor: undefined,
  4351. /**
  4352. * The length of the connectors in pixels. If labels are centered,
  4353. * the distance is reduced to 0.
  4354. *
  4355. * @sample highcharts/bubble-legend/connectorandlabels/
  4356. * Increased connector length
  4357. */
  4358. connectorDistance: 60,
  4359. /**
  4360. * The width of the connectors in pixels.
  4361. *
  4362. * @sample highcharts/bubble-legend/connectorandlabels/
  4363. * Increased connector width
  4364. */
  4365. connectorWidth: 1,
  4366. /**
  4367. * Enable or disable the bubble legend.
  4368. */
  4369. enabled: false,
  4370. /**
  4371. * Options for the bubble legend labels.
  4372. */
  4373. labels: {
  4374. /**
  4375. * An additional class name to apply to the bubble legend
  4376. * label graphical elements. This option does not replace
  4377. * default class names of the graphical element.
  4378. *
  4379. * @sample {highcharts} highcharts/css/bubble-legend/
  4380. * Styling by CSS
  4381. *
  4382. * @type {string}
  4383. */
  4384. className: undefined,
  4385. /**
  4386. * Whether to allow data labels to overlap.
  4387. */
  4388. allowOverlap: false,
  4389. /**
  4390. * A [format string](http://docs.highcharts.com/#formatting)
  4391. * for the bubble legend labels. Available variables are the
  4392. * same as for `formatter`.
  4393. *
  4394. * @sample highcharts/bubble-legend/format/
  4395. * Add a unit
  4396. *
  4397. * @type {string}
  4398. */
  4399. format: '',
  4400. /**
  4401. * Available `this` properties are:
  4402. *
  4403. * - `this.value`: The bubble value.
  4404. *
  4405. * - `this.radius`: The radius of the bubble range.
  4406. *
  4407. * - `this.center`: The center y position of the range.
  4408. *
  4409. * @type {Highcharts.FormatterCallbackFunction<Highcharts.LegendBubbleLegendFormatterContextObject>}
  4410. */
  4411. formatter: undefined,
  4412. /**
  4413. * The alignment of the labels compared to the bubble legend.
  4414. * Can be one of `left`, `center` or `right`.
  4415. * @validvalue ["left", "center", "right"]
  4416. *
  4417. * @sample highcharts/bubble-legend/connectorandlabels/
  4418. * Labels on left
  4419. *
  4420. * @validvalue ["left", "center", "right"]
  4421. */
  4422. align: 'right',
  4423. /**
  4424. * CSS styles for the labels.
  4425. *
  4426. * @type {Highcharts.CSSObject}
  4427. */
  4428. style: {
  4429. /** @ignore-option */
  4430. fontSize: 10,
  4431. /** @ignore-option */
  4432. color: undefined
  4433. },
  4434. /**
  4435. * The x position offset of the label relative to the
  4436. * connector.
  4437. */
  4438. x: 0,
  4439. /**
  4440. * The y position offset of the label relative to the
  4441. * connector.
  4442. */
  4443. y: 0
  4444. },
  4445. /**
  4446. * Miximum bubble legend range size. If values for ranges are not
  4447. * specified, the `minSize` and the `maxSize` are calculated from
  4448. * bubble series.
  4449. */
  4450. maxSize: 60, // Number
  4451. /**
  4452. * Minimum bubble legend range size. If values for ranges are not
  4453. * specified, the `minSize` and the `maxSize` are calculated from
  4454. * bubble series.
  4455. */
  4456. minSize: 10, // Number
  4457. /**
  4458. * The position of the bubble legend in the legend.
  4459. * @sample highcharts/bubble-legend/connectorandlabels/
  4460. * Bubble legend as last item in legend
  4461. */
  4462. legendIndex: 0, // Number
  4463. /**
  4464. * Options for specific range. One range consists of bubble, label
  4465. * and connector.
  4466. *
  4467. * @sample highcharts/bubble-legend/ranges/
  4468. * Manually defined ranges
  4469. * @sample highcharts/bubble-legend/autoranges/
  4470. * Auto calculated ranges
  4471. *
  4472. * @type {Array<*>}
  4473. */
  4474. ranges: {
  4475. /**
  4476. * Range size value, similar to bubble Z data.
  4477. */
  4478. value: undefined,
  4479. /**
  4480. * The color of the border for individual range.
  4481. * @type {Highcharts.ColorString}
  4482. */
  4483. borderColor: undefined,
  4484. /**
  4485. * The color of the bubble for individual range.
  4486. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  4487. */
  4488. color: undefined,
  4489. /**
  4490. * The color of the connector for individual range.
  4491. * @type {Highcharts.ColorString}
  4492. */
  4493. connectorColor: undefined
  4494. },
  4495. /**
  4496. * Whether the bubble legend range value should be represented by
  4497. * the area or the width of the bubble. The default, area,
  4498. * corresponds best to the human perception of the size of each
  4499. * bubble.
  4500. *
  4501. * @sample highcharts/bubble-legend/ranges/
  4502. * Size by width
  4503. *
  4504. * @validvalue ["area", "width"]
  4505. */
  4506. sizeBy: 'area',
  4507. /**
  4508. * When this is true, the absolute value of z determines the size of
  4509. * the bubble. This means that with the default zThreshold of 0, a
  4510. * bubble of value -1 will have the same size as a bubble of value
  4511. * 1, while a bubble of value 0 will have a smaller size according
  4512. * to minSize.
  4513. */
  4514. sizeByAbsoluteValue: false,
  4515. /**
  4516. * Define the visual z index of the bubble legend.
  4517. */
  4518. zIndex: 1,
  4519. /**
  4520. * Ranges with with lower value than zThreshold, are skipped.
  4521. */
  4522. zThreshold: 0
  4523. }
  4524. }
  4525. });
  4526. /**
  4527. * BubbleLegend class.
  4528. *
  4529. * @private
  4530. * @class
  4531. * @name Highcharts.BubbleLegend
  4532. *
  4533. * @param {Highcharts.LegendBubbleLegendOptions} config
  4534. * Bubble legend options
  4535. *
  4536. * @param {Highcharts.LegendOptions} config
  4537. * Legend options
  4538. */
  4539. H.BubbleLegend = function (options, legend) {
  4540. this.init(options, legend);
  4541. };
  4542. H.BubbleLegend.prototype = {
  4543. /**
  4544. * Create basic bubbleLegend properties similar to item in legend.
  4545. *
  4546. * @private
  4547. * @function Highcharts.BubbleLegend#init
  4548. *
  4549. * @param {Highcharts.LegendBubbleLegendOptions} config
  4550. * Bubble legend options
  4551. *
  4552. * @param {Highcharts.LegendOptions} config
  4553. * Legend options
  4554. */
  4555. init: function (options, legend) {
  4556. this.options = options;
  4557. this.visible = true;
  4558. this.chart = legend.chart;
  4559. this.legend = legend;
  4560. },
  4561. setState: noop,
  4562. /**
  4563. * Depending on the position option, add bubbleLegend to legend items.
  4564. *
  4565. * @private
  4566. * @function Highcharts.BubbleLegend#addToLegend
  4567. *
  4568. * @param {Array<*>}
  4569. * All legend items
  4570. */
  4571. addToLegend: function (items) {
  4572. // Insert bubbleLegend into legend items
  4573. items.splice(this.options.legendIndex, 0, this);
  4574. },
  4575. /**
  4576. * Calculate ranges, sizes and call the next steps of bubbleLegend creation.
  4577. *
  4578. * @private
  4579. * @function Highcharts.BubbleLegend#drawLegendSymbol
  4580. *
  4581. * @param {Highcharts.Legend} legend
  4582. * Legend instance
  4583. */
  4584. drawLegendSymbol: function (legend) {
  4585. var bubbleLegend = this,
  4586. chart = bubbleLegend.chart,
  4587. options = bubbleLegend.options,
  4588. size,
  4589. itemDistance = pick(legend.options.itemDistance, 20),
  4590. connectorSpace,
  4591. ranges = options.ranges,
  4592. radius,
  4593. maxLabel,
  4594. connectorDistance = options.connectorDistance;
  4595. // Predict label dimensions
  4596. bubbleLegend.fontMetrics = chart.renderer.fontMetrics(
  4597. options.labels.style.fontSize.toString() + 'px'
  4598. );
  4599. // Do not create bubbleLegend now if ranges or ranges valeus are not
  4600. // specified or if are empty array.
  4601. if (!ranges || !ranges.length || !isNumber(ranges[0].value)) {
  4602. legend.options.bubbleLegend.autoRanges = true;
  4603. return;
  4604. }
  4605. // Sort ranges to right render order
  4606. stableSort(ranges, function (a, b) {
  4607. return b.value - a.value;
  4608. });
  4609. bubbleLegend.ranges = ranges;
  4610. bubbleLegend.setOptions();
  4611. bubbleLegend.render();
  4612. // Get max label size
  4613. maxLabel = bubbleLegend.getMaxLabelSize();
  4614. radius = bubbleLegend.ranges[0].radius;
  4615. size = radius * 2;
  4616. // Space for connectors and labels.
  4617. connectorSpace = connectorDistance - radius + maxLabel.width;
  4618. connectorSpace = connectorSpace > 0 ? connectorSpace : 0;
  4619. bubbleLegend.maxLabel = maxLabel;
  4620. bubbleLegend.movementX = options.labels.align === 'left' ?
  4621. connectorSpace : 0;
  4622. bubbleLegend.legendItemWidth = size + connectorSpace + itemDistance;
  4623. bubbleLegend.legendItemHeight = size + bubbleLegend.fontMetrics.h / 2;
  4624. },
  4625. /**
  4626. * Set style options for each bubbleLegend range.
  4627. *
  4628. * @private
  4629. * @function Highcharts.BubbleLegend#setOptions
  4630. */
  4631. setOptions: function () {
  4632. var bubbleLegend = this,
  4633. ranges = bubbleLegend.ranges,
  4634. options = bubbleLegend.options,
  4635. series = bubbleLegend.chart.series[options.seriesIndex],
  4636. baseline = bubbleLegend.legend.baseline,
  4637. bubbleStyle = {
  4638. 'z-index': options.zIndex,
  4639. 'stroke-width': options.borderWidth
  4640. },
  4641. connectorStyle = {
  4642. 'z-index': options.zIndex,
  4643. 'stroke-width': options.connectorWidth
  4644. },
  4645. labelStyle = bubbleLegend.getLabelStyles(),
  4646. fillOpacity = series.options.marker.fillOpacity,
  4647. styledMode = bubbleLegend.chart.styledMode;
  4648. // Allow to parts of styles be used individually for range
  4649. ranges.forEach(function (range, i) {
  4650. if (!styledMode) {
  4651. bubbleStyle.stroke = pick(
  4652. range.borderColor,
  4653. options.borderColor,
  4654. series.color
  4655. );
  4656. bubbleStyle.fill = pick(
  4657. range.color,
  4658. options.color,
  4659. fillOpacity !== 1 ?
  4660. color(series.color).setOpacity(fillOpacity)
  4661. .get('rgba') :
  4662. series.color
  4663. );
  4664. connectorStyle.stroke = pick(
  4665. range.connectorColor,
  4666. options.connectorColor,
  4667. series.color
  4668. );
  4669. }
  4670. // Set options needed for rendering each range
  4671. ranges[i].radius = bubbleLegend.getRangeRadius(range.value);
  4672. ranges[i] = merge(ranges[i], {
  4673. center: ranges[0].radius - ranges[i].radius + baseline
  4674. });
  4675. if (!styledMode) {
  4676. merge(true, ranges[i], {
  4677. bubbleStyle: merge(false, bubbleStyle),
  4678. connectorStyle: merge(false, connectorStyle),
  4679. labelStyle: labelStyle
  4680. });
  4681. }
  4682. });
  4683. },
  4684. /**
  4685. * Merge options for bubbleLegend labels.
  4686. *
  4687. * @private
  4688. * @function Highcharts.BubbleLegend#getLabelStyles
  4689. */
  4690. getLabelStyles: function () {
  4691. var options = this.options,
  4692. additionalLabelsStyle = {},
  4693. labelsOnLeft = options.labels.align === 'left',
  4694. rtl = this.legend.options.rtl;
  4695. // To separate additional style options
  4696. objectEach(options.labels.style, function (value, key) {
  4697. if (key !== 'color' && key !== 'fontSize' && key !== 'z-index') {
  4698. additionalLabelsStyle[key] = value;
  4699. }
  4700. });
  4701. return merge(false, additionalLabelsStyle, {
  4702. 'font-size': options.labels.style.fontSize,
  4703. fill: pick(
  4704. options.labels.style.color,
  4705. '#000000'
  4706. ),
  4707. 'z-index': options.zIndex,
  4708. align: rtl || labelsOnLeft ? 'right' : 'left'
  4709. });
  4710. },
  4711. /**
  4712. * Calculate radius for each bubble range,
  4713. * used code from BubbleSeries.js 'getRadius' method.
  4714. *
  4715. * @private
  4716. * @function Highcharts.BubbleLegend#getRangeRadius
  4717. *
  4718. * @param {number} value
  4719. * Range value
  4720. *
  4721. * @return {number}
  4722. * Radius for one range
  4723. */
  4724. getRangeRadius: function (value) {
  4725. var bubbleLegend = this,
  4726. options = bubbleLegend.options,
  4727. seriesIndex = bubbleLegend.options.seriesIndex,
  4728. bubbleSeries = bubbleLegend.chart.series[seriesIndex],
  4729. zMax = options.ranges[0].value,
  4730. zMin = options.ranges[options.ranges.length - 1].value,
  4731. minSize = options.minSize,
  4732. maxSize = options.maxSize;
  4733. return bubbleSeries.getRadius.call(
  4734. this,
  4735. zMin,
  4736. zMax,
  4737. minSize,
  4738. maxSize,
  4739. value
  4740. );
  4741. },
  4742. /**
  4743. * Render the legendSymbol group.
  4744. *
  4745. * @private
  4746. * @function Highcharts.BubbleLegend#render
  4747. */
  4748. render: function () {
  4749. var bubbleLegend = this,
  4750. renderer = bubbleLegend.chart.renderer,
  4751. zThreshold = bubbleLegend.options.zThreshold;
  4752. if (!bubbleLegend.symbols) {
  4753. bubbleLegend.symbols = {
  4754. connectors: [],
  4755. bubbleItems: [],
  4756. labels: []
  4757. };
  4758. }
  4759. // Nesting SVG groups to enable handleOverflow
  4760. bubbleLegend.legendSymbol = renderer.g('bubble-legend');
  4761. bubbleLegend.legendItem = renderer.g('bubble-legend-item');
  4762. // To enable default 'hideOverlappingLabels' method
  4763. bubbleLegend.legendSymbol.translateX = 0;
  4764. bubbleLegend.legendSymbol.translateY = 0;
  4765. bubbleLegend.ranges.forEach(function (range) {
  4766. if (range.value >= zThreshold) {
  4767. bubbleLegend.renderRange(range);
  4768. }
  4769. });
  4770. // To use handleOverflow method
  4771. bubbleLegend.legendSymbol.add(bubbleLegend.legendItem);
  4772. bubbleLegend.legendItem.add(bubbleLegend.legendGroup);
  4773. bubbleLegend.hideOverlappingLabels();
  4774. },
  4775. /**
  4776. * Render one range, consisting of bubble symbol, connector and label.
  4777. *
  4778. * @private
  4779. * @function Highcharts.BubbleLegend#renderRange
  4780. *
  4781. * @param {Highcharts.LegendBubbleLegendRangesOptions} config
  4782. * Range options
  4783. *
  4784. * @private
  4785. */
  4786. renderRange: function (range) {
  4787. var bubbleLegend = this,
  4788. mainRange = bubbleLegend.ranges[0],
  4789. legend = bubbleLegend.legend,
  4790. options = bubbleLegend.options,
  4791. labelsOptions = options.labels,
  4792. chart = bubbleLegend.chart,
  4793. renderer = chart.renderer,
  4794. symbols = bubbleLegend.symbols,
  4795. labels = symbols.labels,
  4796. label,
  4797. elementCenter = range.center,
  4798. absoluteRadius = Math.abs(range.radius),
  4799. connectorDistance = options.connectorDistance,
  4800. labelsAlign = labelsOptions.align,
  4801. rtl = legend.options.rtl,
  4802. fontSize = labelsOptions.style.fontSize,
  4803. connectorLength = rtl || labelsAlign === 'left' ?
  4804. -connectorDistance : connectorDistance,
  4805. borderWidth = options.borderWidth,
  4806. connectorWidth = options.connectorWidth,
  4807. posX = mainRange.radius,
  4808. posY = elementCenter - absoluteRadius - borderWidth / 2 +
  4809. connectorWidth / 2,
  4810. labelY,
  4811. labelX,
  4812. fontMetrics = bubbleLegend.fontMetrics,
  4813. labelMovement = fontSize / 2 - (fontMetrics.h - fontSize) / 2,
  4814. crispMovement = (posY % 1 ? 1 : 0.5) -
  4815. (connectorWidth % 2 ? 0 : 0.5),
  4816. styledMode = renderer.styledMode;
  4817. // Set options for centered labels
  4818. if (labelsAlign === 'center') {
  4819. connectorLength = 0; // do not use connector
  4820. options.connectorDistance = 0;
  4821. range.labelStyle.align = 'center';
  4822. }
  4823. labelY = posY + options.labels.y;
  4824. labelX = posX + connectorLength + options.labels.x;
  4825. // Render bubble symbol
  4826. symbols.bubbleItems.push(
  4827. renderer
  4828. .circle(
  4829. posX,
  4830. elementCenter + crispMovement,
  4831. absoluteRadius
  4832. )
  4833. .attr(
  4834. styledMode ? {} : range.bubbleStyle
  4835. )
  4836. .addClass(
  4837. (
  4838. styledMode ?
  4839. 'highcharts-color-' +
  4840. bubbleLegend.options.seriesIndex + ' ' :
  4841. ''
  4842. ) +
  4843. 'highcharts-bubble-legend-symbol ' +
  4844. (options.className || '')
  4845. ).add(
  4846. bubbleLegend.legendSymbol
  4847. )
  4848. );
  4849. // Render connector
  4850. symbols.connectors.push(
  4851. renderer
  4852. .path(renderer.crispLine(
  4853. ['M', posX, posY, 'L', posX + connectorLength, posY],
  4854. options.connectorWidth
  4855. ))
  4856. .attr(
  4857. styledMode ? {} : range.connectorStyle
  4858. )
  4859. .addClass(
  4860. (
  4861. styledMode ?
  4862. 'highcharts-color-' +
  4863. bubbleLegend.options.seriesIndex + ' ' :
  4864. ''
  4865. ) +
  4866. 'highcharts-bubble-legend-connectors ' +
  4867. (options.connectorClassName || '')
  4868. ).add(
  4869. bubbleLegend.legendSymbol
  4870. )
  4871. );
  4872. // Render label
  4873. label = renderer
  4874. .text(
  4875. bubbleLegend.formatLabel(range),
  4876. labelX,
  4877. labelY + labelMovement
  4878. )
  4879. .attr(
  4880. styledMode ? {} : range.labelStyle
  4881. )
  4882. .addClass(
  4883. 'highcharts-bubble-legend-labels ' +
  4884. (options.labels.className || '')
  4885. ).add(
  4886. bubbleLegend.legendSymbol
  4887. );
  4888. labels.push(label);
  4889. // To enable default 'hideOverlappingLabels' method
  4890. label.placed = true;
  4891. label.alignAttr = {
  4892. x: labelX,
  4893. y: labelY + labelMovement
  4894. };
  4895. },
  4896. /**
  4897. * Get the label which takes up the most space.
  4898. *
  4899. * @private
  4900. * @function Highcharts.BubbleLegend#getMaxLabelSize
  4901. */
  4902. getMaxLabelSize: function () {
  4903. var labels = this.symbols.labels,
  4904. maxLabel,
  4905. labelSize;
  4906. labels.forEach(function (label) {
  4907. labelSize = label.getBBox(true);
  4908. if (maxLabel) {
  4909. maxLabel = labelSize.width > maxLabel.width ?
  4910. labelSize : maxLabel;
  4911. } else {
  4912. maxLabel = labelSize;
  4913. }
  4914. });
  4915. return maxLabel || {};
  4916. },
  4917. /**
  4918. * Get formatted label for range.
  4919. *
  4920. * @private
  4921. * @function Highcharts.BubbleLegend#formatLabel
  4922. *
  4923. * @param {Highcharts.LegendBubbleLegendRangesOptions} range
  4924. * Range options
  4925. *
  4926. * @return {string}
  4927. * Range label text
  4928. */
  4929. formatLabel: function (range) {
  4930. var options = this.options,
  4931. formatter = options.labels.formatter,
  4932. format = options.labels.format;
  4933. return format ? H.format(format, range) :
  4934. formatter ? formatter.call(range) :
  4935. numberFormat(range.value, 1);
  4936. },
  4937. /**
  4938. * By using default chart 'hideOverlappingLabels' method, hide or show
  4939. * labels and connectors.
  4940. *
  4941. * @private
  4942. * @function Highcharts.BubbleLegend#hideOverlappingLabels
  4943. */
  4944. hideOverlappingLabels: function () {
  4945. var bubbleLegend = this,
  4946. chart = this.chart,
  4947. allowOverlap = bubbleLegend.options.labels.allowOverlap,
  4948. symbols = bubbleLegend.symbols;
  4949. if (!allowOverlap && symbols) {
  4950. chart.hideOverlappingLabels(symbols.labels);
  4951. // Hide or show connectors
  4952. symbols.labels.forEach(function (label, index) {
  4953. if (!label.newOpacity) {
  4954. symbols.connectors[index].hide();
  4955. } else if (label.newOpacity !== label.oldOpacity) {
  4956. symbols.connectors[index].show();
  4957. }
  4958. });
  4959. }
  4960. },
  4961. /**
  4962. * Calculate ranges from created series.
  4963. *
  4964. * @private
  4965. * @function Highcharts.BubbleLegend#getRanges
  4966. *
  4967. * @return {Array<Highcharts.LegendBubbleLegendRangesOptions>}
  4968. * Array of range objects
  4969. */
  4970. getRanges: function () {
  4971. var bubbleLegend = this.legend.bubbleLegend,
  4972. series = bubbleLegend.chart.series,
  4973. ranges,
  4974. rangesOptions = bubbleLegend.options.ranges,
  4975. zData,
  4976. minZ = Number.MAX_VALUE,
  4977. maxZ = -Number.MAX_VALUE;
  4978. series.forEach(function (s) {
  4979. // Find the min and max Z, like in bubble series
  4980. if (s.isBubble && !s.ignoreSeries) {
  4981. zData = s.zData.filter(isNumber);
  4982. if (zData.length) {
  4983. minZ = pick(s.options.zMin, Math.min(
  4984. minZ,
  4985. Math.max(
  4986. arrayMin(zData),
  4987. s.options.displayNegative === false ?
  4988. s.options.zThreshold :
  4989. -Number.MAX_VALUE
  4990. )
  4991. ));
  4992. maxZ = pick(
  4993. s.options.zMax,
  4994. Math.max(maxZ, arrayMax(zData))
  4995. );
  4996. }
  4997. }
  4998. });
  4999. // Set values for ranges
  5000. if (minZ === maxZ) {
  5001. // Only one range if min and max values are the same.
  5002. ranges = [{ value: maxZ }];
  5003. } else {
  5004. ranges = [
  5005. { value: minZ },
  5006. { value: (minZ + maxZ) / 2 },
  5007. { value: maxZ, autoRanges: true }
  5008. ];
  5009. }
  5010. // Prevent reverse order of ranges after redraw
  5011. if (rangesOptions.length && rangesOptions[0].radius) {
  5012. ranges.reverse();
  5013. }
  5014. // Merge ranges values with user options
  5015. ranges.forEach(function (range, i) {
  5016. if (rangesOptions && rangesOptions[i]) {
  5017. ranges[i] = merge(false, rangesOptions[i], range);
  5018. }
  5019. });
  5020. return ranges;
  5021. },
  5022. /**
  5023. * Calculate bubble legend sizes from rendered series.
  5024. *
  5025. * @private
  5026. * @function Highcharts.BubbleLegend#predictBubbleSizes
  5027. *
  5028. * @return {Array<number,number>}
  5029. * Calculated min and max bubble sizes
  5030. */
  5031. predictBubbleSizes: function () {
  5032. var chart = this.chart,
  5033. fontMetrics = this.fontMetrics,
  5034. legendOptions = chart.legend.options,
  5035. floating = legendOptions.floating,
  5036. horizontal = legendOptions.layout === 'horizontal',
  5037. lastLineHeight = horizontal ? chart.legend.lastLineHeight : 0,
  5038. plotSizeX = chart.plotSizeX,
  5039. plotSizeY = chart.plotSizeY,
  5040. bubbleSeries = chart.series[this.options.seriesIndex],
  5041. minSize = Math.ceil(bubbleSeries.minPxSize),
  5042. maxPxSize = Math.ceil(bubbleSeries.maxPxSize),
  5043. maxSize = bubbleSeries.options.maxSize,
  5044. plotSize = Math.min(plotSizeY, plotSizeX),
  5045. calculatedSize;
  5046. // Calculate prediceted max size of bubble
  5047. if (floating || !(/%$/.test(maxSize))) {
  5048. calculatedSize = maxPxSize;
  5049. } else {
  5050. maxSize = parseFloat(maxSize);
  5051. calculatedSize = ((plotSize + lastLineHeight - fontMetrics.h / 2) *
  5052. maxSize / 100) / (maxSize / 100 + 1);
  5053. // Get maxPxSize from bubble series if calculated bubble legend
  5054. // size will not affect to bubbles series.
  5055. if (
  5056. (horizontal && plotSizeY - calculatedSize >=
  5057. plotSizeX) || (!horizontal && plotSizeX -
  5058. calculatedSize >= plotSizeY)
  5059. ) {
  5060. calculatedSize = maxPxSize;
  5061. }
  5062. }
  5063. return [minSize, Math.ceil(calculatedSize)];
  5064. },
  5065. /**
  5066. * Correct ranges with calculated sizes.
  5067. *
  5068. * @private
  5069. * @function Highcharts.BubbleLegend#updateRanges
  5070. *
  5071. * @param {number} min
  5072. *
  5073. * @param {number} max
  5074. */
  5075. updateRanges: function (min, max) {
  5076. var bubbleLegendOptions = this.legend.options.bubbleLegend;
  5077. bubbleLegendOptions.minSize = min;
  5078. bubbleLegendOptions.maxSize = max;
  5079. bubbleLegendOptions.ranges = this.getRanges();
  5080. },
  5081. /**
  5082. * Because of the possibility of creating another legend line, predicted
  5083. * bubble legend sizes may differ by a few pixels, so it is necessary to
  5084. * correct them.
  5085. *
  5086. * @private
  5087. * @function Highcharts.BubbleLegend#correctSizes
  5088. */
  5089. correctSizes: function () {
  5090. var legend = this.legend,
  5091. chart = this.chart,
  5092. bubbleSeries = chart.series[this.options.seriesIndex],
  5093. bubbleSeriesSize = bubbleSeries.maxPxSize,
  5094. bubbleLegendSize = this.options.maxSize;
  5095. if (Math.abs(Math.ceil(bubbleSeriesSize) - bubbleLegendSize) > 1) {
  5096. this.updateRanges(this.options.minSize, bubbleSeries.maxPxSize);
  5097. legend.render();
  5098. }
  5099. }
  5100. };
  5101. // Start the bubble legend creation process.
  5102. addEvent(H.Legend, 'afterGetAllItems', function (e) {
  5103. var legend = this,
  5104. bubbleLegend = legend.bubbleLegend,
  5105. legendOptions = legend.options,
  5106. options = legendOptions.bubbleLegend,
  5107. bubbleSeriesIndex = legend.chart.getVisibleBubbleSeriesIndex();
  5108. // Remove unnecessary element
  5109. if (bubbleLegend && bubbleLegend.ranges && bubbleLegend.ranges.length) {
  5110. // Allow change the way of calculating ranges in update
  5111. if (options.ranges.length) {
  5112. options.autoRanges = !!options.ranges[0].autoRanges;
  5113. }
  5114. // Update bubbleLegend dimensions in each redraw
  5115. legend.destroyItem(bubbleLegend);
  5116. }
  5117. // Create bubble legend
  5118. if (bubbleSeriesIndex >= 0 &&
  5119. legendOptions.enabled &&
  5120. options.enabled
  5121. ) {
  5122. options.seriesIndex = bubbleSeriesIndex;
  5123. legend.bubbleLegend = new H.BubbleLegend(options, legend);
  5124. legend.bubbleLegend.addToLegend(e.allItems);
  5125. }
  5126. });
  5127. /**
  5128. * Check if there is at least one visible bubble series.
  5129. *
  5130. * @private
  5131. * @function Highcharts.Chart#getVisibleBubbleSeriesIndex
  5132. *
  5133. * @return {number}
  5134. * First visible bubble series index
  5135. */
  5136. Chart.prototype.getVisibleBubbleSeriesIndex = function () {
  5137. var series = this.series,
  5138. i = 0;
  5139. while (i < series.length) {
  5140. if (
  5141. series[i] &&
  5142. series[i].isBubble &&
  5143. series[i].visible &&
  5144. series[i].zData.length
  5145. ) {
  5146. return i;
  5147. }
  5148. i++;
  5149. }
  5150. return -1;
  5151. };
  5152. /**
  5153. * Calculate height for each row in legend.
  5154. *
  5155. * @private
  5156. * @function Highcharts.Legend#getLinesHeights
  5157. *
  5158. * @return {Array<object>}
  5159. * Informations about line height and items amount
  5160. */
  5161. Legend.prototype.getLinesHeights = function () {
  5162. var items = this.allItems,
  5163. lines = [],
  5164. lastLine,
  5165. length = items.length,
  5166. i = 0,
  5167. j = 0;
  5168. for (i = 0; i < length; i++) {
  5169. if (items[i].legendItemHeight) {
  5170. // for bubbleLegend
  5171. items[i].itemHeight = items[i].legendItemHeight;
  5172. }
  5173. if ( // Line break
  5174. items[i] === items[length - 1] ||
  5175. items[i + 1] &&
  5176. items[i]._legendItemPos[1] !==
  5177. items[i + 1]._legendItemPos[1]
  5178. ) {
  5179. lines.push({ height: 0 });
  5180. lastLine = lines[lines.length - 1];
  5181. // Find the highest item in line
  5182. for (j; j <= i; j++) {
  5183. if (items[j].itemHeight > lastLine.height) {
  5184. lastLine.height = items[j].itemHeight;
  5185. }
  5186. }
  5187. lastLine.step = i;
  5188. }
  5189. }
  5190. return lines;
  5191. };
  5192. /**
  5193. * Correct legend items translation in case of different elements heights.
  5194. *
  5195. * @private
  5196. * @function Highcharts.Legend#retranslateItems
  5197. *
  5198. * @param {Array<object>} lines
  5199. * Informations about line height and items amount
  5200. */
  5201. Legend.prototype.retranslateItems = function (lines) {
  5202. var items = this.allItems,
  5203. orgTranslateX,
  5204. orgTranslateY,
  5205. movementX,
  5206. rtl = this.options.rtl,
  5207. actualLine = 0;
  5208. items.forEach(function (item, index) {
  5209. orgTranslateX = item.legendGroup.translateX;
  5210. orgTranslateY = item._legendItemPos[1];
  5211. movementX = item.movementX;
  5212. if (movementX || (rtl && item.ranges)) {
  5213. movementX = rtl ? orgTranslateX - item.options.maxSize / 2 :
  5214. orgTranslateX + movementX;
  5215. item.legendGroup.attr({ translateX: movementX });
  5216. }
  5217. if (index > lines[actualLine].step) {
  5218. actualLine++;
  5219. }
  5220. item.legendGroup.attr({
  5221. translateY: Math.round(
  5222. orgTranslateY + lines[actualLine].height / 2
  5223. )
  5224. });
  5225. item._legendItemPos[1] = orgTranslateY + lines[actualLine].height / 2;
  5226. });
  5227. };
  5228. // Hide or show bubble legend depending on the visible status of bubble series.
  5229. addEvent(Series, 'legendItemClick', function () {
  5230. var series = this,
  5231. chart = series.chart,
  5232. visible = series.visible,
  5233. legend = series.chart.legend,
  5234. status;
  5235. if (legend && legend.bubbleLegend) {
  5236. // Visible property is not set correctly yet, so temporary correct it
  5237. series.visible = !visible;
  5238. // Save future status for getRanges method
  5239. series.ignoreSeries = visible;
  5240. // Check if at lest one bubble series is visible
  5241. status = chart.getVisibleBubbleSeriesIndex() >= 0;
  5242. // Hide bubble legend if all bubble series are disabled
  5243. if (legend.bubbleLegend.visible !== status) {
  5244. // Show or hide bubble legend
  5245. legend.update({
  5246. bubbleLegend: { enabled: status }
  5247. });
  5248. legend.bubbleLegend.visible = status; // Restore default status
  5249. }
  5250. series.visible = visible;
  5251. }
  5252. });
  5253. // If ranges are not specified, determine ranges from rendered bubble series and
  5254. // render legend again.
  5255. wrap(Chart.prototype, 'drawChartBox', function (proceed, options, callback) {
  5256. var chart = this,
  5257. legend = chart.legend,
  5258. bubbleSeries = chart.getVisibleBubbleSeriesIndex() >= 0,
  5259. bubbleLegendOptions,
  5260. bubbleSizes;
  5261. if (
  5262. legend && legend.options.enabled && legend.bubbleLegend &&
  5263. legend.options.bubbleLegend.autoRanges && bubbleSeries
  5264. ) {
  5265. bubbleLegendOptions = legend.bubbleLegend.options;
  5266. bubbleSizes = legend.bubbleLegend.predictBubbleSizes();
  5267. legend.bubbleLegend.updateRanges(bubbleSizes[0], bubbleSizes[1]);
  5268. // Disable animation on init
  5269. if (!bubbleLegendOptions.placed) {
  5270. legend.group.placed = false;
  5271. legend.allItems.forEach(function (item) {
  5272. item.legendGroup.translateY = null;
  5273. });
  5274. }
  5275. // Create legend with bubbleLegend
  5276. legend.render();
  5277. chart.getMargins();
  5278. chart.axes.forEach(function (axis) {
  5279. axis.render();
  5280. if (!bubbleLegendOptions.placed) {
  5281. axis.setScale();
  5282. axis.updateNames();
  5283. // Disable axis animation on init
  5284. objectEach(axis.ticks, function (tick) {
  5285. tick.isNew = true;
  5286. tick.isNewLabel = true;
  5287. });
  5288. }
  5289. });
  5290. bubbleLegendOptions.placed = true;
  5291. // After recalculate axes, calculate margins again.
  5292. chart.getMargins();
  5293. // Call default 'drawChartBox' method.
  5294. proceed.call(chart, options, callback);
  5295. // Check bubble legend sizes and correct them if necessary.
  5296. legend.bubbleLegend.correctSizes();
  5297. // Correct items positions with different dimensions in legend.
  5298. legend.retranslateItems(legend.getLinesHeights());
  5299. } else {
  5300. proceed.call(chart, options, callback);
  5301. if (legend && legend.options.enabled && legend.bubbleLegend) {
  5302. // Allow color change after click in legend on static bubble legend
  5303. legend.render();
  5304. legend.retranslateItems(legend.getLinesHeights());
  5305. }
  5306. }
  5307. });
  5308. }(Highcharts));
  5309. (function (H) {
  5310. /* *
  5311. * (c) 2010-2019 Torstein Honsi
  5312. *
  5313. * License: www.highcharts.com/license
  5314. */
  5315. var arrayMax = H.arrayMax,
  5316. arrayMin = H.arrayMin,
  5317. Axis = H.Axis,
  5318. color = H.color,
  5319. isNumber = H.isNumber,
  5320. noop = H.noop,
  5321. pick = H.pick,
  5322. pInt = H.pInt,
  5323. Point = H.Point,
  5324. Series = H.Series,
  5325. seriesType = H.seriesType,
  5326. seriesTypes = H.seriesTypes;
  5327. /**
  5328. * A bubble series is a three dimensional series type where each point renders
  5329. * an X, Y and Z value. Each points is drawn as a bubble where the position
  5330. * along the X and Y axes mark the X and Y values, and the size of the bubble
  5331. * relates to the Z value. Requires `highcharts-more.js`.
  5332. *
  5333. * @sample {highcharts} highcharts/demo/bubble/
  5334. * Bubble chart
  5335. *
  5336. * @extends plotOptions.scatter
  5337. * @product highcharts highstock
  5338. * @optionparent plotOptions.bubble
  5339. */
  5340. seriesType('bubble', 'scatter', {
  5341. dataLabels: {
  5342. formatter: function () { // #2945
  5343. return this.point.z;
  5344. },
  5345. inside: true,
  5346. verticalAlign: 'middle'
  5347. },
  5348. /**
  5349. * If there are more points in the series than the `animationLimit`, the
  5350. * animation won't run. Animation affects overall performance and doesn't
  5351. * work well with heavy data series.
  5352. *
  5353. * @since 6.1.0
  5354. */
  5355. animationLimit: 250,
  5356. /**
  5357. * Whether to display negative sized bubbles. The threshold is given
  5358. * by the [zThreshold](#plotOptions.bubble.zThreshold) option, and negative
  5359. * bubbles can be visualized by setting
  5360. * [negativeColor](#plotOptions.bubble.negativeColor).
  5361. *
  5362. * @sample {highcharts} highcharts/plotoptions/bubble-negative/
  5363. * Negative bubbles
  5364. *
  5365. * @type {boolean}
  5366. * @default true
  5367. * @since 3.0
  5368. * @apioption plotOptions.bubble.displayNegative
  5369. */
  5370. /**
  5371. * @extends plotOptions.series.marker
  5372. * @excluding enabled, enabledThreshold, height, radius, width
  5373. */
  5374. marker: {
  5375. lineColor: null, // inherit from series.color
  5376. lineWidth: 1,
  5377. /**
  5378. * The fill opacity of the bubble markers.
  5379. */
  5380. fillOpacity: 0.5,
  5381. /**
  5382. * In bubble charts, the radius is overridden and determined based on
  5383. * the point's data value.
  5384. *
  5385. * @ignore
  5386. */
  5387. radius: null,
  5388. states: {
  5389. hover: {
  5390. radiusPlus: 0
  5391. }
  5392. },
  5393. /**
  5394. * A predefined shape or symbol for the marker. Possible values are
  5395. * "circle", "square", "diamond", "triangle" and "triangle-down".
  5396. *
  5397. * Additionally, the URL to a graphic can be given on the form
  5398. * `url(graphic.png)`. Note that for the image to be applied to exported
  5399. * charts, its URL needs to be accessible by the export server.
  5400. *
  5401. * Custom callbacks for symbol path generation can also be added to
  5402. * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then
  5403. * used by its method name, as shown in the demo.
  5404. *
  5405. * @sample {highcharts} highcharts/plotoptions/bubble-symbol/
  5406. * Bubble chart with various symbols
  5407. * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/
  5408. * General chart with predefined, graphic and custom markers
  5409. *
  5410. * @since 5.0.11
  5411. * @validvalue ["circle", "square", "diamond", "triangle",
  5412. * "triangle-down"]
  5413. */
  5414. symbol: 'circle'
  5415. },
  5416. /**
  5417. * Minimum bubble size. Bubbles will automatically size between the
  5418. * `minSize` and `maxSize` to reflect the `z` value of each bubble.
  5419. * Can be either pixels (when no unit is given), or a percentage of
  5420. * the smallest one of the plot width and height.
  5421. *
  5422. * @sample {highcharts} highcharts/plotoptions/bubble-size/
  5423. * Bubble size
  5424. *
  5425. * @type {number|string}
  5426. * @since 3.0
  5427. * @product highcharts highstock
  5428. */
  5429. minSize: 8,
  5430. /**
  5431. * Maximum bubble size. Bubbles will automatically size between the
  5432. * `minSize` and `maxSize` to reflect the `z` value of each bubble.
  5433. * Can be either pixels (when no unit is given), or a percentage of
  5434. * the smallest one of the plot width and height.
  5435. *
  5436. * @sample {highcharts} highcharts/plotoptions/bubble-size/
  5437. * Bubble size
  5438. *
  5439. * @type {number|string}
  5440. * @since 3.0
  5441. * @product highcharts highstock
  5442. */
  5443. maxSize: '20%',
  5444. /**
  5445. * When a point's Z value is below the
  5446. * [zThreshold](#plotOptions.bubble.zThreshold) setting, this color is used.
  5447. *
  5448. * @sample {highcharts} highcharts/plotoptions/bubble-negative/
  5449. * Negative bubbles
  5450. *
  5451. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  5452. * @since 3.0
  5453. * @product highcharts
  5454. * @apioption plotOptions.bubble.negativeColor
  5455. */
  5456. /**
  5457. * Whether the bubble's value should be represented by the area or the
  5458. * width of the bubble. The default, `area`, corresponds best to the
  5459. * human perception of the size of each bubble.
  5460. *
  5461. * @sample {highcharts} highcharts/plotoptions/bubble-sizeby/
  5462. * Comparison of area and size
  5463. *
  5464. * @type {string}
  5465. * @default area
  5466. * @since 3.0.7
  5467. * @validvalue ["area", "width"]
  5468. * @apioption plotOptions.bubble.sizeBy
  5469. */
  5470. /**
  5471. * When this is true, the absolute value of z determines the size of
  5472. * the bubble. This means that with the default `zThreshold` of 0, a
  5473. * bubble of value -1 will have the same size as a bubble of value 1,
  5474. * while a bubble of value 0 will have a smaller size according to
  5475. * `minSize`.
  5476. *
  5477. * @sample {highcharts} highcharts/plotoptions/bubble-sizebyabsolutevalue/
  5478. * Size by absolute value, various thresholds
  5479. *
  5480. * @type {boolean}
  5481. * @default false
  5482. * @since 4.1.9
  5483. * @product highcharts
  5484. * @apioption plotOptions.bubble.sizeByAbsoluteValue
  5485. */
  5486. /**
  5487. * When this is true, the series will not cause the Y axis to cross
  5488. * the zero plane (or [threshold](#plotOptions.series.threshold) option)
  5489. * unless the data actually crosses the plane.
  5490. *
  5491. * For example, if `softThreshold` is `false`, a series of 0, 1, 2,
  5492. * 3 will make the Y axis show negative values according to the `minPadding`
  5493. * option. If `softThreshold` is `true`, the Y axis starts at 0.
  5494. *
  5495. * @since 4.1.9
  5496. * @product highcharts
  5497. */
  5498. softThreshold: false,
  5499. states: {
  5500. hover: {
  5501. halo: {
  5502. size: 5
  5503. }
  5504. }
  5505. },
  5506. tooltip: {
  5507. pointFormat: '({point.x}, {point.y}), Size: {point.z}'
  5508. },
  5509. turboThreshold: 0,
  5510. /**
  5511. * The minimum for the Z value range. Defaults to the highest Z value
  5512. * in the data.
  5513. *
  5514. * @see [zMin](#plotOptions.bubble.zMin)
  5515. *
  5516. * @sample {highcharts} highcharts/plotoptions/bubble-zmin-zmax/
  5517. * Z has a possible range of 0-100
  5518. *
  5519. * @type {number}
  5520. * @since 4.0.3
  5521. * @product highcharts
  5522. * @apioption plotOptions.bubble.zMax
  5523. */
  5524. /**
  5525. * The minimum for the Z value range. Defaults to the lowest Z value
  5526. * in the data.
  5527. *
  5528. * @see [zMax](#plotOptions.bubble.zMax)
  5529. *
  5530. * @sample {highcharts} highcharts/plotoptions/bubble-zmin-zmax/
  5531. * Z has a possible range of 0-100
  5532. *
  5533. * @type {number}
  5534. * @since 4.0.3
  5535. * @product highcharts
  5536. * @apioption plotOptions.bubble.zMin
  5537. */
  5538. /**
  5539. * When [displayNegative](#plotOptions.bubble.displayNegative) is `false`,
  5540. * bubbles with lower Z values are skipped. When `displayNegative`
  5541. * is `true` and a [negativeColor](#plotOptions.bubble.negativeColor)
  5542. * is given, points with lower Z is colored.
  5543. *
  5544. * @sample {highcharts} highcharts/plotoptions/bubble-negative/
  5545. * Negative bubbles
  5546. *
  5547. * @since 3.0
  5548. * @product highcharts
  5549. */
  5550. zThreshold: 0,
  5551. zoneAxis: 'z'
  5552. // Prototype members
  5553. }, {
  5554. pointArrayMap: ['y', 'z'],
  5555. parallelArrays: ['x', 'y', 'z'],
  5556. trackerGroups: ['group', 'dataLabelsGroup'],
  5557. specialGroup: 'group', // To allow clipping (#6296)
  5558. bubblePadding: true,
  5559. zoneAxis: 'z',
  5560. directTouch: true,
  5561. isBubble: true,
  5562. pointAttribs: function (point, state) {
  5563. var markerOptions = this.options.marker,
  5564. fillOpacity = markerOptions.fillOpacity,
  5565. attr = Series.prototype.pointAttribs.call(this, point, state);
  5566. if (fillOpacity !== 1) {
  5567. attr.fill = color(attr.fill).setOpacity(fillOpacity).get('rgba');
  5568. }
  5569. return attr;
  5570. },
  5571. // Get the radius for each point based on the minSize, maxSize and each
  5572. // point's Z value. This must be done prior to Series.translate because
  5573. // the axis needs to add padding in accordance with the point sizes.
  5574. getRadii: function (zMin, zMax, series) {
  5575. var len,
  5576. i,
  5577. zData = this.zData,
  5578. minSize = series.minPxSize,
  5579. maxSize = series.maxPxSize,
  5580. radii = [],
  5581. value;
  5582. // Set the shape type and arguments to be picked up in drawPoints
  5583. for (i = 0, len = zData.length; i < len; i++) {
  5584. value = zData[i];
  5585. // Separate method to get individual radius for bubbleLegend
  5586. radii.push(this.getRadius(zMin, zMax, minSize, maxSize, value));
  5587. }
  5588. this.radii = radii;
  5589. },
  5590. // Get the individual radius for one point.
  5591. getRadius: function (zMin, zMax, minSize, maxSize, value) {
  5592. var options = this.options,
  5593. sizeByArea = options.sizeBy !== 'width',
  5594. zThreshold = options.zThreshold,
  5595. pos,
  5596. zRange = zMax - zMin,
  5597. radius;
  5598. // When sizing by threshold, the absolute value of z determines
  5599. // the size of the bubble.
  5600. if (options.sizeByAbsoluteValue && value !== null) {
  5601. value = Math.abs(value - zThreshold);
  5602. zMax = zRange = Math.max(
  5603. zMax - zThreshold,
  5604. Math.abs(zMin - zThreshold)
  5605. );
  5606. zMin = 0;
  5607. }
  5608. if (!isNumber(value)) {
  5609. radius = null;
  5610. // Issue #4419 - if value is less than zMin, push a radius that's
  5611. // always smaller than the minimum size
  5612. } else if (value < zMin) {
  5613. radius = minSize / 2 - 1;
  5614. } else {
  5615. // Relative size, a number between 0 and 1
  5616. pos = zRange > 0 ? (value - zMin) / zRange : 0.5;
  5617. if (sizeByArea && pos >= 0) {
  5618. pos = Math.sqrt(pos);
  5619. }
  5620. radius = Math.ceil(minSize + pos * (maxSize - minSize)) / 2;
  5621. }
  5622. return radius;
  5623. },
  5624. // Perform animation on the bubbles
  5625. animate: function (init) {
  5626. if (
  5627. !init &&
  5628. this.points.length < this.options.animationLimit // #8099
  5629. ) {
  5630. this.points.forEach(function (point) {
  5631. var graphic = point.graphic,
  5632. animationTarget;
  5633. if (graphic && graphic.width) { // URL symbols don't have width
  5634. animationTarget = {
  5635. x: graphic.x,
  5636. y: graphic.y,
  5637. width: graphic.width,
  5638. height: graphic.height
  5639. };
  5640. // Start values
  5641. graphic.attr({
  5642. x: point.plotX,
  5643. y: point.plotY,
  5644. width: 1,
  5645. height: 1
  5646. });
  5647. // Run animation
  5648. graphic.animate(animationTarget, this.options.animation);
  5649. }
  5650. }, this);
  5651. // delete this function to allow it only once
  5652. this.animate = null;
  5653. }
  5654. },
  5655. // Extend the base translate method to handle bubble size
  5656. translate: function () {
  5657. var i,
  5658. data = this.data,
  5659. point,
  5660. radius,
  5661. radii = this.radii;
  5662. // Run the parent method
  5663. seriesTypes.scatter.prototype.translate.call(this);
  5664. // Set the shape type and arguments to be picked up in drawPoints
  5665. i = data.length;
  5666. while (i--) {
  5667. point = data[i];
  5668. radius = radii ? radii[i] : 0; // #1737
  5669. if (isNumber(radius) && radius >= this.minPxSize / 2) {
  5670. // Shape arguments
  5671. point.marker = H.extend(point.marker, {
  5672. radius: radius,
  5673. width: 2 * radius,
  5674. height: 2 * radius
  5675. });
  5676. // Alignment box for the data label
  5677. point.dlBox = {
  5678. x: point.plotX - radius,
  5679. y: point.plotY - radius,
  5680. width: 2 * radius,
  5681. height: 2 * radius
  5682. };
  5683. } else { // below zThreshold
  5684. // #1691
  5685. point.shapeArgs = point.plotY = point.dlBox = undefined;
  5686. }
  5687. }
  5688. },
  5689. alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
  5690. buildKDTree: noop,
  5691. applyZones: noop
  5692. // Point class
  5693. }, {
  5694. haloPath: function (size) {
  5695. return Point.prototype.haloPath.call(
  5696. this,
  5697. // #6067
  5698. size === 0 ? 0 : (this.marker ? this.marker.radius || 0 : 0) + size
  5699. );
  5700. },
  5701. ttBelow: false
  5702. });
  5703. // Add logic to pad each axis with the amount of pixels necessary to avoid the
  5704. // bubbles to overflow.
  5705. Axis.prototype.beforePadding = function () {
  5706. var axis = this,
  5707. axisLength = this.len,
  5708. chart = this.chart,
  5709. pxMin = 0,
  5710. pxMax = axisLength,
  5711. isXAxis = this.isXAxis,
  5712. dataKey = isXAxis ? 'xData' : 'yData',
  5713. min = this.min,
  5714. extremes = {},
  5715. smallestSize = Math.min(chart.plotWidth, chart.plotHeight),
  5716. zMin = Number.MAX_VALUE,
  5717. zMax = -Number.MAX_VALUE,
  5718. range = this.max - min,
  5719. transA = axisLength / range,
  5720. activeSeries = [];
  5721. // Handle padding on the second pass, or on redraw
  5722. this.series.forEach(function (series) {
  5723. var seriesOptions = series.options,
  5724. zData;
  5725. if (
  5726. series.bubblePadding &&
  5727. (series.visible || !chart.options.chart.ignoreHiddenSeries)
  5728. ) {
  5729. // Correction for #1673
  5730. axis.allowZoomOutside = true;
  5731. // Cache it
  5732. activeSeries.push(series);
  5733. if (isXAxis) { // because X axis is evaluated first
  5734. // For each series, translate the size extremes to pixel values
  5735. ['minSize', 'maxSize'].forEach(function (prop) {
  5736. var length = seriesOptions[prop],
  5737. isPercent = /%$/.test(length);
  5738. length = pInt(length);
  5739. extremes[prop] = isPercent ?
  5740. smallestSize * length / 100 :
  5741. length;
  5742. });
  5743. series.minPxSize = extremes.minSize;
  5744. // Prioritize min size if conflict to make sure bubbles are
  5745. // always visible. #5873
  5746. series.maxPxSize = Math.max(extremes.maxSize, extremes.minSize);
  5747. // Find the min and max Z
  5748. zData = series.zData.filter(H.isNumber);
  5749. if (zData.length) { // #1735
  5750. zMin = pick(seriesOptions.zMin, Math.min(
  5751. zMin,
  5752. Math.max(
  5753. arrayMin(zData),
  5754. seriesOptions.displayNegative === false ?
  5755. seriesOptions.zThreshold :
  5756. -Number.MAX_VALUE
  5757. )
  5758. ));
  5759. zMax = pick(
  5760. seriesOptions.zMax,
  5761. Math.max(zMax, arrayMax(zData))
  5762. );
  5763. }
  5764. }
  5765. }
  5766. });
  5767. activeSeries.forEach(function (series) {
  5768. var data = series[dataKey],
  5769. i = data.length,
  5770. radius;
  5771. if (isXAxis) {
  5772. series.getRadii(zMin, zMax, series);
  5773. }
  5774. if (range > 0) {
  5775. while (i--) {
  5776. if (
  5777. isNumber(data[i]) &&
  5778. axis.dataMin <= data[i] &&
  5779. data[i] <= axis.dataMax
  5780. ) {
  5781. radius = series.radii[i];
  5782. pxMin = Math.min(
  5783. ((data[i] - min) * transA) - radius,
  5784. pxMin
  5785. );
  5786. pxMax = Math.max(
  5787. ((data[i] - min) * transA) + radius,
  5788. pxMax
  5789. );
  5790. }
  5791. }
  5792. }
  5793. });
  5794. // Apply the padding to the min and max properties
  5795. if (activeSeries.length && range > 0 && !this.isLog) {
  5796. pxMax -= axisLength;
  5797. transA *= (
  5798. axisLength +
  5799. Math.max(0, pxMin) - // #8901
  5800. Math.min(pxMax, axisLength)
  5801. ) / axisLength;
  5802. [['min', 'userMin', pxMin], ['max', 'userMax', pxMax]].forEach(
  5803. function (keys) {
  5804. if (pick(axis.options[keys[0]], axis[keys[1]]) === undefined) {
  5805. axis[keys[0]] += keys[2] / transA;
  5806. }
  5807. }
  5808. );
  5809. }
  5810. };
  5811. /**
  5812. * A `bubble` series. If the [type](#series.bubble.type) option is
  5813. * not specified, it is inherited from [chart.type](#chart.type).
  5814. *
  5815. * @extends series,plotOptions.bubble
  5816. * @excluding dataParser, dataURL, stack
  5817. * @product highcharts highstock
  5818. * @apioption series.bubble
  5819. */
  5820. /**
  5821. * An array of data points for the series. For the `bubble` series type,
  5822. * points can be given in the following ways:
  5823. *
  5824. * 1. An array of arrays with 3 or 2 values. In this case, the values correspond
  5825. * to `x,y,z`. If the first value is a string, it is applied as the name of
  5826. * the point, and the `x` value is inferred. The `x` value can also be
  5827. * omitted, in which case the inner arrays should be of length 2\. Then the
  5828. * `x` value is automatically calculated, either starting at 0 and
  5829. * incremented by 1, or from `pointStart` and `pointInterval` given in the
  5830. * series options.
  5831. * ```js
  5832. * data: [
  5833. * [0, 1, 2],
  5834. * [1, 5, 5],
  5835. * [2, 0, 2]
  5836. * ]
  5837. * ```
  5838. *
  5839. * 2. An array of objects with named values. The following snippet shows only a
  5840. * few settings, see the complete options set below. If the total number of
  5841. * data points exceeds the series'
  5842. * [turboThreshold](#series.bubble.turboThreshold), this option is not
  5843. * available.
  5844. * ```js
  5845. * data: [{
  5846. * x: 1,
  5847. * y: 1,
  5848. * z: 1,
  5849. * name: "Point2",
  5850. * color: "#00FF00"
  5851. * }, {
  5852. * x: 1,
  5853. * y: 5,
  5854. * z: 4,
  5855. * name: "Point1",
  5856. * color: "#FF00FF"
  5857. * }]
  5858. * ```
  5859. *
  5860. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  5861. * Arrays of numeric x and y
  5862. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  5863. * Arrays of datetime x and y
  5864. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  5865. * Arrays of point.name and y
  5866. * @sample {highcharts} highcharts/series/data-array-of-objects/
  5867. * Config objects
  5868. *
  5869. * @type {Array<Array<(number|string),number>|Array<(number|string),number,number>|*>}
  5870. * @extends series.line.data
  5871. * @excluding marker
  5872. * @product highcharts
  5873. * @apioption series.bubble.data
  5874. */
  5875. /**
  5876. * The size value for each bubble. The bubbles' diameters are computed
  5877. * based on the `z`, and controlled by series options like `minSize`,
  5878. * `maxSize`, `sizeBy`, `zMin` and `zMax`.
  5879. *
  5880. * @type {number}
  5881. * @product highcharts
  5882. * @apioption series.bubble.data.z
  5883. */
  5884. /**
  5885. * @excluding enabled, enabledThreshold, height, radius, width
  5886. * @apioption series.bubble.marker
  5887. */
  5888. }(Highcharts));
  5889. (function (H) {
  5890. /* *
  5891. * (c) 2010-2019 Grzegorz Blachlinski, Sebastian Bochan
  5892. *
  5893. * License: www.highcharts.com/license
  5894. */
  5895. var seriesType = H.seriesType,
  5896. defined = H.defined;
  5897. /**
  5898. * Packed bubble series
  5899. *
  5900. * @private
  5901. * @class
  5902. * @name Highcharts.seriesTypes.packedbubble
  5903. *
  5904. * @augments Highcharts.Series
  5905. *
  5906. * @requires modules:highcharts-more
  5907. */
  5908. seriesType(
  5909. 'packedbubble',
  5910. 'bubble',
  5911. /**
  5912. * A packed bubble series is a two dimensional series type, where each point
  5913. * renders a value in X, Y position. Each point is drawn as a bubble where
  5914. * the bubbles don't overlap with each other and the radius of the bubble
  5915. * related to the value. Requires `highcharts-more.js`.
  5916. *
  5917. * @sample {highcharts} highcharts/demo/packed-bubble/
  5918. * Packed-bubble chart
  5919. *
  5920. * @extends plotOptions.bubble
  5921. * @since 7.0.0
  5922. * @product highcharts
  5923. * @excluding connectEnds, connectNulls, jitter, keys,
  5924. * sizeByAbsoluteValue, step, zMax, zMin
  5925. * @optionparent plotOptions.packedbubble
  5926. */
  5927. {
  5928. /**
  5929. * Minimum bubble size. Bubbles will automatically size between the
  5930. * `minSize` and `maxSize` to reflect the value of each bubble.
  5931. * Can be either pixels (when no unit is given), or a percentage of
  5932. * the smallest one of the plot width and height.
  5933. *
  5934. * @sample {highcharts} highcharts/plotoptions/bubble-size/
  5935. * Bubble size
  5936. *
  5937. * @type {number|string}
  5938. */
  5939. minSize: '10%',
  5940. /**
  5941. * Maximum bubble size. Bubbles will automatically size between the
  5942. * `minSize` and `maxSize` to reflect the value of each bubble.
  5943. * Can be either pixels (when no unit is given), or a percentage of
  5944. * the smallest one of the plot width and height.
  5945. *
  5946. * @sample {highcharts} highcharts/plotoptions/bubble-size/
  5947. * Bubble size
  5948. *
  5949. * @type {number|string}
  5950. */
  5951. maxSize: '100%',
  5952. sizeBy: 'radius',
  5953. zoneAxis: 'y',
  5954. tooltip: {
  5955. pointFormat: 'Value: {point.value}'
  5956. }
  5957. }, {
  5958. pointArrayMap: ['value'],
  5959. pointValKey: 'value',
  5960. isCartesian: false,
  5961. axisTypes: [],
  5962. /**
  5963. * Create a single array of all points from all series
  5964. * @private
  5965. * @param {Array} Array of all series objects
  5966. * @return {Array} Returns the array of all points.
  5967. */
  5968. accumulateAllPoints: function (series) {
  5969. var chart = series.chart,
  5970. allDataPoints = [],
  5971. i, j;
  5972. for (i = 0; i < chart.series.length; i++) {
  5973. series = chart.series[i];
  5974. if (series.visible || !chart.options.chart.ignoreHiddenSeries) {
  5975. // add data to array only if series is visible
  5976. for (j = 0; j < series.yData.length; j++) {
  5977. allDataPoints.push([
  5978. null, null,
  5979. series.yData[j],
  5980. series.index,
  5981. j
  5982. ]);
  5983. }
  5984. }
  5985. }
  5986. return allDataPoints;
  5987. },
  5988. // Extend the base translate method to handle bubble size, and correct
  5989. // positioning them.
  5990. translate: function () {
  5991. var positions, // calculated positions of bubbles in bubble array
  5992. series = this,
  5993. chart = series.chart,
  5994. data = series.data,
  5995. index = series.index,
  5996. point,
  5997. radius,
  5998. i;
  5999. this.processedXData = this.xData;
  6000. this.generatePoints();
  6001. // merged data is an array with all of the data from all series
  6002. if (!defined(chart.allDataPoints)) {
  6003. chart.allDataPoints = series.accumulateAllPoints(series);
  6004. // calculate radius for all added data
  6005. series.getPointRadius();
  6006. }
  6007. // after getting initial radius, calculate bubble positions
  6008. positions = this.placeBubbles(chart.allDataPoints);
  6009. // Set the shape type and arguments to be picked up in drawPoints
  6010. for (i = 0; i < positions.length; i++) {
  6011. if (positions[i][3] === index) {
  6012. // update the series points with the values from positions
  6013. // array
  6014. point = data[positions[i][4]];
  6015. radius = positions[i][2];
  6016. point.plotX = positions[i][0] - chart.plotLeft +
  6017. chart.diffX;
  6018. point.plotY = positions[i][1] - chart.plotTop +
  6019. chart.diffY;
  6020. point.marker = H.extend(point.marker, {
  6021. radius: radius,
  6022. width: 2 * radius,
  6023. height: 2 * radius
  6024. });
  6025. }
  6026. }
  6027. },
  6028. /**
  6029. * Check if two bubbles overlaps.
  6030. * @private
  6031. * @param {Array} bubble1 first bubble
  6032. * @param {Array} bubble2 second bubble
  6033. * @return {boolean} overlap or not
  6034. */
  6035. checkOverlap: function (bubble1, bubble2) {
  6036. var diffX = bubble1[0] - bubble2[0], // diff of X center values
  6037. diffY = bubble1[1] - bubble2[1], // diff of Y center values
  6038. sumRad = bubble1[2] + bubble2[2]; // sum of bubble radius
  6039. return (
  6040. Math.sqrt(diffX * diffX + diffY * diffY) -
  6041. Math.abs(sumRad)
  6042. ) < -0.001;
  6043. },
  6044. /**
  6045. * Function that is adding one bubble based on positions and sizes
  6046. * of two other bubbles, lastBubble is the last added bubble,
  6047. * newOrigin is the bubble for positioning new bubbles.
  6048. * nextBubble is the curently added bubble for which we are
  6049. * calculating positions
  6050. * @private
  6051. * @param {Array} lastBubble The closest last bubble
  6052. * @param {Array} newOrigin New bubble
  6053. * @param {Array} nextBubble The closest next bubble
  6054. * @return {Array} Bubble with correct positions
  6055. */
  6056. positionBubble: function (lastBubble, newOrigin, nextBubble) {
  6057. var sqrt = Math.sqrt,
  6058. asin = Math.asin,
  6059. acos = Math.acos,
  6060. pow = Math.pow,
  6061. abs = Math.abs,
  6062. distance = sqrt( // dist between lastBubble and newOrigin
  6063. pow((lastBubble[0] - newOrigin[0]), 2) +
  6064. pow((lastBubble[1] - newOrigin[1]), 2)
  6065. ),
  6066. alfa = acos(
  6067. // from cosinus theorem: alfa is an angle used for
  6068. // calculating correct position
  6069. (
  6070. pow(distance, 2) +
  6071. pow(nextBubble[2] + newOrigin[2], 2) -
  6072. pow(nextBubble[2] + lastBubble[2], 2)
  6073. ) / (2 * (nextBubble[2] + newOrigin[2]) * distance)
  6074. ),
  6075. beta = asin( // from sinus theorem.
  6076. abs(lastBubble[0] - newOrigin[0]) /
  6077. distance
  6078. ),
  6079. // providing helping variables, related to angle between
  6080. // lastBubble and newOrigin
  6081. gamma = (lastBubble[1] - newOrigin[1]) < 0 ? 0 : Math.PI,
  6082. // if new origin y is smaller than last bubble y value
  6083. // (2 and 3 quarter),
  6084. // add Math.PI to final angle
  6085. delta = (lastBubble[0] - newOrigin[0]) *
  6086. (lastBubble[1] - newOrigin[1]) < 0 ?
  6087. 1 : -1, // (1st and 3rd quarter)
  6088. finalAngle = gamma + alfa + beta * delta,
  6089. cosA = Math.cos(finalAngle),
  6090. sinA = Math.sin(finalAngle),
  6091. posX = newOrigin[0] + (newOrigin[2] + nextBubble[2]) * sinA,
  6092. // center of new origin + (radius1 + radius2) * sinus A
  6093. posY = newOrigin[1] - (newOrigin[2] + nextBubble[2]) * cosA;
  6094. return [
  6095. posX,
  6096. posY,
  6097. nextBubble[2],
  6098. nextBubble[3],
  6099. nextBubble[4]
  6100. ]; // the same as described before
  6101. },
  6102. /**
  6103. * This is the main function responsible for positioning all of the
  6104. * bubbles.
  6105. * allDataPoints - bubble array, in format [pixel x value,
  6106. * pixel y value, radius, related series index, related point index]
  6107. * @private
  6108. * @param {Array} allDataPoints All points from all series
  6109. * @return {Array} Positions of all bubbles
  6110. */
  6111. placeBubbles: function (allDataPoints) {
  6112. var series = this,
  6113. checkOverlap = series.checkOverlap,
  6114. positionBubble = series.positionBubble,
  6115. bubblePos = [],
  6116. stage = 1,
  6117. j = 0,
  6118. k = 0,
  6119. calculatedBubble,
  6120. sortedArr,
  6121. i;
  6122. // sort all points
  6123. sortedArr = allDataPoints.sort(function (a, b) {
  6124. return b[2] - a[2];
  6125. });
  6126. // if length is 0, return empty array
  6127. if (!sortedArr.length) {
  6128. return [];
  6129. }
  6130. if (sortedArr.length < 2) {
  6131. // if length is 1,return only one bubble
  6132. return [
  6133. 0, 0,
  6134. sortedArr[0][0],
  6135. sortedArr[0][1],
  6136. sortedArr[0][2]
  6137. ];
  6138. }
  6139. // create first bubble in the middle of the chart
  6140. bubblePos.push([
  6141. [
  6142. 0, // starting in 0,0 coordinates
  6143. 0,
  6144. sortedArr[0][2], // radius
  6145. sortedArr[0][3], // series index
  6146. sortedArr[0][4]
  6147. ] // point index
  6148. ]); // 0 level bubble
  6149. bubblePos.push([
  6150. [
  6151. 0,
  6152. 0 - sortedArr[1][2] - sortedArr[0][2],
  6153. // move bubble above first one
  6154. sortedArr[1][2],
  6155. sortedArr[1][3],
  6156. sortedArr[1][4]
  6157. ]
  6158. ]); // 1 level 1st bubble
  6159. // first two already positioned so starting from 2
  6160. for (i = 2; i < sortedArr.length; i++) {
  6161. sortedArr[i][2] = sortedArr[i][2] || 1;
  6162. // in case if radius is calculated as 0.
  6163. calculatedBubble = positionBubble(
  6164. bubblePos[stage][j],
  6165. bubblePos[stage - 1][k],
  6166. sortedArr[i]
  6167. ); // calculate initial bubble position
  6168. if (checkOverlap(calculatedBubble, bubblePos[stage][0])) {
  6169. // if new bubble is overlapping with first bubble in
  6170. // current level (stage)
  6171. bubblePos.push([]);
  6172. k = 0;
  6173. // reset index of bubble, used for positioning the bubbles
  6174. // around it, we are starting from first bubble in next
  6175. // stage because we are changing level to higher
  6176. bubblePos[stage + 1].push(
  6177. positionBubble(
  6178. bubblePos[stage][j],
  6179. bubblePos[stage][0],
  6180. sortedArr[i]
  6181. )
  6182. );
  6183. // (last added bubble, 1st. bbl from cur stage, new bubble)
  6184. stage++; // the new level is created, above current one
  6185. j = 0; // set the index of bubble in current level to 0
  6186. } else if (
  6187. stage > 1 && bubblePos[stage - 1][k + 1] &&
  6188. checkOverlap(calculatedBubble, bubblePos[stage - 1][k + 1])
  6189. ) {
  6190. // If new bubble is overlapping with one of the previous
  6191. // stage bubbles, it means that - bubble, used for
  6192. // positioning the bubbles around it has changed so we need
  6193. // to recalculate it.
  6194. k++;
  6195. bubblePos[stage].push(
  6196. positionBubble(
  6197. bubblePos[stage][j],
  6198. bubblePos[stage - 1][k],
  6199. sortedArr[i]
  6200. )
  6201. );
  6202. // (last added bubble, previous stage bubble, new bubble)
  6203. j++;
  6204. } else { // simply add calculated bubble
  6205. j++;
  6206. bubblePos[stage].push(calculatedBubble);
  6207. }
  6208. }
  6209. series.chart.stages = bubblePos;
  6210. // it may not be necessary but adding it just in case -
  6211. // it is containing all of the bubble levels
  6212. series.chart.rawPositions = [].concat.apply([], bubblePos);
  6213. // bubble positions merged into one array
  6214. series.resizeRadius();
  6215. return series.chart.rawPositions;
  6216. },
  6217. /**
  6218. * The function responsible for resizing the bubble radius.
  6219. * In shortcut: it is taking the initially
  6220. * calculated positions of bubbles. Then it is calculating the min max
  6221. * of both dimensions, creating something in shape of bBox.
  6222. * The comparison of bBox and the size of plotArea
  6223. * (later it may be also the size set by customer) is giving the
  6224. * value how to recalculate the radius so it will match the size
  6225. * @private
  6226. */
  6227. resizeRadius: function () {
  6228. var chart = this.chart,
  6229. positions = chart.rawPositions,
  6230. min = Math.min,
  6231. max = Math.max,
  6232. plotLeft = chart.plotLeft,
  6233. plotTop = chart.plotTop,
  6234. chartHeight = chart.plotHeight,
  6235. chartWidth = chart.plotWidth,
  6236. minX, maxX, minY, maxY,
  6237. radius,
  6238. bBox,
  6239. spaceRatio,
  6240. smallerDimension,
  6241. i;
  6242. minX = minY = Number.POSITIVE_INFINITY; // set initial values
  6243. maxX = maxY = Number.NEGATIVE_INFINITY;
  6244. for (i = 0; i < positions.length; i++) {
  6245. radius = positions[i][2];
  6246. minX = min(minX, positions[i][0] - radius);
  6247. // (x center-radius) is the min x value used by specific bubble
  6248. maxX = max(maxX, positions[i][0] + radius);
  6249. minY = min(minY, positions[i][1] - radius);
  6250. maxY = max(maxY, positions[i][1] + radius);
  6251. }
  6252. bBox = [maxX - minX, maxY - minY];
  6253. spaceRatio = [
  6254. (chartWidth - plotLeft) / bBox[0],
  6255. (chartHeight - plotTop) / bBox[1]
  6256. ];
  6257. smallerDimension = min.apply([], spaceRatio);
  6258. if (Math.abs(smallerDimension - 1) > 1e-10) {
  6259. // if bBox is considered not the same width as possible size
  6260. for (i = 0; i < positions.length; i++) {
  6261. positions[i][2] *= smallerDimension;
  6262. }
  6263. this.placeBubbles(positions);
  6264. } else {
  6265. // If no radius recalculation is needed, we need to position the
  6266. // whole bubbles in center of chart plotarea for this, we are
  6267. // adding two parameters, diffY and diffX, that are related to
  6268. // differences between the initial center and the bounding box.
  6269. chart.diffY = chartHeight / 2 +
  6270. plotTop - minY - (maxY - minY) / 2;
  6271. chart.diffX = chartWidth / 2 +
  6272. plotLeft - minX - (maxX - minX) / 2;
  6273. }
  6274. },
  6275. // Calculate radius of bubbles in series.
  6276. getPointRadius: function () { // bubbles array
  6277. var series = this,
  6278. chart = series.chart,
  6279. plotWidth = chart.plotWidth,
  6280. plotHeight = chart.plotHeight,
  6281. seriesOptions = series.options,
  6282. smallestSize = Math.min(plotWidth, plotHeight),
  6283. extremes = {},
  6284. radii = [],
  6285. allDataPoints = chart.allDataPoints,
  6286. minSize,
  6287. maxSize,
  6288. value,
  6289. radius;
  6290. ['minSize', 'maxSize'].forEach(function (prop) {
  6291. var length = parseInt(seriesOptions[prop], 10),
  6292. isPercent = /%$/.test(length);
  6293. extremes[prop] = isPercent ?
  6294. smallestSize * length / 100 :
  6295. length;
  6296. });
  6297. chart.minRadius = minSize = extremes.minSize;
  6298. chart.maxRadius = maxSize = extremes.maxSize;
  6299. (allDataPoints || []).forEach(function (point, i) {
  6300. value = point[2];
  6301. radius = series.getRadius(
  6302. minSize,
  6303. maxSize,
  6304. minSize,
  6305. maxSize,
  6306. value
  6307. );
  6308. if (value === 0) {
  6309. radius = null;
  6310. }
  6311. allDataPoints[i][2] = radius;
  6312. radii.push(radius);
  6313. });
  6314. this.radii = radii;
  6315. },
  6316. alignDataLabel: H.Series.prototype.alignDataLabel
  6317. }
  6318. );
  6319. // When one series is modified, the others need to be recomputed
  6320. H.addEvent(H.seriesTypes.packedbubble, 'updatedData', function () {
  6321. var self = this;
  6322. this.chart.series.forEach(function (s) {
  6323. if (s.type === self.type) {
  6324. s.isDirty = true;
  6325. }
  6326. });
  6327. });
  6328. // Remove accumulated data points to redistribute all of them again
  6329. // (i.e after hiding series by legend)
  6330. H.addEvent(H.Chart, 'beforeRedraw', function () {
  6331. if (this.allDataPoints) {
  6332. delete this.allDataPoints;
  6333. }
  6334. });
  6335. /**
  6336. * A `packedbubble` series. If the [type](#series.packedbubble.type) option is
  6337. * not specified, it is inherited from [chart.type](#chart.type).
  6338. *
  6339. * @extends series,plotOptions.packedbubble
  6340. * @excluding dataParser, dataURL, stack
  6341. * @product highcharts highstock
  6342. * @apioption series.packedbubble
  6343. */
  6344. /**
  6345. * An array of data points for the series. For the `packedbubble` series type,
  6346. * points can be given in the following ways:
  6347. *
  6348. * 1. An array of `value` values.
  6349. * ```js
  6350. * data: [5, 1, 20]
  6351. * ```
  6352. *
  6353. * 2. An array of objects with named values. The objects are point configuration
  6354. * objects as seen below. If the total number of data points exceeds the
  6355. * series' [turboThreshold](#series.packedbubble.turboThreshold), this option
  6356. * is not available.
  6357. * ```js
  6358. * data: [{
  6359. * value: 1,
  6360. * name: "Point2",
  6361. * color: "#00FF00"
  6362. * }, {
  6363. * value: 5,
  6364. * name: "Point1",
  6365. * color: "#FF00FF"
  6366. * }]
  6367. * ```
  6368. *
  6369. * @sample {highcharts} highcharts/series/data-array-of-objects/
  6370. * Config objects
  6371. *
  6372. * @type {Array<number|*>}
  6373. * @extends series.line.data
  6374. * @excluding marker,x,y
  6375. * @product highcharts
  6376. * @apioption series.packedbubble.data
  6377. */
  6378. /**
  6379. * The value of a bubble. The bubble's size proportional to its `value`.
  6380. *
  6381. * @type {number}
  6382. * @product highcharts
  6383. * @apioption series.packedbubble.data.weight
  6384. */
  6385. /**
  6386. * @excluding enabled, enabledThreshold, height, radius, width
  6387. * @apioption series.packedbubble.marker
  6388. */
  6389. }(Highcharts));
  6390. (function (H) {
  6391. /* *
  6392. * (c) 2010-2019 Torstein Honsi
  6393. *
  6394. * License: www.highcharts.com/license
  6395. */
  6396. // Extensions for polar charts. Additionally, much of the geometry required for
  6397. // polar charts is gathered in RadialAxes.js.
  6398. var pick = H.pick,
  6399. Pointer = H.Pointer,
  6400. Series = H.Series,
  6401. seriesTypes = H.seriesTypes,
  6402. wrap = H.wrap,
  6403. seriesProto = Series.prototype,
  6404. pointerProto = Pointer.prototype,
  6405. colProto;
  6406. if (!H.polarExtended) {
  6407. H.polarExtended = true;
  6408. /**
  6409. * Search a k-d tree by the point angle, used for shared tooltips in polar
  6410. * charts
  6411. */
  6412. seriesProto.searchPointByAngle = function (e) {
  6413. var series = this,
  6414. chart = series.chart,
  6415. xAxis = series.xAxis,
  6416. center = xAxis.pane.center,
  6417. plotX = e.chartX - center[0] - chart.plotLeft,
  6418. plotY = e.chartY - center[1] - chart.plotTop;
  6419. return this.searchKDTree({
  6420. clientX: 180 + (Math.atan2(plotX, plotY) * (-180 / Math.PI))
  6421. });
  6422. };
  6423. /**
  6424. * #6212 Calculate connectors for spline series in polar chart.
  6425. * @param {boolean} calculateNeighbours
  6426. * Check if connectors should be calculated for neighbour points as
  6427. * well allows short recurence
  6428. */
  6429. seriesProto.getConnectors = function (
  6430. segment,
  6431. index,
  6432. calculateNeighbours,
  6433. connectEnds
  6434. ) {
  6435. var i,
  6436. prevPointInd,
  6437. nextPointInd,
  6438. previousPoint,
  6439. nextPoint,
  6440. previousX,
  6441. previousY,
  6442. nextX,
  6443. nextY,
  6444. plotX,
  6445. plotY,
  6446. ret,
  6447. // 1 means control points midway between points, 2 means 1/3 from
  6448. // the point, 3 is 1/4 etc;
  6449. smoothing = 1.5,
  6450. denom = smoothing + 1,
  6451. leftContX,
  6452. leftContY,
  6453. rightContX,
  6454. rightContY,
  6455. dLControlPoint, // distance left control point
  6456. dRControlPoint,
  6457. leftContAngle,
  6458. rightContAngle,
  6459. jointAngle,
  6460. addedNumber = connectEnds ? 1 : 0;
  6461. // Calculate final index of points depending on the initial index value.
  6462. // Because of calculating neighbours, index may be outisde segment
  6463. // array.
  6464. if (index >= 0 && index <= segment.length - 1) {
  6465. i = index;
  6466. } else if (index < 0) {
  6467. i = segment.length - 1 + index;
  6468. } else {
  6469. i = 0;
  6470. }
  6471. prevPointInd = (i - 1 < 0) ? segment.length - (1 + addedNumber) : i - 1;
  6472. nextPointInd = (i + 1 > segment.length - 1) ? addedNumber : i + 1;
  6473. previousPoint = segment[prevPointInd];
  6474. nextPoint = segment[nextPointInd];
  6475. previousX = previousPoint.plotX;
  6476. previousY = previousPoint.plotY;
  6477. nextX = nextPoint.plotX;
  6478. nextY = nextPoint.plotY;
  6479. plotX = segment[i].plotX; // actual point
  6480. plotY = segment[i].plotY;
  6481. leftContX = (smoothing * plotX + previousX) / denom;
  6482. leftContY = (smoothing * plotY + previousY) / denom;
  6483. rightContX = (smoothing * plotX + nextX) / denom;
  6484. rightContY = (smoothing * plotY + nextY) / denom;
  6485. dLControlPoint = Math.sqrt(
  6486. Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2)
  6487. );
  6488. dRControlPoint = Math.sqrt(
  6489. Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2)
  6490. );
  6491. leftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX);
  6492. rightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX);
  6493. jointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2);
  6494. // Ensure the right direction, jointAngle should be in the same quadrant
  6495. // as leftContAngle
  6496. if (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) {
  6497. jointAngle -= Math.PI;
  6498. }
  6499. // Find the corrected control points for a spline straight through the
  6500. // point
  6501. leftContX = plotX + Math.cos(jointAngle) * dLControlPoint;
  6502. leftContY = plotY + Math.sin(jointAngle) * dLControlPoint;
  6503. rightContX = plotX + Math.cos(Math.PI + jointAngle) * dRControlPoint;
  6504. rightContY = plotY + Math.sin(Math.PI + jointAngle) * dRControlPoint;
  6505. // push current point's connectors into returned object
  6506. ret = {
  6507. rightContX: rightContX,
  6508. rightContY: rightContY,
  6509. leftContX: leftContX,
  6510. leftContY: leftContY,
  6511. plotX: plotX,
  6512. plotY: plotY
  6513. };
  6514. // calculate connectors for previous and next point and push them inside
  6515. // returned object
  6516. if (calculateNeighbours) {
  6517. ret.prevPointCont = this.getConnectors(
  6518. segment,
  6519. prevPointInd,
  6520. false,
  6521. connectEnds
  6522. );
  6523. }
  6524. return ret;
  6525. };
  6526. /**
  6527. * Translate a point's plotX and plotY from the internal angle and radius
  6528. * measures to true plotX, plotY coordinates
  6529. */
  6530. seriesProto.toXY = function (point) {
  6531. var xy,
  6532. chart = this.chart,
  6533. plotX = point.plotX,
  6534. plotY = point.plotY,
  6535. clientX;
  6536. // Save rectangular plotX, plotY for later computation
  6537. point.rectPlotX = plotX;
  6538. point.rectPlotY = plotY;
  6539. // Find the polar plotX and plotY
  6540. xy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY);
  6541. point.plotX = point.polarPlotX = xy.x - chart.plotLeft;
  6542. point.plotY = point.polarPlotY = xy.y - chart.plotTop;
  6543. // If shared tooltip, record the angle in degrees in order to align X
  6544. // points. Otherwise, use a standard k-d tree to get the nearest point
  6545. // in two dimensions.
  6546. if (this.kdByAngle) {
  6547. clientX = (
  6548. (plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle
  6549. ) % 360;
  6550. if (clientX < 0) { // #2665
  6551. clientX += 360;
  6552. }
  6553. point.clientX = clientX;
  6554. } else {
  6555. point.clientX = point.plotX;
  6556. }
  6557. };
  6558. if (seriesTypes.spline) {
  6559. /**
  6560. * Overridden method for calculating a spline from one point to the next
  6561. */
  6562. wrap(
  6563. seriesTypes.spline.prototype,
  6564. 'getPointSpline',
  6565. function (proceed, segment, point, i) {
  6566. var ret,
  6567. connectors;
  6568. if (this.chart.polar) {
  6569. // moveTo or lineTo
  6570. if (!i) {
  6571. ret = ['M', point.plotX, point.plotY];
  6572. } else { // curve from last point to this
  6573. connectors = this.getConnectors(
  6574. segment,
  6575. i,
  6576. true,
  6577. this.connectEnds
  6578. );
  6579. ret = [
  6580. 'C',
  6581. connectors.prevPointCont.rightContX,
  6582. connectors.prevPointCont.rightContY,
  6583. connectors.leftContX,
  6584. connectors.leftContY,
  6585. connectors.plotX,
  6586. connectors.plotY
  6587. ];
  6588. }
  6589. } else {
  6590. ret = proceed.call(this, segment, point, i);
  6591. }
  6592. return ret;
  6593. }
  6594. );
  6595. // #6430 Areasplinerange series use unwrapped getPointSpline method, so
  6596. // we need to set this method again.
  6597. if (seriesTypes.areasplinerange) {
  6598. seriesTypes.areasplinerange.prototype.getPointSpline =
  6599. seriesTypes.spline.prototype.getPointSpline;
  6600. }
  6601. }
  6602. /**
  6603. * Extend translate. The plotX and plotY values are computed as if the polar
  6604. * chart were a cartesian plane, where plotX denotes the angle in radians
  6605. * and (yAxis.len - plotY) is the pixel distance from center.
  6606. */
  6607. H.addEvent(Series, 'afterTranslate', function () {
  6608. var chart = this.chart,
  6609. points,
  6610. i;
  6611. if (chart.polar) {
  6612. // Prepare k-d-tree handling. It searches by angle (clientX) in
  6613. // case of shared tooltip, and by two dimensional distance in case
  6614. // of non-shared.
  6615. this.kdByAngle = chart.tooltip && chart.tooltip.shared;
  6616. if (this.kdByAngle) {
  6617. this.searchPoint = this.searchPointByAngle;
  6618. } else {
  6619. this.options.findNearestPointBy = 'xy';
  6620. }
  6621. // Postprocess plot coordinates
  6622. if (!this.preventPostTranslate) {
  6623. points = this.points;
  6624. i = points.length;
  6625. while (i--) {
  6626. // Translate plotX, plotY from angle and radius to true plot
  6627. // coordinates
  6628. this.toXY(points[i]);
  6629. }
  6630. }
  6631. // Perform clip after render
  6632. if (!this.hasClipCircleSetter) {
  6633. this.hasClipCircleSetter = Boolean(
  6634. H.addEvent(this, 'afterRender', function () {
  6635. var circ;
  6636. if (chart.polar) {
  6637. circ = this.yAxis.center;
  6638. this.group.clip(
  6639. chart.renderer.clipCircle(
  6640. circ[0],
  6641. circ[1],
  6642. circ[2] / 2
  6643. )
  6644. );
  6645. this.setClip = H.noop;
  6646. }
  6647. })
  6648. );
  6649. }
  6650. }
  6651. }, { order: 2 }); // Run after translation of ||-coords
  6652. /**
  6653. * Extend getSegmentPath to allow connecting ends across 0 to provide a
  6654. * closed circle in line-like series.
  6655. */
  6656. wrap(seriesProto, 'getGraphPath', function (proceed, points) {
  6657. var series = this,
  6658. i,
  6659. firstValid,
  6660. popLastPoint;
  6661. // Connect the path
  6662. if (this.chart.polar) {
  6663. points = points || this.points;
  6664. // Append first valid point in order to connect the ends
  6665. for (i = 0; i < points.length; i++) {
  6666. if (!points[i].isNull) {
  6667. firstValid = i;
  6668. break;
  6669. }
  6670. }
  6671. /**
  6672. * Polar charts only. Whether to connect the ends of a line series
  6673. * plot across the extremes.
  6674. *
  6675. * @sample {highcharts} highcharts/plotoptions/line-connectends-false/
  6676. * Do not connect
  6677. *
  6678. * @type {boolean}
  6679. * @since 2.3.0
  6680. * @product highcharts
  6681. * @apioption plotOptions.series.connectEnds
  6682. */
  6683. if (this.options.connectEnds !== false &&
  6684. firstValid !== undefined
  6685. ) {
  6686. this.connectEnds = true; // re-used in splines
  6687. points.splice(points.length, 0, points[firstValid]);
  6688. popLastPoint = true;
  6689. }
  6690. // For area charts, pseudo points are added to the graph, now we
  6691. // need to translate these
  6692. points.forEach(function (point) {
  6693. if (point.polarPlotY === undefined) {
  6694. series.toXY(point);
  6695. }
  6696. });
  6697. }
  6698. // Run uber method
  6699. var ret = proceed.apply(this, [].slice.call(arguments, 1));
  6700. // #6212 points.splice method is adding points to an array. In case of
  6701. // areaspline getGraphPath method is used two times and in both times
  6702. // points are added to an array. That is why points.pop is used, to get
  6703. // unmodified points.
  6704. if (popLastPoint) {
  6705. points.pop();
  6706. }
  6707. return ret;
  6708. });
  6709. var polarAnimate = function (proceed, init) {
  6710. var chart = this.chart,
  6711. animation = this.options.animation,
  6712. group = this.group,
  6713. markerGroup = this.markerGroup,
  6714. center = this.xAxis.center,
  6715. plotLeft = chart.plotLeft,
  6716. plotTop = chart.plotTop,
  6717. attribs;
  6718. // Specific animation for polar charts
  6719. if (chart.polar) {
  6720. // Enable animation on polar charts only in SVG. In VML, the scaling
  6721. // is different, plus animation would be so slow it would't matter.
  6722. if (chart.renderer.isSVG) {
  6723. if (animation === true) {
  6724. animation = {};
  6725. }
  6726. // Initialize the animation
  6727. if (init) {
  6728. // Scale down the group and place it in the center
  6729. attribs = {
  6730. translateX: center[0] + plotLeft,
  6731. translateY: center[1] + plotTop,
  6732. scaleX: 0.001, // #1499
  6733. scaleY: 0.001
  6734. };
  6735. group.attr(attribs);
  6736. if (markerGroup) {
  6737. markerGroup.attr(attribs);
  6738. }
  6739. // Run the animation
  6740. } else {
  6741. attribs = {
  6742. translateX: plotLeft,
  6743. translateY: plotTop,
  6744. scaleX: 1,
  6745. scaleY: 1
  6746. };
  6747. group.animate(attribs, animation);
  6748. if (markerGroup) {
  6749. markerGroup.animate(attribs, animation);
  6750. }
  6751. // Delete this function to allow it only once
  6752. this.animate = null;
  6753. }
  6754. }
  6755. // For non-polar charts, revert to the basic animation
  6756. } else {
  6757. proceed.call(this, init);
  6758. }
  6759. };
  6760. // Define the animate method for regular series
  6761. wrap(seriesProto, 'animate', polarAnimate);
  6762. if (seriesTypes.column) {
  6763. colProto = seriesTypes.column.prototype;
  6764. colProto.polarArc = function (low, high, start, end) {
  6765. var center = this.xAxis.center,
  6766. len = this.yAxis.len;
  6767. return this.chart.renderer.symbols.arc(
  6768. center[0],
  6769. center[1],
  6770. len - high,
  6771. null,
  6772. {
  6773. start: start,
  6774. end: end,
  6775. innerR: len - pick(low, len)
  6776. }
  6777. );
  6778. };
  6779. /**
  6780. * Define the animate method for columnseries
  6781. */
  6782. wrap(colProto, 'animate', polarAnimate);
  6783. /**
  6784. * Extend the column prototype's translate method
  6785. */
  6786. wrap(colProto, 'translate', function (proceed) {
  6787. var xAxis = this.xAxis,
  6788. startAngleRad = xAxis.startAngleRad,
  6789. start,
  6790. points,
  6791. point,
  6792. i;
  6793. this.preventPostTranslate = true;
  6794. // Run uber method
  6795. proceed.call(this);
  6796. // Postprocess plot coordinates
  6797. if (xAxis.isRadial) {
  6798. points = this.points;
  6799. i = points.length;
  6800. while (i--) {
  6801. point = points[i];
  6802. start = point.barX + startAngleRad;
  6803. point.shapeType = 'path';
  6804. point.shapeArgs = {
  6805. d: this.polarArc(
  6806. point.yBottom,
  6807. point.plotY,
  6808. start,
  6809. start + point.pointWidth
  6810. )
  6811. };
  6812. // Provide correct plotX, plotY for tooltip
  6813. this.toXY(point);
  6814. point.tooltipPos = [point.plotX, point.plotY];
  6815. point.ttBelow = point.plotY > xAxis.center[1];
  6816. }
  6817. }
  6818. });
  6819. /**
  6820. * Align column data labels outside the columns. #1199.
  6821. */
  6822. wrap(colProto, 'alignDataLabel', function (
  6823. proceed,
  6824. point,
  6825. dataLabel,
  6826. options,
  6827. alignTo,
  6828. isNew
  6829. ) {
  6830. if (this.chart.polar) {
  6831. var angle = point.rectPlotX / Math.PI * 180,
  6832. align,
  6833. verticalAlign;
  6834. // Align nicely outside the perimeter of the columns
  6835. if (options.align === null) {
  6836. if (angle > 20 && angle < 160) {
  6837. align = 'left'; // right hemisphere
  6838. } else if (angle > 200 && angle < 340) {
  6839. align = 'right'; // left hemisphere
  6840. } else {
  6841. align = 'center'; // top or bottom
  6842. }
  6843. options.align = align;
  6844. }
  6845. if (options.verticalAlign === null) {
  6846. if (angle < 45 || angle > 315) {
  6847. verticalAlign = 'bottom'; // top part
  6848. } else if (angle > 135 && angle < 225) {
  6849. verticalAlign = 'top'; // bottom part
  6850. } else {
  6851. verticalAlign = 'middle'; // left or right
  6852. }
  6853. options.verticalAlign = verticalAlign;
  6854. }
  6855. seriesProto.alignDataLabel.call(
  6856. this,
  6857. point,
  6858. dataLabel,
  6859. options,
  6860. alignTo,
  6861. isNew
  6862. );
  6863. } else {
  6864. proceed.call(this, point, dataLabel, options, alignTo, isNew);
  6865. }
  6866. });
  6867. }
  6868. /**
  6869. * Extend getCoordinates to prepare for polar axis values
  6870. */
  6871. wrap(pointerProto, 'getCoordinates', function (proceed, e) {
  6872. var chart = this.chart,
  6873. ret = {
  6874. xAxis: [],
  6875. yAxis: []
  6876. };
  6877. if (chart.polar) {
  6878. chart.axes.forEach(function (axis) {
  6879. var isXAxis = axis.isXAxis,
  6880. center = axis.center,
  6881. x = e.chartX - center[0] - chart.plotLeft,
  6882. y = e.chartY - center[1] - chart.plotTop;
  6883. ret[isXAxis ? 'xAxis' : 'yAxis'].push({
  6884. axis: axis,
  6885. value: axis.translate(
  6886. isXAxis ?
  6887. Math.PI - Math.atan2(x, y) : // angle
  6888. // distance from center
  6889. Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)),
  6890. true
  6891. )
  6892. });
  6893. });
  6894. } else {
  6895. ret = proceed.call(this, e);
  6896. }
  6897. return ret;
  6898. });
  6899. H.SVGRenderer.prototype.clipCircle = function (x, y, r) {
  6900. var wrapper,
  6901. id = H.uniqueKey(),
  6902. clipPath = this.createElement('clipPath').attr({
  6903. id: id
  6904. }).add(this.defs);
  6905. wrapper = this.circle(x, y, r).add(clipPath);
  6906. wrapper.id = id;
  6907. wrapper.clipPath = clipPath;
  6908. return wrapper;
  6909. };
  6910. H.addEvent(H.Chart, 'getAxes', function () {
  6911. if (!this.pane) {
  6912. this.pane = [];
  6913. }
  6914. H.splat(this.options.pane).forEach(function (paneOptions) {
  6915. new H.Pane( // eslint-disable-line no-new
  6916. paneOptions,
  6917. this
  6918. );
  6919. }, this);
  6920. });
  6921. H.addEvent(H.Chart, 'afterDrawChartBox', function () {
  6922. this.pane.forEach(function (pane) {
  6923. pane.render();
  6924. });
  6925. });
  6926. /**
  6927. * Extend chart.get to also search in panes. Used internally in
  6928. * responsiveness and chart.update.
  6929. */
  6930. wrap(H.Chart.prototype, 'get', function (proceed, id) {
  6931. return H.find(this.pane, function (pane) {
  6932. return pane.options.id === id;
  6933. }) || proceed.call(this, id);
  6934. });
  6935. }
  6936. }(Highcharts));
  6937. return (function () {
  6938. }());
  6939. }));