highcharts-3d.src.js 230 KB

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