highcharts-3d.src.js 225 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337
  1. /**
  2. * @license Highcharts JS v9.0.1 (2021-02-16)
  3. *
  4. * 3D features for Highcharts JS
  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('highcharts/highcharts-3d', ['highcharts'], function (Highcharts) {
  15. factory(Highcharts);
  16. factory.Highcharts = Highcharts;
  17. return factory;
  18. });
  19. } else {
  20. factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
  21. }
  22. }(function (Highcharts) {
  23. var _modules = Highcharts ? Highcharts._modules : {};
  24. function _registerModule(obj, path, args, fn) {
  25. if (!obj.hasOwnProperty(path)) {
  26. obj[path] = fn.apply(null, args);
  27. }
  28. }
  29. _registerModule(_modules, 'Extensions/Math3D.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
  30. /* *
  31. *
  32. * (c) 2010-2021 Torstein Honsi
  33. *
  34. * License: www.highcharts.com/license
  35. *
  36. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  37. *
  38. * */
  39. var pick = U.pick;
  40. // Mathematical Functionility
  41. var deg2rad = H.deg2rad;
  42. /* eslint-disable max-len */
  43. /**
  44. * Apply 3-D rotation
  45. * Euler Angles (XYZ):
  46. * cosA = cos(Alfa|Roll)
  47. * cosB = cos(Beta|Pitch)
  48. * cosG = cos(Gamma|Yaw)
  49. *
  50. * Composite rotation:
  51. * | cosB * cosG | cosB * sinG | -sinB |
  52. * | sinA * sinB * cosG - cosA * sinG | sinA * sinB * sinG + cosA * cosG | sinA * cosB |
  53. * | cosA * sinB * cosG + sinA * sinG | cosA * sinB * sinG - sinA * cosG | cosA * cosB |
  54. *
  55. * Now, Gamma/Yaw is not used (angle=0), so we assume cosG = 1 and sinG = 0, so
  56. * we get:
  57. * | cosB | 0 | - sinB |
  58. * | sinA * sinB | cosA | sinA * cosB |
  59. * | cosA * sinB | - sinA | cosA * cosB |
  60. *
  61. * But in browsers, y is reversed, so we get sinA => -sinA. The general result
  62. * is:
  63. * | cosB | 0 | - sinB | | x | | px |
  64. * | - sinA * sinB | cosA | - sinA * cosB | x | y | = | py |
  65. * | cosA * sinB | sinA | cosA * cosB | | z | | pz |
  66. *
  67. * @private
  68. * @function rotate3D
  69. */
  70. /* eslint-enable max-len */
  71. /**
  72. * @private
  73. * @param {number} x
  74. * X coordinate
  75. * @param {number} y
  76. * Y coordinate
  77. * @param {number} z
  78. * Z coordinate
  79. * @param {Highcharts.Rotation3dObject} angles
  80. * Rotation angles
  81. * @return {Highcharts.Rotation3dObject}
  82. * Rotated position
  83. */
  84. function rotate3D(x, y, z, angles) {
  85. return {
  86. x: angles.cosB * x - angles.sinB * z,
  87. y: -angles.sinA * angles.sinB * x + angles.cosA * y -
  88. angles.cosB * angles.sinA * z,
  89. z: angles.cosA * angles.sinB * x + angles.sinA * y +
  90. angles.cosA * angles.cosB * z
  91. };
  92. }
  93. /**
  94. * Perspective3D function is available in global Highcharts scope because is
  95. * needed also outside of perspective() function (#8042).
  96. * @private
  97. * @function Highcharts.perspective3D
  98. *
  99. * @param {Highcharts.Position3DObject} coordinate
  100. * 3D position
  101. *
  102. * @param {Highcharts.Position3DObject} origin
  103. * 3D root position
  104. *
  105. * @param {number} distance
  106. * Perspective distance
  107. *
  108. * @return {Highcharts.PositionObject}
  109. * Perspective 3D Position
  110. *
  111. * @requires highcharts-3d
  112. */
  113. function perspective3D(coordinate, origin, distance) {
  114. var projection = ((distance > 0) && (distance < Number.POSITIVE_INFINITY)) ?
  115. distance / (coordinate.z + origin.z + distance) :
  116. 1;
  117. return {
  118. x: coordinate.x * projection,
  119. y: coordinate.y * projection
  120. };
  121. }
  122. H.perspective3D = perspective3D;
  123. /**
  124. * Transforms a given array of points according to the angles in chart.options.
  125. *
  126. * @private
  127. * @function Highcharts.perspective
  128. *
  129. * @param {Array<Highcharts.Position3DObject>} points
  130. * The array of points
  131. *
  132. * @param {Highcharts.Chart} chart
  133. * The chart
  134. *
  135. * @param {boolean} [insidePlotArea]
  136. * Whether to verify that the points are inside the plotArea
  137. *
  138. * @param {boolean} [useInvertedPersp]
  139. * Whether to use inverted perspective in calculations
  140. *
  141. * @return {Array<Highcharts.Position3DObject>}
  142. * An array of transformed points
  143. *
  144. * @requires highcharts-3d
  145. */
  146. function perspective(points, chart, insidePlotArea, useInvertedPersp) {
  147. var options3d = chart.options.chart.options3d,
  148. /* The useInvertedPersp argument is used for
  149. * inverted charts with already inverted elements,
  150. * such as dataLabels or tooltip positions.
  151. */
  152. inverted = pick(useInvertedPersp,
  153. insidePlotArea ? chart.inverted : false),
  154. origin = {
  155. x: chart.plotWidth / 2,
  156. y: chart.plotHeight / 2,
  157. z: options3d.depth / 2,
  158. vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
  159. },
  160. scale = chart.scale3d || 1,
  161. beta = deg2rad * options3d.beta * (inverted ? -1 : 1),
  162. alpha = deg2rad * options3d.alpha * (inverted ? -1 : 1),
  163. angles = {
  164. cosA: Math.cos(alpha),
  165. cosB: Math.cos(-beta),
  166. sinA: Math.sin(alpha),
  167. sinB: Math.sin(-beta)
  168. };
  169. if (!insidePlotArea) {
  170. origin.x += chart.plotLeft;
  171. origin.y += chart.plotTop;
  172. }
  173. // Transform each point
  174. return points.map(function (point) {
  175. var rotated = rotate3D((inverted ? point.y : point.x) - origin.x, (inverted ? point.x : point.y) - origin.y, (point.z || 0) - origin.z,
  176. angles),
  177. // Apply perspective
  178. coordinate = perspective3D(rotated,
  179. origin,
  180. origin.vd);
  181. // Apply translation
  182. coordinate.x = coordinate.x * scale + origin.x;
  183. coordinate.y = coordinate.y * scale + origin.y;
  184. coordinate.z = rotated.z * scale + origin.z;
  185. return {
  186. x: (inverted ? coordinate.y : coordinate.x),
  187. y: (inverted ? coordinate.x : coordinate.y),
  188. z: coordinate.z
  189. };
  190. });
  191. }
  192. H.perspective = perspective;
  193. /**
  194. * Calculate a distance from camera to points - made for calculating zIndex of
  195. * scatter points.
  196. *
  197. * @private
  198. * @function Highcharts.pointCameraDistance
  199. *
  200. * @param {Highcharts.Dictionary<number>} coordinates
  201. * Coordinates of the specific point
  202. *
  203. * @param {Highcharts.Chart} chart
  204. * Related chart
  205. *
  206. * @return {number}
  207. * Distance from camera to point
  208. *
  209. * @requires highcharts-3d
  210. */
  211. function pointCameraDistance(coordinates, chart) {
  212. var options3d = chart.options.chart.options3d,
  213. cameraPosition = {
  214. x: chart.plotWidth / 2,
  215. y: chart.plotHeight / 2,
  216. z: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0) +
  217. options3d.depth
  218. },
  219. // Added support for objects with plotX or x coordinates.
  220. distance = Math.sqrt(Math.pow(cameraPosition.x - pick(coordinates.plotX,
  221. coordinates.x), 2) +
  222. Math.pow(cameraPosition.y - pick(coordinates.plotY,
  223. coordinates.y), 2) +
  224. Math.pow(cameraPosition.z - pick(coordinates.plotZ,
  225. coordinates.z), 2));
  226. return distance;
  227. }
  228. H.pointCameraDistance = pointCameraDistance;
  229. /**
  230. * Calculate area of a 2D polygon using Shoelace algorithm
  231. * https://en.wikipedia.org/wiki/Shoelace_formula
  232. *
  233. * @private
  234. * @function Highcharts.shapeArea
  235. *
  236. * @param {Array<Highcharts.PositionObject>} vertexes
  237. * 2D Polygon
  238. *
  239. * @return {number}
  240. * Calculated area
  241. *
  242. * @requires highcharts-3d
  243. */
  244. function shapeArea(vertexes) {
  245. var area = 0,
  246. i,
  247. j;
  248. for (i = 0; i < vertexes.length; i++) {
  249. j = (i + 1) % vertexes.length;
  250. area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y;
  251. }
  252. return area / 2;
  253. }
  254. H.shapeArea = shapeArea;
  255. /**
  256. * Calculate area of a 3D polygon after perspective projection
  257. *
  258. * @private
  259. * @function Highcharts.shapeArea3d
  260. *
  261. * @param {Array<Highcharts.Position3DObject>} vertexes
  262. * 3D Polygon
  263. *
  264. * @param {Highcharts.Chart} chart
  265. * Related chart
  266. *
  267. * @param {boolean} [insidePlotArea]
  268. * Whether to verify that the points are inside the plotArea
  269. *
  270. * @return {number}
  271. * Calculated area
  272. *
  273. * @requires highcharts-3d
  274. */
  275. function shapeArea3D(vertexes, chart, insidePlotArea) {
  276. return shapeArea(perspective(vertexes, chart, insidePlotArea));
  277. }
  278. H.shapeArea3d = shapeArea3D;
  279. var mathModule = {
  280. perspective: perspective,
  281. perspective3D: perspective3D,
  282. pointCameraDistance: pointCameraDistance,
  283. shapeArea: shapeArea,
  284. shapeArea3D: shapeArea3D
  285. };
  286. return mathModule;
  287. });
  288. _registerModule(_modules, 'Core/Renderer/SVG/SVGElement3D.js', [_modules['Core/Color/Color.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Utilities.js']], function (Color, SVGElement, U) {
  289. /* *
  290. *
  291. * (c) 2010-2021 Torstein Honsi
  292. *
  293. * Extensions to the SVGRenderer class to enable 3D shapes
  294. *
  295. * License: www.highcharts.com/license
  296. *
  297. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  298. *
  299. * */
  300. var color = Color.parse;
  301. var defined = U.defined,
  302. merge = U.merge,
  303. objectEach = U.objectEach,
  304. pick = U.pick;
  305. /* *
  306. *
  307. * Namespace
  308. *
  309. * */
  310. var SVGElement3D;
  311. (function (SVGElement3D) {
  312. /* *
  313. *
  314. * Functions
  315. *
  316. * */
  317. /* eslint-disable valid-jsdoc */
  318. SVGElement3D.base = {
  319. /**
  320. * The init is used by base - renderer.Element
  321. * @private
  322. */
  323. initArgs: function (args) {
  324. var elem3d = this,
  325. renderer = elem3d.renderer,
  326. paths = renderer[elem3d.pathType + 'Path'](args),
  327. zIndexes = paths.zIndexes;
  328. // build parts
  329. elem3d.parts.forEach(function (part) {
  330. elem3d[part] = renderer.path(paths[part]).attr({
  331. 'class': 'highcharts-3d-' + part,
  332. zIndex: zIndexes[part] || 0
  333. }).add(elem3d);
  334. });
  335. elem3d.attr({
  336. 'stroke-linejoin': 'round',
  337. zIndex: zIndexes.group
  338. });
  339. // store original destroy
  340. elem3d.originalDestroy = elem3d.destroy;
  341. elem3d.destroy = elem3d.destroyParts;
  342. // Store information if any side of element was rendered by force.
  343. elem3d.forcedSides = paths.forcedSides;
  344. },
  345. /**
  346. * Single property setter that applies options to each part
  347. * @private
  348. */
  349. singleSetterForParts: function (prop, val, values, verb, duration, complete) {
  350. var elem3d = this,
  351. newAttr = {},
  352. optionsToApply = [null,
  353. null, (verb || 'attr'),
  354. duration,
  355. complete],
  356. hasZIndexes = values && values.zIndexes;
  357. if (!values) {
  358. newAttr[prop] = val;
  359. optionsToApply[0] = newAttr;
  360. }
  361. else {
  362. // It is needed to deal with the whole group zIndexing
  363. // in case of graph rotation
  364. if (hasZIndexes && hasZIndexes.group) {
  365. this.attr({
  366. zIndex: hasZIndexes.group
  367. });
  368. }
  369. objectEach(values, function (partVal, part) {
  370. newAttr[part] = {};
  371. newAttr[part][prop] = partVal;
  372. // include zIndexes if provided
  373. if (hasZIndexes) {
  374. newAttr[part].zIndex = values.zIndexes[part] || 0;
  375. }
  376. });
  377. optionsToApply[1] = newAttr;
  378. }
  379. return elem3d.processParts.apply(elem3d, optionsToApply);
  380. },
  381. /**
  382. * Calls function for each part. Used for attr, animate and destroy.
  383. * @private
  384. */
  385. processParts: function (props, partsProps, verb, duration, complete) {
  386. var elem3d = this;
  387. elem3d.parts.forEach(function (part) {
  388. // if different props for different parts
  389. if (partsProps) {
  390. props = pick(partsProps[part], false);
  391. }
  392. // only if something to set, but allow undefined
  393. if (props !== false) {
  394. elem3d[part][verb](props, duration, complete);
  395. }
  396. });
  397. return elem3d;
  398. },
  399. /**
  400. * Destroy all parts
  401. * @private
  402. */
  403. destroyParts: function () {
  404. this.processParts(null, null, 'destroy');
  405. return this.originalDestroy();
  406. }
  407. };
  408. SVGElement3D.cuboid = merge(SVGElement3D.base, {
  409. parts: ['front', 'top', 'side'],
  410. pathType: 'cuboid',
  411. attr: function (args, val, complete, continueAnimation) {
  412. // Resolve setting attributes by string name
  413. if (typeof args === 'string' && typeof val !== 'undefined') {
  414. var key = args;
  415. args = {};
  416. args[key] = val;
  417. }
  418. if (args.shapeArgs || defined(args.x)) {
  419. return this.singleSetterForParts('d', null, this.renderer[this.pathType + 'Path'](args.shapeArgs || args));
  420. }
  421. return SVGElement.prototype.attr.call(this, args, void 0, complete, continueAnimation);
  422. },
  423. animate: function (args, duration, complete) {
  424. if (defined(args.x) && defined(args.y)) {
  425. var paths = this.renderer[this.pathType + 'Path'](args),
  426. forcedSides = paths.forcedSides;
  427. this.singleSetterForParts('d', null, paths, 'animate', duration, complete);
  428. this.attr({
  429. zIndex: paths.zIndexes.group
  430. });
  431. // If sides that are forced to render changed, recalculate
  432. // colors.
  433. if (forcedSides !== this.forcedSides) {
  434. this.forcedSides = forcedSides;
  435. SVGElement3D.cuboid.fillSetter.call(this, this.fill);
  436. }
  437. }
  438. else {
  439. SVGElement.prototype.animate.call(this, args, duration, complete);
  440. }
  441. return this;
  442. },
  443. fillSetter: function (fill) {
  444. var elem3d = this;
  445. elem3d.forcedSides = elem3d.forcedSides || [];
  446. elem3d.singleSetterForParts('fill', null, {
  447. front: fill,
  448. // Do not change color if side was forced to render.
  449. top: color(fill).brighten(elem3d.forcedSides.indexOf('top') >= 0 ? 0 : 0.1).get(),
  450. side: color(fill).brighten(elem3d.forcedSides.indexOf('side') >= 0 ? 0 : -0.1).get()
  451. });
  452. // fill for animation getter (#6776)
  453. elem3d.color = elem3d.fill = fill;
  454. return elem3d;
  455. }
  456. });
  457. /* eslint-enable valid-jsdoc */
  458. })(SVGElement3D || (SVGElement3D = {}));
  459. return SVGElement3D;
  460. });
  461. _registerModule(_modules, 'Core/Renderer/SVG/SVGRenderer3D.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Extensions/Math3D.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Renderer/SVG/SVGElement3D.js'], _modules['Core/Renderer/SVG/SVGRenderer.js'], _modules['Core/Utilities.js']], function (A, Color, H, Math3D, SVGElement, SVGElement3D, SVGRenderer, U) {
  462. /* *
  463. *
  464. * (c) 2010-2021 Torstein Honsi
  465. *
  466. * Extensions to the SVGRenderer class to enable 3D shapes
  467. *
  468. * License: www.highcharts.com/license
  469. *
  470. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  471. *
  472. * */
  473. var animObject = A.animObject;
  474. var color = Color.parse;
  475. var charts = H.charts,
  476. deg2rad = H.deg2rad;
  477. var perspective = Math3D.perspective,
  478. shapeArea = Math3D.shapeArea;
  479. var defined = U.defined,
  480. extend = U.extend,
  481. merge = U.merge,
  482. pick = U.pick;
  483. /* *
  484. *
  485. * Constants
  486. *
  487. * */
  488. var cos = Math.cos,
  489. sin = Math.sin,
  490. PI = Math.PI,
  491. dFactor = (4 * (Math.sqrt(2) - 1) / 3) / (PI / 2);
  492. /* *
  493. *
  494. * Functions
  495. *
  496. * */
  497. /* eslint-disable valid-jsdoc */
  498. /**
  499. * Method to construct a curved path. Can 'wrap' around more then 180 degrees.
  500. * @private
  501. */
  502. function curveTo(cx, cy, rx, ry, start, end, dx, dy) {
  503. var result = [],
  504. arcAngle = end - start;
  505. if ((end > start) && (end - start > Math.PI / 2 + 0.0001)) {
  506. result = result.concat(curveTo(cx, cy, rx, ry, start, start + (Math.PI / 2), dx, dy));
  507. result = result.concat(curveTo(cx, cy, rx, ry, start + (Math.PI / 2), end, dx, dy));
  508. return result;
  509. }
  510. if ((end < start) && (start - end > Math.PI / 2 + 0.0001)) {
  511. result = result.concat(curveTo(cx, cy, rx, ry, start, start - (Math.PI / 2), dx, dy));
  512. result = result.concat(curveTo(cx, cy, rx, ry, start - (Math.PI / 2), end, dx, dy));
  513. return result;
  514. }
  515. return [[
  516. 'C',
  517. cx + (rx * Math.cos(start)) -
  518. ((rx * dFactor * arcAngle) * Math.sin(start)) + dx,
  519. cy + (ry * Math.sin(start)) +
  520. ((ry * dFactor * arcAngle) * Math.cos(start)) + dy,
  521. cx + (rx * Math.cos(end)) +
  522. ((rx * dFactor * arcAngle) * Math.sin(end)) + dx,
  523. cy + (ry * Math.sin(end)) -
  524. ((ry * dFactor * arcAngle) * Math.cos(end)) + dy,
  525. cx + (rx * Math.cos(end)) + dx,
  526. cy + (ry * Math.sin(end)) + dy
  527. ]];
  528. }
  529. /* *
  530. *
  531. * Composition
  532. *
  533. * */
  534. SVGRenderer.prototype.elements3d = SVGElement3D;
  535. SVGRenderer.prototype.toLinePath = function (points, closed) {
  536. var result = [];
  537. // Put "L x y" for each point
  538. points.forEach(function (point) {
  539. result.push(['L', point.x, point.y]);
  540. });
  541. if (points.length) {
  542. // Set the first element to M
  543. result[0][0] = 'M';
  544. // If it is a closed line, add Z
  545. if (closed) {
  546. result.push(['Z']);
  547. }
  548. }
  549. return result;
  550. };
  551. SVGRenderer.prototype.toLineSegments = function (points) {
  552. var result = [],
  553. m = true;
  554. points.forEach(function (point) {
  555. result.push(m ? ['M', point.x, point.y] : ['L', point.x, point.y]);
  556. m = !m;
  557. });
  558. return result;
  559. };
  560. // A 3-D Face is defined by it's 3D vertexes, and is only visible if it's
  561. // vertexes are counter-clockwise (Back-face culling). It is used as a
  562. // polyhedron Element
  563. SVGRenderer.prototype.face3d = function (args) {
  564. var renderer = this,
  565. ret = this.createElement('path');
  566. ret.vertexes = [];
  567. ret.insidePlotArea = false;
  568. ret.enabled = true;
  569. /* eslint-disable no-invalid-this */
  570. ret.attr = function (hash) {
  571. if (typeof hash === 'object' &&
  572. (defined(hash.enabled) ||
  573. defined(hash.vertexes) ||
  574. defined(hash.insidePlotArea))) {
  575. this.enabled = pick(hash.enabled, this.enabled);
  576. this.vertexes = pick(hash.vertexes, this.vertexes);
  577. this.insidePlotArea = pick(hash.insidePlotArea, this.insidePlotArea);
  578. delete hash.enabled;
  579. delete hash.vertexes;
  580. delete hash.insidePlotArea;
  581. var chart = charts[renderer.chartIndex],
  582. vertexes2d = perspective(this.vertexes,
  583. chart,
  584. this.insidePlotArea),
  585. path = renderer.toLinePath(vertexes2d,
  586. true),
  587. area = shapeArea(vertexes2d),
  588. visibility = (this.enabled && area > 0) ? 'visible' : 'hidden';
  589. hash.d = path;
  590. hash.visibility = visibility;
  591. }
  592. return SVGElement.prototype.attr.apply(this, arguments);
  593. };
  594. ret.animate = function (params) {
  595. if (typeof params === 'object' &&
  596. (defined(params.enabled) ||
  597. defined(params.vertexes) ||
  598. defined(params.insidePlotArea))) {
  599. this.enabled = pick(params.enabled, this.enabled);
  600. this.vertexes = pick(params.vertexes, this.vertexes);
  601. this.insidePlotArea = pick(params.insidePlotArea, this.insidePlotArea);
  602. delete params.enabled;
  603. delete params.vertexes;
  604. delete params.insidePlotArea;
  605. var chart = charts[renderer.chartIndex],
  606. vertexes2d = perspective(this.vertexes,
  607. chart,
  608. this.insidePlotArea),
  609. path = renderer.toLinePath(vertexes2d,
  610. true),
  611. area = shapeArea(vertexes2d),
  612. visibility = (this.enabled && area > 0) ? 'visible' : 'hidden';
  613. params.d = path;
  614. this.attr('visibility', visibility);
  615. }
  616. return SVGElement.prototype.animate.apply(this, arguments);
  617. };
  618. /* eslint-enable no-invalid-this */
  619. return ret.attr(args);
  620. };
  621. // A Polyhedron is a handy way of defining a group of 3-D faces. It's only
  622. // attribute is `faces`, an array of attributes of each one of it's Face3D
  623. // instances.
  624. SVGRenderer.prototype.polyhedron = function (args) {
  625. var renderer = this,
  626. result = this.g(),
  627. destroy = result.destroy;
  628. if (!this.styledMode) {
  629. result.attr({
  630. 'stroke-linejoin': 'round'
  631. });
  632. }
  633. result.faces = [];
  634. /* eslint-disable no-invalid-this */
  635. // destroy all children
  636. result.destroy = function () {
  637. for (var i = 0; i < result.faces.length; i++) {
  638. result.faces[i].destroy();
  639. }
  640. return destroy.call(this);
  641. };
  642. result.attr = function (hash, val, complete, continueAnimation) {
  643. if (typeof hash === 'object' && defined(hash.faces)) {
  644. while (result.faces.length > hash.faces.length) {
  645. result.faces.pop().destroy();
  646. }
  647. while (result.faces.length < hash.faces.length) {
  648. result.faces.push(renderer.face3d().add(result));
  649. }
  650. for (var i = 0; i < hash.faces.length; i++) {
  651. if (renderer.styledMode) {
  652. delete hash.faces[i].fill;
  653. }
  654. result.faces[i].attr(hash.faces[i], null, complete, continueAnimation);
  655. }
  656. delete hash.faces;
  657. }
  658. return SVGElement.prototype.attr.apply(this, arguments);
  659. };
  660. result.animate = function (params, duration, complete) {
  661. if (params && params.faces) {
  662. while (result.faces.length > params.faces.length) {
  663. result.faces.pop().destroy();
  664. }
  665. while (result.faces.length < params.faces.length) {
  666. result.faces.push(renderer.face3d().add(result));
  667. }
  668. for (var i = 0; i < params.faces.length; i++) {
  669. result.faces[i].animate(params.faces[i], duration, complete);
  670. }
  671. delete params.faces;
  672. }
  673. return SVGElement.prototype.animate.apply(this, arguments);
  674. };
  675. /* eslint-enable no-invalid-this */
  676. return result.attr(args);
  677. };
  678. /**
  679. * return result, generalization
  680. * @private
  681. * @requires highcharts-3d
  682. */
  683. SVGRenderer.prototype.element3d = function (type, shapeArgs) {
  684. // base
  685. var ret = this.g();
  686. // extend
  687. extend(ret, this.elements3d[type]);
  688. // init
  689. ret.initArgs(shapeArgs);
  690. // return
  691. return ret;
  692. };
  693. // generelized, so now use simply
  694. SVGRenderer.prototype.cuboid = function (shapeArgs) {
  695. return this.element3d('cuboid', shapeArgs);
  696. };
  697. // Generates a cuboid path and zIndexes
  698. SVGRenderer.prototype.cuboidPath = function (shapeArgs) {
  699. var x = shapeArgs.x,
  700. y = shapeArgs.y,
  701. z = shapeArgs.z || 0,
  702. // For side calculation (right/left)
  703. // there is a need for height (and other shapeArgs arguments)
  704. // to be at least 1px
  705. h = shapeArgs.height,
  706. w = shapeArgs.width,
  707. d = shapeArgs.depth,
  708. chart = charts[this.chartIndex],
  709. front,
  710. back,
  711. top,
  712. bottom,
  713. left,
  714. right,
  715. shape,
  716. path1,
  717. path2,
  718. path3,
  719. isFront,
  720. isTop,
  721. isRight,
  722. options3d = chart.options.chart.options3d,
  723. alpha = options3d.alpha,
  724. // Priority for x axis is the biggest,
  725. // because of x direction has biggest influence on zIndex
  726. incrementX = 1000000,
  727. // y axis has the smallest priority in case of our charts
  728. // (needs to be set because of stacking)
  729. incrementY = 10,
  730. incrementZ = 100,
  731. zIndex = 0,
  732. // The 8 corners of the cube
  733. pArr = [{
  734. x: x,
  735. y: y,
  736. z: z
  737. }, {
  738. x: x + w,
  739. y: y,
  740. z: z
  741. }, {
  742. x: x + w,
  743. y: y + h,
  744. z: z
  745. }, {
  746. x: x,
  747. y: y + h,
  748. z: z
  749. }, {
  750. x: x,
  751. y: y + h,
  752. z: z + d
  753. }, {
  754. x: x + w,
  755. y: y + h,
  756. z: z + d
  757. }, {
  758. x: x + w,
  759. y: y,
  760. z: z + d
  761. }, {
  762. x: x,
  763. y: y,
  764. z: z + d
  765. }],
  766. forcedSides = [],
  767. pickShape;
  768. // apply perspective
  769. pArr = perspective(pArr, chart, shapeArgs.insidePlotArea);
  770. /**
  771. * helper method to decide which side is visible
  772. * @private
  773. */
  774. function mapSidePath(i) {
  775. // Added support for 0 value in columns, where height is 0
  776. // but the shape is rendered.
  777. // Height is used from 1st to 6th element of pArr
  778. if (h === 0 && i > 1 && i < 6) { // [2, 3, 4, 5]
  779. return {
  780. x: pArr[i].x,
  781. // when height is 0 instead of cuboid we render plane
  782. // so it is needed to add fake 10 height to imitate cuboid
  783. // for side calculation
  784. y: pArr[i].y + 10,
  785. z: pArr[i].z
  786. };
  787. }
  788. // It is needed to calculate dummy sides (front/back) for breaking
  789. // points in case of x and depth values. If column has side,
  790. // it means that x values of front and back side are different.
  791. if (pArr[0].x === pArr[7].x && i >= 4) { // [4, 5, 6, 7]
  792. return {
  793. x: pArr[i].x + 10,
  794. // when height is 0 instead of cuboid we render plane
  795. // so it is needed to add fake 10 height to imitate cuboid
  796. // for side calculation
  797. y: pArr[i].y,
  798. z: pArr[i].z
  799. };
  800. }
  801. // Added dummy depth
  802. if (d === 0 && i < 2 || i > 5) { // [0, 1, 6, 7]
  803. return {
  804. x: pArr[i].x,
  805. // when height is 0 instead of cuboid we render plane
  806. // so it is needed to add fake 10 height to imitate cuboid
  807. // for side calculation
  808. y: pArr[i].y,
  809. z: pArr[i].z + 10
  810. };
  811. }
  812. return pArr[i];
  813. }
  814. /**
  815. * method creating the final side
  816. * @private
  817. */
  818. function mapPath(i) {
  819. return pArr[i];
  820. }
  821. /**
  822. * First value - path with specific face
  823. * Second value - added information about side for later calculations.
  824. * Possible second values are 0 for path1, 1 for path2 and -1 for no path
  825. * chosen.
  826. * Third value - string containing information about current side
  827. * of cuboid for forcing side rendering.
  828. * @private
  829. */
  830. pickShape = function (verticesIndex1, verticesIndex2, side) {
  831. var ret = [[], -1],
  832. // An array of vertices for cuboid face
  833. face1 = verticesIndex1.map(mapPath),
  834. face2 = verticesIndex2.map(mapPath),
  835. // dummy face is calculated the same way as standard face,
  836. // but if cuboid height is 0 additional height is added so it is
  837. // possible to use this vertices array for visible face calculation
  838. dummyFace1 = verticesIndex1.map(mapSidePath),
  839. dummyFace2 = verticesIndex2.map(mapSidePath);
  840. if (shapeArea(face1) < 0) {
  841. ret = [face1, 0];
  842. }
  843. else if (shapeArea(face2) < 0) {
  844. ret = [face2, 1];
  845. }
  846. else if (side) {
  847. forcedSides.push(side);
  848. if (shapeArea(dummyFace1) < 0) {
  849. ret = [face1, 0];
  850. }
  851. else if (shapeArea(dummyFace2) < 0) {
  852. ret = [face2, 1];
  853. }
  854. else {
  855. ret = [face1, 0]; // force side calculation.
  856. }
  857. }
  858. return ret;
  859. };
  860. // front or back
  861. front = [3, 2, 1, 0];
  862. back = [7, 6, 5, 4];
  863. shape = pickShape(front, back, 'front');
  864. path1 = shape[0];
  865. isFront = shape[1];
  866. // top or bottom
  867. top = [1, 6, 7, 0];
  868. bottom = [4, 5, 2, 3];
  869. shape = pickShape(top, bottom, 'top');
  870. path2 = shape[0];
  871. isTop = shape[1];
  872. // side
  873. right = [1, 2, 5, 6];
  874. left = [0, 7, 4, 3];
  875. shape = pickShape(right, left, 'side');
  876. path3 = shape[0];
  877. isRight = shape[1];
  878. /* New block used for calculating zIndex. It is basing on X, Y and Z
  879. position of specific columns. All zIndexes (for X, Y and Z values) are
  880. added to the final zIndex, where every value has different priority. The
  881. biggest priority is in X and Z directions, the lowest index is for
  882. stacked columns (Y direction and the same X and Z positions). Big
  883. differences between priorities is made because we need to ensure that
  884. even for big changes in Y and Z parameters all columns will be drawn
  885. correctly. */
  886. if (isRight === 1) {
  887. // It is needed to connect value with current chart width
  888. // for big chart size.
  889. zIndex += incrementX * (chart.plotWidth - x);
  890. }
  891. else if (!isRight) {
  892. zIndex += incrementX * x;
  893. }
  894. zIndex += incrementY * (!isTop ||
  895. // Numbers checked empirically
  896. (alpha >= 0 && alpha <= 180 || alpha < 360 && alpha > 357.5) ?
  897. chart.plotHeight - y : 10 + y);
  898. if (isFront === 1) {
  899. zIndex += incrementZ * (z);
  900. }
  901. else if (!isFront) {
  902. zIndex += incrementZ * (1000 - z);
  903. }
  904. return {
  905. front: this.toLinePath(path1, true),
  906. top: this.toLinePath(path2, true),
  907. side: this.toLinePath(path3, true),
  908. zIndexes: {
  909. group: Math.round(zIndex)
  910. },
  911. forcedSides: forcedSides,
  912. // additional info about zIndexes
  913. isFront: isFront,
  914. isTop: isTop
  915. }; // #4774
  916. };
  917. // SECTORS //
  918. SVGRenderer.prototype.arc3d = function (attribs) {
  919. var wrapper = this.g(), renderer = wrapper.renderer, customAttribs = ['x', 'y', 'r', 'innerR', 'start', 'end', 'depth'];
  920. /**
  921. * Get custom attributes. Don't mutate the original object and return an
  922. * object with only custom attr.
  923. * @private
  924. */
  925. function suckOutCustom(params) {
  926. var hasCA = false,
  927. ca = {},
  928. key;
  929. params = merge(params); // Don't mutate the original object
  930. for (key in params) {
  931. if (customAttribs.indexOf(key) !== -1) {
  932. ca[key] = params[key];
  933. delete params[key];
  934. hasCA = true;
  935. }
  936. }
  937. return hasCA ? [ca, params] : false;
  938. }
  939. attribs = merge(attribs);
  940. attribs.alpha = (attribs.alpha || 0) * deg2rad;
  941. attribs.beta = (attribs.beta || 0) * deg2rad;
  942. // Create the different sub sections of the shape
  943. wrapper.top = renderer.path();
  944. wrapper.side1 = renderer.path();
  945. wrapper.side2 = renderer.path();
  946. wrapper.inn = renderer.path();
  947. wrapper.out = renderer.path();
  948. /* eslint-disable no-invalid-this */
  949. // Add all faces
  950. wrapper.onAdd = function () {
  951. var parent = wrapper.parentGroup,
  952. className = wrapper.attr('class');
  953. wrapper.top.add(wrapper);
  954. // These faces are added outside the wrapper group because the z index
  955. // relates to neighbour elements as well
  956. ['out', 'inn', 'side1', 'side2'].forEach(function (face) {
  957. wrapper[face]
  958. .attr({
  959. 'class': className + ' highcharts-3d-side'
  960. })
  961. .add(parent);
  962. });
  963. };
  964. // Cascade to faces
  965. ['addClass', 'removeClass'].forEach(function (fn) {
  966. wrapper[fn] = function () {
  967. var args = arguments;
  968. ['top', 'out', 'inn', 'side1', 'side2'].forEach(function (face) {
  969. wrapper[face][fn].apply(wrapper[face], args);
  970. });
  971. };
  972. });
  973. /**
  974. * Compute the transformed paths and set them to the composite shapes
  975. * @private
  976. */
  977. wrapper.setPaths = function (attribs) {
  978. var paths = wrapper.renderer.arc3dPath(attribs),
  979. zIndex = paths.zTop * 100;
  980. wrapper.attribs = attribs;
  981. wrapper.top.attr({ d: paths.top, zIndex: paths.zTop });
  982. wrapper.inn.attr({ d: paths.inn, zIndex: paths.zInn });
  983. wrapper.out.attr({ d: paths.out, zIndex: paths.zOut });
  984. wrapper.side1.attr({ d: paths.side1, zIndex: paths.zSide1 });
  985. wrapper.side2.attr({ d: paths.side2, zIndex: paths.zSide2 });
  986. // show all children
  987. wrapper.zIndex = zIndex;
  988. wrapper.attr({ zIndex: zIndex });
  989. // Set the radial gradient center the first time
  990. if (attribs.center) {
  991. wrapper.top.setRadialReference(attribs.center);
  992. delete attribs.center;
  993. }
  994. };
  995. wrapper.setPaths(attribs);
  996. /**
  997. * Apply the fill to the top and a darker shade to the sides
  998. * @private
  999. */
  1000. wrapper.fillSetter = function (value) {
  1001. var darker = color(value).brighten(-0.1).get();
  1002. this.fill = value;
  1003. this.side1.attr({ fill: darker });
  1004. this.side2.attr({ fill: darker });
  1005. this.inn.attr({ fill: darker });
  1006. this.out.attr({ fill: darker });
  1007. this.top.attr({ fill: value });
  1008. return this;
  1009. };
  1010. // Apply the same value to all. These properties cascade down to the
  1011. // children when set to the composite arc3d.
  1012. ['opacity', 'translateX', 'translateY', 'visibility'].forEach(function (setter) {
  1013. wrapper[setter + 'Setter'] = function (value, key) {
  1014. wrapper[key] = value;
  1015. ['out', 'inn', 'side1', 'side2', 'top'].forEach(function (el) {
  1016. wrapper[el].attr(key, value);
  1017. });
  1018. };
  1019. });
  1020. // Override attr to remove shape attributes and use those to set child paths
  1021. wrapper.attr = function (params) {
  1022. var ca,
  1023. paramArr;
  1024. if (typeof params === 'object') {
  1025. paramArr = suckOutCustom(params);
  1026. if (paramArr) {
  1027. ca = paramArr[0];
  1028. arguments[0] = paramArr[1];
  1029. extend(wrapper.attribs, ca);
  1030. wrapper.setPaths(wrapper.attribs);
  1031. }
  1032. }
  1033. return SVGElement.prototype.attr.apply(wrapper, arguments);
  1034. };
  1035. // Override the animate function by sucking out custom parameters related to
  1036. // the shapes directly, and update the shapes from the animation step.
  1037. wrapper.animate = function (params, animation, complete) {
  1038. var paramArr,
  1039. from = this.attribs,
  1040. to,
  1041. anim,
  1042. randomProp = 'data-' + Math.random().toString(26).substring(2, 9);
  1043. // Attribute-line properties connected to 3D. These shouldn't have been
  1044. // in the attribs collection in the first place.
  1045. delete params.center;
  1046. delete params.z;
  1047. delete params.alpha;
  1048. delete params.beta;
  1049. anim = animObject(pick(animation, this.renderer.globalAnimation));
  1050. if (anim.duration) {
  1051. paramArr = suckOutCustom(params);
  1052. // Params need to have a property in order for the step to run
  1053. // (#5765, #7097, #7437)
  1054. wrapper[randomProp] = 0;
  1055. params[randomProp] = 1;
  1056. wrapper[randomProp + 'Setter'] = H.noop;
  1057. if (paramArr) {
  1058. to = paramArr[0]; // custom attr
  1059. anim.step = function (a, fx) {
  1060. /**
  1061. * @private
  1062. */
  1063. function interpolate(key) {
  1064. return from[key] + (pick(to[key], from[key]) -
  1065. from[key]) * fx.pos;
  1066. }
  1067. if (fx.prop === randomProp) {
  1068. fx.elem.setPaths(merge(from, {
  1069. x: interpolate('x'),
  1070. y: interpolate('y'),
  1071. r: interpolate('r'),
  1072. innerR: interpolate('innerR'),
  1073. start: interpolate('start'),
  1074. end: interpolate('end'),
  1075. depth: interpolate('depth')
  1076. }));
  1077. }
  1078. };
  1079. }
  1080. animation = anim; // Only when duration (#5572)
  1081. }
  1082. return SVGElement.prototype.animate.call(this, params, animation, complete);
  1083. };
  1084. // destroy all children
  1085. wrapper.destroy = function () {
  1086. this.top.destroy();
  1087. this.out.destroy();
  1088. this.inn.destroy();
  1089. this.side1.destroy();
  1090. this.side2.destroy();
  1091. return SVGElement.prototype.destroy.call(this);
  1092. };
  1093. // hide all children
  1094. wrapper.hide = function () {
  1095. this.top.hide();
  1096. this.out.hide();
  1097. this.inn.hide();
  1098. this.side1.hide();
  1099. this.side2.hide();
  1100. };
  1101. wrapper.show = function (inherit) {
  1102. this.top.show(inherit);
  1103. this.out.show(inherit);
  1104. this.inn.show(inherit);
  1105. this.side1.show(inherit);
  1106. this.side2.show(inherit);
  1107. };
  1108. /* eslint-enable no-invalid-this */
  1109. return wrapper;
  1110. };
  1111. // Generate the paths required to draw a 3D arc
  1112. SVGRenderer.prototype.arc3dPath = function (shapeArgs) {
  1113. var cx = shapeArgs.x, // x coordinate of the center
  1114. cy = shapeArgs.y, // y coordinate of the center
  1115. start = shapeArgs.start, // start angle
  1116. end = shapeArgs.end - 0.00001, // end angle
  1117. r = shapeArgs.r, // radius
  1118. ir = shapeArgs.innerR || 0, // inner radius
  1119. d = shapeArgs.depth || 0, // depth
  1120. alpha = shapeArgs.alpha, // alpha rotation of the chart
  1121. beta = shapeArgs.beta; // beta rotation of the chart
  1122. // Derived Variables
  1123. var cs = Math.cos(start), // cosinus of the start angle
  1124. ss = Math.sin(start), // sinus of the start angle
  1125. ce = Math.cos(end), // cosinus of the end angle
  1126. se = Math.sin(end), // sinus of the end angle
  1127. rx = r * Math.cos(beta), // x-radius
  1128. ry = r * Math.cos(alpha), // y-radius
  1129. irx = ir * Math.cos(beta), // x-radius (inner)
  1130. iry = ir * Math.cos(alpha), // y-radius (inner)
  1131. dx = d * Math.sin(beta), // distance between top and bottom in x
  1132. dy = d * Math.sin(alpha); // distance between top and bottom in y
  1133. // TOP
  1134. var top = [
  1135. ['M',
  1136. cx + (rx * cs),
  1137. cy + (ry * ss)]
  1138. ];
  1139. top = top.concat(curveTo(cx, cy, rx, ry, start, end, 0, 0));
  1140. top.push([
  1141. 'L', cx + (irx * ce), cy + (iry * se)
  1142. ]);
  1143. top = top.concat(curveTo(cx, cy, irx, iry, end, start, 0, 0));
  1144. top.push(['Z']);
  1145. // OUTSIDE
  1146. var b = (beta > 0 ? Math.PI / 2 : 0),
  1147. a = (alpha > 0 ? 0 : Math.PI / 2);
  1148. var start2 = start > -b ? start : (end > -b ? -b : start),
  1149. end2 = end < PI - a ? end : (start < PI - a ? PI - a : end),
  1150. midEnd = 2 * PI - a;
  1151. // When slice goes over bottom middle, need to add both, left and right
  1152. // outer side. Additionally, when we cross right hand edge, create sharp
  1153. // edge. Outer shape/wall:
  1154. //
  1155. // -------
  1156. // / ^ \
  1157. // 4) / / \ \ 1)
  1158. // / / \ \
  1159. // / / \ \
  1160. // (c)=> ==== ==== <=(d)
  1161. // \ \ / /
  1162. // \ \<=(a)/ /
  1163. // \ \ / / <=(b)
  1164. // 3) \ v / 2)
  1165. // -------
  1166. //
  1167. // (a) - inner side
  1168. // (b) - outer side
  1169. // (c) - left edge (sharp)
  1170. // (d) - right edge (sharp)
  1171. // 1..n - rendering order for startAngle = 0, when set to e.g 90, order
  1172. // changes clockwise (1->2, 2->3, n->1) and counterclockwise for negative
  1173. // startAngle
  1174. var out = [
  1175. ['M',
  1176. cx + (rx * cos(start2)),
  1177. cy + (ry * sin(start2))]
  1178. ];
  1179. out = out.concat(curveTo(cx, cy, rx, ry, start2, end2, 0, 0));
  1180. // When shape is wide, it can cross both, (c) and (d) edges, when using
  1181. // startAngle
  1182. if (end > midEnd && start < midEnd) {
  1183. // Go to outer side
  1184. out.push([
  1185. 'L', cx + (rx * cos(end2)) + dx, cy + (ry * sin(end2)) + dy
  1186. ]);
  1187. // Curve to the right edge of the slice (d)
  1188. out = out.concat(curveTo(cx, cy, rx, ry, end2, midEnd, dx, dy));
  1189. // Go to the inner side
  1190. out.push([
  1191. 'L', cx + (rx * cos(midEnd)), cy + (ry * sin(midEnd))
  1192. ]);
  1193. // Curve to the true end of the slice
  1194. out = out.concat(curveTo(cx, cy, rx, ry, midEnd, end, 0, 0));
  1195. // Go to the outer side
  1196. out.push([
  1197. 'L', cx + (rx * cos(end)) + dx, cy + (ry * sin(end)) + dy
  1198. ]);
  1199. // Go back to middle (d)
  1200. out = out.concat(curveTo(cx, cy, rx, ry, end, midEnd, dx, dy));
  1201. out.push([
  1202. 'L', cx + (rx * cos(midEnd)), cy + (ry * sin(midEnd))
  1203. ]);
  1204. // Go back to the left edge
  1205. out = out.concat(curveTo(cx, cy, rx, ry, midEnd, end2, 0, 0));
  1206. // But shape can cross also only (c) edge:
  1207. }
  1208. else if (end > PI - a && start < PI - a) {
  1209. // Go to outer side
  1210. out.push([
  1211. 'L',
  1212. cx + (rx * Math.cos(end2)) + dx,
  1213. cy + (ry * Math.sin(end2)) + dy
  1214. ]);
  1215. // Curve to the true end of the slice
  1216. out = out.concat(curveTo(cx, cy, rx, ry, end2, end, dx, dy));
  1217. // Go to the inner side
  1218. out.push([
  1219. 'L', cx + (rx * Math.cos(end)), cy + (ry * Math.sin(end))
  1220. ]);
  1221. // Go back to the artifical end2
  1222. out = out.concat(curveTo(cx, cy, rx, ry, end, end2, 0, 0));
  1223. }
  1224. out.push([
  1225. 'L', cx + (rx * Math.cos(end2)) + dx, cy + (ry * Math.sin(end2)) + dy
  1226. ]);
  1227. out = out.concat(curveTo(cx, cy, rx, ry, end2, start2, dx, dy));
  1228. out.push(['Z']);
  1229. // INSIDE
  1230. var inn = [
  1231. ['M',
  1232. cx + (irx * cs),
  1233. cy + (iry * ss)]
  1234. ];
  1235. inn = inn.concat(curveTo(cx, cy, irx, iry, start, end, 0, 0));
  1236. inn.push([
  1237. 'L', cx + (irx * Math.cos(end)) + dx, cy + (iry * Math.sin(end)) + dy
  1238. ]);
  1239. inn = inn.concat(curveTo(cx, cy, irx, iry, end, start, dx, dy));
  1240. inn.push(['Z']);
  1241. // SIDES
  1242. var side1 = [
  1243. ['M',
  1244. cx + (rx * cs),
  1245. cy + (ry * ss)],
  1246. ['L',
  1247. cx + (rx * cs) + dx,
  1248. cy + (ry * ss) + dy],
  1249. ['L',
  1250. cx + (irx * cs) + dx,
  1251. cy + (iry * ss) + dy],
  1252. ['L',
  1253. cx + (irx * cs),
  1254. cy + (iry * ss)],
  1255. ['Z']
  1256. ];
  1257. var side2 = [
  1258. ['M',
  1259. cx + (rx * ce),
  1260. cy + (ry * se)],
  1261. ['L',
  1262. cx + (rx * ce) + dx,
  1263. cy + (ry * se) + dy],
  1264. ['L',
  1265. cx + (irx * ce) + dx,
  1266. cy + (iry * se) + dy],
  1267. ['L',
  1268. cx + (irx * ce),
  1269. cy + (iry * se)],
  1270. ['Z']
  1271. ];
  1272. // correction for changed position of vanishing point caused by alpha and
  1273. // beta rotations
  1274. var angleCorr = Math.atan2(dy, -dx),
  1275. angleEnd = Math.abs(end + angleCorr),
  1276. angleStart = Math.abs(start + angleCorr),
  1277. angleMid = Math.abs((start + end) / 2 + angleCorr);
  1278. /**
  1279. * set to 0-PI range
  1280. * @private
  1281. */
  1282. function toZeroPIRange(angle) {
  1283. angle = angle % (2 * Math.PI);
  1284. if (angle > Math.PI) {
  1285. angle = 2 * Math.PI - angle;
  1286. }
  1287. return angle;
  1288. }
  1289. angleEnd = toZeroPIRange(angleEnd);
  1290. angleStart = toZeroPIRange(angleStart);
  1291. angleMid = toZeroPIRange(angleMid);
  1292. // *1e5 is to compensate pInt in zIndexSetter
  1293. var incPrecision = 1e5,
  1294. a1 = angleMid * incPrecision,
  1295. a2 = angleStart * incPrecision,
  1296. a3 = angleEnd * incPrecision;
  1297. return {
  1298. top: top,
  1299. // max angle is PI, so this is always higher
  1300. zTop: Math.PI * incPrecision + 1,
  1301. out: out,
  1302. zOut: Math.max(a1, a2, a3),
  1303. inn: inn,
  1304. zInn: Math.max(a1, a2, a3),
  1305. side1: side1,
  1306. zSide1: a3 * 0.99,
  1307. side2: side2,
  1308. zSide2: a2 * 0.99
  1309. };
  1310. };
  1311. /* *
  1312. *
  1313. * Default Export
  1314. *
  1315. * */
  1316. return SVGRenderer;
  1317. });
  1318. _registerModule(_modules, 'Core/Axis/Tick3D.js', [_modules['Core/Utilities.js']], function (U) {
  1319. /* *
  1320. *
  1321. * (c) 2010-2021 Torstein Honsi
  1322. *
  1323. * Extenstion for 3d axes
  1324. *
  1325. * License: www.highcharts.com/license
  1326. *
  1327. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1328. *
  1329. * */
  1330. var addEvent = U.addEvent,
  1331. extend = U.extend,
  1332. wrap = U.wrap;
  1333. /* eslint-disable valid-jsdoc */
  1334. /**
  1335. * Tick with 3D support
  1336. * @private
  1337. * @class
  1338. */
  1339. var Tick3D = /** @class */ (function () {
  1340. function Tick3D() {
  1341. }
  1342. /* *
  1343. *
  1344. * Static Functions
  1345. *
  1346. * */
  1347. /**
  1348. * @private
  1349. */
  1350. Tick3D.compose = function (TickClass) {
  1351. addEvent(TickClass, 'afterGetLabelPosition', Tick3D.onAfterGetLabelPosition);
  1352. var tickProto = TickClass.prototype;
  1353. wrap(tickProto, 'getMarkPath', Tick3D.wrapGetMarkPath);
  1354. };
  1355. /**
  1356. * @private
  1357. */
  1358. Tick3D.onAfterGetLabelPosition = function (e) {
  1359. var axis3D = this.axis.axis3D;
  1360. if (axis3D) {
  1361. extend(e.pos, axis3D.fix3dPosition(e.pos));
  1362. }
  1363. };
  1364. /**
  1365. * @private
  1366. */
  1367. Tick3D.wrapGetMarkPath = function (proceed) {
  1368. var chart = this.axis.chart;
  1369. var axis3D = this.axis.axis3D;
  1370. var path = proceed.apply(this,
  1371. [].slice.call(arguments, 1));
  1372. if (axis3D) {
  1373. var start = path[0];
  1374. var end = path[1];
  1375. if (start[0] === 'M' && end[0] === 'L') {
  1376. var pArr = [
  1377. axis3D.fix3dPosition({ x: start[1],
  1378. y: start[2],
  1379. z: 0 }),
  1380. axis3D.fix3dPosition({ x: end[1],
  1381. y: end[2],
  1382. z: 0 })
  1383. ];
  1384. return this.axis.chart.renderer.toLineSegments(pArr);
  1385. }
  1386. }
  1387. return path;
  1388. };
  1389. return Tick3D;
  1390. }());
  1391. return Tick3D;
  1392. });
  1393. _registerModule(_modules, 'Core/Axis/Axis3D.js', [_modules['Core/Globals.js'], _modules['Extensions/Math3D.js'], _modules['Core/Axis/Tick.js'], _modules['Core/Axis/Tick3D.js'], _modules['Core/Utilities.js']], function (H, Math3D, Tick, Tick3D, U) {
  1394. /* *
  1395. *
  1396. * (c) 2010-2021 Torstein Honsi
  1397. *
  1398. * Extenstion for 3d axes
  1399. *
  1400. * License: www.highcharts.com/license
  1401. *
  1402. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1403. *
  1404. * */
  1405. var perspective = Math3D.perspective,
  1406. perspective3D = Math3D.perspective3D,
  1407. shapeArea = Math3D.shapeArea;
  1408. var addEvent = U.addEvent,
  1409. merge = U.merge,
  1410. pick = U.pick,
  1411. wrap = U.wrap;
  1412. var deg2rad = H.deg2rad;
  1413. /* eslint-disable valid-jsdoc */
  1414. /**
  1415. * Adds 3D support to axes.
  1416. * @private
  1417. * @class
  1418. */
  1419. var Axis3DAdditions = /** @class */ (function () {
  1420. /* *
  1421. *
  1422. * Constructors
  1423. *
  1424. * */
  1425. /**
  1426. * @private
  1427. */
  1428. function Axis3DAdditions(axis) {
  1429. this.axis = axis;
  1430. }
  1431. /* *
  1432. *
  1433. * Functions
  1434. *
  1435. * */
  1436. /**
  1437. * @private
  1438. * @param {Highcharts.Axis} axis
  1439. * Related axis.
  1440. * @param {Highcharts.Position3DObject} pos
  1441. * Position to fix.
  1442. * @param {boolean} [isTitle]
  1443. * Whether this is a title position.
  1444. * @return {Highcharts.Position3DObject}
  1445. * Fixed position.
  1446. */
  1447. Axis3DAdditions.prototype.fix3dPosition = function (pos, isTitle) {
  1448. var axis3D = this;
  1449. var axis = axis3D.axis;
  1450. var chart = axis.chart;
  1451. // Do not do this if the chart is not 3D
  1452. if (axis.coll === 'colorAxis' ||
  1453. !chart.chart3d ||
  1454. !chart.is3d()) {
  1455. return pos;
  1456. }
  1457. var alpha = deg2rad * chart.options.chart.options3d.alpha,
  1458. beta = deg2rad * chart.options.chart.options3d.beta,
  1459. positionMode = pick(isTitle && axis.options.title.position3d,
  1460. axis.options.labels.position3d),
  1461. skew = pick(isTitle && axis.options.title.skew3d,
  1462. axis.options.labels.skew3d),
  1463. frame = chart.chart3d.frame3d,
  1464. plotLeft = chart.plotLeft,
  1465. plotRight = chart.plotWidth + plotLeft,
  1466. plotTop = chart.plotTop,
  1467. plotBottom = chart.plotHeight + plotTop,
  1468. // Indicates that we are labelling an X or Z axis on the "back" of
  1469. // the chart
  1470. reverseFlap = false,
  1471. offsetX = 0,
  1472. offsetY = 0,
  1473. vecX,
  1474. vecY = { x: 0,
  1475. y: 1,
  1476. z: 0 };
  1477. pos = axis.axis3D.swapZ({ x: pos.x, y: pos.y, z: 0 });
  1478. if (axis.isZAxis) { // Z Axis
  1479. if (axis.opposite) {
  1480. if (frame.axes.z.top === null) {
  1481. return {};
  1482. }
  1483. offsetY = pos.y - plotTop;
  1484. pos.x = frame.axes.z.top.x;
  1485. pos.y = frame.axes.z.top.y;
  1486. vecX = frame.axes.z.top.xDir;
  1487. reverseFlap = !frame.top.frontFacing;
  1488. }
  1489. else {
  1490. if (frame.axes.z.bottom === null) {
  1491. return {};
  1492. }
  1493. offsetY = pos.y - plotBottom;
  1494. pos.x = frame.axes.z.bottom.x;
  1495. pos.y = frame.axes.z.bottom.y;
  1496. vecX = frame.axes.z.bottom.xDir;
  1497. reverseFlap = !frame.bottom.frontFacing;
  1498. }
  1499. }
  1500. else if (axis.horiz) { // X Axis
  1501. if (axis.opposite) {
  1502. if (frame.axes.x.top === null) {
  1503. return {};
  1504. }
  1505. offsetY = pos.y - plotTop;
  1506. pos.y = frame.axes.x.top.y;
  1507. pos.z = frame.axes.x.top.z;
  1508. vecX = frame.axes.x.top.xDir;
  1509. reverseFlap = !frame.top.frontFacing;
  1510. }
  1511. else {
  1512. if (frame.axes.x.bottom === null) {
  1513. return {};
  1514. }
  1515. offsetY = pos.y - plotBottom;
  1516. pos.y = frame.axes.x.bottom.y;
  1517. pos.z = frame.axes.x.bottom.z;
  1518. vecX = frame.axes.x.bottom.xDir;
  1519. reverseFlap = !frame.bottom.frontFacing;
  1520. }
  1521. }
  1522. else { // Y Axis
  1523. if (axis.opposite) {
  1524. if (frame.axes.y.right === null) {
  1525. return {};
  1526. }
  1527. offsetX = pos.x - plotRight;
  1528. pos.x = frame.axes.y.right.x;
  1529. pos.z = frame.axes.y.right.z;
  1530. vecX = frame.axes.y.right.xDir;
  1531. // Rotate 90º on opposite edge
  1532. vecX = { x: vecX.z, y: vecX.y, z: -vecX.x };
  1533. }
  1534. else {
  1535. if (frame.axes.y.left === null) {
  1536. return {};
  1537. }
  1538. offsetX = pos.x - plotLeft;
  1539. pos.x = frame.axes.y.left.x;
  1540. pos.z = frame.axes.y.left.z;
  1541. vecX = frame.axes.y.left.xDir;
  1542. }
  1543. }
  1544. if (positionMode === 'chart') {
  1545. // Labels preserve their direction relative to the chart
  1546. // nothing to do
  1547. }
  1548. else if (positionMode === 'flap') {
  1549. // Labels are rotated around the axis direction to face the screen
  1550. if (!axis.horiz) { // Y Axis
  1551. vecX = { x: Math.cos(beta), y: 0, z: Math.sin(beta) };
  1552. }
  1553. else { // X and Z Axis
  1554. var sin = Math.sin(alpha);
  1555. var cos = Math.cos(alpha);
  1556. if (axis.opposite) {
  1557. sin = -sin;
  1558. }
  1559. if (reverseFlap) {
  1560. sin = -sin;
  1561. }
  1562. vecY = { x: vecX.z * sin, y: cos, z: -vecX.x * sin };
  1563. }
  1564. }
  1565. else if (positionMode === 'ortho') {
  1566. // Labels will be rotated to be ortogonal to the axis
  1567. if (!axis.horiz) { // Y Axis
  1568. vecX = { x: Math.cos(beta), y: 0, z: Math.sin(beta) };
  1569. }
  1570. else { // X and Z Axis
  1571. var sina = Math.sin(alpha);
  1572. var cosa = Math.cos(alpha);
  1573. var sinb = Math.sin(beta);
  1574. var cosb = Math.cos(beta);
  1575. var vecZ = { x: sinb * cosa,
  1576. y: -sina,
  1577. z: -cosa * cosb };
  1578. vecY = {
  1579. x: vecX.y * vecZ.z - vecX.z * vecZ.y,
  1580. y: vecX.z * vecZ.x - vecX.x * vecZ.z,
  1581. z: vecX.x * vecZ.y - vecX.y * vecZ.x
  1582. };
  1583. var scale = 1 / Math.sqrt(vecY.x * vecY.x + vecY.y * vecY.y + vecY.z * vecY.z);
  1584. if (reverseFlap) {
  1585. scale = -scale;
  1586. }
  1587. vecY = { x: scale * vecY.x, y: scale * vecY.y, z: scale * vecY.z };
  1588. }
  1589. }
  1590. else { // positionMode == 'offset'
  1591. // Labels will be skewd to maintain vertical / horizontal offsets
  1592. // from axis
  1593. if (!axis.horiz) { // Y Axis
  1594. vecX = { x: Math.cos(beta), y: 0, z: Math.sin(beta) };
  1595. }
  1596. else { // X and Z Axis
  1597. vecY = {
  1598. x: Math.sin(beta) * Math.sin(alpha),
  1599. y: Math.cos(alpha),
  1600. z: -Math.cos(beta) * Math.sin(alpha)
  1601. };
  1602. }
  1603. }
  1604. pos.x += offsetX * vecX.x + offsetY * vecY.x;
  1605. pos.y += offsetX * vecX.y + offsetY * vecY.y;
  1606. pos.z += offsetX * vecX.z + offsetY * vecY.z;
  1607. var projected = perspective([pos],
  1608. axis.chart)[0];
  1609. if (skew) {
  1610. // Check if the label text would be mirrored
  1611. var isMirrored = shapeArea(perspective([
  1612. pos,
  1613. { x: pos.x + vecX.x,
  1614. y: pos.y + vecX.y,
  1615. z: pos.z + vecX.z },
  1616. { x: pos.x + vecY.x,
  1617. y: pos.y + vecY.y,
  1618. z: pos.z + vecY.z }
  1619. ],
  1620. axis.chart)) < 0;
  1621. if (isMirrored) {
  1622. vecX = { x: -vecX.x, y: -vecX.y, z: -vecX.z };
  1623. }
  1624. var pointsProjected = perspective([
  1625. { x: pos.x,
  1626. y: pos.y,
  1627. z: pos.z },
  1628. { x: pos.x + vecX.x,
  1629. y: pos.y + vecX.y,
  1630. z: pos.z + vecX.z },
  1631. { x: pos.x + vecY.x,
  1632. y: pos.y + vecY.y,
  1633. z: pos.z + vecY.z }
  1634. ],
  1635. axis.chart);
  1636. projected.matrix = [
  1637. pointsProjected[1].x - pointsProjected[0].x,
  1638. pointsProjected[1].y - pointsProjected[0].y,
  1639. pointsProjected[2].x - pointsProjected[0].x,
  1640. pointsProjected[2].y - pointsProjected[0].y,
  1641. projected.x,
  1642. projected.y
  1643. ];
  1644. projected.matrix[4] -= projected.x * projected.matrix[0] +
  1645. projected.y * projected.matrix[2];
  1646. projected.matrix[5] -= projected.x * projected.matrix[1] +
  1647. projected.y * projected.matrix[3];
  1648. }
  1649. return projected;
  1650. };
  1651. /**
  1652. * @private
  1653. */
  1654. Axis3DAdditions.prototype.swapZ = function (p, insidePlotArea) {
  1655. var axis = this.axis;
  1656. if (axis.isZAxis) {
  1657. var plotLeft = insidePlotArea ? 0 : axis.chart.plotLeft;
  1658. return {
  1659. x: plotLeft + p.z,
  1660. y: p.y,
  1661. z: p.x - plotLeft
  1662. };
  1663. }
  1664. return p;
  1665. };
  1666. return Axis3DAdditions;
  1667. }());
  1668. /**
  1669. * Axis with 3D support.
  1670. * @private
  1671. * @class
  1672. */
  1673. var Axis3D = /** @class */ (function () {
  1674. function Axis3D() {
  1675. }
  1676. /* *
  1677. *
  1678. * Static Functions
  1679. *
  1680. * */
  1681. /**
  1682. * Extends axis class with 3D support.
  1683. * @private
  1684. */
  1685. Axis3D.compose = function (AxisClass) {
  1686. merge(true, AxisClass.defaultOptions, Axis3D.defaultOptions);
  1687. AxisClass.keepProps.push('axis3D');
  1688. addEvent(AxisClass, 'init', Axis3D.onInit);
  1689. addEvent(AxisClass, 'afterSetOptions', Axis3D.onAfterSetOptions);
  1690. addEvent(AxisClass, 'drawCrosshair', Axis3D.onDrawCrosshair);
  1691. addEvent(AxisClass, 'destroy', Axis3D.onDestroy);
  1692. var axisProto = AxisClass.prototype;
  1693. wrap(axisProto, 'getLinePath', Axis3D.wrapGetLinePath);
  1694. wrap(axisProto, 'getPlotBandPath', Axis3D.wrapGetPlotBandPath);
  1695. wrap(axisProto, 'getPlotLinePath', Axis3D.wrapGetPlotLinePath);
  1696. wrap(axisProto, 'getSlotWidth', Axis3D.wrapGetSlotWidth);
  1697. wrap(axisProto, 'getTitlePosition', Axis3D.wrapGetTitlePosition);
  1698. Tick3D.compose(Tick);
  1699. };
  1700. /**
  1701. * @private
  1702. */
  1703. Axis3D.onAfterSetOptions = function () {
  1704. var axis = this;
  1705. var chart = axis.chart;
  1706. var options = axis.options;
  1707. if (chart.is3d && chart.is3d() && axis.coll !== 'colorAxis') {
  1708. options.tickWidth = pick(options.tickWidth, 0);
  1709. options.gridLineWidth = pick(options.gridLineWidth, 1);
  1710. }
  1711. };
  1712. /**
  1713. * @private
  1714. */
  1715. Axis3D.onDestroy = function () {
  1716. ['backFrame', 'bottomFrame', 'sideFrame'].forEach(function (prop) {
  1717. if (this[prop]) {
  1718. this[prop] = this[prop].destroy();
  1719. }
  1720. }, this);
  1721. };
  1722. /**
  1723. * @private
  1724. */
  1725. Axis3D.onDrawCrosshair = function (e) {
  1726. var axis = this;
  1727. if (axis.chart.is3d() &&
  1728. axis.coll !== 'colorAxis') {
  1729. if (e.point) {
  1730. e.point.crosshairPos = axis.isXAxis ?
  1731. e.point.axisXpos :
  1732. axis.len - e.point.axisYpos;
  1733. }
  1734. }
  1735. };
  1736. /**
  1737. * @private
  1738. */
  1739. Axis3D.onInit = function () {
  1740. var axis = this;
  1741. if (!axis.axis3D) {
  1742. axis.axis3D = new Axis3DAdditions(axis);
  1743. }
  1744. };
  1745. /**
  1746. * Do not draw axislines in 3D.
  1747. * @private
  1748. */
  1749. Axis3D.wrapGetLinePath = function (proceed) {
  1750. var axis = this;
  1751. // Do not do this if the chart is not 3D
  1752. if (!axis.chart.is3d() || axis.coll === 'colorAxis') {
  1753. return proceed.apply(axis, [].slice.call(arguments, 1));
  1754. }
  1755. return [];
  1756. };
  1757. /**
  1758. * @private
  1759. */
  1760. Axis3D.wrapGetPlotBandPath = function (proceed) {
  1761. // Do not do this if the chart is not 3D
  1762. if (!this.chart.is3d() || this.coll === 'colorAxis') {
  1763. return proceed.apply(this, [].slice.call(arguments, 1));
  1764. }
  1765. var args = arguments,
  1766. from = args[1],
  1767. to = args[2],
  1768. path = [],
  1769. fromPath = this.getPlotLinePath({ value: from }),
  1770. toPath = this.getPlotLinePath({ value: to });
  1771. if (fromPath && toPath) {
  1772. for (var i = 0; i < fromPath.length; i += 2) {
  1773. var fromStartSeg = fromPath[i],
  1774. fromEndSeg = fromPath[i + 1],
  1775. toStartSeg = toPath[i],
  1776. toEndSeg = toPath[i + 1];
  1777. if (fromStartSeg[0] === 'M' &&
  1778. fromEndSeg[0] === 'L' &&
  1779. toStartSeg[0] === 'M' &&
  1780. toEndSeg[0] === 'L') {
  1781. path.push(fromStartSeg, fromEndSeg, toEndSeg,
  1782. // lineTo instead of moveTo
  1783. ['L', toStartSeg[1], toStartSeg[2]], ['Z']);
  1784. }
  1785. }
  1786. }
  1787. return path;
  1788. };
  1789. /**
  1790. * @private
  1791. */
  1792. Axis3D.wrapGetPlotLinePath = function (proceed) {
  1793. var axis = this;
  1794. var axis3D = axis.axis3D;
  1795. var chart = axis.chart;
  1796. var path = proceed.apply(axis,
  1797. [].slice.call(arguments, 1));
  1798. // Do not do this if the chart is not 3D
  1799. if (axis.coll === 'colorAxis' ||
  1800. !chart.chart3d ||
  1801. !chart.is3d()) {
  1802. return path;
  1803. }
  1804. if (path === null) {
  1805. return path;
  1806. }
  1807. var options3d = chart.options.chart.options3d,
  1808. d = axis.isZAxis ? chart.plotWidth : options3d.depth,
  1809. frame = chart.chart3d.frame3d,
  1810. startSegment = path[0],
  1811. endSegment = path[1],
  1812. pArr,
  1813. pathSegments = [];
  1814. if (startSegment[0] === 'M' && endSegment[0] === 'L') {
  1815. pArr = [
  1816. axis3D.swapZ({ x: startSegment[1], y: startSegment[2], z: 0 }),
  1817. axis3D.swapZ({ x: startSegment[1], y: startSegment[2], z: d }),
  1818. axis3D.swapZ({ x: endSegment[1], y: endSegment[2], z: 0 }),
  1819. axis3D.swapZ({ x: endSegment[1], y: endSegment[2], z: d })
  1820. ];
  1821. if (!this.horiz) { // Y-Axis
  1822. if (frame.front.visible) {
  1823. pathSegments.push(pArr[0], pArr[2]);
  1824. }
  1825. if (frame.back.visible) {
  1826. pathSegments.push(pArr[1], pArr[3]);
  1827. }
  1828. if (frame.left.visible) {
  1829. pathSegments.push(pArr[0], pArr[1]);
  1830. }
  1831. if (frame.right.visible) {
  1832. pathSegments.push(pArr[2], pArr[3]);
  1833. }
  1834. }
  1835. else if (this.isZAxis) { // Z-Axis
  1836. if (frame.left.visible) {
  1837. pathSegments.push(pArr[0], pArr[2]);
  1838. }
  1839. if (frame.right.visible) {
  1840. pathSegments.push(pArr[1], pArr[3]);
  1841. }
  1842. if (frame.top.visible) {
  1843. pathSegments.push(pArr[0], pArr[1]);
  1844. }
  1845. if (frame.bottom.visible) {
  1846. pathSegments.push(pArr[2], pArr[3]);
  1847. }
  1848. }
  1849. else { // X-Axis
  1850. if (frame.front.visible) {
  1851. pathSegments.push(pArr[0], pArr[2]);
  1852. }
  1853. if (frame.back.visible) {
  1854. pathSegments.push(pArr[1], pArr[3]);
  1855. }
  1856. if (frame.top.visible) {
  1857. pathSegments.push(pArr[0], pArr[1]);
  1858. }
  1859. if (frame.bottom.visible) {
  1860. pathSegments.push(pArr[2], pArr[3]);
  1861. }
  1862. }
  1863. pathSegments = perspective(pathSegments, this.chart, false);
  1864. }
  1865. return chart.renderer.toLineSegments(pathSegments);
  1866. };
  1867. /**
  1868. * Wrap getSlotWidth function to calculate individual width value for each
  1869. * slot (#8042).
  1870. * @private
  1871. */
  1872. Axis3D.wrapGetSlotWidth = function (proceed, tick) {
  1873. var axis = this;
  1874. var chart = axis.chart;
  1875. var ticks = axis.ticks;
  1876. var gridGroup = axis.gridGroup;
  1877. if (axis.categories &&
  1878. chart.frameShapes &&
  1879. chart.is3d() &&
  1880. gridGroup &&
  1881. tick &&
  1882. tick.label) {
  1883. var firstGridLine = gridGroup.element.childNodes[0].getBBox(),
  1884. frame3DLeft = chart.frameShapes.left.getBBox(),
  1885. options3d = chart.options.chart.options3d,
  1886. origin = {
  1887. x: chart.plotWidth / 2,
  1888. y: chart.plotHeight / 2,
  1889. z: options3d.depth / 2,
  1890. vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
  1891. },
  1892. labelPos,
  1893. prevLabelPos,
  1894. nextLabelPos,
  1895. slotWidth,
  1896. tickId = tick.pos,
  1897. prevTick = ticks[tickId - 1],
  1898. nextTick = ticks[tickId + 1];
  1899. // Check whether the tick is not the first one and previous tick
  1900. // exists, then calculate position of previous label.
  1901. if (tickId !== 0 && prevTick && prevTick.label && prevTick.label.xy) {
  1902. prevLabelPos = perspective3D({
  1903. x: prevTick.label.xy.x,
  1904. y: prevTick.label.xy.y,
  1905. z: null
  1906. }, origin, origin.vd);
  1907. }
  1908. // If next label position is defined, then recalculate its position
  1909. // basing on the perspective.
  1910. if (nextTick && nextTick.label && nextTick.label.xy) {
  1911. nextLabelPos = perspective3D({
  1912. x: nextTick.label.xy.x,
  1913. y: nextTick.label.xy.y,
  1914. z: null
  1915. }, origin, origin.vd);
  1916. }
  1917. labelPos = {
  1918. x: tick.label.xy.x,
  1919. y: tick.label.xy.y,
  1920. z: null
  1921. };
  1922. labelPos = perspective3D(labelPos, origin, origin.vd);
  1923. // If tick is first one, check whether next label position is
  1924. // already calculated, then return difference between the first and
  1925. // the second label. If there is no next label position calculated,
  1926. // return the difference between the first grid line and left 3d
  1927. // frame.
  1928. slotWidth = Math.abs(prevLabelPos ?
  1929. labelPos.x - prevLabelPos.x : nextLabelPos ?
  1930. nextLabelPos.x - labelPos.x :
  1931. firstGridLine.x - frame3DLeft.x);
  1932. return slotWidth;
  1933. }
  1934. return proceed.apply(axis, [].slice.call(arguments, 1));
  1935. };
  1936. /**
  1937. * @private
  1938. */
  1939. Axis3D.wrapGetTitlePosition = function (proceed) {
  1940. var pos = proceed.apply(this,
  1941. [].slice.call(arguments, 1));
  1942. return this.axis3D ?
  1943. this.axis3D.fix3dPosition(pos, true) :
  1944. pos;
  1945. };
  1946. /* *
  1947. *
  1948. * Static Properties
  1949. *
  1950. * */
  1951. /**
  1952. * @optionparent xAxis
  1953. */
  1954. Axis3D.defaultOptions = {
  1955. labels: {
  1956. /**
  1957. * Defines how the labels are be repositioned according to the 3D
  1958. * chart orientation.
  1959. *
  1960. * - `'offset'`: Maintain a fixed horizontal/vertical distance from
  1961. * the tick marks, despite the chart orientation. This is the
  1962. * backwards compatible behavior, and causes skewing of X and Z
  1963. * axes.
  1964. *
  1965. * - `'chart'`: Preserve 3D position relative to the chart. This
  1966. * looks nice, but hard to read if the text isn't forward-facing.
  1967. *
  1968. * - `'flap'`: Rotated text along the axis to compensate for the
  1969. * chart orientation. This tries to maintain text as legible as
  1970. * possible on all orientations.
  1971. *
  1972. * - `'ortho'`: Rotated text along the axis direction so that the
  1973. * labels are orthogonal to the axis. This is very similar to
  1974. * `'flap'`, but prevents skewing the labels (X and Y scaling are
  1975. * still present).
  1976. *
  1977. * @sample highcharts/3d/skewed-labels/
  1978. * Skewed labels
  1979. *
  1980. * @since 5.0.15
  1981. * @validvalue ['offset', 'chart', 'flap', 'ortho']
  1982. * @product highcharts
  1983. * @requires highcharts-3d
  1984. */
  1985. position3d: 'offset',
  1986. /**
  1987. * If enabled, the axis labels will skewed to follow the
  1988. * perspective.
  1989. *
  1990. * This will fix overlapping labels and titles, but texts become
  1991. * less legible due to the distortion.
  1992. *
  1993. * The final appearance depends heavily on `labels.position3d`.
  1994. *
  1995. * @sample highcharts/3d/skewed-labels/
  1996. * Skewed labels
  1997. *
  1998. * @since 5.0.15
  1999. * @product highcharts
  2000. * @requires highcharts-3d
  2001. */
  2002. skew3d: false
  2003. },
  2004. title: {
  2005. /**
  2006. * Defines how the title is repositioned according to the 3D chart
  2007. * orientation.
  2008. *
  2009. * - `'offset'`: Maintain a fixed horizontal/vertical distance from
  2010. * the tick marks, despite the chart orientation. This is the
  2011. * backwards compatible behavior, and causes skewing of X and Z
  2012. * axes.
  2013. *
  2014. * - `'chart'`: Preserve 3D position relative to the chart. This
  2015. * looks nice, but hard to read if the text isn't forward-facing.
  2016. *
  2017. * - `'flap'`: Rotated text along the axis to compensate for the
  2018. * chart orientation. This tries to maintain text as legible as
  2019. * possible on all orientations.
  2020. *
  2021. * - `'ortho'`: Rotated text along the axis direction so that the
  2022. * labels are orthogonal to the axis. This is very similar to
  2023. * `'flap'`, but prevents skewing the labels (X and Y scaling are
  2024. * still present).
  2025. *
  2026. * - `undefined`: Will use the config from `labels.position3d`
  2027. *
  2028. * @sample highcharts/3d/skewed-labels/
  2029. * Skewed labels
  2030. *
  2031. * @type {"offset"|"chart"|"flap"|"ortho"|null}
  2032. * @since 5.0.15
  2033. * @product highcharts
  2034. * @requires highcharts-3d
  2035. */
  2036. position3d: null,
  2037. /**
  2038. * If enabled, the axis title will skewed to follow the perspective.
  2039. *
  2040. * This will fix overlapping labels and titles, but texts become
  2041. * less legible due to the distortion.
  2042. *
  2043. * The final appearance depends heavily on `title.position3d`.
  2044. *
  2045. * A `null` value will use the config from `labels.skew3d`.
  2046. *
  2047. * @sample highcharts/3d/skewed-labels/
  2048. * Skewed labels
  2049. *
  2050. * @type {boolean|null}
  2051. * @since 5.0.15
  2052. * @product highcharts
  2053. * @requires highcharts-3d
  2054. */
  2055. skew3d: null
  2056. }
  2057. };
  2058. return Axis3D;
  2059. }());
  2060. return Axis3D;
  2061. });
  2062. _registerModule(_modules, 'Core/Axis/ZAxis.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Utilities.js']], function (Axis, U) {
  2063. /* *
  2064. *
  2065. * (c) 2010-2021 Torstein Honsi
  2066. *
  2067. * License: www.highcharts.com/license
  2068. *
  2069. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  2070. *
  2071. * */
  2072. var __extends = (this && this.__extends) || (function () {
  2073. var extendStatics = function (d,
  2074. b) {
  2075. extendStatics = Object.setPrototypeOf ||
  2076. ({ __proto__: [] } instanceof Array && function (d,
  2077. b) { d.__proto__ = b; }) ||
  2078. function (d,
  2079. b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  2080. return extendStatics(d, b);
  2081. };
  2082. return function (d, b) {
  2083. extendStatics(d, b);
  2084. function __() { this.constructor = d; }
  2085. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  2086. };
  2087. })();
  2088. var addEvent = U.addEvent,
  2089. merge = U.merge,
  2090. pick = U.pick,
  2091. splat = U.splat;
  2092. /* eslint-disable valid-jsdoc */
  2093. /**
  2094. * 3D chart with support of z coordinates.
  2095. * @private
  2096. * @class
  2097. */
  2098. var ZChart = /** @class */ (function () {
  2099. function ZChart() {
  2100. }
  2101. /* *
  2102. *
  2103. * Static Functions
  2104. *
  2105. * */
  2106. ZChart.compose = function (ChartClass) {
  2107. addEvent(ChartClass, 'afterGetAxes', ZChart.onAfterGetAxes);
  2108. var chartProto = ChartClass.prototype;
  2109. chartProto.addZAxis = ZChart.wrapAddZAxis;
  2110. chartProto.collectionsWithInit.zAxis = [chartProto.addZAxis];
  2111. chartProto.collectionsWithUpdate.push('zAxis');
  2112. };
  2113. /**
  2114. * Get the Z axis in addition to the default X and Y.
  2115. * @private
  2116. */
  2117. ZChart.onAfterGetAxes = function () {
  2118. var chart = this;
  2119. var options = this.options;
  2120. var zAxisOptions = options.zAxis = splat(options.zAxis || {});
  2121. if (!chart.is3d()) {
  2122. return;
  2123. }
  2124. chart.zAxis = [];
  2125. zAxisOptions.forEach(function (axisOptions, i) {
  2126. axisOptions.index = i;
  2127. // Z-Axis is shown horizontally, so it's kind of a X-Axis
  2128. axisOptions.isX = true;
  2129. chart
  2130. .addZAxis(axisOptions)
  2131. .setScale();
  2132. });
  2133. };
  2134. /**
  2135. * @private
  2136. */
  2137. ZChart.wrapAddZAxis = function (options) {
  2138. return new ZAxis(this, options);
  2139. };
  2140. return ZChart;
  2141. }());
  2142. /**
  2143. * 3D axis for z coordinates.
  2144. */
  2145. var ZAxis = /** @class */ (function (_super) {
  2146. __extends(ZAxis, _super);
  2147. /* *
  2148. *
  2149. * Constructors
  2150. *
  2151. * */
  2152. function ZAxis(chart, userOptions) {
  2153. var _this = _super.call(this,
  2154. chart,
  2155. userOptions) || this;
  2156. _this.isZAxis = true;
  2157. return _this;
  2158. }
  2159. /* *
  2160. *
  2161. * Functions
  2162. *
  2163. * */
  2164. ZAxis.prototype.getSeriesExtremes = function () {
  2165. var axis = this;
  2166. var chart = axis.chart;
  2167. axis.hasVisibleSeries = false;
  2168. // Reset properties in case we're redrawing (#3353)
  2169. axis.dataMin = axis.dataMax = axis.ignoreMinPadding = axis.ignoreMaxPadding = void 0;
  2170. if (axis.stacking) {
  2171. axis.stacking.buildStacks();
  2172. }
  2173. // loop through this axis' series
  2174. axis.series.forEach(function (series) {
  2175. if (series.visible ||
  2176. !(chart.options.chart &&
  2177. chart.options.chart.ignoreHiddenSeries)) {
  2178. var seriesOptions = series.options,
  2179. zData,
  2180. threshold = seriesOptions.threshold;
  2181. axis.hasVisibleSeries = true;
  2182. // Validate threshold in logarithmic axes
  2183. if (axis.positiveValuesOnly && threshold <= 0) {
  2184. threshold = void 0;
  2185. }
  2186. zData = series.zData;
  2187. if (zData.length) {
  2188. axis.dataMin = Math.min(pick(axis.dataMin, zData[0]), Math.min.apply(null, zData));
  2189. axis.dataMax = Math.max(pick(axis.dataMax, zData[0]), Math.max.apply(null, zData));
  2190. }
  2191. }
  2192. });
  2193. };
  2194. /**
  2195. * @private
  2196. */
  2197. ZAxis.prototype.setAxisSize = function () {
  2198. var axis = this;
  2199. var chart = axis.chart;
  2200. _super.prototype.setAxisSize.call(this);
  2201. axis.width = axis.len = (chart.options.chart &&
  2202. chart.options.chart.options3d &&
  2203. chart.options.chart.options3d.depth) || 0;
  2204. axis.right = chart.chartWidth - axis.width - axis.left;
  2205. };
  2206. /**
  2207. * @private
  2208. */
  2209. ZAxis.prototype.setOptions = function (userOptions) {
  2210. userOptions = merge({
  2211. offset: 0,
  2212. lineWidth: 0
  2213. }, userOptions);
  2214. // #14793, this used to be set on the prototype
  2215. this.isZAxis = true;
  2216. _super.prototype.setOptions.call(this, userOptions);
  2217. this.coll = 'zAxis';
  2218. };
  2219. /* *
  2220. *
  2221. * Static Properties
  2222. *
  2223. * */
  2224. ZAxis.ZChartComposition = ZChart;
  2225. return ZAxis;
  2226. }(Axis));
  2227. return ZAxis;
  2228. });
  2229. _registerModule(_modules, 'Core/Chart/Chart3D.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Axis/Axis3D.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Animation/Fx.js'], _modules['Core/Globals.js'], _modules['Extensions/Math3D.js'], _modules['Core/Options.js'], _modules['Core/Utilities.js'], _modules['Core/Axis/ZAxis.js']], function (Axis, Axis3D, Chart, Fx, H, Math3D, O, U, ZAxis) {
  2230. /* *
  2231. *
  2232. * (c) 2010-2021 Torstein Honsi
  2233. *
  2234. * Extension for 3D charts
  2235. *
  2236. * License: www.highcharts.com/license
  2237. *
  2238. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  2239. *
  2240. * */
  2241. var perspective = Math3D.perspective,
  2242. shapeArea3D = Math3D.shapeArea3D;
  2243. var genericDefaultOptions = O.defaultOptions;
  2244. var addEvent = U.addEvent,
  2245. isArray = U.isArray,
  2246. merge = U.merge,
  2247. pick = U.pick,
  2248. wrap = U.wrap;
  2249. var Chart3D;
  2250. (function (Chart3D) {
  2251. /* *
  2252. *
  2253. * Interfaces
  2254. *
  2255. * */
  2256. /* *
  2257. *
  2258. * Classes
  2259. *
  2260. * */
  2261. var Composition = /** @class */ (function () {
  2262. /* *
  2263. *
  2264. * Constructors
  2265. *
  2266. * */
  2267. /**
  2268. * @private
  2269. */
  2270. function Composition(chart) {
  2271. this.frame3d = void 0;
  2272. this.chart = chart;
  2273. }
  2274. /* *
  2275. *
  2276. * Functions
  2277. *
  2278. * */
  2279. Composition.prototype.get3dFrame = function () {
  2280. var chart = this.chart,
  2281. options3d = chart.options.chart.options3d,
  2282. frameOptions = options3d.frame,
  2283. xm = chart.plotLeft,
  2284. xp = chart.plotLeft + chart.plotWidth,
  2285. ym = chart.plotTop,
  2286. yp = chart.plotTop + chart.plotHeight,
  2287. zm = 0,
  2288. zp = options3d.depth,
  2289. faceOrientation = function (vertexes) {
  2290. var area = shapeArea3D(vertexes,
  2291. chart);
  2292. // Give it 0.5 squared-pixel as a margin for rounding errors
  2293. if (area > 0.5) {
  2294. return 1;
  2295. }
  2296. if (area < -0.5) {
  2297. return -1;
  2298. }
  2299. return 0;
  2300. }, bottomOrientation = faceOrientation([
  2301. { x: xm, y: yp, z: zp },
  2302. { x: xp, y: yp, z: zp },
  2303. { x: xp, y: yp, z: zm },
  2304. { x: xm, y: yp, z: zm }
  2305. ]), topOrientation = faceOrientation([
  2306. { x: xm, y: ym, z: zm },
  2307. { x: xp, y: ym, z: zm },
  2308. { x: xp, y: ym, z: zp },
  2309. { x: xm, y: ym, z: zp }
  2310. ]), leftOrientation = faceOrientation([
  2311. { x: xm, y: ym, z: zm },
  2312. { x: xm, y: ym, z: zp },
  2313. { x: xm, y: yp, z: zp },
  2314. { x: xm, y: yp, z: zm }
  2315. ]), rightOrientation = faceOrientation([
  2316. { x: xp, y: ym, z: zp },
  2317. { x: xp, y: ym, z: zm },
  2318. { x: xp, y: yp, z: zm },
  2319. { x: xp, y: yp, z: zp }
  2320. ]), frontOrientation = faceOrientation([
  2321. { x: xm, y: yp, z: zm },
  2322. { x: xp, y: yp, z: zm },
  2323. { x: xp, y: ym, z: zm },
  2324. { x: xm, y: ym, z: zm }
  2325. ]), backOrientation = faceOrientation([
  2326. { x: xm, y: ym, z: zp },
  2327. { x: xp, y: ym, z: zp },
  2328. { x: xp, y: yp, z: zp },
  2329. { x: xm, y: yp, z: zp }
  2330. ]), defaultShowBottom = false, defaultShowTop = false, defaultShowLeft = false, defaultShowRight = false, defaultShowFront = false, defaultShowBack = true;
  2331. // The 'default' criteria to visible faces of the frame is looking
  2332. // up every axis to decide whenever the left/right//top/bottom sides
  2333. // of the frame will be shown
  2334. []
  2335. .concat(chart.xAxis, chart.yAxis, chart.zAxis)
  2336. .forEach(function (axis) {
  2337. if (axis) {
  2338. if (axis.horiz) {
  2339. if (axis.opposite) {
  2340. defaultShowTop = true;
  2341. }
  2342. else {
  2343. defaultShowBottom = true;
  2344. }
  2345. }
  2346. else {
  2347. if (axis.opposite) {
  2348. defaultShowRight = true;
  2349. }
  2350. else {
  2351. defaultShowLeft = true;
  2352. }
  2353. }
  2354. }
  2355. });
  2356. var getFaceOptions = function (sources, faceOrientation, defaultVisible) {
  2357. var faceAttrs = ['size', 'color', 'visible'];
  2358. var options = {};
  2359. for (var i = 0; i < faceAttrs.length; i++) {
  2360. var attr = faceAttrs[i];
  2361. for (var j = 0; j < sources.length; j++) {
  2362. if (typeof sources[j] === 'object') {
  2363. var val = sources[j][attr];
  2364. if (typeof val !== 'undefined' && val !== null) {
  2365. options[attr] = val;
  2366. break;
  2367. }
  2368. }
  2369. }
  2370. }
  2371. var isVisible = defaultVisible;
  2372. if (options.visible === true || options.visible === false) {
  2373. isVisible = options.visible;
  2374. }
  2375. else if (options.visible === 'auto') {
  2376. isVisible = faceOrientation > 0;
  2377. }
  2378. return {
  2379. size: pick(options.size, 1),
  2380. color: pick(options.color, 'none'),
  2381. frontFacing: faceOrientation > 0,
  2382. visible: isVisible
  2383. };
  2384. };
  2385. // docs @TODO: Add all frame options (left, right, top, bottom,
  2386. // front, back) to apioptions JSDoc once the new system is up.
  2387. var ret = {
  2388. axes: {},
  2389. // FIXME: Previously, left/right, top/bottom and front/back
  2390. // pairs shared size and color.
  2391. // For compatibility and consistency sake, when one face have
  2392. // size/color/visibility set, the opposite face will default to
  2393. // the same values. Also, left/right used to be called 'side',
  2394. // so that's also added as a fallback.
  2395. bottom: getFaceOptions([frameOptions.bottom,
  2396. frameOptions.top,
  2397. frameOptions],
  2398. bottomOrientation,
  2399. defaultShowBottom),
  2400. top: getFaceOptions([frameOptions.top,
  2401. frameOptions.bottom,
  2402. frameOptions],
  2403. topOrientation,
  2404. defaultShowTop),
  2405. left: getFaceOptions([
  2406. frameOptions.left,
  2407. frameOptions.right,
  2408. frameOptions.side,
  2409. frameOptions
  2410. ],
  2411. leftOrientation,
  2412. defaultShowLeft),
  2413. right: getFaceOptions([
  2414. frameOptions.right,
  2415. frameOptions.left,
  2416. frameOptions.side,
  2417. frameOptions
  2418. ],
  2419. rightOrientation,
  2420. defaultShowRight),
  2421. back: getFaceOptions([frameOptions.back,
  2422. frameOptions.front,
  2423. frameOptions],
  2424. backOrientation,
  2425. defaultShowBack),
  2426. front: getFaceOptions([frameOptions.front,
  2427. frameOptions.back,
  2428. frameOptions],
  2429. frontOrientation,
  2430. defaultShowFront)
  2431. };
  2432. // Decide the bast place to put axis title/labels based on the
  2433. // visible faces. Ideally, The labels can only be on the edge
  2434. // between a visible face and an invisble one. Also, the Y label
  2435. // should be one the left-most edge (right-most if opposite).
  2436. if (options3d.axisLabelPosition === 'auto') {
  2437. var isValidEdge = function (face1,
  2438. face2) {
  2439. return ((face1.visible !== face2.visible) ||
  2440. (face1.visible &&
  2441. face2.visible &&
  2442. (face1.frontFacing !== face2.frontFacing)));
  2443. };
  2444. var yEdges = [];
  2445. if (isValidEdge(ret.left, ret.front)) {
  2446. yEdges.push({
  2447. y: (ym + yp) / 2,
  2448. x: xm,
  2449. z: zm,
  2450. xDir: { x: 1, y: 0, z: 0 }
  2451. });
  2452. }
  2453. if (isValidEdge(ret.left, ret.back)) {
  2454. yEdges.push({
  2455. y: (ym + yp) / 2,
  2456. x: xm,
  2457. z: zp,
  2458. xDir: { x: 0, y: 0, z: -1 }
  2459. });
  2460. }
  2461. if (isValidEdge(ret.right, ret.front)) {
  2462. yEdges.push({
  2463. y: (ym + yp) / 2,
  2464. x: xp,
  2465. z: zm,
  2466. xDir: { x: 0, y: 0, z: 1 }
  2467. });
  2468. }
  2469. if (isValidEdge(ret.right, ret.back)) {
  2470. yEdges.push({
  2471. y: (ym + yp) / 2,
  2472. x: xp,
  2473. z: zp,
  2474. xDir: { x: -1, y: 0, z: 0 }
  2475. });
  2476. }
  2477. var xBottomEdges = [];
  2478. if (isValidEdge(ret.bottom, ret.front)) {
  2479. xBottomEdges.push({
  2480. x: (xm + xp) / 2,
  2481. y: yp,
  2482. z: zm,
  2483. xDir: { x: 1, y: 0, z: 0 }
  2484. });
  2485. }
  2486. if (isValidEdge(ret.bottom, ret.back)) {
  2487. xBottomEdges.push({
  2488. x: (xm + xp) / 2,
  2489. y: yp,
  2490. z: zp,
  2491. xDir: { x: -1, y: 0, z: 0 }
  2492. });
  2493. }
  2494. var xTopEdges = [];
  2495. if (isValidEdge(ret.top, ret.front)) {
  2496. xTopEdges.push({
  2497. x: (xm + xp) / 2,
  2498. y: ym,
  2499. z: zm,
  2500. xDir: { x: 1, y: 0, z: 0 }
  2501. });
  2502. }
  2503. if (isValidEdge(ret.top, ret.back)) {
  2504. xTopEdges.push({
  2505. x: (xm + xp) / 2,
  2506. y: ym,
  2507. z: zp,
  2508. xDir: { x: -1, y: 0, z: 0 }
  2509. });
  2510. }
  2511. var zBottomEdges = [];
  2512. if (isValidEdge(ret.bottom, ret.left)) {
  2513. zBottomEdges.push({
  2514. z: (zm + zp) / 2,
  2515. y: yp,
  2516. x: xm,
  2517. xDir: { x: 0, y: 0, z: -1 }
  2518. });
  2519. }
  2520. if (isValidEdge(ret.bottom, ret.right)) {
  2521. zBottomEdges.push({
  2522. z: (zm + zp) / 2,
  2523. y: yp,
  2524. x: xp,
  2525. xDir: { x: 0, y: 0, z: 1 }
  2526. });
  2527. }
  2528. var zTopEdges = [];
  2529. if (isValidEdge(ret.top, ret.left)) {
  2530. zTopEdges.push({
  2531. z: (zm + zp) / 2,
  2532. y: ym,
  2533. x: xm,
  2534. xDir: { x: 0, y: 0, z: -1 }
  2535. });
  2536. }
  2537. if (isValidEdge(ret.top, ret.right)) {
  2538. zTopEdges.push({
  2539. z: (zm + zp) / 2,
  2540. y: ym,
  2541. x: xp,
  2542. xDir: { x: 0, y: 0, z: 1 }
  2543. });
  2544. }
  2545. var pickEdge = function (edges,
  2546. axis,
  2547. mult) {
  2548. if (edges.length === 0) {
  2549. return null;
  2550. }
  2551. if (edges.length === 1) {
  2552. return edges[0];
  2553. }
  2554. var best = 0,
  2555. projections = perspective(edges,
  2556. chart,
  2557. false);
  2558. for (var i = 1; i < projections.length; i++) {
  2559. if (mult * projections[i][axis] >
  2560. mult * projections[best][axis]) {
  2561. best = i;
  2562. }
  2563. else if ((mult * projections[i][axis] ===
  2564. mult * projections[best][axis]) &&
  2565. (projections[i].z < projections[best].z)) {
  2566. best = i;
  2567. }
  2568. }
  2569. return edges[best];
  2570. };
  2571. ret.axes = {
  2572. y: {
  2573. 'left': pickEdge(yEdges, 'x', -1),
  2574. 'right': pickEdge(yEdges, 'x', +1)
  2575. },
  2576. x: {
  2577. 'top': pickEdge(xTopEdges, 'y', -1),
  2578. 'bottom': pickEdge(xBottomEdges, 'y', +1)
  2579. },
  2580. z: {
  2581. 'top': pickEdge(zTopEdges, 'y', -1),
  2582. 'bottom': pickEdge(zBottomEdges, 'y', +1)
  2583. }
  2584. };
  2585. }
  2586. else {
  2587. ret.axes = {
  2588. y: {
  2589. 'left': { x: xm, z: zm, xDir: { x: 1, y: 0, z: 0 } },
  2590. 'right': { x: xp, z: zm, xDir: { x: 0, y: 0, z: 1 } }
  2591. },
  2592. x: {
  2593. 'top': { y: ym, z: zm, xDir: { x: 1, y: 0, z: 0 } },
  2594. 'bottom': { y: yp, z: zm, xDir: { x: 1, y: 0, z: 0 } }
  2595. },
  2596. z: {
  2597. 'top': {
  2598. x: defaultShowLeft ? xp : xm,
  2599. y: ym,
  2600. xDir: defaultShowLeft ?
  2601. { x: 0, y: 0, z: 1 } :
  2602. { x: 0, y: 0, z: -1 }
  2603. },
  2604. 'bottom': {
  2605. x: defaultShowLeft ? xp : xm,
  2606. y: yp,
  2607. xDir: defaultShowLeft ?
  2608. { x: 0, y: 0, z: 1 } :
  2609. { x: 0, y: 0, z: -1 }
  2610. }
  2611. }
  2612. };
  2613. }
  2614. return ret;
  2615. };
  2616. /**
  2617. * Calculate scale of the 3D view. That is required to fit chart's 3D
  2618. * projection into the actual plotting area. Reported as #4933.
  2619. *
  2620. * @notice
  2621. * This function should ideally take the plot values instead of a chart
  2622. * object, but since the chart object is needed for perspective it is
  2623. * not practical. Possible to make both getScale and perspective more
  2624. * logical and also immutable.
  2625. *
  2626. * @private
  2627. * @function getScale
  2628. *
  2629. * @param {number} depth
  2630. * The depth of the chart
  2631. *
  2632. * @return {number}
  2633. * The scale to fit the 3D chart into the plotting area.
  2634. *
  2635. * @requires highcharts-3d
  2636. */
  2637. Composition.prototype.getScale = function (depth) {
  2638. var chart = this.chart,
  2639. plotLeft = chart.plotLeft,
  2640. plotRight = chart.plotWidth + plotLeft,
  2641. plotTop = chart.plotTop,
  2642. plotBottom = chart.plotHeight + plotTop,
  2643. originX = plotLeft + chart.plotWidth / 2,
  2644. originY = plotTop + chart.plotHeight / 2,
  2645. bbox3d = {
  2646. minX: Number.MAX_VALUE,
  2647. maxX: -Number.MAX_VALUE,
  2648. minY: Number.MAX_VALUE,
  2649. maxY: -Number.MAX_VALUE
  2650. },
  2651. corners,
  2652. scale = 1;
  2653. // Top left corners:
  2654. corners = [{
  2655. x: plotLeft,
  2656. y: plotTop,
  2657. z: 0
  2658. }, {
  2659. x: plotLeft,
  2660. y: plotTop,
  2661. z: depth
  2662. }];
  2663. // Top right corners:
  2664. [0, 1].forEach(function (i) {
  2665. corners.push({
  2666. x: plotRight,
  2667. y: corners[i].y,
  2668. z: corners[i].z
  2669. });
  2670. });
  2671. // All bottom corners:
  2672. [0, 1, 2, 3].forEach(function (i) {
  2673. corners.push({
  2674. x: corners[i].x,
  2675. y: plotBottom,
  2676. z: corners[i].z
  2677. });
  2678. });
  2679. // Calculate 3D corners:
  2680. corners = perspective(corners, chart, false);
  2681. // Get bounding box of 3D element:
  2682. corners.forEach(function (corner) {
  2683. bbox3d.minX = Math.min(bbox3d.minX, corner.x);
  2684. bbox3d.maxX = Math.max(bbox3d.maxX, corner.x);
  2685. bbox3d.minY = Math.min(bbox3d.minY, corner.y);
  2686. bbox3d.maxY = Math.max(bbox3d.maxY, corner.y);
  2687. });
  2688. // Left edge:
  2689. if (plotLeft > bbox3d.minX) {
  2690. scale = Math.min(scale, 1 - Math.abs((plotLeft + originX) / (bbox3d.minX + originX)) % 1);
  2691. }
  2692. // Right edge:
  2693. if (plotRight < bbox3d.maxX) {
  2694. scale = Math.min(scale, (plotRight - originX) / (bbox3d.maxX - originX));
  2695. }
  2696. // Top edge:
  2697. if (plotTop > bbox3d.minY) {
  2698. if (bbox3d.minY < 0) {
  2699. scale = Math.min(scale, (plotTop + originY) / (-bbox3d.minY + plotTop + originY));
  2700. }
  2701. else {
  2702. scale = Math.min(scale, 1 - (plotTop + originY) / (bbox3d.minY + originY) % 1);
  2703. }
  2704. }
  2705. // Bottom edge:
  2706. if (plotBottom < bbox3d.maxY) {
  2707. scale = Math.min(scale, Math.abs((plotBottom - originY) / (bbox3d.maxY - originY)));
  2708. }
  2709. return scale;
  2710. };
  2711. return Composition;
  2712. }());
  2713. Chart3D.Composition = Composition;
  2714. /* *
  2715. *
  2716. * Constants
  2717. *
  2718. * */
  2719. /**
  2720. * @optionparent
  2721. * @private
  2722. */
  2723. Chart3D.defaultOptions = {
  2724. chart: {
  2725. /**
  2726. * Options to render charts in 3 dimensions. This feature requires
  2727. * `highcharts-3d.js`, found in the download package or online at
  2728. * [code.highcharts.com/highcharts-3d.js](https://code.highcharts.com/highcharts-3d.js).
  2729. *
  2730. * @since 4.0
  2731. * @product highcharts
  2732. * @requires highcharts-3d
  2733. */
  2734. options3d: {
  2735. /**
  2736. * Wether to render the chart using the 3D functionality.
  2737. *
  2738. * @since 4.0
  2739. * @product highcharts
  2740. */
  2741. enabled: false,
  2742. /**
  2743. * One of the two rotation angles for the chart.
  2744. *
  2745. * @since 4.0
  2746. * @product highcharts
  2747. */
  2748. alpha: 0,
  2749. /**
  2750. * One of the two rotation angles for the chart.
  2751. *
  2752. * @since 4.0
  2753. * @product highcharts
  2754. */
  2755. beta: 0,
  2756. /**
  2757. * The total depth of the chart.
  2758. *
  2759. * @since 4.0
  2760. * @product highcharts
  2761. */
  2762. depth: 100,
  2763. /**
  2764. * Whether the 3d box should automatically adjust to the chart
  2765. * plot area.
  2766. *
  2767. * @since 4.2.4
  2768. * @product highcharts
  2769. */
  2770. fitToPlot: true,
  2771. /**
  2772. * Defines the distance the viewer is standing in front of the
  2773. * chart, this setting is important to calculate the perspective
  2774. * effect in column and scatter charts. It is not used for 3D
  2775. * pie charts.
  2776. *
  2777. * @since 4.0
  2778. * @product highcharts
  2779. */
  2780. viewDistance: 25,
  2781. /**
  2782. * Set it to `"auto"` to automatically move the labels to the
  2783. * best edge.
  2784. *
  2785. * @type {"auto"|null}
  2786. * @since 5.0.12
  2787. * @product highcharts
  2788. */
  2789. axisLabelPosition: null,
  2790. /**
  2791. * Provides the option to draw a frame around the charts by
  2792. * defining a bottom, front and back panel.
  2793. *
  2794. * @since 4.0
  2795. * @product highcharts
  2796. * @requires highcharts-3d
  2797. */
  2798. frame: {
  2799. /**
  2800. * Whether the frames are visible.
  2801. */
  2802. visible: 'default',
  2803. /**
  2804. * General pixel thickness for the frame faces.
  2805. */
  2806. size: 1,
  2807. /**
  2808. * The bottom of the frame around a 3D chart.
  2809. *
  2810. * @since 4.0
  2811. * @product highcharts
  2812. * @requires highcharts-3d
  2813. */
  2814. /**
  2815. * The color of the panel.
  2816. *
  2817. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  2818. * @default transparent
  2819. * @since 4.0
  2820. * @product highcharts
  2821. * @apioption chart.options3d.frame.bottom.color
  2822. */
  2823. /**
  2824. * The thickness of the panel.
  2825. *
  2826. * @type {number}
  2827. * @default 1
  2828. * @since 4.0
  2829. * @product highcharts
  2830. * @apioption chart.options3d.frame.bottom.size
  2831. */
  2832. /**
  2833. * Whether to display the frame. Possible values are `true`,
  2834. * `false`, `"auto"` to display only the frames behind the
  2835. * data, and `"default"` to display faces behind the data
  2836. * based on the axis layout, ignoring the point of view.
  2837. *
  2838. * @sample {highcharts} highcharts/3d/scatter-frame/
  2839. * Auto frames
  2840. *
  2841. * @type {boolean|"default"|"auto"}
  2842. * @default default
  2843. * @since 5.0.12
  2844. * @product highcharts
  2845. * @apioption chart.options3d.frame.bottom.visible
  2846. */
  2847. /**
  2848. * The bottom of the frame around a 3D chart.
  2849. */
  2850. bottom: {},
  2851. /**
  2852. * The top of the frame around a 3D chart.
  2853. *
  2854. * @extends chart.options3d.frame.bottom
  2855. */
  2856. top: {},
  2857. /**
  2858. * The left side of the frame around a 3D chart.
  2859. *
  2860. * @extends chart.options3d.frame.bottom
  2861. */
  2862. left: {},
  2863. /**
  2864. * The right of the frame around a 3D chart.
  2865. *
  2866. * @extends chart.options3d.frame.bottom
  2867. */
  2868. right: {},
  2869. /**
  2870. * The back side of the frame around a 3D chart.
  2871. *
  2872. * @extends chart.options3d.frame.bottom
  2873. */
  2874. back: {},
  2875. /**
  2876. * The front of the frame around a 3D chart.
  2877. *
  2878. * @extends chart.options3d.frame.bottom
  2879. */
  2880. front: {}
  2881. }
  2882. }
  2883. }
  2884. };
  2885. /* *
  2886. *
  2887. * Functions
  2888. *
  2889. * */
  2890. /**
  2891. * @private
  2892. */
  2893. function compose(ChartClass, FxClass) {
  2894. var chartProto = ChartClass.prototype;
  2895. var fxProto = FxClass.prototype;
  2896. /**
  2897. * Shorthand to check the is3d flag.
  2898. * @private
  2899. * @return {boolean}
  2900. * Whether it is a 3D chart.
  2901. */
  2902. chartProto.is3d = function () {
  2903. return (this.options.chart.options3d &&
  2904. this.options.chart.options3d.enabled); // #4280
  2905. };
  2906. chartProto.propsRequireDirtyBox.push('chart.options3d');
  2907. chartProto.propsRequireUpdateSeries.push('chart.options3d');
  2908. /**
  2909. * Animation setter for matrix property.
  2910. * @private
  2911. */
  2912. fxProto.matrixSetter = function () {
  2913. var interpolated;
  2914. if (this.pos < 1 &&
  2915. (isArray(this.start) || isArray(this.end))) {
  2916. var start = this.start || [1, 0, 0, 1, 0, 0];
  2917. var end = this.end || [1, 0, 0, 1, 0, 0];
  2918. interpolated = [];
  2919. for (var i = 0; i < 6; i++) {
  2920. interpolated.push(this.pos * end[i] + (1 - this.pos) * start[i]);
  2921. }
  2922. }
  2923. else {
  2924. interpolated = this.end;
  2925. }
  2926. this.elem.attr(this.prop, interpolated, null, true);
  2927. };
  2928. merge(true, genericDefaultOptions, Chart3D.defaultOptions);
  2929. addEvent(ChartClass, 'init', onInit);
  2930. addEvent(ChartClass, 'addSeries', onAddSeries);
  2931. addEvent(ChartClass, 'afterDrawChartBox', onAfterDrawChartBox);
  2932. addEvent(ChartClass, 'afterGetContainer', onAfterGetContainer);
  2933. addEvent(ChartClass, 'afterInit', onAfterInit);
  2934. addEvent(ChartClass, 'afterSetChartSize', onAfterSetChartSize);
  2935. addEvent(ChartClass, 'beforeRedraw', onBeforeRedraw);
  2936. addEvent(ChartClass, 'beforeRender', onBeforeRender);
  2937. wrap(H.Chart.prototype, 'isInsidePlot', wrapIsInsidePlot);
  2938. wrap(ChartClass, 'renderSeries', wrapRenderSeries);
  2939. wrap(ChartClass, 'setClassName', wrapSetClassName);
  2940. }
  2941. Chart3D.compose = compose;
  2942. /**
  2943. * Legacy support for HC < 6 to make 'scatter' series in a 3D chart route to
  2944. * the real 'scatter3d' series type. (#8407)
  2945. * @private
  2946. */
  2947. function onAddSeries(e) {
  2948. if (this.is3d()) {
  2949. if (e.options.type === 'scatter') {
  2950. e.options.type = 'scatter3d';
  2951. }
  2952. }
  2953. }
  2954. /**
  2955. * @private
  2956. */
  2957. function onAfterDrawChartBox() {
  2958. if (this.chart3d &&
  2959. this.is3d()) {
  2960. var chart = this,
  2961. renderer = chart.renderer,
  2962. options3d = this.options.chart.options3d,
  2963. frame = this.chart3d.get3dFrame(),
  2964. xm = this.plotLeft,
  2965. xp = this.plotLeft + this.plotWidth,
  2966. ym = this.plotTop,
  2967. yp = this.plotTop + this.plotHeight,
  2968. zm = 0,
  2969. zp = options3d.depth,
  2970. xmm = xm - (frame.left.visible ? frame.left.size : 0),
  2971. xpp = xp + (frame.right.visible ? frame.right.size : 0),
  2972. ymm = ym - (frame.top.visible ? frame.top.size : 0),
  2973. ypp = yp + (frame.bottom.visible ? frame.bottom.size : 0),
  2974. zmm = zm - (frame.front.visible ? frame.front.size : 0),
  2975. zpp = zp + (frame.back.visible ? frame.back.size : 0),
  2976. verb = chart.hasRendered ? 'animate' : 'attr';
  2977. this.chart3d.frame3d = frame;
  2978. if (!this.frameShapes) {
  2979. this.frameShapes = {
  2980. bottom: renderer.polyhedron().add(),
  2981. top: renderer.polyhedron().add(),
  2982. left: renderer.polyhedron().add(),
  2983. right: renderer.polyhedron().add(),
  2984. back: renderer.polyhedron().add(),
  2985. front: renderer.polyhedron().add()
  2986. };
  2987. }
  2988. this.frameShapes.bottom[verb]({
  2989. 'class': 'highcharts-3d-frame highcharts-3d-frame-bottom',
  2990. zIndex: frame.bottom.frontFacing ? -1000 : 1000,
  2991. faces: [{
  2992. fill: H.color(frame.bottom.color).brighten(0.1).get(),
  2993. vertexes: [{
  2994. x: xmm,
  2995. y: ypp,
  2996. z: zmm
  2997. }, {
  2998. x: xpp,
  2999. y: ypp,
  3000. z: zmm
  3001. }, {
  3002. x: xpp,
  3003. y: ypp,
  3004. z: zpp
  3005. }, {
  3006. x: xmm,
  3007. y: ypp,
  3008. z: zpp
  3009. }],
  3010. enabled: frame.bottom.visible
  3011. },
  3012. {
  3013. fill: H.color(frame.bottom.color).brighten(0.1).get(),
  3014. vertexes: [{
  3015. x: xm,
  3016. y: yp,
  3017. z: zp
  3018. }, {
  3019. x: xp,
  3020. y: yp,
  3021. z: zp
  3022. }, {
  3023. x: xp,
  3024. y: yp,
  3025. z: zm
  3026. }, {
  3027. x: xm,
  3028. y: yp,
  3029. z: zm
  3030. }],
  3031. enabled: frame.bottom.visible
  3032. },
  3033. {
  3034. fill: H.color(frame.bottom.color).brighten(-0.1).get(),
  3035. vertexes: [{
  3036. x: xmm,
  3037. y: ypp,
  3038. z: zmm
  3039. }, {
  3040. x: xmm,
  3041. y: ypp,
  3042. z: zpp
  3043. }, {
  3044. x: xm,
  3045. y: yp,
  3046. z: zp
  3047. }, {
  3048. x: xm,
  3049. y: yp,
  3050. z: zm
  3051. }],
  3052. enabled: frame.bottom.visible && !frame.left.visible
  3053. },
  3054. {
  3055. fill: H.color(frame.bottom.color).brighten(-0.1).get(),
  3056. vertexes: [{
  3057. x: xpp,
  3058. y: ypp,
  3059. z: zpp
  3060. }, {
  3061. x: xpp,
  3062. y: ypp,
  3063. z: zmm
  3064. }, {
  3065. x: xp,
  3066. y: yp,
  3067. z: zm
  3068. }, {
  3069. x: xp,
  3070. y: yp,
  3071. z: zp
  3072. }],
  3073. enabled: frame.bottom.visible && !frame.right.visible
  3074. },
  3075. {
  3076. fill: H.color(frame.bottom.color).get(),
  3077. vertexes: [{
  3078. x: xpp,
  3079. y: ypp,
  3080. z: zmm
  3081. }, {
  3082. x: xmm,
  3083. y: ypp,
  3084. z: zmm
  3085. }, {
  3086. x: xm,
  3087. y: yp,
  3088. z: zm
  3089. }, {
  3090. x: xp,
  3091. y: yp,
  3092. z: zm
  3093. }],
  3094. enabled: frame.bottom.visible && !frame.front.visible
  3095. },
  3096. {
  3097. fill: H.color(frame.bottom.color).get(),
  3098. vertexes: [{
  3099. x: xmm,
  3100. y: ypp,
  3101. z: zpp
  3102. }, {
  3103. x: xpp,
  3104. y: ypp,
  3105. z: zpp
  3106. }, {
  3107. x: xp,
  3108. y: yp,
  3109. z: zp
  3110. }, {
  3111. x: xm,
  3112. y: yp,
  3113. z: zp
  3114. }],
  3115. enabled: frame.bottom.visible && !frame.back.visible
  3116. }]
  3117. });
  3118. this.frameShapes.top[verb]({
  3119. 'class': 'highcharts-3d-frame highcharts-3d-frame-top',
  3120. zIndex: frame.top.frontFacing ? -1000 : 1000,
  3121. faces: [{
  3122. fill: H.color(frame.top.color).brighten(0.1).get(),
  3123. vertexes: [{
  3124. x: xmm,
  3125. y: ymm,
  3126. z: zpp
  3127. }, {
  3128. x: xpp,
  3129. y: ymm,
  3130. z: zpp
  3131. }, {
  3132. x: xpp,
  3133. y: ymm,
  3134. z: zmm
  3135. }, {
  3136. x: xmm,
  3137. y: ymm,
  3138. z: zmm
  3139. }],
  3140. enabled: frame.top.visible
  3141. },
  3142. {
  3143. fill: H.color(frame.top.color).brighten(0.1).get(),
  3144. vertexes: [{
  3145. x: xm,
  3146. y: ym,
  3147. z: zm
  3148. }, {
  3149. x: xp,
  3150. y: ym,
  3151. z: zm
  3152. }, {
  3153. x: xp,
  3154. y: ym,
  3155. z: zp
  3156. }, {
  3157. x: xm,
  3158. y: ym,
  3159. z: zp
  3160. }],
  3161. enabled: frame.top.visible
  3162. },
  3163. {
  3164. fill: H.color(frame.top.color).brighten(-0.1).get(),
  3165. vertexes: [{
  3166. x: xmm,
  3167. y: ymm,
  3168. z: zpp
  3169. }, {
  3170. x: xmm,
  3171. y: ymm,
  3172. z: zmm
  3173. }, {
  3174. x: xm,
  3175. y: ym,
  3176. z: zm
  3177. }, {
  3178. x: xm,
  3179. y: ym,
  3180. z: zp
  3181. }],
  3182. enabled: frame.top.visible && !frame.left.visible
  3183. },
  3184. {
  3185. fill: H.color(frame.top.color).brighten(-0.1).get(),
  3186. vertexes: [{
  3187. x: xpp,
  3188. y: ymm,
  3189. z: zmm
  3190. }, {
  3191. x: xpp,
  3192. y: ymm,
  3193. z: zpp
  3194. }, {
  3195. x: xp,
  3196. y: ym,
  3197. z: zp
  3198. }, {
  3199. x: xp,
  3200. y: ym,
  3201. z: zm
  3202. }],
  3203. enabled: frame.top.visible && !frame.right.visible
  3204. },
  3205. {
  3206. fill: H.color(frame.top.color).get(),
  3207. vertexes: [{
  3208. x: xmm,
  3209. y: ymm,
  3210. z: zmm
  3211. }, {
  3212. x: xpp,
  3213. y: ymm,
  3214. z: zmm
  3215. }, {
  3216. x: xp,
  3217. y: ym,
  3218. z: zm
  3219. }, {
  3220. x: xm,
  3221. y: ym,
  3222. z: zm
  3223. }],
  3224. enabled: frame.top.visible && !frame.front.visible
  3225. },
  3226. {
  3227. fill: H.color(frame.top.color).get(),
  3228. vertexes: [{
  3229. x: xpp,
  3230. y: ymm,
  3231. z: zpp
  3232. }, {
  3233. x: xmm,
  3234. y: ymm,
  3235. z: zpp
  3236. }, {
  3237. x: xm,
  3238. y: ym,
  3239. z: zp
  3240. }, {
  3241. x: xp,
  3242. y: ym,
  3243. z: zp
  3244. }],
  3245. enabled: frame.top.visible && !frame.back.visible
  3246. }]
  3247. });
  3248. this.frameShapes.left[verb]({
  3249. 'class': 'highcharts-3d-frame highcharts-3d-frame-left',
  3250. zIndex: frame.left.frontFacing ? -1000 : 1000,
  3251. faces: [{
  3252. fill: H.color(frame.left.color).brighten(0.1).get(),
  3253. vertexes: [{
  3254. x: xmm,
  3255. y: ypp,
  3256. z: zmm
  3257. }, {
  3258. x: xm,
  3259. y: yp,
  3260. z: zm
  3261. }, {
  3262. x: xm,
  3263. y: yp,
  3264. z: zp
  3265. }, {
  3266. x: xmm,
  3267. y: ypp,
  3268. z: zpp
  3269. }],
  3270. enabled: frame.left.visible && !frame.bottom.visible
  3271. },
  3272. {
  3273. fill: H.color(frame.left.color).brighten(0.1).get(),
  3274. vertexes: [{
  3275. x: xmm,
  3276. y: ymm,
  3277. z: zpp
  3278. }, {
  3279. x: xm,
  3280. y: ym,
  3281. z: zp
  3282. }, {
  3283. x: xm,
  3284. y: ym,
  3285. z: zm
  3286. }, {
  3287. x: xmm,
  3288. y: ymm,
  3289. z: zmm
  3290. }],
  3291. enabled: frame.left.visible && !frame.top.visible
  3292. },
  3293. {
  3294. fill: H.color(frame.left.color).brighten(-0.1).get(),
  3295. vertexes: [{
  3296. x: xmm,
  3297. y: ypp,
  3298. z: zpp
  3299. }, {
  3300. x: xmm,
  3301. y: ymm,
  3302. z: zpp
  3303. }, {
  3304. x: xmm,
  3305. y: ymm,
  3306. z: zmm
  3307. }, {
  3308. x: xmm,
  3309. y: ypp,
  3310. z: zmm
  3311. }],
  3312. enabled: frame.left.visible
  3313. },
  3314. {
  3315. fill: H.color(frame.left.color).brighten(-0.1).get(),
  3316. vertexes: [{
  3317. x: xm,
  3318. y: ym,
  3319. z: zp
  3320. }, {
  3321. x: xm,
  3322. y: yp,
  3323. z: zp
  3324. }, {
  3325. x: xm,
  3326. y: yp,
  3327. z: zm
  3328. }, {
  3329. x: xm,
  3330. y: ym,
  3331. z: zm
  3332. }],
  3333. enabled: frame.left.visible
  3334. },
  3335. {
  3336. fill: H.color(frame.left.color).get(),
  3337. vertexes: [{
  3338. x: xmm,
  3339. y: ypp,
  3340. z: zmm
  3341. }, {
  3342. x: xmm,
  3343. y: ymm,
  3344. z: zmm
  3345. }, {
  3346. x: xm,
  3347. y: ym,
  3348. z: zm
  3349. }, {
  3350. x: xm,
  3351. y: yp,
  3352. z: zm
  3353. }],
  3354. enabled: frame.left.visible && !frame.front.visible
  3355. },
  3356. {
  3357. fill: H.color(frame.left.color).get(),
  3358. vertexes: [{
  3359. x: xmm,
  3360. y: ymm,
  3361. z: zpp
  3362. }, {
  3363. x: xmm,
  3364. y: ypp,
  3365. z: zpp
  3366. }, {
  3367. x: xm,
  3368. y: yp,
  3369. z: zp
  3370. }, {
  3371. x: xm,
  3372. y: ym,
  3373. z: zp
  3374. }],
  3375. enabled: frame.left.visible && !frame.back.visible
  3376. }]
  3377. });
  3378. this.frameShapes.right[verb]({
  3379. 'class': 'highcharts-3d-frame highcharts-3d-frame-right',
  3380. zIndex: frame.right.frontFacing ? -1000 : 1000,
  3381. faces: [{
  3382. fill: H.color(frame.right.color).brighten(0.1).get(),
  3383. vertexes: [{
  3384. x: xpp,
  3385. y: ypp,
  3386. z: zpp
  3387. }, {
  3388. x: xp,
  3389. y: yp,
  3390. z: zp
  3391. }, {
  3392. x: xp,
  3393. y: yp,
  3394. z: zm
  3395. }, {
  3396. x: xpp,
  3397. y: ypp,
  3398. z: zmm
  3399. }],
  3400. enabled: frame.right.visible && !frame.bottom.visible
  3401. },
  3402. {
  3403. fill: H.color(frame.right.color).brighten(0.1).get(),
  3404. vertexes: [{
  3405. x: xpp,
  3406. y: ymm,
  3407. z: zmm
  3408. }, {
  3409. x: xp,
  3410. y: ym,
  3411. z: zm
  3412. }, {
  3413. x: xp,
  3414. y: ym,
  3415. z: zp
  3416. }, {
  3417. x: xpp,
  3418. y: ymm,
  3419. z: zpp
  3420. }],
  3421. enabled: frame.right.visible && !frame.top.visible
  3422. },
  3423. {
  3424. fill: H.color(frame.right.color).brighten(-0.1).get(),
  3425. vertexes: [{
  3426. x: xp,
  3427. y: ym,
  3428. z: zm
  3429. }, {
  3430. x: xp,
  3431. y: yp,
  3432. z: zm
  3433. }, {
  3434. x: xp,
  3435. y: yp,
  3436. z: zp
  3437. }, {
  3438. x: xp,
  3439. y: ym,
  3440. z: zp
  3441. }],
  3442. enabled: frame.right.visible
  3443. },
  3444. {
  3445. fill: H.color(frame.right.color).brighten(-0.1).get(),
  3446. vertexes: [{
  3447. x: xpp,
  3448. y: ypp,
  3449. z: zmm
  3450. }, {
  3451. x: xpp,
  3452. y: ymm,
  3453. z: zmm
  3454. }, {
  3455. x: xpp,
  3456. y: ymm,
  3457. z: zpp
  3458. }, {
  3459. x: xpp,
  3460. y: ypp,
  3461. z: zpp
  3462. }],
  3463. enabled: frame.right.visible
  3464. },
  3465. {
  3466. fill: H.color(frame.right.color).get(),
  3467. vertexes: [{
  3468. x: xpp,
  3469. y: ymm,
  3470. z: zmm
  3471. }, {
  3472. x: xpp,
  3473. y: ypp,
  3474. z: zmm
  3475. }, {
  3476. x: xp,
  3477. y: yp,
  3478. z: zm
  3479. }, {
  3480. x: xp,
  3481. y: ym,
  3482. z: zm
  3483. }],
  3484. enabled: frame.right.visible && !frame.front.visible
  3485. },
  3486. {
  3487. fill: H.color(frame.right.color).get(),
  3488. vertexes: [{
  3489. x: xpp,
  3490. y: ypp,
  3491. z: zpp
  3492. }, {
  3493. x: xpp,
  3494. y: ymm,
  3495. z: zpp
  3496. }, {
  3497. x: xp,
  3498. y: ym,
  3499. z: zp
  3500. }, {
  3501. x: xp,
  3502. y: yp,
  3503. z: zp
  3504. }],
  3505. enabled: frame.right.visible && !frame.back.visible
  3506. }]
  3507. });
  3508. this.frameShapes.back[verb]({
  3509. 'class': 'highcharts-3d-frame highcharts-3d-frame-back',
  3510. zIndex: frame.back.frontFacing ? -1000 : 1000,
  3511. faces: [{
  3512. fill: H.color(frame.back.color).brighten(0.1).get(),
  3513. vertexes: [{
  3514. x: xpp,
  3515. y: ypp,
  3516. z: zpp
  3517. }, {
  3518. x: xmm,
  3519. y: ypp,
  3520. z: zpp
  3521. }, {
  3522. x: xm,
  3523. y: yp,
  3524. z: zp
  3525. }, {
  3526. x: xp,
  3527. y: yp,
  3528. z: zp
  3529. }],
  3530. enabled: frame.back.visible && !frame.bottom.visible
  3531. },
  3532. {
  3533. fill: H.color(frame.back.color).brighten(0.1).get(),
  3534. vertexes: [{
  3535. x: xmm,
  3536. y: ymm,
  3537. z: zpp
  3538. }, {
  3539. x: xpp,
  3540. y: ymm,
  3541. z: zpp
  3542. }, {
  3543. x: xp,
  3544. y: ym,
  3545. z: zp
  3546. }, {
  3547. x: xm,
  3548. y: ym,
  3549. z: zp
  3550. }],
  3551. enabled: frame.back.visible && !frame.top.visible
  3552. },
  3553. {
  3554. fill: H.color(frame.back.color).brighten(-0.1).get(),
  3555. vertexes: [{
  3556. x: xmm,
  3557. y: ypp,
  3558. z: zpp
  3559. }, {
  3560. x: xmm,
  3561. y: ymm,
  3562. z: zpp
  3563. }, {
  3564. x: xm,
  3565. y: ym,
  3566. z: zp
  3567. }, {
  3568. x: xm,
  3569. y: yp,
  3570. z: zp
  3571. }],
  3572. enabled: frame.back.visible && !frame.left.visible
  3573. },
  3574. {
  3575. fill: H.color(frame.back.color).brighten(-0.1).get(),
  3576. vertexes: [{
  3577. x: xpp,
  3578. y: ymm,
  3579. z: zpp
  3580. }, {
  3581. x: xpp,
  3582. y: ypp,
  3583. z: zpp
  3584. }, {
  3585. x: xp,
  3586. y: yp,
  3587. z: zp
  3588. }, {
  3589. x: xp,
  3590. y: ym,
  3591. z: zp
  3592. }],
  3593. enabled: frame.back.visible && !frame.right.visible
  3594. },
  3595. {
  3596. fill: H.color(frame.back.color).get(),
  3597. vertexes: [{
  3598. x: xm,
  3599. y: ym,
  3600. z: zp
  3601. }, {
  3602. x: xp,
  3603. y: ym,
  3604. z: zp
  3605. }, {
  3606. x: xp,
  3607. y: yp,
  3608. z: zp
  3609. }, {
  3610. x: xm,
  3611. y: yp,
  3612. z: zp
  3613. }],
  3614. enabled: frame.back.visible
  3615. },
  3616. {
  3617. fill: H.color(frame.back.color).get(),
  3618. vertexes: [{
  3619. x: xmm,
  3620. y: ypp,
  3621. z: zpp
  3622. }, {
  3623. x: xpp,
  3624. y: ypp,
  3625. z: zpp
  3626. }, {
  3627. x: xpp,
  3628. y: ymm,
  3629. z: zpp
  3630. }, {
  3631. x: xmm,
  3632. y: ymm,
  3633. z: zpp
  3634. }],
  3635. enabled: frame.back.visible
  3636. }]
  3637. });
  3638. this.frameShapes.front[verb]({
  3639. 'class': 'highcharts-3d-frame highcharts-3d-frame-front',
  3640. zIndex: frame.front.frontFacing ? -1000 : 1000,
  3641. faces: [{
  3642. fill: H.color(frame.front.color).brighten(0.1).get(),
  3643. vertexes: [{
  3644. x: xmm,
  3645. y: ypp,
  3646. z: zmm
  3647. }, {
  3648. x: xpp,
  3649. y: ypp,
  3650. z: zmm
  3651. }, {
  3652. x: xp,
  3653. y: yp,
  3654. z: zm
  3655. }, {
  3656. x: xm,
  3657. y: yp,
  3658. z: zm
  3659. }],
  3660. enabled: frame.front.visible && !frame.bottom.visible
  3661. },
  3662. {
  3663. fill: H.color(frame.front.color).brighten(0.1).get(),
  3664. vertexes: [{
  3665. x: xpp,
  3666. y: ymm,
  3667. z: zmm
  3668. }, {
  3669. x: xmm,
  3670. y: ymm,
  3671. z: zmm
  3672. }, {
  3673. x: xm,
  3674. y: ym,
  3675. z: zm
  3676. }, {
  3677. x: xp,
  3678. y: ym,
  3679. z: zm
  3680. }],
  3681. enabled: frame.front.visible && !frame.top.visible
  3682. },
  3683. {
  3684. fill: H.color(frame.front.color).brighten(-0.1).get(),
  3685. vertexes: [{
  3686. x: xmm,
  3687. y: ymm,
  3688. z: zmm
  3689. }, {
  3690. x: xmm,
  3691. y: ypp,
  3692. z: zmm
  3693. }, {
  3694. x: xm,
  3695. y: yp,
  3696. z: zm
  3697. }, {
  3698. x: xm,
  3699. y: ym,
  3700. z: zm
  3701. }],
  3702. enabled: frame.front.visible && !frame.left.visible
  3703. },
  3704. {
  3705. fill: H.color(frame.front.color).brighten(-0.1).get(),
  3706. vertexes: [{
  3707. x: xpp,
  3708. y: ypp,
  3709. z: zmm
  3710. }, {
  3711. x: xpp,
  3712. y: ymm,
  3713. z: zmm
  3714. }, {
  3715. x: xp,
  3716. y: ym,
  3717. z: zm
  3718. }, {
  3719. x: xp,
  3720. y: yp,
  3721. z: zm
  3722. }],
  3723. enabled: frame.front.visible && !frame.right.visible
  3724. },
  3725. {
  3726. fill: H.color(frame.front.color).get(),
  3727. vertexes: [{
  3728. x: xp,
  3729. y: ym,
  3730. z: zm
  3731. }, {
  3732. x: xm,
  3733. y: ym,
  3734. z: zm
  3735. }, {
  3736. x: xm,
  3737. y: yp,
  3738. z: zm
  3739. }, {
  3740. x: xp,
  3741. y: yp,
  3742. z: zm
  3743. }],
  3744. enabled: frame.front.visible
  3745. },
  3746. {
  3747. fill: H.color(frame.front.color).get(),
  3748. vertexes: [{
  3749. x: xpp,
  3750. y: ypp,
  3751. z: zmm
  3752. }, {
  3753. x: xmm,
  3754. y: ypp,
  3755. z: zmm
  3756. }, {
  3757. x: xmm,
  3758. y: ymm,
  3759. z: zmm
  3760. }, {
  3761. x: xpp,
  3762. y: ymm,
  3763. z: zmm
  3764. }],
  3765. enabled: frame.front.visible
  3766. }]
  3767. });
  3768. }
  3769. }
  3770. /**
  3771. * Add the required CSS classes for column sides (#6018)
  3772. * @private
  3773. */
  3774. function onAfterGetContainer() {
  3775. if (this.styledMode) {
  3776. this.renderer.definition({
  3777. tagName: 'style',
  3778. textContent: '.highcharts-3d-top{' +
  3779. 'filter: url(#highcharts-brighter)' +
  3780. '}\n' +
  3781. '.highcharts-3d-side{' +
  3782. 'filter: url(#highcharts-darker)' +
  3783. '}\n'
  3784. });
  3785. // Add add definitions used by brighter and darker faces of the
  3786. // cuboids.
  3787. [{
  3788. name: 'darker',
  3789. slope: 0.6
  3790. }, {
  3791. name: 'brighter',
  3792. slope: 1.4
  3793. }].forEach(function (cfg) {
  3794. this.renderer.definition({
  3795. tagName: 'filter',
  3796. attributes: {
  3797. id: 'highcharts-' + cfg.name
  3798. },
  3799. children: [{
  3800. tagName: 'feComponentTransfer',
  3801. children: [{
  3802. tagName: 'feFuncR',
  3803. attributes: {
  3804. type: 'linear',
  3805. slope: cfg.slope
  3806. }
  3807. }, {
  3808. tagName: 'feFuncG',
  3809. attributes: {
  3810. type: 'linear',
  3811. slope: cfg.slope
  3812. }
  3813. }, {
  3814. tagName: 'feFuncB',
  3815. attributes: {
  3816. type: 'linear',
  3817. slope: cfg.slope
  3818. }
  3819. }]
  3820. }]
  3821. });
  3822. }, this);
  3823. }
  3824. }
  3825. /**
  3826. * Legacy support for HC < 6 to make 'scatter' series in a 3D chart route to
  3827. * the real 'scatter3d' series type. (#8407)
  3828. * @private
  3829. */
  3830. function onAfterInit() {
  3831. var options = this.options;
  3832. if (this.is3d()) {
  3833. (options.series || []).forEach(function (s) {
  3834. var type = s.type ||
  3835. options.chart.type ||
  3836. options.chart.defaultSeriesType;
  3837. if (type === 'scatter') {
  3838. s.type = 'scatter3d';
  3839. }
  3840. });
  3841. }
  3842. }
  3843. /**
  3844. * @private
  3845. */
  3846. function onAfterSetChartSize() {
  3847. var chart = this,
  3848. options3d = chart.options.chart.options3d;
  3849. if (chart.chart3d &&
  3850. chart.is3d()) {
  3851. // Add a 0-360 normalisation for alfa and beta angles in 3d graph
  3852. if (options3d) {
  3853. options3d.alpha = options3d.alpha % 360 + (options3d.alpha >= 0 ? 0 : 360);
  3854. options3d.beta = options3d.beta % 360 + (options3d.beta >= 0 ? 0 : 360);
  3855. }
  3856. var inverted = chart.inverted, clipBox = chart.clipBox, margin = chart.margin, x = inverted ? 'y' : 'x', y = inverted ? 'x' : 'y', w = inverted ? 'height' : 'width', h = inverted ? 'width' : 'height';
  3857. clipBox[x] = -(margin[3] || 0);
  3858. clipBox[y] = -(margin[0] || 0);
  3859. clipBox[w] =
  3860. chart.chartWidth + (margin[3] || 0) + (margin[1] || 0);
  3861. clipBox[h] =
  3862. chart.chartHeight + (margin[0] || 0) + (margin[2] || 0);
  3863. // Set scale, used later in perspective method():
  3864. // getScale uses perspective, so scale3d has to be reset.
  3865. chart.scale3d = 1;
  3866. if (options3d.fitToPlot === true) {
  3867. chart.scale3d = chart.chart3d.getScale(options3d.depth);
  3868. }
  3869. // Recalculate the 3d frame with every call of setChartSize,
  3870. // instead of doing it after every redraw(). It avoids ticks
  3871. // and axis title outside of chart.
  3872. chart.chart3d.frame3d = chart.chart3d.get3dFrame(); // #7942
  3873. }
  3874. }
  3875. /**
  3876. * @private
  3877. */
  3878. function onBeforeRedraw() {
  3879. if (this.is3d()) {
  3880. // Set to force a redraw of all elements
  3881. this.isDirtyBox = true;
  3882. }
  3883. }
  3884. /**
  3885. * @private
  3886. */
  3887. function onBeforeRender() {
  3888. if (this.chart3d && this.is3d()) {
  3889. this.chart3d.frame3d = this.chart3d.get3dFrame();
  3890. }
  3891. }
  3892. /**
  3893. * @private
  3894. */
  3895. function onInit() {
  3896. if (!this.chart3d) {
  3897. this.chart3d = new Composition(this);
  3898. }
  3899. }
  3900. /**
  3901. * @private
  3902. */
  3903. function wrapIsInsidePlot(proceed) {
  3904. return this.is3d() || proceed.apply(this, [].slice.call(arguments, 1));
  3905. }
  3906. /**
  3907. * Draw the series in the reverse order (#3803, #3917)
  3908. * @private
  3909. */
  3910. function wrapRenderSeries(proceed) {
  3911. var series,
  3912. i = this.series.length;
  3913. if (this.is3d()) {
  3914. while (i--) {
  3915. series = this.series[i];
  3916. series.translate();
  3917. series.render();
  3918. }
  3919. }
  3920. else {
  3921. proceed.call(this);
  3922. }
  3923. }
  3924. /**
  3925. * @private
  3926. */
  3927. function wrapSetClassName(proceed) {
  3928. proceed.apply(this, [].slice.call(arguments, 1));
  3929. if (this.is3d()) {
  3930. this.container.className += ' highcharts-3d-chart';
  3931. }
  3932. }
  3933. })(Chart3D || (Chart3D = {}));
  3934. Chart3D.compose(Chart, Fx);
  3935. ZAxis.ZChartComposition.compose(Chart);
  3936. Axis3D.compose(Axis);
  3937. /**
  3938. * Note: As of v5.0.12, `frame.left` or `frame.right` should be used instead.
  3939. *
  3940. * The side for the frame around a 3D chart.
  3941. *
  3942. * @deprecated
  3943. * @since 4.0
  3944. * @product highcharts
  3945. * @requires highcharts-3d
  3946. * @apioption chart.options3d.frame.side
  3947. */
  3948. /**
  3949. * The color of the panel.
  3950. *
  3951. * @deprecated
  3952. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  3953. * @default transparent
  3954. * @since 4.0
  3955. * @product highcharts
  3956. * @apioption chart.options3d.frame.side.color
  3957. */
  3958. /**
  3959. * The thickness of the panel.
  3960. *
  3961. * @deprecated
  3962. * @type {number}
  3963. * @default 1
  3964. * @since 4.0
  3965. * @product highcharts
  3966. * @apioption chart.options3d.frame.side.size
  3967. */
  3968. ''; // adds doclets above to transpiled file
  3969. return Chart3D;
  3970. });
  3971. _registerModule(_modules, 'Core/Series/Series3D.js', [_modules['Extensions/Math3D.js'], _modules['Core/Series/Series.js'], _modules['Core/Utilities.js']], function (Math3D, Series, U) {
  3972. /* *
  3973. *
  3974. * (c) 2010-2021 Torstein Honsi
  3975. *
  3976. * Extension to the Series object in 3D charts.
  3977. *
  3978. * License: www.highcharts.com/license
  3979. *
  3980. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  3981. *
  3982. * */
  3983. var __extends = (this && this.__extends) || (function () {
  3984. var extendStatics = function (d,
  3985. b) {
  3986. extendStatics = Object.setPrototypeOf ||
  3987. ({ __proto__: [] } instanceof Array && function (d,
  3988. b) { d.__proto__ = b; }) ||
  3989. function (d,
  3990. b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  3991. return extendStatics(d, b);
  3992. };
  3993. return function (d, b) {
  3994. extendStatics(d, b);
  3995. function __() { this.constructor = d; }
  3996. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  3997. };
  3998. })();
  3999. var perspective = Math3D.perspective;
  4000. var addEvent = U.addEvent,
  4001. extend = U.extend,
  4002. merge = U.merge,
  4003. pick = U.pick,
  4004. isNumber = U.isNumber;
  4005. /* *
  4006. *
  4007. * Class
  4008. *
  4009. * */
  4010. var Series3D = /** @class */ (function (_super) {
  4011. __extends(Series3D, _super);
  4012. function Series3D() {
  4013. return _super !== null && _super.apply(this, arguments) || this;
  4014. }
  4015. /* *
  4016. *
  4017. * Functions
  4018. *
  4019. * */
  4020. /* eslint-disable valid-jsdoc */
  4021. Series3D.prototype.translate = function () {
  4022. _super.prototype.translate.apply(this, arguments);
  4023. if (this.chart.is3d()) {
  4024. this.translate3dPoints();
  4025. }
  4026. };
  4027. /**
  4028. * Translate the plotX, plotY properties and add plotZ.
  4029. * @private
  4030. */
  4031. Series3D.prototype.translate3dPoints = function () {
  4032. var series = this,
  4033. seriesOptions = series.options,
  4034. chart = series.chart,
  4035. zAxis = pick(series.zAxis,
  4036. chart.options.zAxis[0]),
  4037. rawPoints = [],
  4038. rawPoint,
  4039. projectedPoints,
  4040. projectedPoint,
  4041. zValue,
  4042. i,
  4043. rawPointsX = [],
  4044. stack = seriesOptions.stacking ?
  4045. (isNumber(seriesOptions.stack) ? seriesOptions.stack : 0) :
  4046. series.index || 0;
  4047. series.zPadding = stack *
  4048. (seriesOptions.depth || 0 + (seriesOptions.groupZPadding || 1));
  4049. for (i = 0; i < series.data.length; i++) {
  4050. rawPoint = series.data[i];
  4051. if (zAxis && zAxis.translate) {
  4052. zValue = zAxis.logarithmic && zAxis.val2lin ?
  4053. zAxis.val2lin(rawPoint.z) :
  4054. rawPoint.z; // #4562
  4055. rawPoint.plotZ = zAxis.translate(zValue);
  4056. rawPoint.isInside = rawPoint.isInside ?
  4057. (zValue >= zAxis.min &&
  4058. zValue <= zAxis.max) :
  4059. false;
  4060. }
  4061. else {
  4062. rawPoint.plotZ = series.zPadding;
  4063. }
  4064. rawPoint.axisXpos = rawPoint.plotX;
  4065. rawPoint.axisYpos = rawPoint.plotY;
  4066. rawPoint.axisZpos = rawPoint.plotZ;
  4067. rawPoints.push({
  4068. x: rawPoint.plotX,
  4069. y: rawPoint.plotY,
  4070. z: rawPoint.plotZ
  4071. });
  4072. rawPointsX.push(rawPoint.plotX || 0);
  4073. }
  4074. series.rawPointsX = rawPointsX;
  4075. projectedPoints = perspective(rawPoints, chart, true);
  4076. for (i = 0; i < series.data.length; i++) {
  4077. rawPoint = series.data[i];
  4078. projectedPoint = projectedPoints[i];
  4079. rawPoint.plotX = projectedPoint.x;
  4080. rawPoint.plotY = projectedPoint.y;
  4081. rawPoint.plotZ = projectedPoint.z;
  4082. }
  4083. };
  4084. /* *
  4085. *
  4086. * Static Properties
  4087. *
  4088. * */
  4089. Series3D.defaultOptions = merge(Series.defaultOptions);
  4090. return Series3D;
  4091. }(Series));
  4092. /* *
  4093. *
  4094. * Compatibility
  4095. *
  4096. * */
  4097. /* eslint-disable no-invalid-this */
  4098. addEvent(Series, 'afterTranslate', function () {
  4099. if (this.chart.is3d()) {
  4100. this.translate3dPoints();
  4101. }
  4102. });
  4103. /* eslint-enable no-invalid-this */
  4104. extend(Series.prototype, {
  4105. translate3dPoints: Series3D.prototype.translate3dPoints
  4106. });
  4107. /* *
  4108. *
  4109. * Default Export
  4110. *
  4111. * */
  4112. return Series3D;
  4113. });
  4114. _registerModule(_modules, 'Series/Column3D/Column3DComposition.js', [_modules['Series/Column/ColumnSeries.js'], _modules['Core/Globals.js'], _modules['Core/Series/Series.js'], _modules['Extensions/Math3D.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Extensions/Stacking.js'], _modules['Core/Utilities.js']], function (ColumnSeries, H, Series, Math3D, SeriesRegistry, StackItem, U) {
  4115. /* *
  4116. *
  4117. * (c) 2010-2021 Torstein Honsi
  4118. *
  4119. * License: www.highcharts.com/license
  4120. *
  4121. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4122. *
  4123. * */
  4124. var columnProto = ColumnSeries.prototype;
  4125. var svg = H.svg;
  4126. var perspective = Math3D.perspective;
  4127. var addEvent = U.addEvent,
  4128. pick = U.pick,
  4129. wrap = U.wrap;
  4130. /* *
  4131. *
  4132. * Functions
  4133. *
  4134. * */
  4135. /* eslint-disable no-invalid-this */
  4136. /**
  4137. * @private
  4138. * @param {Highcharts.Chart} chart
  4139. * Chart with stacks
  4140. * @param {string} stacking
  4141. * Stacking option
  4142. * @return {Highcharts.Stack3DDictionary}
  4143. */
  4144. function retrieveStacks(chart, stacking) {
  4145. var series = chart.series,
  4146. stacks = {};
  4147. var stackNumber,
  4148. i = 1;
  4149. series.forEach(function (s) {
  4150. stackNumber = pick(s.options.stack, (stacking ? 0 : series.length - 1 - s.index)); // #3841, #4532
  4151. if (!stacks[stackNumber]) {
  4152. stacks[stackNumber] = { series: [s], position: i };
  4153. i++;
  4154. }
  4155. else {
  4156. stacks[stackNumber].series.push(s);
  4157. }
  4158. });
  4159. stacks.totalStacks = i + 1;
  4160. return stacks;
  4161. }
  4162. wrap(columnProto, 'translate', function (proceed) {
  4163. proceed.apply(this, [].slice.call(arguments, 1));
  4164. // Do not do this if the chart is not 3D
  4165. if (this.chart.is3d()) {
  4166. this.translate3dShapes();
  4167. }
  4168. });
  4169. // Don't use justifyDataLabel when point is outsidePlot
  4170. wrap(Series.prototype, 'justifyDataLabel', function (proceed) {
  4171. return !(arguments[2].outside3dPlot) ?
  4172. proceed.apply(this, [].slice.call(arguments, 1)) :
  4173. false;
  4174. });
  4175. columnProto.translate3dPoints = function () { };
  4176. columnProto.translate3dShapes = function () {
  4177. var series = this,
  4178. chart = series.chart,
  4179. seriesOptions = series.options,
  4180. depth = seriesOptions.depth,
  4181. stack = seriesOptions.stacking ?
  4182. (seriesOptions.stack || 0) :
  4183. series.index, // #4743
  4184. z = stack * (depth + (seriesOptions.groupZPadding || 1)),
  4185. borderCrisp = series.borderWidth % 2 ? 0.5 : 0,
  4186. point2dPos; // Position of point in 2D, used for 3D position calculation.
  4187. if (chart.inverted && !series.yAxis.reversed) {
  4188. borderCrisp *= -1;
  4189. }
  4190. if (seriesOptions.grouping !== false) {
  4191. z = 0;
  4192. }
  4193. z += (seriesOptions.groupZPadding || 1);
  4194. series.data.forEach(function (point) {
  4195. // #7103 Reset outside3dPlot flag
  4196. point.outside3dPlot = null;
  4197. if (point.y !== null) {
  4198. var shapeArgs = point.shapeArgs, tooltipPos = point.tooltipPos,
  4199. // Array for final shapeArgs calculation.
  4200. // We are checking two dimensions (x and y).
  4201. dimensions = [['x', 'width'], ['y', 'height']], borderlessBase; // Crisped rects can have +/- 0.5 pixels offset.
  4202. // #3131 We need to check if column is inside plotArea.
  4203. dimensions.forEach(function (d) {
  4204. borderlessBase = shapeArgs[d[0]] - borderCrisp;
  4205. if (borderlessBase < 0) {
  4206. // If borderLessBase is smaller than 0, it is needed to set
  4207. // its value to 0 or 0.5 depending on borderWidth
  4208. // borderWidth may be even or odd.
  4209. shapeArgs[d[1]] +=
  4210. shapeArgs[d[0]] + borderCrisp;
  4211. shapeArgs[d[0]] = -borderCrisp;
  4212. borderlessBase = 0;
  4213. }
  4214. if ((borderlessBase + shapeArgs[d[1]] >
  4215. series[d[0] + 'Axis'].len) &&
  4216. // Do not change height/width of column if 0 (#6708)
  4217. shapeArgs[d[1]] !== 0) {
  4218. shapeArgs[d[1]] =
  4219. series[d[0] + 'Axis'].len -
  4220. shapeArgs[d[0]];
  4221. }
  4222. if (
  4223. // Do not remove columns with zero height/width.
  4224. (shapeArgs[d[1]] !== 0) &&
  4225. (shapeArgs[d[0]] >=
  4226. series[d[0] + 'Axis'].len ||
  4227. shapeArgs[d[0]] + shapeArgs[d[1]] <=
  4228. borderCrisp)) {
  4229. // Set args to 0 if column is outside the chart.
  4230. for (var key in shapeArgs) { // eslint-disable-line guard-for-in
  4231. shapeArgs[key] = 0;
  4232. }
  4233. // #7103 outside3dPlot flag is set on Points which are
  4234. // currently outside of plot.
  4235. point.outside3dPlot = true;
  4236. }
  4237. });
  4238. // Change from 2d to 3d
  4239. if (point.shapeType === 'rect') {
  4240. point.shapeType = 'cuboid';
  4241. }
  4242. shapeArgs.z = z;
  4243. shapeArgs.depth = depth;
  4244. shapeArgs.insidePlotArea = true;
  4245. // Point's position in 2D
  4246. point2dPos = {
  4247. x: shapeArgs.x + shapeArgs.width / 2,
  4248. y: shapeArgs.y,
  4249. z: z + depth / 2 // The center of column in Z dimension
  4250. };
  4251. // Recalculate point positions for inverted graphs
  4252. if (chart.inverted) {
  4253. point2dPos.x = shapeArgs.height;
  4254. point2dPos.y = point.clientX;
  4255. }
  4256. // Calculate and store point's position in 3D,
  4257. // using perspective method.
  4258. point.plot3d = perspective([point2dPos], chart, true, false)[0];
  4259. // Translate the tooltip position in 3d space
  4260. tooltipPos = perspective([{
  4261. x: tooltipPos[0],
  4262. y: tooltipPos[1],
  4263. z: z + depth / 2 // The center of column in Z dimension
  4264. }], chart, true, false)[0];
  4265. point.tooltipPos = [tooltipPos.x, tooltipPos.y];
  4266. }
  4267. });
  4268. // store for later use #4067
  4269. series.z = z;
  4270. };
  4271. wrap(columnProto, 'animate', function (proceed) {
  4272. if (!this.chart.is3d()) {
  4273. proceed.apply(this, [].slice.call(arguments, 1));
  4274. }
  4275. else {
  4276. var args = arguments,
  4277. init = args[1],
  4278. yAxis = this.yAxis,
  4279. series = this,
  4280. reversed = this.yAxis.reversed;
  4281. if (svg) { // VML is too slow anyway
  4282. if (init) {
  4283. series.data.forEach(function (point) {
  4284. if (point.y !== null) {
  4285. point.height = point.shapeArgs.height;
  4286. point.shapey = point.shapeArgs.y; // #2968
  4287. point.shapeArgs.height = 1;
  4288. if (!reversed) {
  4289. if (point.stackY) {
  4290. point.shapeArgs.y =
  4291. point.plotY +
  4292. yAxis.translate(point.stackY);
  4293. }
  4294. else {
  4295. point.shapeArgs.y =
  4296. point.plotY +
  4297. (point.negative ?
  4298. -point.height :
  4299. point.height);
  4300. }
  4301. }
  4302. }
  4303. });
  4304. }
  4305. else { // run the animation
  4306. series.data.forEach(function (point) {
  4307. if (point.y !== null) {
  4308. point.shapeArgs.height = point.height;
  4309. point.shapeArgs.y = point.shapey; // #2968
  4310. // null value do not have a graphic
  4311. if (point.graphic) {
  4312. point.graphic.animate(point.shapeArgs, series.options.animation);
  4313. }
  4314. }
  4315. });
  4316. // redraw datalabels to the correct position
  4317. this.drawDataLabels();
  4318. }
  4319. }
  4320. }
  4321. });
  4322. // In case of 3d columns there is no sense to add this columns to a specific
  4323. // series group - if series is added to a group all columns will have the same
  4324. // zIndex in comparison with different series.
  4325. wrap(columnProto, 'plotGroup', function (proceed, prop, _name, _visibility, _zIndex, parent) {
  4326. if (prop !== 'dataLabelsGroup') {
  4327. if (this.chart.is3d()) {
  4328. if (this[prop]) {
  4329. delete this[prop];
  4330. }
  4331. if (parent) {
  4332. if (!this.chart.columnGroup) {
  4333. this.chart.columnGroup =
  4334. this.chart.renderer.g('columnGroup').add(parent);
  4335. }
  4336. this[prop] = this.chart.columnGroup;
  4337. this.chart.columnGroup.attr(this.getPlotBox());
  4338. this[prop].survive = true;
  4339. if (prop === 'group' || prop === 'markerGroup') {
  4340. arguments[3] = 'visible';
  4341. // For 3D column group and markerGroup should be visible
  4342. }
  4343. }
  4344. }
  4345. }
  4346. return proceed.apply(this, Array.prototype.slice.call(arguments, 1));
  4347. });
  4348. // When series is not added to group it is needed to change setVisible method to
  4349. // allow correct Legend funcionality. This wrap is basing on pie chart series.
  4350. wrap(columnProto, 'setVisible', function (proceed, vis) {
  4351. var series = this,
  4352. pointVis;
  4353. if (series.chart.is3d()) {
  4354. series.data.forEach(function (point) {
  4355. point.visible = point.options.visible = vis =
  4356. typeof vis === 'undefined' ?
  4357. !pick(series.visible, point.visible) : vis;
  4358. pointVis = vis ? 'visible' : 'hidden';
  4359. series.options.data[series.data.indexOf(point)] =
  4360. point.options;
  4361. if (point.graphic) {
  4362. point.graphic.attr({
  4363. visibility: pointVis
  4364. });
  4365. }
  4366. });
  4367. }
  4368. proceed.apply(this, Array.prototype.slice.call(arguments, 1));
  4369. });
  4370. addEvent(ColumnSeries, 'afterInit', function () {
  4371. if (this.chart.is3d()) {
  4372. var series = this,
  4373. seriesOptions = this.options,
  4374. grouping = seriesOptions.grouping,
  4375. stacking = seriesOptions.stacking,
  4376. reversedStacks = pick(this.yAxis.options.reversedStacks,
  4377. true),
  4378. z = 0;
  4379. // @todo grouping === true ?
  4380. if (!(typeof grouping !== 'undefined' && !grouping)) {
  4381. var stacks = retrieveStacks(this.chart,
  4382. stacking),
  4383. stack = seriesOptions.stack || 0,
  4384. i; // position within the stack
  4385. for (i = 0; i < stacks[stack].series.length; i++) {
  4386. if (stacks[stack].series[i] === this) {
  4387. break;
  4388. }
  4389. }
  4390. z = (10 * (stacks.totalStacks - stacks[stack].position)) +
  4391. (reversedStacks ? i : -i); // #4369
  4392. // In case when axis is reversed, columns are also reversed inside
  4393. // the group (#3737)
  4394. if (!this.xAxis.reversed) {
  4395. z = (stacks.totalStacks * 10) - z;
  4396. }
  4397. }
  4398. seriesOptions.depth = seriesOptions.depth || 25;
  4399. series.z = series.z || 0;
  4400. seriesOptions.zIndex = z;
  4401. }
  4402. });
  4403. // eslint-disable-next-line valid-jsdoc
  4404. /**
  4405. * @private
  4406. */
  4407. function pointAttribs(proceed) {
  4408. var attr = proceed.apply(this,
  4409. [].slice.call(arguments, 1));
  4410. if (this.chart.is3d && this.chart.is3d()) {
  4411. // Set the fill color to the fill color to provide a smooth edge
  4412. attr.stroke = this.options.edgeColor || attr.fill;
  4413. attr['stroke-width'] = pick(this.options.edgeWidth, 1); // #4055
  4414. }
  4415. return attr;
  4416. }
  4417. // eslint-disable-next-line valid-jsdoc
  4418. /**
  4419. * In 3D mode, all column-series are rendered in one main group. Because of that
  4420. * we need to apply inactive state on all points.
  4421. * @private
  4422. */
  4423. function setState(proceed, state, inherit) {
  4424. var is3d = this.chart.is3d && this.chart.is3d();
  4425. if (is3d) {
  4426. this.options.inactiveOtherPoints = true;
  4427. }
  4428. proceed.call(this, state, inherit);
  4429. if (is3d) {
  4430. this.options.inactiveOtherPoints = false;
  4431. }
  4432. }
  4433. // eslint-disable-next-line valid-jsdoc
  4434. /**
  4435. * In 3D mode, simple checking for a new shape to animate is not enough.
  4436. * Additionally check if graphic is a group of elements
  4437. * @private
  4438. */
  4439. function hasNewShapeType(proceed) {
  4440. var args = [];
  4441. for (var _i = 1; _i < arguments.length; _i++) {
  4442. args[_i - 1] = arguments[_i];
  4443. }
  4444. return this.series.chart.is3d() ?
  4445. this.graphic && this.graphic.element.nodeName !== 'g' :
  4446. proceed.apply(this, args);
  4447. }
  4448. wrap(columnProto, 'pointAttribs', pointAttribs);
  4449. wrap(columnProto, 'setState', setState);
  4450. wrap(columnProto.pointClass.prototype, 'hasNewShapeType', hasNewShapeType);
  4451. if (SeriesRegistry.seriesTypes.columnRange) {
  4452. var columnRangeProto = SeriesRegistry.seriesTypes.columnrange.prototype;
  4453. wrap(columnRangeProto, 'pointAttribs', pointAttribs);
  4454. wrap(columnRangeProto, 'setState', setState);
  4455. wrap(columnRangeProto.pointClass.prototype, 'hasNewShapeType', hasNewShapeType);
  4456. columnRangeProto.plotGroup = columnProto.plotGroup;
  4457. columnRangeProto.setVisible = columnProto.setVisible;
  4458. }
  4459. wrap(Series.prototype, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo) {
  4460. var chart = this.chart;
  4461. // In 3D we need to pass point.outsidePlot option to the justifyDataLabel
  4462. // method for disabling justifying dataLabels in columns outside plot
  4463. options.outside3dPlot = point.outside3dPlot;
  4464. // Only do this for 3D columns and it's derived series
  4465. if (chart.is3d() &&
  4466. this.is('column')) {
  4467. var series = this,
  4468. seriesOptions = series.options,
  4469. inside = pick(options.inside, !!series.options.stacking),
  4470. options3d = chart.options.chart.options3d,
  4471. xOffset = point.pointWidth / 2 || 0;
  4472. var dLPosition = {
  4473. x: alignTo.x + xOffset,
  4474. y: alignTo.y,
  4475. z: series.z + seriesOptions.depth / 2
  4476. };
  4477. if (chart.inverted) {
  4478. // Inside dataLabels are positioned according to above
  4479. // logic and there is no need to position them using
  4480. // non-3D algorighm (that use alignTo.width)
  4481. if (inside) {
  4482. alignTo.width = 0;
  4483. dLPosition.x += point.shapeArgs.height / 2;
  4484. }
  4485. // When chart is upside down
  4486. // (alpha angle between 180 and 360 degrees)
  4487. // it is needed to add column width to calculated value.
  4488. if (options3d.alpha >= 90 && options3d.alpha <= 270) {
  4489. dLPosition.y += point.shapeArgs.width;
  4490. }
  4491. }
  4492. // dLPosition is recalculated for 3D graphs
  4493. dLPosition = perspective([dLPosition], chart, true, false)[0];
  4494. alignTo.x = dLPosition.x - xOffset;
  4495. // #7103 If point is outside of plotArea, hide data label.
  4496. alignTo.y = point.outside3dPlot ? -9e9 : dLPosition.y;
  4497. }
  4498. proceed.apply(this, [].slice.call(arguments, 1));
  4499. });
  4500. // Added stackLabels position calculation for 3D charts.
  4501. wrap(StackItem.prototype, 'getStackBox', function (proceed, chart, stackItem, x, y, xWidth, h, axis) {
  4502. var stackBox = proceed.apply(this,
  4503. [].slice.call(arguments, 1));
  4504. // Only do this for 3D graph
  4505. if (chart.is3d() && stackItem.base) {
  4506. // First element of stackItem.base is an index of base series.
  4507. var baseSeriesInd = +(stackItem.base).split(',')[0];
  4508. var columnSeries = chart.series[baseSeriesInd];
  4509. var options3d = chart.options.chart.options3d;
  4510. // Only do this if base series is a column or inherited type,
  4511. // use its barW, z and depth parameters
  4512. // for correct stackLabels position calculation
  4513. if (columnSeries &&
  4514. columnSeries instanceof SeriesRegistry.seriesTypes.column) {
  4515. var dLPosition = {
  4516. x: stackBox.x + (chart.inverted ? h : xWidth / 2),
  4517. y: stackBox.y,
  4518. z: columnSeries.options.depth / 2
  4519. };
  4520. if (chart.inverted) {
  4521. // Do not use default offset calculation logic
  4522. // for 3D inverted stackLabels.
  4523. stackBox.width = 0;
  4524. // When chart is upside down
  4525. // (alpha angle between 180 and 360 degrees)
  4526. // it is needed to add column width to calculated value.
  4527. if (options3d.alpha >= 90 && options3d.alpha <= 270) {
  4528. dLPosition.y += xWidth;
  4529. }
  4530. }
  4531. dLPosition = perspective([dLPosition], chart, true, false)[0];
  4532. stackBox.x = dLPosition.x - xWidth / 2;
  4533. stackBox.y = dLPosition.y;
  4534. }
  4535. }
  4536. return stackBox;
  4537. });
  4538. /*
  4539. @merge v6.2
  4540. @todo
  4541. EXTENSION FOR 3D CYLINDRICAL COLUMNS
  4542. Not supported
  4543. */
  4544. /*
  4545. var defaultOptions = H.getOptions();
  4546. defaultOptions.plotOptions.cylinder =
  4547. merge(defaultOptions.plotOptions.column);
  4548. var CylinderSeries = extendClass(seriesTypes.column, {
  4549. type: 'cylinder'
  4550. });
  4551. seriesTypes.cylinder = CylinderSeries;
  4552. wrap(seriesTypes.cylinder.prototype, 'translate', function (proceed) {
  4553. proceed.apply(this, [].slice.call(arguments, 1));
  4554. // Do not do this if the chart is not 3D
  4555. if (!this.chart.is3d()) {
  4556. return;
  4557. }
  4558. var series = this,
  4559. chart = series.chart,
  4560. options = chart.options,
  4561. cylOptions = options.plotOptions.cylinder,
  4562. options3d = options.chart.options3d,
  4563. depth = cylOptions.depth || 0,
  4564. alpha = chart.alpha3d;
  4565. var z = cylOptions.stacking ?
  4566. (this.options.stack || 0) * depth :
  4567. series._i * depth;
  4568. z += depth / 2;
  4569. if (cylOptions.grouping !== false) { z = 0; }
  4570. each(series.data, function (point) {
  4571. var shapeArgs = point.shapeArgs,
  4572. deg2rad = H.deg2rad;
  4573. point.shapeType = 'arc3d';
  4574. shapeArgs.x += depth / 2;
  4575. shapeArgs.z = z;
  4576. shapeArgs.start = 0;
  4577. shapeArgs.end = 2 * PI;
  4578. shapeArgs.r = depth * 0.95;
  4579. shapeArgs.innerR = 0;
  4580. shapeArgs.depth =
  4581. shapeArgs.height * (1 / sin((90 - alpha) * deg2rad)) - z;
  4582. shapeArgs.alpha = 90 - alpha;
  4583. shapeArgs.beta = 0;
  4584. });
  4585. });
  4586. */
  4587. /* *
  4588. *
  4589. * Default Export
  4590. *
  4591. * */
  4592. /* *
  4593. *
  4594. * API Options
  4595. *
  4596. * */
  4597. /**
  4598. * Depth of the columns in a 3D column chart.
  4599. *
  4600. * @type {number}
  4601. * @default 25
  4602. * @since 4.0
  4603. * @product highcharts
  4604. * @requires highcharts-3d
  4605. * @apioption plotOptions.column.depth
  4606. */
  4607. /**
  4608. * 3D columns only. The color of the edges. Similar to `borderColor`, except it
  4609. * defaults to the same color as the column.
  4610. *
  4611. * @type {Highcharts.ColorString}
  4612. * @product highcharts
  4613. * @requires highcharts-3d
  4614. * @apioption plotOptions.column.edgeColor
  4615. */
  4616. /**
  4617. * 3D columns only. The width of the colored edges.
  4618. *
  4619. * @type {number}
  4620. * @default 1
  4621. * @product highcharts
  4622. * @requires highcharts-3d
  4623. * @apioption plotOptions.column.edgeWidth
  4624. */
  4625. /**
  4626. * The spacing between columns on the Z Axis in a 3D chart.
  4627. *
  4628. * @type {number}
  4629. * @default 1
  4630. * @since 4.0
  4631. * @product highcharts
  4632. * @requires highcharts-3d
  4633. * @apioption plotOptions.column.groupZPadding
  4634. */
  4635. ''; // keeps doclets above in transpiled file
  4636. return ColumnSeries;
  4637. });
  4638. _registerModule(_modules, 'Series/Pie3D/Pie3DPoint.js', [_modules['Core/Series/SeriesRegistry.js']], function (SeriesRegistry) {
  4639. /* *
  4640. *
  4641. * (c) 2010-2021 Torstein Honsi
  4642. *
  4643. * 3D pie series
  4644. *
  4645. * License: www.highcharts.com/license
  4646. *
  4647. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4648. *
  4649. * */
  4650. var __extends = (this && this.__extends) || (function () {
  4651. var extendStatics = function (d,
  4652. b) {
  4653. extendStatics = Object.setPrototypeOf ||
  4654. ({ __proto__: [] } instanceof Array && function (d,
  4655. b) { d.__proto__ = b; }) ||
  4656. function (d,
  4657. b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  4658. return extendStatics(d, b);
  4659. };
  4660. return function (d, b) {
  4661. extendStatics(d, b);
  4662. function __() { this.constructor = d; }
  4663. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  4664. };
  4665. })();
  4666. var PiePoint = SeriesRegistry.seriesTypes.pie.prototype.pointClass;
  4667. /* *
  4668. *
  4669. * Constants
  4670. *
  4671. * */
  4672. var superHaloPath = PiePoint.prototype.haloPath;
  4673. /* *
  4674. *
  4675. * Class
  4676. *
  4677. * */
  4678. var Pie3DPoint = /** @class */ (function (_super) {
  4679. __extends(Pie3DPoint, _super);
  4680. function Pie3DPoint() {
  4681. /* *
  4682. *
  4683. * Properties
  4684. *
  4685. * */
  4686. var _this = _super !== null && _super.apply(this,
  4687. arguments) || this;
  4688. _this.series = void 0;
  4689. return _this;
  4690. /* eslint-enable valid-jsdoc */
  4691. }
  4692. /* *
  4693. *
  4694. * Functions
  4695. *
  4696. * */
  4697. /* eslint-disable valid-jsdoc */
  4698. /**
  4699. * @private
  4700. */
  4701. Pie3DPoint.prototype.haloPath = function () {
  4702. return this.series.chart.is3d() ? [] : superHaloPath.apply(this, arguments);
  4703. };
  4704. return Pie3DPoint;
  4705. }(PiePoint));
  4706. /* *
  4707. *
  4708. * Default Export
  4709. *
  4710. * */
  4711. return Pie3DPoint;
  4712. });
  4713. _registerModule(_modules, 'Series/Pie3D/Pie3DSeries.js', [_modules['Core/Globals.js'], _modules['Series/Pie3D/Pie3DPoint.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (H, Pie3DPoint, SeriesRegistry, U) {
  4714. /* *
  4715. *
  4716. * (c) 2010-2021 Torstein Honsi
  4717. *
  4718. * 3D pie series
  4719. *
  4720. * License: www.highcharts.com/license
  4721. *
  4722. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4723. *
  4724. * */
  4725. var __extends = (this && this.__extends) || (function () {
  4726. var extendStatics = function (d,
  4727. b) {
  4728. extendStatics = Object.setPrototypeOf ||
  4729. ({ __proto__: [] } instanceof Array && function (d,
  4730. b) { d.__proto__ = b; }) ||
  4731. function (d,
  4732. b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  4733. return extendStatics(d, b);
  4734. };
  4735. return function (d, b) {
  4736. extendStatics(d, b);
  4737. function __() { this.constructor = d; }
  4738. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  4739. };
  4740. })();
  4741. var deg2rad = H.deg2rad,
  4742. svg = H.svg;
  4743. var PieSeries = SeriesRegistry.seriesTypes.pie;
  4744. var extend = U.extend,
  4745. pick = U.pick;
  4746. /* *
  4747. *
  4748. * Class
  4749. *
  4750. * */
  4751. var Pie3DSeries = /** @class */ (function (_super) {
  4752. __extends(Pie3DSeries, _super);
  4753. function Pie3DSeries() {
  4754. return _super !== null && _super.apply(this, arguments) || this;
  4755. }
  4756. /* *
  4757. *
  4758. * Functions
  4759. *
  4760. * */
  4761. /* eslint-disable valid-jsdoc */
  4762. /**
  4763. * @private
  4764. */
  4765. Pie3DSeries.prototype.addPoint = function () {
  4766. _super.prototype.addPoint.apply(this, arguments);
  4767. if (this.chart.is3d()) {
  4768. // destroy (and rebuild) everything!!!
  4769. this.update(this.userOptions, true); // #3845 pass the old options
  4770. }
  4771. };
  4772. /**
  4773. * @private
  4774. */
  4775. Pie3DSeries.prototype.animate = function (init) {
  4776. if (!this.chart.is3d()) {
  4777. _super.prototype.animate.apply(this, arguments);
  4778. }
  4779. else {
  4780. var animation = this.options.animation,
  4781. attribs,
  4782. center = this.center,
  4783. group = this.group,
  4784. markerGroup = this.markerGroup;
  4785. if (svg) { // VML is too slow anyway
  4786. if (animation === true) {
  4787. animation = {};
  4788. }
  4789. // Initialize the animation
  4790. if (init) {
  4791. // Scale down the group and place it in the center
  4792. group.oldtranslateX = pick(group.oldtranslateX, group.translateX);
  4793. group.oldtranslateY = pick(group.oldtranslateY, group.translateY);
  4794. attribs = {
  4795. translateX: center[0],
  4796. translateY: center[1],
  4797. scaleX: 0.001,
  4798. scaleY: 0.001
  4799. };
  4800. group.attr(attribs);
  4801. if (markerGroup) {
  4802. markerGroup.attrSetters = group.attrSetters;
  4803. markerGroup.attr(attribs);
  4804. }
  4805. // Run the animation
  4806. }
  4807. else {
  4808. attribs = {
  4809. translateX: group.oldtranslateX,
  4810. translateY: group.oldtranslateY,
  4811. scaleX: 1,
  4812. scaleY: 1
  4813. };
  4814. group.animate(attribs, animation);
  4815. if (markerGroup) {
  4816. markerGroup.animate(attribs, animation);
  4817. }
  4818. }
  4819. }
  4820. }
  4821. };
  4822. /**
  4823. * @private
  4824. */
  4825. Pie3DSeries.prototype.drawDataLabels = function () {
  4826. if (this.chart.is3d()) {
  4827. var series = this,
  4828. chart = series.chart,
  4829. options3d = chart.options.chart.options3d;
  4830. series.data.forEach(function (point) {
  4831. var shapeArgs = point.shapeArgs,
  4832. r = shapeArgs.r,
  4833. // #3240 issue with datalabels for 0 and null values
  4834. a1 = (shapeArgs.alpha || options3d.alpha) * deg2rad,
  4835. b1 = (shapeArgs.beta || options3d.beta) * deg2rad,
  4836. a2 = (shapeArgs.start + shapeArgs.end) / 2,
  4837. labelPosition = point.labelPosition,
  4838. connectorPosition = labelPosition.connectorPosition,
  4839. yOffset = (-r * (1 - Math.cos(a1)) * Math.sin(a2)),
  4840. xOffset = r * (Math.cos(b1) - 1) * Math.cos(a2);
  4841. // Apply perspective on label positions
  4842. [
  4843. labelPosition.natural,
  4844. connectorPosition.breakAt,
  4845. connectorPosition.touchingSliceAt
  4846. ].forEach(function (coordinates) {
  4847. coordinates.x += xOffset;
  4848. coordinates.y += yOffset;
  4849. });
  4850. });
  4851. }
  4852. _super.prototype.drawDataLabels.apply(this, arguments);
  4853. };
  4854. /**
  4855. * @private
  4856. */
  4857. Pie3DSeries.prototype.pointAttribs = function (point) {
  4858. var attr = _super.prototype.pointAttribs.apply(this,
  4859. arguments),
  4860. options = this.options;
  4861. if (this.chart.is3d() && !this.chart.styledMode) {
  4862. attr.stroke = options.edgeColor || point.color || this.color;
  4863. attr['stroke-width'] = pick(options.edgeWidth, 1);
  4864. }
  4865. return attr;
  4866. };
  4867. /**
  4868. * @private
  4869. */
  4870. Pie3DSeries.prototype.translate = function () {
  4871. _super.prototype.translate.apply(this, arguments);
  4872. // Do not do this if the chart is not 3D
  4873. if (!this.chart.is3d()) {
  4874. return;
  4875. }
  4876. var series = this,
  4877. seriesOptions = series.options,
  4878. depth = seriesOptions.depth || 0,
  4879. options3d = series.chart.options.chart.options3d,
  4880. alpha = options3d.alpha,
  4881. beta = options3d.beta,
  4882. z = seriesOptions.stacking ?
  4883. (seriesOptions.stack || 0) * depth :
  4884. series._i * depth;
  4885. z += depth / 2;
  4886. if (seriesOptions.grouping !== false) {
  4887. z = 0;
  4888. }
  4889. series.data.forEach(function (point) {
  4890. var shapeArgs = point.shapeArgs,
  4891. angle;
  4892. point.shapeType = 'arc3d';
  4893. shapeArgs.z = z;
  4894. shapeArgs.depth = depth * 0.75;
  4895. shapeArgs.alpha = alpha;
  4896. shapeArgs.beta = beta;
  4897. shapeArgs.center = series.center;
  4898. angle = (shapeArgs.end + shapeArgs.start) / 2;
  4899. point.slicedTranslation = {
  4900. translateX: Math.round(Math.cos(angle) *
  4901. seriesOptions.slicedOffset *
  4902. Math.cos(alpha * deg2rad)),
  4903. translateY: Math.round(Math.sin(angle) *
  4904. seriesOptions.slicedOffset *
  4905. Math.cos(alpha * deg2rad))
  4906. };
  4907. });
  4908. };
  4909. return Pie3DSeries;
  4910. }(PieSeries));
  4911. extend(Pie3DSeries, {
  4912. pointClass: Pie3DPoint
  4913. });
  4914. /* *
  4915. *
  4916. * Default Export
  4917. *
  4918. * */
  4919. /* *
  4920. *
  4921. * API Options
  4922. *
  4923. * */
  4924. /**
  4925. * The thickness of a 3D pie.
  4926. *
  4927. * @type {number}
  4928. * @default 0
  4929. * @since 4.0
  4930. * @product highcharts
  4931. * @requires highcharts-3d
  4932. * @apioption plotOptions.pie.depth
  4933. */
  4934. ''; // keeps doclets above after transpilation
  4935. return Pie3DSeries;
  4936. });
  4937. _registerModule(_modules, 'Series/Pie3D/Pie3DComposition.js', [_modules['Series/Pie3D/Pie3DPoint.js'], _modules['Series/Pie3D/Pie3DSeries.js'], _modules['Core/Series/SeriesRegistry.js']], function (Pie3DPoint, Pie3DSeries, SeriesRegistry) {
  4938. /* *
  4939. *
  4940. * (c) 2010-2021 Torstein Honsi
  4941. *
  4942. * 3D pie series
  4943. *
  4944. * License: www.highcharts.com/license
  4945. *
  4946. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4947. *
  4948. * */
  4949. /* *
  4950. *
  4951. * Imports
  4952. *
  4953. * */
  4954. /* *
  4955. *
  4956. * Composition
  4957. *
  4958. * */
  4959. SeriesRegistry.seriesTypes.pie.prototype.pointClass.prototype.haloPath = Pie3DPoint.prototype.haloPath;
  4960. SeriesRegistry.seriesTypes.pie = Pie3DSeries;
  4961. });
  4962. _registerModule(_modules, 'Series/Scatter3D/Scatter3DPoint.js', [_modules['Series/Scatter/ScatterSeries.js'], _modules['Core/Utilities.js']], function (ScatterSeries, U) {
  4963. /* *
  4964. *
  4965. * (c) 2010-2021 Torstein Honsi
  4966. *
  4967. * Scatter 3D series.
  4968. *
  4969. * License: www.highcharts.com/license
  4970. *
  4971. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4972. *
  4973. * */
  4974. var __extends = (this && this.__extends) || (function () {
  4975. var extendStatics = function (d,
  4976. b) {
  4977. extendStatics = Object.setPrototypeOf ||
  4978. ({ __proto__: [] } instanceof Array && function (d,
  4979. b) { d.__proto__ = b; }) ||
  4980. function (d,
  4981. b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  4982. return extendStatics(d, b);
  4983. };
  4984. return function (d, b) {
  4985. extendStatics(d, b);
  4986. function __() { this.constructor = d; }
  4987. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  4988. };
  4989. })();
  4990. var defined = U.defined;
  4991. /* *
  4992. *
  4993. * Class
  4994. *
  4995. * */
  4996. var Scatter3DPoint = /** @class */ (function (_super) {
  4997. __extends(Scatter3DPoint, _super);
  4998. function Scatter3DPoint() {
  4999. /* *
  5000. *
  5001. * Properties
  5002. *
  5003. * */
  5004. var _this = _super !== null && _super.apply(this,
  5005. arguments) || this;
  5006. _this.options = void 0;
  5007. _this.series = void 0;
  5008. return _this;
  5009. }
  5010. /* *
  5011. *
  5012. * Functions
  5013. *
  5014. * */
  5015. Scatter3DPoint.prototype.applyOptions = function () {
  5016. _super.prototype.applyOptions.apply(this, arguments);
  5017. if (!defined(this.z)) {
  5018. this.z = 0;
  5019. }
  5020. return this;
  5021. };
  5022. return Scatter3DPoint;
  5023. }(ScatterSeries.prototype.pointClass));
  5024. /* *
  5025. *
  5026. * Default Export
  5027. *
  5028. * */
  5029. return Scatter3DPoint;
  5030. });
  5031. _registerModule(_modules, 'Series/Scatter3D/Scatter3DSeries.js', [_modules['Extensions/Math3D.js'], _modules['Series/Scatter3D/Scatter3DPoint.js'], _modules['Series/Scatter/ScatterSeries.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (Math3D, Scatter3DPoint, ScatterSeries, SeriesRegistry, U) {
  5032. /* *
  5033. *
  5034. * (c) 2010-2021 Torstein Honsi
  5035. *
  5036. * Scatter 3D series.
  5037. *
  5038. * License: www.highcharts.com/license
  5039. *
  5040. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  5041. *
  5042. * */
  5043. var __extends = (this && this.__extends) || (function () {
  5044. var extendStatics = function (d,
  5045. b) {
  5046. extendStatics = Object.setPrototypeOf ||
  5047. ({ __proto__: [] } instanceof Array && function (d,
  5048. b) { d.__proto__ = b; }) ||
  5049. function (d,
  5050. b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  5051. return extendStatics(d, b);
  5052. };
  5053. return function (d, b) {
  5054. extendStatics(d, b);
  5055. function __() { this.constructor = d; }
  5056. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  5057. };
  5058. })();
  5059. var pointCameraDistance = Math3D.pointCameraDistance;
  5060. var extend = U.extend,
  5061. merge = U.merge;
  5062. /* *
  5063. *
  5064. * Class
  5065. *
  5066. * */
  5067. /**
  5068. * @private
  5069. * @class
  5070. * @name Highcharts.seriesTypes.scatter3d
  5071. *
  5072. * @augments Highcharts.Series
  5073. */
  5074. var Scatter3DSeries = /** @class */ (function (_super) {
  5075. __extends(Scatter3DSeries, _super);
  5076. function Scatter3DSeries() {
  5077. /* *
  5078. *
  5079. * Static Properties
  5080. *
  5081. * */
  5082. var _this = _super !== null && _super.apply(this,
  5083. arguments) || this;
  5084. /* *
  5085. *
  5086. * Properties
  5087. *
  5088. * */
  5089. _this.data = void 0;
  5090. _this.options = void 0;
  5091. _this.points = void 0;
  5092. return _this;
  5093. }
  5094. /* *
  5095. *
  5096. * Functions
  5097. *
  5098. * */
  5099. Scatter3DSeries.prototype.pointAttribs = function (point) {
  5100. var attribs = _super.prototype.pointAttribs.apply(this,
  5101. arguments);
  5102. if (this.chart.is3d() && point) {
  5103. attribs.zIndex =
  5104. pointCameraDistance(point, this.chart);
  5105. }
  5106. return attribs;
  5107. };
  5108. /**
  5109. * A 3D scatter plot uses x, y and z coordinates to display values for three
  5110. * variables for a set of data.
  5111. *
  5112. * @sample {highcharts} highcharts/3d/scatter/
  5113. * Simple 3D scatter
  5114. * @sample {highcharts} highcharts/demo/3d-scatter-draggable
  5115. * Draggable 3d scatter
  5116. *
  5117. * @extends plotOptions.scatter
  5118. * @excluding dragDrop, cluster, boostThreshold, boostBlending
  5119. * @product highcharts
  5120. * @requires highcharts-3d
  5121. * @optionparent plotOptions.scatter3d
  5122. */
  5123. Scatter3DSeries.defaultOptions = merge(ScatterSeries.defaultOptions, {
  5124. tooltip: {
  5125. pointFormat: 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>z: <b>{point.z}</b><br/>'
  5126. }
  5127. });
  5128. return Scatter3DSeries;
  5129. }(ScatterSeries));
  5130. extend(Scatter3DSeries.prototype, {
  5131. axisTypes: ['xAxis', 'yAxis', 'zAxis'],
  5132. // Require direct touch rather than using the k-d-tree, because the
  5133. // k-d-tree currently doesn't take the xyz coordinate system into
  5134. // account (#4552)
  5135. directTouch: true,
  5136. parallelArrays: ['x', 'y', 'z'],
  5137. pointArrayMap: ['x', 'y', 'z'],
  5138. pointClass: Scatter3DPoint
  5139. });
  5140. SeriesRegistry.registerSeriesType('scatter3d', Scatter3DSeries);
  5141. /* *
  5142. *
  5143. * Default Export
  5144. *
  5145. * */
  5146. /* *
  5147. *
  5148. * API Options
  5149. *
  5150. * */
  5151. /**
  5152. * A `scatter3d` series. If the [type](#series.scatter3d.type) option is
  5153. * not specified, it is inherited from [chart.type](#chart.type).
  5154. *
  5155. * scatter3d](#plotOptions.scatter3d).
  5156. *
  5157. * @extends series,plotOptions.scatter3d
  5158. * @excluding boostThreshold, boostBlending
  5159. * @product highcharts
  5160. * @requires highcharts-3d
  5161. * @apioption series.scatter3d
  5162. */
  5163. /**
  5164. * An array of data points for the series. For the `scatter3d` series
  5165. * type, points can be given in the following ways:
  5166. *
  5167. * 1. An array of arrays with 3 values. In this case, the values correspond
  5168. * to `x,y,z`. If the first value is a string, it is applied as the name
  5169. * of the point, and the `x` value is inferred.
  5170. *
  5171. * ```js
  5172. * data: [
  5173. * [0, 0, 1],
  5174. * [1, 8, 7],
  5175. * [2, 9, 2]
  5176. * ]
  5177. * ```
  5178. *
  5179. * 3. An array of objects with named values. The following snippet shows only a
  5180. * few settings, see the complete options set below. If the total number of data
  5181. * points exceeds the series'
  5182. * [turboThreshold](#series.scatter3d.turboThreshold), this option is not
  5183. * available.
  5184. *
  5185. * ```js
  5186. * data: [{
  5187. * x: 1,
  5188. * y: 2,
  5189. * z: 24,
  5190. * name: "Point2",
  5191. * color: "#00FF00"
  5192. * }, {
  5193. * x: 1,
  5194. * y: 4,
  5195. * z: 12,
  5196. * name: "Point1",
  5197. * color: "#FF00FF"
  5198. * }]
  5199. * ```
  5200. *
  5201. * @sample {highcharts} highcharts/chart/reflow-true/
  5202. * Numerical values
  5203. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  5204. * Arrays of numeric x and y
  5205. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  5206. * Arrays of datetime x and y
  5207. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  5208. * Arrays of point.name and y
  5209. * @sample {highcharts} highcharts/series/data-array-of-objects/
  5210. * Config objects
  5211. *
  5212. * @type {Array<Array<number>|*>}
  5213. * @extends series.scatter.data
  5214. * @product highcharts
  5215. * @apioption series.scatter3d.data
  5216. */
  5217. /**
  5218. * The z value for each data point.
  5219. *
  5220. * @type {number}
  5221. * @product highcharts
  5222. * @apioption series.scatter3d.data.z
  5223. */
  5224. ''; // adds doclets above to transpiled file
  5225. return Scatter3DSeries;
  5226. });
  5227. _registerModule(_modules, 'Series/Area3DSeries.js', [_modules['Extensions/Math3D.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (Math3D, SeriesRegistry, U) {
  5228. /* *
  5229. *
  5230. * (c) 2010-2021 Grzegorz Blachliński
  5231. *
  5232. * License: www.highcharts.com/license
  5233. *
  5234. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  5235. *
  5236. * */
  5237. var perspective = Math3D.perspective;
  5238. var _a = SeriesRegistry.seriesTypes,
  5239. AreaSeriesClass = _a.area,
  5240. LineSeriesClass = _a.line;
  5241. var pick = U.pick,
  5242. wrap = U.wrap;
  5243. /* eslint-disable no-invalid-this */
  5244. wrap(AreaSeriesClass.prototype, 'getGraphPath', function (proceed) {
  5245. var series = this,
  5246. svgPath = proceed.apply(series,
  5247. [].slice.call(arguments, 1));
  5248. // Do not do this if the chart is not 3D
  5249. if (!series.chart.is3d()) {
  5250. return svgPath;
  5251. }
  5252. var getGraphPath = LineSeriesClass.prototype.getGraphPath,
  5253. graphPath = [],
  5254. options = series.options,
  5255. stacking = options.stacking,
  5256. bottomPath,
  5257. bottomPoints = [],
  5258. graphPoints = [],
  5259. i,
  5260. areaPath,
  5261. connectNulls = pick(// #10574
  5262. options.connectNulls,
  5263. stacking === 'percent'),
  5264. translatedThreshold = Math.round(// #10909
  5265. series.yAxis.getThreshold(options.threshold)),
  5266. options3d;
  5267. if (series.rawPointsX) {
  5268. for (var i = 0; i < series.points.length; i++) {
  5269. bottomPoints.push({
  5270. x: series.rawPointsX[i],
  5271. y: options.stacking ? series.points[i].yBottom : translatedThreshold,
  5272. z: series.zPadding
  5273. });
  5274. }
  5275. }
  5276. if (series.chart.options && series.chart.options.chart) {
  5277. options3d = series.chart.options.chart.options3d;
  5278. bottomPoints = perspective(bottomPoints, series.chart, true).map(function (point) {
  5279. return { plotX: point.x, plotY: point.y, plotZ: point.z };
  5280. });
  5281. if (series.group && options3d && options3d.depth && options3d.beta) {
  5282. // Markers should take the global zIndex of series group.
  5283. if (series.markerGroup) {
  5284. series.markerGroup.add(series.group);
  5285. series.markerGroup.attr({
  5286. translateX: 0,
  5287. translateY: 0
  5288. });
  5289. }
  5290. series.group.attr({
  5291. zIndex: Math.max(1, (options3d.beta > 270 || options3d.beta < 90) ?
  5292. options3d.depth - Math.round(series.zPadding || 0) :
  5293. Math.round(series.zPadding || 0))
  5294. });
  5295. }
  5296. }
  5297. bottomPoints.reversed = true;
  5298. bottomPath = getGraphPath.call(series, bottomPoints, true, true);
  5299. if (bottomPath[0] && bottomPath[0][0] === 'M') {
  5300. bottomPath[0] = ['L', bottomPath[0][1], bottomPath[0][2]];
  5301. }
  5302. if (series.areaPath) {
  5303. // Remove previously used bottomPath and add the new one.
  5304. areaPath = series.areaPath.splice(0, series.areaPath.length / 2).concat(bottomPath);
  5305. areaPath.xMap = series.areaPath.xMap; // Use old xMap in the new areaPath
  5306. series.areaPath = areaPath;
  5307. graphPath = getGraphPath.call(series, graphPoints, false, connectNulls);
  5308. }
  5309. return svgPath;
  5310. });
  5311. });
  5312. _registerModule(_modules, 'masters/highcharts-3d.src.js', [], function () {
  5313. });
  5314. }));