Chart3D.js 64 KB

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