Chart3D.js 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672
  1. /* *
  2. *
  3. * (c) 2010-2020 Torstein Honsi
  4. *
  5. * Extension for 3D charts
  6. *
  7. * License: www.highcharts.com/license
  8. *
  9. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  10. *
  11. * */
  12. 'use strict';
  13. import Axis from '../parts/Axis.js';
  14. import Axis3D from './Axis3D.js';
  15. import Chart from '../parts/Chart.js';
  16. import H from '../parts/Globals.js';
  17. import O from '../parts/Options.js';
  18. var genericDefaultOptions = O.defaultOptions;
  19. import U from '../parts/Utilities.js';
  20. var addEvent = U.addEvent, Fx = U.Fx, isArray = U.isArray, merge = U.merge, pick = U.pick, wrap = U.wrap;
  21. import ZAxis from './ZAxis.js';
  22. var perspective = H.perspective;
  23. var Chart3D;
  24. (function (Chart3D) {
  25. /* *
  26. *
  27. * Interfaces
  28. *
  29. * */
  30. /* *
  31. *
  32. * Classes
  33. *
  34. * */
  35. var Composition = /** @class */ (function () {
  36. /* *
  37. *
  38. * Constructors
  39. *
  40. * */
  41. /**
  42. * @private
  43. */
  44. function Composition(chart) {
  45. this.frame3d = void 0;
  46. this.chart = chart;
  47. }
  48. /* *
  49. *
  50. * Functions
  51. *
  52. * */
  53. Composition.prototype.get3dFrame = function () {
  54. var chart = this.chart, options3d = chart.options.chart.options3d, frameOptions = options3d.frame, xm = chart.plotLeft, xp = chart.plotLeft + chart.plotWidth, ym = chart.plotTop, yp = chart.plotTop + chart.plotHeight, zm = 0, zp = options3d.depth, faceOrientation = function (vertexes) {
  55. var area = H.shapeArea3d(vertexes, chart);
  56. // Give it 0.5 squared-pixel as a margin for rounding errors
  57. if (area > 0.5) {
  58. return 1;
  59. }
  60. if (area < -0.5) {
  61. return -1;
  62. }
  63. return 0;
  64. }, bottomOrientation = faceOrientation([
  65. { x: xm, y: yp, z: zp },
  66. { x: xp, y: yp, z: zp },
  67. { x: xp, y: yp, z: zm },
  68. { x: xm, y: yp, z: zm }
  69. ]), topOrientation = faceOrientation([
  70. { x: xm, y: ym, z: zm },
  71. { x: xp, y: ym, z: zm },
  72. { x: xp, y: ym, z: zp },
  73. { x: xm, y: ym, z: zp }
  74. ]), leftOrientation = faceOrientation([
  75. { x: xm, y: ym, z: zm },
  76. { x: xm, y: ym, z: zp },
  77. { x: xm, y: yp, z: zp },
  78. { x: xm, y: yp, z: zm }
  79. ]), rightOrientation = faceOrientation([
  80. { x: xp, y: ym, z: zp },
  81. { x: xp, y: ym, z: zm },
  82. { x: xp, y: yp, z: zm },
  83. { x: xp, y: yp, z: zp }
  84. ]), frontOrientation = faceOrientation([
  85. { x: xm, y: yp, z: zm },
  86. { x: xp, y: yp, z: zm },
  87. { x: xp, y: ym, z: zm },
  88. { x: xm, y: ym, z: zm }
  89. ]), backOrientation = faceOrientation([
  90. { x: xm, y: ym, z: zp },
  91. { x: xp, y: ym, z: zp },
  92. { x: xp, y: yp, z: zp },
  93. { x: xm, y: yp, z: zp }
  94. ]), defaultShowBottom = false, defaultShowTop = false, defaultShowLeft = false, defaultShowRight = false, defaultShowFront = false, defaultShowBack = true;
  95. // The 'default' criteria to visible faces of the frame is looking
  96. // up every axis to decide whenever the left/right//top/bottom sides
  97. // of the frame will be shown
  98. []
  99. .concat(chart.xAxis, chart.yAxis, chart.zAxis)
  100. .forEach(function (axis) {
  101. if (axis) {
  102. if (axis.horiz) {
  103. if (axis.opposite) {
  104. defaultShowTop = true;
  105. }
  106. else {
  107. defaultShowBottom = true;
  108. }
  109. }
  110. else {
  111. if (axis.opposite) {
  112. defaultShowRight = true;
  113. }
  114. else {
  115. defaultShowLeft = true;
  116. }
  117. }
  118. }
  119. });
  120. var getFaceOptions = function (sources, faceOrientation, defaultVisible) {
  121. var faceAttrs = ['size', 'color', 'visible'];
  122. var options = {};
  123. for (var i = 0; i < faceAttrs.length; i++) {
  124. var attr = faceAttrs[i];
  125. for (var j = 0; j < sources.length; j++) {
  126. if (typeof sources[j] === 'object') {
  127. var val = sources[j][attr];
  128. if (typeof val !== 'undefined' && val !== null) {
  129. options[attr] = val;
  130. break;
  131. }
  132. }
  133. }
  134. }
  135. var isVisible = defaultVisible;
  136. if (options.visible === true || options.visible === false) {
  137. isVisible = options.visible;
  138. }
  139. else if (options.visible === 'auto') {
  140. isVisible = faceOrientation > 0;
  141. }
  142. return {
  143. size: pick(options.size, 1),
  144. color: pick(options.color, 'none'),
  145. frontFacing: faceOrientation > 0,
  146. visible: isVisible
  147. };
  148. };
  149. // docs @TODO: Add all frame options (left, right, top, bottom,
  150. // front, back) to apioptions JSDoc once the new system is up.
  151. var ret = {
  152. axes: {},
  153. // FIXME: Previously, left/right, top/bottom and front/back
  154. // pairs shared size and color.
  155. // For compatibility and consistency sake, when one face have
  156. // size/color/visibility set, the opposite face will default to
  157. // the same values. Also, left/right used to be called 'side',
  158. // so that's also added as a fallback.
  159. bottom: getFaceOptions([frameOptions.bottom, frameOptions.top, frameOptions], bottomOrientation, defaultShowBottom),
  160. top: getFaceOptions([frameOptions.top, frameOptions.bottom, frameOptions], topOrientation, defaultShowTop),
  161. left: getFaceOptions([
  162. frameOptions.left,
  163. frameOptions.right,
  164. frameOptions.side,
  165. frameOptions
  166. ], leftOrientation, defaultShowLeft),
  167. right: getFaceOptions([
  168. frameOptions.right,
  169. frameOptions.left,
  170. frameOptions.side,
  171. frameOptions
  172. ], rightOrientation, defaultShowRight),
  173. back: getFaceOptions([frameOptions.back, frameOptions.front, frameOptions], backOrientation, defaultShowBack),
  174. front: getFaceOptions([frameOptions.front, frameOptions.back, frameOptions], frontOrientation, defaultShowFront)
  175. };
  176. // Decide the bast place to put axis title/labels based on the
  177. // visible faces. Ideally, The labels can only be on the edge
  178. // between a visible face and an invisble one. Also, the Y label
  179. // should be one the left-most edge (right-most if opposite).
  180. if (options3d.axisLabelPosition === 'auto') {
  181. var isValidEdge = function (face1, face2) {
  182. return ((face1.visible !== face2.visible) ||
  183. (face1.visible &&
  184. face2.visible &&
  185. (face1.frontFacing !== face2.frontFacing)));
  186. };
  187. var yEdges = [];
  188. if (isValidEdge(ret.left, ret.front)) {
  189. yEdges.push({
  190. y: (ym + yp) / 2,
  191. x: xm,
  192. z: zm,
  193. xDir: { x: 1, y: 0, z: 0 }
  194. });
  195. }
  196. if (isValidEdge(ret.left, ret.back)) {
  197. yEdges.push({
  198. y: (ym + yp) / 2,
  199. x: xm,
  200. z: zp,
  201. xDir: { x: 0, y: 0, z: -1 }
  202. });
  203. }
  204. if (isValidEdge(ret.right, ret.front)) {
  205. yEdges.push({
  206. y: (ym + yp) / 2,
  207. x: xp,
  208. z: zm,
  209. xDir: { x: 0, y: 0, z: 1 }
  210. });
  211. }
  212. if (isValidEdge(ret.right, ret.back)) {
  213. yEdges.push({
  214. y: (ym + yp) / 2,
  215. x: xp,
  216. z: zp,
  217. xDir: { x: -1, y: 0, z: 0 }
  218. });
  219. }
  220. var xBottomEdges = [];
  221. if (isValidEdge(ret.bottom, ret.front)) {
  222. xBottomEdges.push({
  223. x: (xm + xp) / 2,
  224. y: yp,
  225. z: zm,
  226. xDir: { x: 1, y: 0, z: 0 }
  227. });
  228. }
  229. if (isValidEdge(ret.bottom, ret.back)) {
  230. xBottomEdges.push({
  231. x: (xm + xp) / 2,
  232. y: yp,
  233. z: zp,
  234. xDir: { x: -1, y: 0, z: 0 }
  235. });
  236. }
  237. var xTopEdges = [];
  238. if (isValidEdge(ret.top, ret.front)) {
  239. xTopEdges.push({
  240. x: (xm + xp) / 2,
  241. y: ym,
  242. z: zm,
  243. xDir: { x: 1, y: 0, z: 0 }
  244. });
  245. }
  246. if (isValidEdge(ret.top, ret.back)) {
  247. xTopEdges.push({
  248. x: (xm + xp) / 2,
  249. y: ym,
  250. z: zp,
  251. xDir: { x: -1, y: 0, z: 0 }
  252. });
  253. }
  254. var zBottomEdges = [];
  255. if (isValidEdge(ret.bottom, ret.left)) {
  256. zBottomEdges.push({
  257. z: (zm + zp) / 2,
  258. y: yp,
  259. x: xm,
  260. xDir: { x: 0, y: 0, z: -1 }
  261. });
  262. }
  263. if (isValidEdge(ret.bottom, ret.right)) {
  264. zBottomEdges.push({
  265. z: (zm + zp) / 2,
  266. y: yp,
  267. x: xp,
  268. xDir: { x: 0, y: 0, z: 1 }
  269. });
  270. }
  271. var zTopEdges = [];
  272. if (isValidEdge(ret.top, ret.left)) {
  273. zTopEdges.push({
  274. z: (zm + zp) / 2,
  275. y: ym,
  276. x: xm,
  277. xDir: { x: 0, y: 0, z: -1 }
  278. });
  279. }
  280. if (isValidEdge(ret.top, ret.right)) {
  281. zTopEdges.push({
  282. z: (zm + zp) / 2,
  283. y: ym,
  284. x: xp,
  285. xDir: { x: 0, y: 0, z: 1 }
  286. });
  287. }
  288. var pickEdge = function (edges, axis, mult) {
  289. if (edges.length === 0) {
  290. return null;
  291. }
  292. if (edges.length === 1) {
  293. return edges[0];
  294. }
  295. var best = 0, projections = perspective(edges, chart, false);
  296. for (var i = 1; i < projections.length; i++) {
  297. if (mult * projections[i][axis] >
  298. mult * projections[best][axis]) {
  299. best = i;
  300. }
  301. else if ((mult * projections[i][axis] ===
  302. mult * projections[best][axis]) &&
  303. (projections[i].z < projections[best].z)) {
  304. best = i;
  305. }
  306. }
  307. return edges[best];
  308. };
  309. ret.axes = {
  310. y: {
  311. 'left': pickEdge(yEdges, 'x', -1),
  312. 'right': pickEdge(yEdges, 'x', +1)
  313. },
  314. x: {
  315. 'top': pickEdge(xTopEdges, 'y', -1),
  316. 'bottom': pickEdge(xBottomEdges, 'y', +1)
  317. },
  318. z: {
  319. 'top': pickEdge(zTopEdges, 'y', -1),
  320. 'bottom': pickEdge(zBottomEdges, 'y', +1)
  321. }
  322. };
  323. }
  324. else {
  325. ret.axes = {
  326. y: {
  327. 'left': { x: xm, z: zm, xDir: { x: 1, y: 0, z: 0 } },
  328. 'right': { x: xp, z: zm, xDir: { x: 0, y: 0, z: 1 } }
  329. },
  330. x: {
  331. 'top': { y: ym, z: zm, xDir: { x: 1, y: 0, z: 0 } },
  332. 'bottom': { y: yp, z: zm, xDir: { x: 1, y: 0, z: 0 } }
  333. },
  334. z: {
  335. 'top': {
  336. x: defaultShowLeft ? xp : xm,
  337. y: ym,
  338. xDir: defaultShowLeft ?
  339. { x: 0, y: 0, z: 1 } :
  340. { x: 0, y: 0, z: -1 }
  341. },
  342. 'bottom': {
  343. x: defaultShowLeft ? xp : xm,
  344. y: yp,
  345. xDir: defaultShowLeft ?
  346. { x: 0, y: 0, z: 1 } :
  347. { x: 0, y: 0, z: -1 }
  348. }
  349. }
  350. };
  351. }
  352. return ret;
  353. };
  354. /**
  355. * Calculate scale of the 3D view. That is required to fit chart's 3D
  356. * projection into the actual plotting area. Reported as #4933.
  357. *
  358. * @notice
  359. * This function should ideally take the plot values instead of a chart
  360. * object, but since the chart object is needed for perspective it is
  361. * not practical. Possible to make both getScale and perspective more
  362. * logical and also immutable.
  363. *
  364. * @private
  365. * @function getScale
  366. *
  367. * @param {number} depth
  368. * The depth of the chart
  369. *
  370. * @return {number}
  371. * The scale to fit the 3D chart into the plotting area.
  372. *
  373. * @requires highcharts-3d
  374. */
  375. Composition.prototype.getScale = function (depth) {
  376. var chart = this.chart, plotLeft = chart.plotLeft, plotRight = chart.plotWidth + plotLeft, plotTop = chart.plotTop, plotBottom = chart.plotHeight + plotTop, originX = plotLeft + chart.plotWidth / 2, originY = plotTop + chart.plotHeight / 2, bbox3d = {
  377. minX: Number.MAX_VALUE,
  378. maxX: -Number.MAX_VALUE,
  379. minY: Number.MAX_VALUE,
  380. maxY: -Number.MAX_VALUE
  381. }, corners, scale = 1;
  382. // Top left corners:
  383. corners = [{
  384. x: plotLeft,
  385. y: plotTop,
  386. z: 0
  387. }, {
  388. x: plotLeft,
  389. y: plotTop,
  390. z: depth
  391. }];
  392. // Top right corners:
  393. [0, 1].forEach(function (i) {
  394. corners.push({
  395. x: plotRight,
  396. y: corners[i].y,
  397. z: corners[i].z
  398. });
  399. });
  400. // All bottom corners:
  401. [0, 1, 2, 3].forEach(function (i) {
  402. corners.push({
  403. x: corners[i].x,
  404. y: plotBottom,
  405. z: corners[i].z
  406. });
  407. });
  408. // Calculate 3D corners:
  409. corners = perspective(corners, chart, false);
  410. // Get bounding box of 3D element:
  411. corners.forEach(function (corner) {
  412. bbox3d.minX = Math.min(bbox3d.minX, corner.x);
  413. bbox3d.maxX = Math.max(bbox3d.maxX, corner.x);
  414. bbox3d.minY = Math.min(bbox3d.minY, corner.y);
  415. bbox3d.maxY = Math.max(bbox3d.maxY, corner.y);
  416. });
  417. // Left edge:
  418. if (plotLeft > bbox3d.minX) {
  419. scale = Math.min(scale, 1 - Math.abs((plotLeft + originX) / (bbox3d.minX + originX)) % 1);
  420. }
  421. // Right edge:
  422. if (plotRight < bbox3d.maxX) {
  423. scale = Math.min(scale, (plotRight - originX) / (bbox3d.maxX - originX));
  424. }
  425. // Top edge:
  426. if (plotTop > bbox3d.minY) {
  427. if (bbox3d.minY < 0) {
  428. scale = Math.min(scale, (plotTop + originY) / (-bbox3d.minY + plotTop + originY));
  429. }
  430. else {
  431. scale = Math.min(scale, 1 - (plotTop + originY) / (bbox3d.minY + originY) % 1);
  432. }
  433. }
  434. // Bottom edge:
  435. if (plotBottom < bbox3d.maxY) {
  436. scale = Math.min(scale, Math.abs((plotBottom - originY) / (bbox3d.maxY - originY)));
  437. }
  438. return scale;
  439. };
  440. return Composition;
  441. }());
  442. Chart3D.Composition = Composition;
  443. /* *
  444. *
  445. * Constants
  446. *
  447. * */
  448. /**
  449. * @optionparent
  450. * @private
  451. */
  452. Chart3D.defaultOptions = {
  453. chart: {
  454. /**
  455. * Options to render charts in 3 dimensions. This feature requires
  456. * `highcharts-3d.js`, found in the download package or online at
  457. * [code.highcharts.com/highcharts-3d.js](https://code.highcharts.com/highcharts-3d.js).
  458. *
  459. * @since 4.0
  460. * @product highcharts
  461. * @requires highcharts-3d
  462. */
  463. options3d: {
  464. /**
  465. * Wether to render the chart using the 3D functionality.
  466. *
  467. * @since 4.0
  468. * @product highcharts
  469. */
  470. enabled: false,
  471. /**
  472. * One of the two rotation angles for the chart.
  473. *
  474. * @since 4.0
  475. * @product highcharts
  476. */
  477. alpha: 0,
  478. /**
  479. * One of the two rotation angles for the chart.
  480. *
  481. * @since 4.0
  482. * @product highcharts
  483. */
  484. beta: 0,
  485. /**
  486. * The total depth of the chart.
  487. *
  488. * @since 4.0
  489. * @product highcharts
  490. */
  491. depth: 100,
  492. /**
  493. * Whether the 3d box should automatically adjust to the chart
  494. * plot area.
  495. *
  496. * @since 4.2.4
  497. * @product highcharts
  498. */
  499. fitToPlot: true,
  500. /**
  501. * Defines the distance the viewer is standing in front of the
  502. * chart, this setting is important to calculate the perspective
  503. * effect in column and scatter charts. It is not used for 3D
  504. * pie charts.
  505. *
  506. * @since 4.0
  507. * @product highcharts
  508. */
  509. viewDistance: 25,
  510. /**
  511. * Set it to `"auto"` to automatically move the labels to the
  512. * best edge.
  513. *
  514. * @type {"auto"|null}
  515. * @since 5.0.12
  516. * @product highcharts
  517. */
  518. axisLabelPosition: null,
  519. /**
  520. * Provides the option to draw a frame around the charts by
  521. * defining a bottom, front and back panel.
  522. *
  523. * @since 4.0
  524. * @product highcharts
  525. * @requires highcharts-3d
  526. */
  527. frame: {
  528. /**
  529. * Whether the frames are visible.
  530. */
  531. visible: 'default',
  532. /**
  533. * General pixel thickness for the frame faces.
  534. */
  535. size: 1,
  536. /**
  537. * The bottom of the frame around a 3D chart.
  538. *
  539. * @since 4.0
  540. * @product highcharts
  541. * @requires highcharts-3d
  542. */
  543. /**
  544. * The color of the panel.
  545. *
  546. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  547. * @default transparent
  548. * @since 4.0
  549. * @product highcharts
  550. * @apioption chart.options3d.frame.bottom.color
  551. */
  552. /**
  553. * The thickness of the panel.
  554. *
  555. * @type {number}
  556. * @default 1
  557. * @since 4.0
  558. * @product highcharts
  559. * @apioption chart.options3d.frame.bottom.size
  560. */
  561. /**
  562. * Whether to display the frame. Possible values are `true`,
  563. * `false`, `"auto"` to display only the frames behind the
  564. * data, and `"default"` to display faces behind the data
  565. * based on the axis layout, ignoring the point of view.
  566. *
  567. * @sample {highcharts} highcharts/3d/scatter-frame/
  568. * Auto frames
  569. *
  570. * @type {boolean|"default"|"auto"}
  571. * @default default
  572. * @since 5.0.12
  573. * @product highcharts
  574. * @apioption chart.options3d.frame.bottom.visible
  575. */
  576. /**
  577. * The bottom of the frame around a 3D chart.
  578. */
  579. bottom: {},
  580. /**
  581. * The top of the frame around a 3D chart.
  582. *
  583. * @extends chart.options3d.frame.bottom
  584. */
  585. top: {},
  586. /**
  587. * The left side of the frame around a 3D chart.
  588. *
  589. * @extends chart.options3d.frame.bottom
  590. */
  591. left: {},
  592. /**
  593. * The right of the frame around a 3D chart.
  594. *
  595. * @extends chart.options3d.frame.bottom
  596. */
  597. right: {},
  598. /**
  599. * The back side of the frame around a 3D chart.
  600. *
  601. * @extends chart.options3d.frame.bottom
  602. */
  603. back: {},
  604. /**
  605. * The front of the frame around a 3D chart.
  606. *
  607. * @extends chart.options3d.frame.bottom
  608. */
  609. front: {}
  610. }
  611. }
  612. }
  613. };
  614. /* *
  615. *
  616. * Functions
  617. *
  618. * */
  619. /**
  620. * @private
  621. */
  622. function compose(ChartClass, FxClass) {
  623. var chartProto = ChartClass.prototype;
  624. var fxProto = FxClass.prototype;
  625. /**
  626. * Shorthand to check the is3d flag.
  627. * @private
  628. * @return {boolean}
  629. * Whether it is a 3D chart.
  630. */
  631. chartProto.is3d = function () {
  632. return (this.options.chart.options3d &&
  633. this.options.chart.options3d.enabled); // #4280
  634. };
  635. chartProto.propsRequireDirtyBox.push('chart.options3d');
  636. chartProto.propsRequireUpdateSeries.push('chart.options3d');
  637. /**
  638. * Animation setter for matrix property.
  639. * @private
  640. */
  641. fxProto.matrixSetter = function () {
  642. var interpolated;
  643. if (this.pos < 1 &&
  644. (isArray(this.start) || isArray(this.end))) {
  645. var start = this.start || [1, 0, 0, 1, 0, 0];
  646. var end = this.end || [1, 0, 0, 1, 0, 0];
  647. interpolated = [];
  648. for (var i = 0; i < 6; i++) {
  649. interpolated.push(this.pos * end[i] + (1 - this.pos) * start[i]);
  650. }
  651. }
  652. else {
  653. interpolated = this.end;
  654. }
  655. this.elem.attr(this.prop, interpolated, null, true);
  656. };
  657. merge(true, genericDefaultOptions, Chart3D.defaultOptions);
  658. addEvent(ChartClass, 'init', onInit);
  659. addEvent(ChartClass, 'addSeries', onAddSeries);
  660. addEvent(ChartClass, 'afterDrawChartBox', onAfterDrawChartBox);
  661. addEvent(ChartClass, 'afterGetContainer', onAfterGetContainer);
  662. addEvent(ChartClass, 'afterInit', onAfterInit);
  663. addEvent(ChartClass, 'afterSetChartSize', onAfterSetChartSize);
  664. addEvent(ChartClass, 'beforeRedraw', onBeforeRedraw);
  665. addEvent(ChartClass, 'beforeRender', onBeforeRender);
  666. wrap(H.Chart.prototype, 'isInsidePlot', wrapIsInsidePlot);
  667. wrap(ChartClass, 'renderSeries', wrapRenderSeries);
  668. wrap(ChartClass, 'setClassName', wrapSetClassName);
  669. }
  670. Chart3D.compose = compose;
  671. /**
  672. * Legacy support for HC < 6 to make 'scatter' series in a 3D chart route to
  673. * the real 'scatter3d' series type. (#8407)
  674. * @private
  675. */
  676. function onAddSeries(e) {
  677. if (this.is3d()) {
  678. if (e.options.type === 'scatter') {
  679. e.options.type = 'scatter3d';
  680. }
  681. }
  682. }
  683. /**
  684. * @private
  685. */
  686. function onAfterDrawChartBox() {
  687. if (this.chart3d &&
  688. this.is3d()) {
  689. var chart = this, renderer = chart.renderer, options3d = this.options.chart.options3d, frame = this.chart3d.get3dFrame(), xm = this.plotLeft, xp = this.plotLeft + this.plotWidth, ym = this.plotTop, yp = this.plotTop + this.plotHeight, zm = 0, zp = options3d.depth, xmm = xm - (frame.left.visible ? frame.left.size : 0), xpp = xp + (frame.right.visible ? frame.right.size : 0), ymm = ym - (frame.top.visible ? frame.top.size : 0), ypp = yp + (frame.bottom.visible ? frame.bottom.size : 0), zmm = zm - (frame.front.visible ? frame.front.size : 0), zpp = zp + (frame.back.visible ? frame.back.size : 0), verb = chart.hasRendered ? 'animate' : 'attr';
  690. this.chart3d.frame3d = frame;
  691. if (!this.frameShapes) {
  692. this.frameShapes = {
  693. bottom: renderer.polyhedron().add(),
  694. top: renderer.polyhedron().add(),
  695. left: renderer.polyhedron().add(),
  696. right: renderer.polyhedron().add(),
  697. back: renderer.polyhedron().add(),
  698. front: renderer.polyhedron().add()
  699. };
  700. }
  701. this.frameShapes.bottom[verb]({
  702. 'class': 'highcharts-3d-frame highcharts-3d-frame-bottom',
  703. zIndex: frame.bottom.frontFacing ? -1000 : 1000,
  704. faces: [{
  705. fill: H.color(frame.bottom.color).brighten(0.1).get(),
  706. vertexes: [{
  707. x: xmm,
  708. y: ypp,
  709. z: zmm
  710. }, {
  711. x: xpp,
  712. y: ypp,
  713. z: zmm
  714. }, {
  715. x: xpp,
  716. y: ypp,
  717. z: zpp
  718. }, {
  719. x: xmm,
  720. y: ypp,
  721. z: zpp
  722. }],
  723. enabled: frame.bottom.visible
  724. },
  725. {
  726. fill: H.color(frame.bottom.color).brighten(0.1).get(),
  727. vertexes: [{
  728. x: xm,
  729. y: yp,
  730. z: zp
  731. }, {
  732. x: xp,
  733. y: yp,
  734. z: zp
  735. }, {
  736. x: xp,
  737. y: yp,
  738. z: zm
  739. }, {
  740. x: xm,
  741. y: yp,
  742. z: zm
  743. }],
  744. enabled: frame.bottom.visible
  745. },
  746. {
  747. fill: H.color(frame.bottom.color).brighten(-0.1).get(),
  748. vertexes: [{
  749. x: xmm,
  750. y: ypp,
  751. z: zmm
  752. }, {
  753. x: xmm,
  754. y: ypp,
  755. z: zpp
  756. }, {
  757. x: xm,
  758. y: yp,
  759. z: zp
  760. }, {
  761. x: xm,
  762. y: yp,
  763. z: zm
  764. }],
  765. enabled: frame.bottom.visible && !frame.left.visible
  766. },
  767. {
  768. fill: H.color(frame.bottom.color).brighten(-0.1).get(),
  769. vertexes: [{
  770. x: xpp,
  771. y: ypp,
  772. z: zpp
  773. }, {
  774. x: xpp,
  775. y: ypp,
  776. z: zmm
  777. }, {
  778. x: xp,
  779. y: yp,
  780. z: zm
  781. }, {
  782. x: xp,
  783. y: yp,
  784. z: zp
  785. }],
  786. enabled: frame.bottom.visible && !frame.right.visible
  787. },
  788. {
  789. fill: H.color(frame.bottom.color).get(),
  790. vertexes: [{
  791. x: xpp,
  792. y: ypp,
  793. z: zmm
  794. }, {
  795. x: xmm,
  796. y: ypp,
  797. z: zmm
  798. }, {
  799. x: xm,
  800. y: yp,
  801. z: zm
  802. }, {
  803. x: xp,
  804. y: yp,
  805. z: zm
  806. }],
  807. enabled: frame.bottom.visible && !frame.front.visible
  808. },
  809. {
  810. fill: H.color(frame.bottom.color).get(),
  811. vertexes: [{
  812. x: xmm,
  813. y: ypp,
  814. z: zpp
  815. }, {
  816. x: xpp,
  817. y: ypp,
  818. z: zpp
  819. }, {
  820. x: xp,
  821. y: yp,
  822. z: zp
  823. }, {
  824. x: xm,
  825. y: yp,
  826. z: zp
  827. }],
  828. enabled: frame.bottom.visible && !frame.back.visible
  829. }]
  830. });
  831. this.frameShapes.top[verb]({
  832. 'class': 'highcharts-3d-frame highcharts-3d-frame-top',
  833. zIndex: frame.top.frontFacing ? -1000 : 1000,
  834. faces: [{
  835. fill: H.color(frame.top.color).brighten(0.1).get(),
  836. vertexes: [{
  837. x: xmm,
  838. y: ymm,
  839. z: zpp
  840. }, {
  841. x: xpp,
  842. y: ymm,
  843. z: zpp
  844. }, {
  845. x: xpp,
  846. y: ymm,
  847. z: zmm
  848. }, {
  849. x: xmm,
  850. y: ymm,
  851. z: zmm
  852. }],
  853. enabled: frame.top.visible
  854. },
  855. {
  856. fill: H.color(frame.top.color).brighten(0.1).get(),
  857. vertexes: [{
  858. x: xm,
  859. y: ym,
  860. z: zm
  861. }, {
  862. x: xp,
  863. y: ym,
  864. z: zm
  865. }, {
  866. x: xp,
  867. y: ym,
  868. z: zp
  869. }, {
  870. x: xm,
  871. y: ym,
  872. z: zp
  873. }],
  874. enabled: frame.top.visible
  875. },
  876. {
  877. fill: H.color(frame.top.color).brighten(-0.1).get(),
  878. vertexes: [{
  879. x: xmm,
  880. y: ymm,
  881. z: zpp
  882. }, {
  883. x: xmm,
  884. y: ymm,
  885. z: zmm
  886. }, {
  887. x: xm,
  888. y: ym,
  889. z: zm
  890. }, {
  891. x: xm,
  892. y: ym,
  893. z: zp
  894. }],
  895. enabled: frame.top.visible && !frame.left.visible
  896. },
  897. {
  898. fill: H.color(frame.top.color).brighten(-0.1).get(),
  899. vertexes: [{
  900. x: xpp,
  901. y: ymm,
  902. z: zmm
  903. }, {
  904. x: xpp,
  905. y: ymm,
  906. z: zpp
  907. }, {
  908. x: xp,
  909. y: ym,
  910. z: zp
  911. }, {
  912. x: xp,
  913. y: ym,
  914. z: zm
  915. }],
  916. enabled: frame.top.visible && !frame.right.visible
  917. },
  918. {
  919. fill: H.color(frame.top.color).get(),
  920. vertexes: [{
  921. x: xmm,
  922. y: ymm,
  923. z: zmm
  924. }, {
  925. x: xpp,
  926. y: ymm,
  927. z: zmm
  928. }, {
  929. x: xp,
  930. y: ym,
  931. z: zm
  932. }, {
  933. x: xm,
  934. y: ym,
  935. z: zm
  936. }],
  937. enabled: frame.top.visible && !frame.front.visible
  938. },
  939. {
  940. fill: H.color(frame.top.color).get(),
  941. vertexes: [{
  942. x: xpp,
  943. y: ymm,
  944. z: zpp
  945. }, {
  946. x: xmm,
  947. y: ymm,
  948. z: zpp
  949. }, {
  950. x: xm,
  951. y: ym,
  952. z: zp
  953. }, {
  954. x: xp,
  955. y: ym,
  956. z: zp
  957. }],
  958. enabled: frame.top.visible && !frame.back.visible
  959. }]
  960. });
  961. this.frameShapes.left[verb]({
  962. 'class': 'highcharts-3d-frame highcharts-3d-frame-left',
  963. zIndex: frame.left.frontFacing ? -1000 : 1000,
  964. faces: [{
  965. fill: H.color(frame.left.color).brighten(0.1).get(),
  966. vertexes: [{
  967. x: xmm,
  968. y: ypp,
  969. z: zmm
  970. }, {
  971. x: xm,
  972. y: yp,
  973. z: zm
  974. }, {
  975. x: xm,
  976. y: yp,
  977. z: zp
  978. }, {
  979. x: xmm,
  980. y: ypp,
  981. z: zpp
  982. }],
  983. enabled: frame.left.visible && !frame.bottom.visible
  984. },
  985. {
  986. fill: H.color(frame.left.color).brighten(0.1).get(),
  987. vertexes: [{
  988. x: xmm,
  989. y: ymm,
  990. z: zpp
  991. }, {
  992. x: xm,
  993. y: ym,
  994. z: zp
  995. }, {
  996. x: xm,
  997. y: ym,
  998. z: zm
  999. }, {
  1000. x: xmm,
  1001. y: ymm,
  1002. z: zmm
  1003. }],
  1004. enabled: frame.left.visible && !frame.top.visible
  1005. },
  1006. {
  1007. fill: H.color(frame.left.color).brighten(-0.1).get(),
  1008. vertexes: [{
  1009. x: xmm,
  1010. y: ypp,
  1011. z: zpp
  1012. }, {
  1013. x: xmm,
  1014. y: ymm,
  1015. z: zpp
  1016. }, {
  1017. x: xmm,
  1018. y: ymm,
  1019. z: zmm
  1020. }, {
  1021. x: xmm,
  1022. y: ypp,
  1023. z: zmm
  1024. }],
  1025. enabled: frame.left.visible
  1026. },
  1027. {
  1028. fill: H.color(frame.left.color).brighten(-0.1).get(),
  1029. vertexes: [{
  1030. x: xm,
  1031. y: ym,
  1032. z: zp
  1033. }, {
  1034. x: xm,
  1035. y: yp,
  1036. z: zp
  1037. }, {
  1038. x: xm,
  1039. y: yp,
  1040. z: zm
  1041. }, {
  1042. x: xm,
  1043. y: ym,
  1044. z: zm
  1045. }],
  1046. enabled: frame.left.visible
  1047. },
  1048. {
  1049. fill: H.color(frame.left.color).get(),
  1050. vertexes: [{
  1051. x: xmm,
  1052. y: ypp,
  1053. z: zmm
  1054. }, {
  1055. x: xmm,
  1056. y: ymm,
  1057. z: zmm
  1058. }, {
  1059. x: xm,
  1060. y: ym,
  1061. z: zm
  1062. }, {
  1063. x: xm,
  1064. y: yp,
  1065. z: zm
  1066. }],
  1067. enabled: frame.left.visible && !frame.front.visible
  1068. },
  1069. {
  1070. fill: H.color(frame.left.color).get(),
  1071. vertexes: [{
  1072. x: xmm,
  1073. y: ymm,
  1074. z: zpp
  1075. }, {
  1076. x: xmm,
  1077. y: ypp,
  1078. z: zpp
  1079. }, {
  1080. x: xm,
  1081. y: yp,
  1082. z: zp
  1083. }, {
  1084. x: xm,
  1085. y: ym,
  1086. z: zp
  1087. }],
  1088. enabled: frame.left.visible && !frame.back.visible
  1089. }]
  1090. });
  1091. this.frameShapes.right[verb]({
  1092. 'class': 'highcharts-3d-frame highcharts-3d-frame-right',
  1093. zIndex: frame.right.frontFacing ? -1000 : 1000,
  1094. faces: [{
  1095. fill: H.color(frame.right.color).brighten(0.1).get(),
  1096. vertexes: [{
  1097. x: xpp,
  1098. y: ypp,
  1099. z: zpp
  1100. }, {
  1101. x: xp,
  1102. y: yp,
  1103. z: zp
  1104. }, {
  1105. x: xp,
  1106. y: yp,
  1107. z: zm
  1108. }, {
  1109. x: xpp,
  1110. y: ypp,
  1111. z: zmm
  1112. }],
  1113. enabled: frame.right.visible && !frame.bottom.visible
  1114. },
  1115. {
  1116. fill: H.color(frame.right.color).brighten(0.1).get(),
  1117. vertexes: [{
  1118. x: xpp,
  1119. y: ymm,
  1120. z: zmm
  1121. }, {
  1122. x: xp,
  1123. y: ym,
  1124. z: zm
  1125. }, {
  1126. x: xp,
  1127. y: ym,
  1128. z: zp
  1129. }, {
  1130. x: xpp,
  1131. y: ymm,
  1132. z: zpp
  1133. }],
  1134. enabled: frame.right.visible && !frame.top.visible
  1135. },
  1136. {
  1137. fill: H.color(frame.right.color).brighten(-0.1).get(),
  1138. vertexes: [{
  1139. x: xp,
  1140. y: ym,
  1141. z: zm
  1142. }, {
  1143. x: xp,
  1144. y: yp,
  1145. z: zm
  1146. }, {
  1147. x: xp,
  1148. y: yp,
  1149. z: zp
  1150. }, {
  1151. x: xp,
  1152. y: ym,
  1153. z: zp
  1154. }],
  1155. enabled: frame.right.visible
  1156. },
  1157. {
  1158. fill: H.color(frame.right.color).brighten(-0.1).get(),
  1159. vertexes: [{
  1160. x: xpp,
  1161. y: ypp,
  1162. z: zmm
  1163. }, {
  1164. x: xpp,
  1165. y: ymm,
  1166. z: zmm
  1167. }, {
  1168. x: xpp,
  1169. y: ymm,
  1170. z: zpp
  1171. }, {
  1172. x: xpp,
  1173. y: ypp,
  1174. z: zpp
  1175. }],
  1176. enabled: frame.right.visible
  1177. },
  1178. {
  1179. fill: H.color(frame.right.color).get(),
  1180. vertexes: [{
  1181. x: xpp,
  1182. y: ymm,
  1183. z: zmm
  1184. }, {
  1185. x: xpp,
  1186. y: ypp,
  1187. z: zmm
  1188. }, {
  1189. x: xp,
  1190. y: yp,
  1191. z: zm
  1192. }, {
  1193. x: xp,
  1194. y: ym,
  1195. z: zm
  1196. }],
  1197. enabled: frame.right.visible && !frame.front.visible
  1198. },
  1199. {
  1200. fill: H.color(frame.right.color).get(),
  1201. vertexes: [{
  1202. x: xpp,
  1203. y: ypp,
  1204. z: zpp
  1205. }, {
  1206. x: xpp,
  1207. y: ymm,
  1208. z: zpp
  1209. }, {
  1210. x: xp,
  1211. y: ym,
  1212. z: zp
  1213. }, {
  1214. x: xp,
  1215. y: yp,
  1216. z: zp
  1217. }],
  1218. enabled: frame.right.visible && !frame.back.visible
  1219. }]
  1220. });
  1221. this.frameShapes.back[verb]({
  1222. 'class': 'highcharts-3d-frame highcharts-3d-frame-back',
  1223. zIndex: frame.back.frontFacing ? -1000 : 1000,
  1224. faces: [{
  1225. fill: H.color(frame.back.color).brighten(0.1).get(),
  1226. vertexes: [{
  1227. x: xpp,
  1228. y: ypp,
  1229. z: zpp
  1230. }, {
  1231. x: xmm,
  1232. y: ypp,
  1233. z: zpp
  1234. }, {
  1235. x: xm,
  1236. y: yp,
  1237. z: zp
  1238. }, {
  1239. x: xp,
  1240. y: yp,
  1241. z: zp
  1242. }],
  1243. enabled: frame.back.visible && !frame.bottom.visible
  1244. },
  1245. {
  1246. fill: H.color(frame.back.color).brighten(0.1).get(),
  1247. vertexes: [{
  1248. x: xmm,
  1249. y: ymm,
  1250. z: zpp
  1251. }, {
  1252. x: xpp,
  1253. y: ymm,
  1254. z: zpp
  1255. }, {
  1256. x: xp,
  1257. y: ym,
  1258. z: zp
  1259. }, {
  1260. x: xm,
  1261. y: ym,
  1262. z: zp
  1263. }],
  1264. enabled: frame.back.visible && !frame.top.visible
  1265. },
  1266. {
  1267. fill: H.color(frame.back.color).brighten(-0.1).get(),
  1268. vertexes: [{
  1269. x: xmm,
  1270. y: ypp,
  1271. z: zpp
  1272. }, {
  1273. x: xmm,
  1274. y: ymm,
  1275. z: zpp
  1276. }, {
  1277. x: xm,
  1278. y: ym,
  1279. z: zp
  1280. }, {
  1281. x: xm,
  1282. y: yp,
  1283. z: zp
  1284. }],
  1285. enabled: frame.back.visible && !frame.left.visible
  1286. },
  1287. {
  1288. fill: H.color(frame.back.color).brighten(-0.1).get(),
  1289. vertexes: [{
  1290. x: xpp,
  1291. y: ymm,
  1292. z: zpp
  1293. }, {
  1294. x: xpp,
  1295. y: ypp,
  1296. z: zpp
  1297. }, {
  1298. x: xp,
  1299. y: yp,
  1300. z: zp
  1301. }, {
  1302. x: xp,
  1303. y: ym,
  1304. z: zp
  1305. }],
  1306. enabled: frame.back.visible && !frame.right.visible
  1307. },
  1308. {
  1309. fill: H.color(frame.back.color).get(),
  1310. vertexes: [{
  1311. x: xm,
  1312. y: ym,
  1313. z: zp
  1314. }, {
  1315. x: xp,
  1316. y: ym,
  1317. z: zp
  1318. }, {
  1319. x: xp,
  1320. y: yp,
  1321. z: zp
  1322. }, {
  1323. x: xm,
  1324. y: yp,
  1325. z: zp
  1326. }],
  1327. enabled: frame.back.visible
  1328. },
  1329. {
  1330. fill: H.color(frame.back.color).get(),
  1331. vertexes: [{
  1332. x: xmm,
  1333. y: ypp,
  1334. z: zpp
  1335. }, {
  1336. x: xpp,
  1337. y: ypp,
  1338. z: zpp
  1339. }, {
  1340. x: xpp,
  1341. y: ymm,
  1342. z: zpp
  1343. }, {
  1344. x: xmm,
  1345. y: ymm,
  1346. z: zpp
  1347. }],
  1348. enabled: frame.back.visible
  1349. }]
  1350. });
  1351. this.frameShapes.front[verb]({
  1352. 'class': 'highcharts-3d-frame highcharts-3d-frame-front',
  1353. zIndex: frame.front.frontFacing ? -1000 : 1000,
  1354. faces: [{
  1355. fill: H.color(frame.front.color).brighten(0.1).get(),
  1356. vertexes: [{
  1357. x: xmm,
  1358. y: ypp,
  1359. z: zmm
  1360. }, {
  1361. x: xpp,
  1362. y: ypp,
  1363. z: zmm
  1364. }, {
  1365. x: xp,
  1366. y: yp,
  1367. z: zm
  1368. }, {
  1369. x: xm,
  1370. y: yp,
  1371. z: zm
  1372. }],
  1373. enabled: frame.front.visible && !frame.bottom.visible
  1374. },
  1375. {
  1376. fill: H.color(frame.front.color).brighten(0.1).get(),
  1377. vertexes: [{
  1378. x: xpp,
  1379. y: ymm,
  1380. z: zmm
  1381. }, {
  1382. x: xmm,
  1383. y: ymm,
  1384. z: zmm
  1385. }, {
  1386. x: xm,
  1387. y: ym,
  1388. z: zm
  1389. }, {
  1390. x: xp,
  1391. y: ym,
  1392. z: zm
  1393. }],
  1394. enabled: frame.front.visible && !frame.top.visible
  1395. },
  1396. {
  1397. fill: H.color(frame.front.color).brighten(-0.1).get(),
  1398. vertexes: [{
  1399. x: xmm,
  1400. y: ymm,
  1401. z: zmm
  1402. }, {
  1403. x: xmm,
  1404. y: ypp,
  1405. z: zmm
  1406. }, {
  1407. x: xm,
  1408. y: yp,
  1409. z: zm
  1410. }, {
  1411. x: xm,
  1412. y: ym,
  1413. z: zm
  1414. }],
  1415. enabled: frame.front.visible && !frame.left.visible
  1416. },
  1417. {
  1418. fill: H.color(frame.front.color).brighten(-0.1).get(),
  1419. vertexes: [{
  1420. x: xpp,
  1421. y: ypp,
  1422. z: zmm
  1423. }, {
  1424. x: xpp,
  1425. y: ymm,
  1426. z: zmm
  1427. }, {
  1428. x: xp,
  1429. y: ym,
  1430. z: zm
  1431. }, {
  1432. x: xp,
  1433. y: yp,
  1434. z: zm
  1435. }],
  1436. enabled: frame.front.visible && !frame.right.visible
  1437. },
  1438. {
  1439. fill: H.color(frame.front.color).get(),
  1440. vertexes: [{
  1441. x: xp,
  1442. y: ym,
  1443. z: zm
  1444. }, {
  1445. x: xm,
  1446. y: ym,
  1447. z: zm
  1448. }, {
  1449. x: xm,
  1450. y: yp,
  1451. z: zm
  1452. }, {
  1453. x: xp,
  1454. y: yp,
  1455. z: zm
  1456. }],
  1457. enabled: frame.front.visible
  1458. },
  1459. {
  1460. fill: H.color(frame.front.color).get(),
  1461. vertexes: [{
  1462. x: xpp,
  1463. y: ypp,
  1464. z: zmm
  1465. }, {
  1466. x: xmm,
  1467. y: ypp,
  1468. z: zmm
  1469. }, {
  1470. x: xmm,
  1471. y: ymm,
  1472. z: zmm
  1473. }, {
  1474. x: xpp,
  1475. y: ymm,
  1476. z: zmm
  1477. }],
  1478. enabled: frame.front.visible
  1479. }]
  1480. });
  1481. }
  1482. }
  1483. /**
  1484. * Add the required CSS classes for column sides (#6018)
  1485. * @private
  1486. */
  1487. function onAfterGetContainer() {
  1488. if (this.styledMode) {
  1489. this.renderer.definition({
  1490. tagName: 'style',
  1491. textContent: '.highcharts-3d-top{' +
  1492. 'filter: url(#highcharts-brighter)' +
  1493. '}\n' +
  1494. '.highcharts-3d-side{' +
  1495. 'filter: url(#highcharts-darker)' +
  1496. '}\n'
  1497. });
  1498. // Add add definitions used by brighter and darker faces of the
  1499. // cuboids.
  1500. [{
  1501. name: 'darker',
  1502. slope: 0.6
  1503. }, {
  1504. name: 'brighter',
  1505. slope: 1.4
  1506. }].forEach(function (cfg) {
  1507. this.renderer.definition({
  1508. tagName: 'filter',
  1509. id: 'highcharts-' + cfg.name,
  1510. children: [{
  1511. tagName: 'feComponentTransfer',
  1512. children: [{
  1513. tagName: 'feFuncR',
  1514. type: 'linear',
  1515. slope: cfg.slope
  1516. }, {
  1517. tagName: 'feFuncG',
  1518. type: 'linear',
  1519. slope: cfg.slope
  1520. }, {
  1521. tagName: 'feFuncB',
  1522. type: 'linear',
  1523. slope: cfg.slope
  1524. }]
  1525. }]
  1526. });
  1527. }, this);
  1528. }
  1529. }
  1530. /**
  1531. * Legacy support for HC < 6 to make 'scatter' series in a 3D chart route to
  1532. * the real 'scatter3d' series type. (#8407)
  1533. * @private
  1534. */
  1535. function onAfterInit() {
  1536. var options = this.options;
  1537. if (this.is3d()) {
  1538. (options.series || []).forEach(function (s) {
  1539. var type = s.type ||
  1540. options.chart.type ||
  1541. options.chart.defaultSeriesType;
  1542. if (type === 'scatter') {
  1543. s.type = 'scatter3d';
  1544. }
  1545. });
  1546. }
  1547. }
  1548. /**
  1549. * @private
  1550. */
  1551. function onAfterSetChartSize() {
  1552. var chart = this, options3d = chart.options.chart.options3d;
  1553. if (chart.chart3d &&
  1554. chart.is3d()) {
  1555. // Add a 0-360 normalisation for alfa and beta angles in 3d graph
  1556. if (options3d) {
  1557. options3d.alpha = options3d.alpha % 360 + (options3d.alpha >= 0 ? 0 : 360);
  1558. options3d.beta = options3d.beta % 360 + (options3d.beta >= 0 ? 0 : 360);
  1559. }
  1560. 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';
  1561. clipBox[x] = -(margin[3] || 0);
  1562. clipBox[y] = -(margin[0] || 0);
  1563. clipBox[w] =
  1564. chart.chartWidth + (margin[3] || 0) + (margin[1] || 0);
  1565. clipBox[h] =
  1566. chart.chartHeight + (margin[0] || 0) + (margin[2] || 0);
  1567. // Set scale, used later in perspective method():
  1568. // getScale uses perspective, so scale3d has to be reset.
  1569. chart.scale3d = 1;
  1570. if (options3d.fitToPlot === true) {
  1571. chart.scale3d = chart.chart3d.getScale(options3d.depth);
  1572. }
  1573. // Recalculate the 3d frame with every call of setChartSize,
  1574. // instead of doing it after every redraw(). It avoids ticks
  1575. // and axis title outside of chart.
  1576. chart.chart3d.frame3d = chart.chart3d.get3dFrame(); // #7942
  1577. }
  1578. }
  1579. /**
  1580. * @private
  1581. */
  1582. function onBeforeRedraw() {
  1583. if (this.is3d()) {
  1584. // Set to force a redraw of all elements
  1585. this.isDirtyBox = true;
  1586. }
  1587. }
  1588. /**
  1589. * @private
  1590. */
  1591. function onBeforeRender() {
  1592. if (this.chart3d && this.is3d()) {
  1593. this.chart3d.frame3d = this.chart3d.get3dFrame();
  1594. }
  1595. }
  1596. /**
  1597. * @private
  1598. */
  1599. function onInit() {
  1600. if (!this.chart3d) {
  1601. this.chart3d = new Composition(this);
  1602. }
  1603. }
  1604. /**
  1605. * @private
  1606. */
  1607. function wrapIsInsidePlot(proceed) {
  1608. return this.is3d() || proceed.apply(this, [].slice.call(arguments, 1));
  1609. }
  1610. /**
  1611. * Draw the series in the reverse order (#3803, #3917)
  1612. * @private
  1613. */
  1614. function wrapRenderSeries(proceed) {
  1615. var series, i = this.series.length;
  1616. if (this.is3d()) {
  1617. while (i--) {
  1618. series = this.series[i];
  1619. series.translate();
  1620. series.render();
  1621. }
  1622. }
  1623. else {
  1624. proceed.call(this);
  1625. }
  1626. }
  1627. /**
  1628. * @private
  1629. */
  1630. function wrapSetClassName(proceed) {
  1631. proceed.apply(this, [].slice.call(arguments, 1));
  1632. if (this.is3d()) {
  1633. this.container.className += ' highcharts-3d-chart';
  1634. }
  1635. }
  1636. })(Chart3D || (Chart3D = {}));
  1637. Chart3D.compose(Chart, Fx);
  1638. ZAxis.ZChartComposition.compose(Chart);
  1639. Axis3D.compose(Axis);
  1640. /**
  1641. * Note: As of v5.0.12, `frame.left` or `frame.right` should be used instead.
  1642. *
  1643. * The side for the frame around a 3D chart.
  1644. *
  1645. * @deprecated
  1646. * @since 4.0
  1647. * @product highcharts
  1648. * @requires highcharts-3d
  1649. * @apioption chart.options3d.frame.side
  1650. */
  1651. /**
  1652. * The color of the panel.
  1653. *
  1654. * @deprecated
  1655. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  1656. * @default transparent
  1657. * @since 4.0
  1658. * @product highcharts
  1659. * @apioption chart.options3d.frame.side.color
  1660. */
  1661. /**
  1662. * The thickness of the panel.
  1663. *
  1664. * @deprecated
  1665. * @type {number}
  1666. * @default 1
  1667. * @since 4.0
  1668. * @product highcharts
  1669. * @apioption chart.options3d.frame.side.size
  1670. */
  1671. ''; // adds doclets above to transpiled file
  1672. export default Chart3D;