You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1527 lines
41 KiB

9 years ago
  1. // ==ClosureCompiler==
  2. // @compilation_level SIMPLE_OPTIMIZATIONS
  3. /**
  4. * @license Highcharts JS v4.1.8 (2015-08-20)
  5. *
  6. * (c) 2009-2013 Torstein Hønsi
  7. *
  8. * License: www.highcharts.com/license
  9. */
  10. // JSLint options:
  11. /*global Highcharts, HighchartsAdapter, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */
  12. (function (Highcharts) {
  13. /**
  14. Shorthands for often used function
  15. */
  16. /**
  17. * Mathematical Functionility
  18. */
  19. var PI = Math.PI,
  20. deg2rad = (PI / 180), // degrees to radians
  21. sin = Math.sin,
  22. cos = Math.cos,
  23. pick = Highcharts.pick,
  24. round = Math.round;
  25. /**
  26. * Transforms a given array of points according to the angles in chart.options.
  27. * Parameters:
  28. * - points: the array of points
  29. * - chart: the chart
  30. * - insidePlotArea: wether to verifiy the points are inside the plotArea
  31. * Returns:
  32. * - an array of transformed points
  33. */
  34. function perspective(points, chart, insidePlotArea) {
  35. var options3d = chart.options.chart.options3d,
  36. inverted = false,
  37. origin;
  38. if (insidePlotArea) {
  39. inverted = chart.inverted;
  40. origin = {
  41. x: chart.plotWidth / 2,
  42. y: chart.plotHeight / 2,
  43. z: options3d.depth / 2,
  44. vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
  45. };
  46. } else {
  47. origin = {
  48. x: chart.plotLeft + (chart.plotWidth / 2),
  49. y: chart.plotTop + (chart.plotHeight / 2),
  50. z: options3d.depth / 2,
  51. vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
  52. };
  53. }
  54. var result = [],
  55. xe = origin.x,
  56. ye = origin.y,
  57. ze = origin.z,
  58. vd = origin.vd,
  59. angle1 = deg2rad * (inverted ? options3d.beta : -options3d.beta),
  60. angle2 = deg2rad * (inverted ? -options3d.alpha : options3d.alpha),
  61. s1 = sin(angle1),
  62. c1 = cos(angle1),
  63. s2 = sin(angle2),
  64. c2 = cos(angle2);
  65. var x, y, z, px, py, pz;
  66. // Transform each point
  67. Highcharts.each(points, function (point) {
  68. x = (inverted ? point.y : point.x) - xe;
  69. y = (inverted ? point.x : point.y) - ye;
  70. z = (point.z || 0) - ze;
  71. //Apply 3-D rotation
  72. px = c1 * x - s1 * z;
  73. py = -s1 * s2 * x - c1 * s2 * z + c2 * y;
  74. pz = s1 * c2 * x + c1 * c2 * z + s2 * y;
  75. //Apply perspective
  76. if ((vd > 0) && (vd < Number.POSITIVE_INFINITY)) {
  77. px = px * (vd / (pz + ze + vd));
  78. py = py * (vd / (pz + ze + vd));
  79. }
  80. //Apply translation
  81. px = px + xe;
  82. py = py + ye;
  83. pz = pz + ze;
  84. result.push({
  85. x: (inverted ? py : px),
  86. y: (inverted ? px : py),
  87. z: pz
  88. });
  89. });
  90. return result;
  91. }
  92. // Make function acessible to plugins
  93. Highcharts.perspective = perspective;
  94. /***
  95. EXTENSION TO THE SVG-RENDERER TO ENABLE 3D SHAPES
  96. ***/
  97. ////// HELPER METHODS //////
  98. var dFactor = (4 * (Math.sqrt(2) - 1) / 3) / (PI / 2);
  99. function defined(obj) {
  100. return obj !== undefined && obj !== null;
  101. }
  102. //Shoelace algorithm -- http://en.wikipedia.org/wiki/Shoelace_formula
  103. function shapeArea(vertexes) {
  104. var area = 0,
  105. i,
  106. j;
  107. for (i = 0; i < vertexes.length; i++) {
  108. j = (i + 1) % vertexes.length;
  109. area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y;
  110. }
  111. return area / 2;
  112. }
  113. function averageZ(vertexes) {
  114. var z = 0,
  115. i;
  116. for (i = 0; i < vertexes.length; i++) {
  117. z += vertexes[i].z;
  118. }
  119. return vertexes.length ? z / vertexes.length : 0;
  120. }
  121. /** Method to construct a curved path
  122. * Can 'wrap' around more then 180 degrees
  123. */
  124. function curveTo(cx, cy, rx, ry, start, end, dx, dy) {
  125. var result = [];
  126. if ((end > start) && (end - start > PI / 2 + 0.0001)) {
  127. result = result.concat(curveTo(cx, cy, rx, ry, start, start + (PI / 2), dx, dy));
  128. result = result.concat(curveTo(cx, cy, rx, ry, start + (PI / 2), end, dx, dy));
  129. return result;
  130. } else if ((end < start) && (start - end > PI / 2 + 0.0001)) {
  131. result = result.concat(curveTo(cx, cy, rx, ry, start, start - (PI / 2), dx, dy));
  132. result = result.concat(curveTo(cx, cy, rx, ry, start - (PI / 2), end, dx, dy));
  133. return result;
  134. } else {
  135. var arcAngle = end - start;
  136. return [
  137. 'C',
  138. cx + (rx * cos(start)) - ((rx * dFactor * arcAngle) * sin(start)) + dx,
  139. cy + (ry * sin(start)) + ((ry * dFactor * arcAngle) * cos(start)) + dy,
  140. cx + (rx * cos(end)) + ((rx * dFactor * arcAngle) * sin(end)) + dx,
  141. cy + (ry * sin(end)) - ((ry * dFactor * arcAngle) * cos(end)) + dy,
  142. cx + (rx * cos(end)) + dx,
  143. cy + (ry * sin(end)) + dy
  144. ];
  145. }
  146. }
  147. Highcharts.SVGRenderer.prototype.toLinePath = function (points, closed) {
  148. var result = [];
  149. // Put "L x y" for each point
  150. Highcharts.each(points, function (point) {
  151. result.push('L', point.x, point.y);
  152. });
  153. if (points.length) {
  154. // Set the first element to M
  155. result[0] = 'M';
  156. // If it is a closed line, add Z
  157. if (closed) {
  158. result.push('Z');
  159. }
  160. }
  161. return result;
  162. };
  163. ////// CUBOIDS //////
  164. Highcharts.SVGRenderer.prototype.cuboid = function (shapeArgs) {
  165. var result = this.g(),
  166. paths = this.cuboidPath(shapeArgs);
  167. // create the 3 sides
  168. result.front = this.path(paths[0]).attr({zIndex: paths[3], 'stroke-linejoin': 'round'}).add(result);
  169. result.top = this.path(paths[1]).attr({zIndex: paths[4], 'stroke-linejoin': 'round'}).add(result);
  170. result.side = this.path(paths[2]).attr({zIndex: paths[5], 'stroke-linejoin': 'round'}).add(result);
  171. // apply the fill everywhere, the top a bit brighter, the side a bit darker
  172. result.fillSetter = function (color) {
  173. var c0 = color,
  174. c1 = Highcharts.Color(color).brighten(0.1).get(),
  175. c2 = Highcharts.Color(color).brighten(-0.1).get();
  176. this.front.attr({fill: c0});
  177. this.top.attr({fill: c1});
  178. this.side.attr({fill: c2});
  179. this.color = color;
  180. return this;
  181. };
  182. // apply opacaity everywhere
  183. result.opacitySetter = function (opacity) {
  184. this.front.attr({opacity: opacity});
  185. this.top.attr({opacity: opacity});
  186. this.side.attr({opacity: opacity});
  187. return this;
  188. };
  189. result.attr = function (args) {
  190. if (args.shapeArgs || defined(args.x)) {
  191. var shapeArgs = args.shapeArgs || args;
  192. var paths = this.renderer.cuboidPath(shapeArgs);
  193. this.front.attr({d: paths[0], zIndex: paths[3]});
  194. this.top.attr({d: paths[1], zIndex: paths[4]});
  195. this.side.attr({d: paths[2], zIndex: paths[5]});
  196. } else {
  197. Highcharts.SVGElement.prototype.attr.call(this, args);
  198. }
  199. return this;
  200. };
  201. result.animate = function (args, duration, complete) {
  202. if (defined(args.x) && defined(args.y)) {
  203. var paths = this.renderer.cuboidPath(args);
  204. this.front.attr({zIndex: paths[3]}).animate({d: paths[0]}, duration, complete);
  205. this.top.attr({zIndex: paths[4]}).animate({d: paths[1]}, duration, complete);
  206. this.side.attr({zIndex: paths[5]}).animate({d: paths[2]}, duration, complete);
  207. } else if (args.opacity) {
  208. this.front.animate(args, duration, complete);
  209. this.top.animate(args, duration, complete);
  210. this.side.animate(args, duration, complete);
  211. } else {
  212. Highcharts.SVGElement.prototype.animate.call(this, args, duration, complete);
  213. }
  214. return this;
  215. };
  216. // destroy all children
  217. result.destroy = function () {
  218. this.front.destroy();
  219. this.top.destroy();
  220. this.side.destroy();
  221. return null;
  222. };
  223. // Apply the Z index to the cuboid group
  224. result.attr({ zIndex: -paths[3] });
  225. return result;
  226. };
  227. /**
  228. * Generates a cuboid
  229. */
  230. Highcharts.SVGRenderer.prototype.cuboidPath = function (shapeArgs) {
  231. var x = shapeArgs.x,
  232. y = shapeArgs.y,
  233. z = shapeArgs.z,
  234. h = shapeArgs.height,
  235. w = shapeArgs.width,
  236. d = shapeArgs.depth,
  237. chart = Highcharts.charts[this.chartIndex],
  238. map = Highcharts.map;
  239. // The 8 corners of the cube
  240. var pArr = [
  241. {x: x, y: y, z: z},
  242. {x: x + w, y: y, z: z},
  243. {x: x + w, y: y + h, z: z},
  244. {x: x, y: y + h, z: z},
  245. {x: x, y: y + h, z: z + d},
  246. {x: x + w, y: y + h, z: z + d},
  247. {x: x + w, y: y, z: z + d},
  248. {x: x, y: y, z: z + d}
  249. ];
  250. // apply perspective
  251. pArr = perspective(pArr, chart, shapeArgs.insidePlotArea);
  252. // helper method to decide which side is visible
  253. var pickShape = function (path1, path2) {
  254. path1 = map(path1, function (i) { return pArr[i]; });
  255. path2 = map(path2, function (i) { return pArr[i]; });
  256. if (shapeArea(path1) < 0) {
  257. return path1;
  258. } else if (shapeArea(path2) < 0) {
  259. return path2;
  260. } else {
  261. return [];
  262. }
  263. };
  264. // front or back
  265. var front = [3, 2, 1, 0];
  266. var back = [7, 6, 5, 4];
  267. var path1 = pickShape(front, back);
  268. // top or bottom
  269. var top = [1, 6, 7, 0];
  270. var bottom = [4, 5, 2, 3];
  271. var path2 = pickShape(top, bottom);
  272. // side
  273. var right = [1, 2, 5, 6];
  274. var left = [0, 7, 4, 3];
  275. var path3 = pickShape(right, left);
  276. return [this.toLinePath(path1, true), this.toLinePath(path2, true), this.toLinePath(path3, true), averageZ(path1), averageZ(path2), averageZ(path3)];
  277. };
  278. ////// SECTORS //////
  279. Highcharts.SVGRenderer.prototype.arc3d = function (shapeArgs) {
  280. shapeArgs.alpha *= deg2rad;
  281. shapeArgs.beta *= deg2rad;
  282. var result = this.g(),
  283. paths = this.arc3dPath(shapeArgs),
  284. renderer = result.renderer;
  285. var zIndex = paths.zTop * 100;
  286. result.shapeArgs = shapeArgs; // Store for later use
  287. // create the different sub sections of the shape
  288. result.top = renderer.path(paths.top).setRadialReference(shapeArgs.center).attr({zIndex: paths.zTop}).add(result);
  289. result.side1 = renderer.path(paths.side2).attr({zIndex: paths.zSide1});
  290. result.side2 = renderer.path(paths.side1).attr({zIndex: paths.zSide2});
  291. result.inn = renderer.path(paths.inn).attr({zIndex: paths.zInn});
  292. result.out = renderer.path(paths.out).attr({zIndex: paths.zOut});
  293. // apply the fill to the top and a darker shade to the sides
  294. result.fillSetter = function (color) {
  295. this.color = color;
  296. var c0 = color,
  297. c2 = Highcharts.Color(color).brighten(-0.1).get();
  298. this.side1.attr({fill: c2});
  299. this.side2.attr({fill: c2});
  300. this.inn.attr({fill: c2});
  301. this.out.attr({fill: c2});
  302. this.top.attr({fill: c0});
  303. return this;
  304. };
  305. // apply the translation to all
  306. result.translateXSetter = function (value) {
  307. this.out.attr({translateX: value});
  308. this.inn.attr({translateX: value});
  309. this.side1.attr({translateX: value});
  310. this.side2.attr({translateX: value});
  311. this.top.attr({translateX: value});
  312. };
  313. result.translateYSetter = function (value) {
  314. this.out.attr({translateY: value});
  315. this.inn.attr({translateY: value});
  316. this.side1.attr({translateY: value});
  317. this.side2.attr({translateY: value});
  318. this.top.attr({translateY: value});
  319. };
  320. result.animate = function (args, duration, complete) {
  321. if (defined(args.end) || defined(args.start)) {
  322. this._shapeArgs = this.shapeArgs;
  323. Highcharts.SVGElement.prototype.animate.call(this, {
  324. _args: args
  325. }, {
  326. duration: duration,
  327. start: function () {
  328. var args = arguments,
  329. fx = args[0],
  330. elem = fx.elem,
  331. end = elem._shapeArgs;
  332. if (end.fill !== elem.color) {
  333. elem.attr({
  334. fill: end.fill
  335. });
  336. }
  337. },
  338. step: function () {
  339. var args = arguments,
  340. fx = args[1],
  341. result = fx.elem,
  342. start = result._shapeArgs,
  343. end = fx.end,
  344. pos = fx.pos,
  345. sA = Highcharts.merge(start, {
  346. x: start.x + ((end.x - start.x) * pos),
  347. y: start.y + ((end.y - start.y) * pos),
  348. r: start.r + ((end.r - start.r) * pos),
  349. innerR: start.innerR + ((end.innerR - start.innerR) * pos),
  350. start: start.start + ((end.start - start.start) * pos),
  351. end: start.end + ((end.end - start.end) * pos)
  352. });
  353. var paths = result.renderer.arc3dPath(sA);
  354. result.shapeArgs = sA;
  355. result.top.attr({d: paths.top, zIndex: paths.zTop});
  356. result.inn.attr({d: paths.inn, zIndex: paths.zInn});
  357. result.out.attr({d: paths.out, zIndex: paths.zOut});
  358. result.side1.attr({d: paths.side1, zIndex: paths.zSide1});
  359. result.side2.attr({d: paths.side2, zIndex: paths.zSide2});
  360. }
  361. }, complete);
  362. } else {
  363. Highcharts.SVGElement.prototype.animate.call(this, args, duration, complete);
  364. }
  365. return this;
  366. };
  367. // destroy all children
  368. result.destroy = function () {
  369. this.top.destroy();
  370. this.out.destroy();
  371. this.inn.destroy();
  372. this.side1.destroy();
  373. this.side2.destroy();
  374. Highcharts.SVGElement.prototype.destroy.call(this);
  375. };
  376. // hide all children
  377. result.hide = function () {
  378. this.top.hide();
  379. this.out.hide();
  380. this.inn.hide();
  381. this.side1.hide();
  382. this.side2.hide();
  383. };
  384. result.show = function () {
  385. this.top.show();
  386. this.out.show();
  387. this.inn.show();
  388. this.side1.show();
  389. this.side2.show();
  390. };
  391. // show all children
  392. result.zIndex = zIndex;
  393. result.attr({zIndex: zIndex});
  394. return result;
  395. };
  396. /**
  397. * Generate the paths required to draw a 3D arc
  398. */
  399. Highcharts.SVGRenderer.prototype.arc3dPath = function (shapeArgs) {
  400. var cx = shapeArgs.x, // x coordinate of the center
  401. cy = shapeArgs.y, // y coordinate of the center
  402. start = shapeArgs.start, // start angle
  403. end = shapeArgs.end - 0.00001, // end angle
  404. r = shapeArgs.r, // radius
  405. ir = shapeArgs.innerR, // inner radius
  406. d = shapeArgs.depth, // depth
  407. alpha = shapeArgs.alpha, // alpha rotation of the chart
  408. beta = shapeArgs.beta; // beta rotation of the chart
  409. // Derived Variables
  410. var cs = cos(start), // cosinus of the start angle
  411. ss = sin(start), // sinus of the start angle
  412. ce = cos(end), // cosinus of the end angle
  413. se = sin(end), // sinus of the end angle
  414. rx = r * cos(beta), // x-radius
  415. ry = r * cos(alpha), // y-radius
  416. irx = ir * cos(beta), // x-radius (inner)
  417. iry = ir * cos(alpha), // y-radius (inner)
  418. dx = d * sin(beta), // distance between top and bottom in x
  419. dy = d * sin(alpha); // distance between top and bottom in y
  420. // TOP
  421. var top = ['M', cx + (rx * cs), cy + (ry * ss)];
  422. top = top.concat(curveTo(cx, cy, rx, ry, start, end, 0, 0));
  423. top = top.concat([
  424. 'L', cx + (irx * ce), cy + (iry * se)
  425. ]);
  426. top = top.concat(curveTo(cx, cy, irx, iry, end, start, 0, 0));
  427. top = top.concat(['Z']);
  428. // OUTSIDE
  429. var b = (beta > 0 ? PI / 2 : 0),
  430. a = (alpha > 0 ? 0 : PI / 2);
  431. var start2 = start > -b ? start : (end > -b ? -b : start),
  432. end2 = end < PI - a ? end : (start < PI - a ? PI - a : end);
  433. var out = ['M', cx + (rx * cos(start2)), cy + (ry * sin(start2))];
  434. out = out.concat(curveTo(cx, cy, rx, ry, start2, end2, 0, 0));
  435. out = out.concat([
  436. 'L', cx + (rx * cos(end2)) + dx, cy + (ry * sin(end2)) + dy
  437. ]);
  438. out = out.concat(curveTo(cx, cy, rx, ry, end2, start2, dx, dy));
  439. out = out.concat(['Z']);
  440. // INSIDE
  441. var inn = ['M', cx + (irx * cs), cy + (iry * ss)];
  442. inn = inn.concat(curveTo(cx, cy, irx, iry, start, end, 0, 0));
  443. inn = inn.concat([
  444. 'L', cx + (irx * cos(end)) + dx, cy + (iry * sin(end)) + dy
  445. ]);
  446. inn = inn.concat(curveTo(cx, cy, irx, iry, end, start, dx, dy));
  447. inn = inn.concat(['Z']);
  448. // SIDES
  449. var side1 = [
  450. 'M', cx + (rx * cs), cy + (ry * ss),
  451. 'L', cx + (rx * cs) + dx, cy + (ry * ss) + dy,
  452. 'L', cx + (irx * cs) + dx, cy + (iry * ss) + dy,
  453. 'L', cx + (irx * cs), cy + (iry * ss),
  454. 'Z'
  455. ];
  456. var side2 = [
  457. 'M', cx + (rx * ce), cy + (ry * se),
  458. 'L', cx + (rx * ce) + dx, cy + (ry * se) + dy,
  459. 'L', cx + (irx * ce) + dx, cy + (iry * se) + dy,
  460. 'L', cx + (irx * ce), cy + (iry * se),
  461. 'Z'
  462. ];
  463. var a1 = sin((start + end) / 2),
  464. a2 = sin(start),
  465. a3 = sin(end);
  466. return {
  467. top: top,
  468. zTop: r,
  469. out: out,
  470. zOut: Math.max(a1, a2, a3) * r,
  471. inn: inn,
  472. zInn: Math.max(a1, a2, a3) * r,
  473. side1: side1,
  474. zSide1: a2 * (r * 0.99),
  475. side2: side2,
  476. zSide2: a3 * (r * 0.99)
  477. };
  478. };
  479. /***
  480. EXTENSION FOR 3D CHARTS
  481. ***/
  482. // Shorthand to check the is3d flag
  483. Highcharts.Chart.prototype.is3d = function () {
  484. return this.options.chart.options3d && this.options.chart.options3d.enabled; // #4280
  485. };
  486. Highcharts.wrap(Highcharts.Chart.prototype, 'isInsidePlot', function (proceed) {
  487. if (this.is3d()) {
  488. return true;
  489. } else {
  490. return proceed.apply(this, [].slice.call(arguments, 1));
  491. }
  492. });
  493. var defaultChartOptions = Highcharts.getOptions();
  494. defaultChartOptions.chart.options3d = {
  495. enabled: false,
  496. alpha: 0,
  497. beta: 0,
  498. depth: 100,
  499. viewDistance: 25,
  500. frame: {
  501. bottom: { size: 1, color: 'rgba(255,255,255,0)' },
  502. side: { size: 1, color: 'rgba(255,255,255,0)' },
  503. back: { size: 1, color: 'rgba(255,255,255,0)' }
  504. }
  505. };
  506. Highcharts.wrap(Highcharts.Chart.prototype, 'init', function (proceed) {
  507. var args = [].slice.call(arguments, 1),
  508. plotOptions,
  509. pieOptions;
  510. if (args[0].chart.options3d && args[0].chart.options3d.enabled) {
  511. plotOptions = args[0].plotOptions || {};
  512. pieOptions = plotOptions.pie || {};
  513. pieOptions.borderColor = Highcharts.pick(pieOptions.borderColor, undefined);
  514. }
  515. proceed.apply(this, args);
  516. });
  517. Highcharts.wrap(Highcharts.Chart.prototype, 'setChartSize', function (proceed) {
  518. proceed.apply(this, [].slice.call(arguments, 1));
  519. if (this.is3d()) {
  520. var inverted = this.inverted,
  521. clipBox = this.clipBox,
  522. margin = this.margin,
  523. x = inverted ? 'y' : 'x',
  524. y = inverted ? 'x' : 'y',
  525. w = inverted ? 'height' : 'width',
  526. h = inverted ? 'width' : 'height';
  527. clipBox[x] = -(margin[3] || 0);
  528. clipBox[y] = -(margin[0] || 0);
  529. clipBox[w] = this.chartWidth + (margin[3] || 0) + (margin[1] || 0);
  530. clipBox[h] = this.chartHeight + (margin[0] || 0) + (margin[2] || 0);
  531. }
  532. });
  533. Highcharts.wrap(Highcharts.Chart.prototype, 'redraw', function (proceed) {
  534. if (this.is3d()) {
  535. // Set to force a redraw of all elements
  536. this.isDirtyBox = true;
  537. }
  538. proceed.apply(this, [].slice.call(arguments, 1));
  539. });
  540. // Draw the series in the reverse order (#3803, #3917)
  541. Highcharts.wrap(Highcharts.Chart.prototype, 'renderSeries', function (proceed) {
  542. var series,
  543. i = this.series.length;
  544. if (this.is3d()) {
  545. while (i--) {
  546. series = this.series[i];
  547. series.translate();
  548. series.render();
  549. }
  550. } else {
  551. proceed.call(this);
  552. }
  553. });
  554. Highcharts.Chart.prototype.retrieveStacks = function (stacking) {
  555. var series = this.series,
  556. stacks = {},
  557. stackNumber,
  558. i = 1;
  559. Highcharts.each(this.series, function (S) {
  560. stackNumber = stacking ? (S.options.stack || 0) : series.length - 1 - S.index; // #3841
  561. if (!stacks[stackNumber]) {
  562. stacks[stackNumber] = { series: [S], position: i};
  563. i++;
  564. } else {
  565. stacks[stackNumber].series.push(S);
  566. }
  567. });
  568. stacks.totalStacks = i + 1;
  569. return stacks;
  570. };
  571. /***
  572. EXTENSION TO THE AXIS
  573. ***/
  574. Highcharts.wrap(Highcharts.Axis.prototype, 'setOptions', function (proceed, userOptions) {
  575. var options;
  576. proceed.call(this, userOptions);
  577. if (this.chart.is3d()) {
  578. options = this.options;
  579. options.tickWidth = Highcharts.pick(options.tickWidth, 0);
  580. options.gridLineWidth = Highcharts.pick(options.gridLineWidth, 1);
  581. }
  582. });
  583. Highcharts.wrap(Highcharts.Axis.prototype, 'render', function (proceed) {
  584. proceed.apply(this, [].slice.call(arguments, 1));
  585. // Do not do this if the chart is not 3D
  586. if (!this.chart.is3d()) {
  587. return;
  588. }
  589. var chart = this.chart,
  590. renderer = chart.renderer,
  591. options3d = chart.options.chart.options3d,
  592. frame = options3d.frame,
  593. fbottom = frame.bottom,
  594. fback = frame.back,
  595. fside = frame.side,
  596. depth = options3d.depth,
  597. height = this.height,
  598. width = this.width,
  599. left = this.left,
  600. top = this.top;
  601. if (this.isZAxis) {
  602. return;
  603. } else if (this.horiz) {
  604. var bottomShape = {
  605. x: left,
  606. y: top + (chart.xAxis[0].opposite ? -fbottom.size : height),
  607. z: 0,
  608. width: width,
  609. height: fbottom.size,
  610. depth: depth,
  611. insidePlotArea: false
  612. };
  613. if (!this.bottomFrame) {
  614. this.bottomFrame = renderer.cuboid(bottomShape).attr({
  615. fill: fbottom.color,
  616. zIndex: (chart.yAxis[0].reversed && options3d.alpha > 0 ? 4 : -1)
  617. })
  618. .css({
  619. stroke: fbottom.color
  620. }).add();
  621. } else {
  622. this.bottomFrame.animate(bottomShape);
  623. }
  624. } else {
  625. // BACK
  626. var backShape = {
  627. x: left + (chart.yAxis[0].opposite ? 0 : -fside.size),
  628. y: top + (chart.xAxis[0].opposite ? -fbottom.size : 0),
  629. z: depth,
  630. width: width + fside.size,
  631. height: height + fbottom.size,
  632. depth: fback.size,
  633. insidePlotArea: false
  634. };
  635. if (!this.backFrame) {
  636. this.backFrame = renderer.cuboid(backShape).attr({
  637. fill: fback.color,
  638. zIndex: -3
  639. }).css({
  640. stroke: fback.color
  641. }).add();
  642. } else {
  643. this.backFrame.animate(backShape);
  644. }
  645. var sideShape = {
  646. x: left + (chart.yAxis[0].opposite ? width : -fside.size),
  647. y: top + (chart.xAxis[0].opposite ? -fbottom.size : 0),
  648. z: 0,
  649. width: fside.size,
  650. height: height + fbottom.size,
  651. depth: depth,
  652. insidePlotArea: false
  653. };
  654. if (!this.sideFrame) {
  655. this.sideFrame = renderer.cuboid(sideShape).attr({
  656. fill: fside.color,
  657. zIndex: -2
  658. }).css({
  659. stroke: fside.color
  660. }).add();
  661. } else {
  662. this.sideFrame.animate(sideShape);
  663. }
  664. }
  665. });
  666. Highcharts.wrap(Highcharts.Axis.prototype, 'getPlotLinePath', function (proceed) {
  667. var path = proceed.apply(this, [].slice.call(arguments, 1));
  668. // Do not do this if the chart is not 3D
  669. if (!this.chart.is3d()) {
  670. return path;
  671. }
  672. if (path === null) { return path; }
  673. var chart = this.chart,
  674. options3d = chart.options.chart.options3d;
  675. var d = this.isZAxis ? this.chart.plotWidth : options3d.depth,
  676. opposite = this.opposite;
  677. if (this.horiz) {
  678. opposite = !opposite;
  679. }
  680. var pArr = [
  681. this.swapZ({ x: path[1], y: path[2], z: (opposite ? d : 0)}),
  682. this.swapZ({ x: path[1], y: path[2], z: d }),
  683. this.swapZ({ x: path[4], y: path[5], z: d }),
  684. this.swapZ({ x: path[4], y: path[5], z: (opposite ? 0 : d)})
  685. ];
  686. pArr = perspective(pArr, this.chart, false);
  687. path = this.chart.renderer.toLinePath(pArr, false);
  688. return path;
  689. });
  690. // Do not draw axislines in 3D
  691. Highcharts.wrap(Highcharts.Axis.prototype, 'getLinePath', function (proceed) {
  692. return this.chart.is3d() ? [] : proceed.apply(this, [].slice.call(arguments, 1));
  693. });
  694. Highcharts.wrap(Highcharts.Axis.prototype, 'getPlotBandPath', function (proceed) {
  695. // Do not do this if the chart is not 3D
  696. if (!this.chart.is3d()) {
  697. return proceed.apply(this, [].slice.call(arguments, 1));
  698. } else {
  699. var args = arguments,
  700. from = args[1],
  701. to = args[2];
  702. var toPath = this.getPlotLinePath(to),
  703. path = this.getPlotLinePath(from);
  704. if (path && toPath) {
  705. path.push(
  706. 'L',
  707. toPath[10], // These two do not exist in the regular getPlotLine
  708. toPath[11], // ---- # 3005
  709. 'L',
  710. toPath[7],
  711. toPath[8],
  712. 'L',
  713. toPath[4],
  714. toPath[5],
  715. 'L',
  716. toPath[1],
  717. toPath[2]
  718. );
  719. } else { // outside the axis area
  720. path = null;
  721. }
  722. return path;
  723. }
  724. });
  725. /***
  726. EXTENSION TO THE TICKS
  727. ***/
  728. Highcharts.wrap(Highcharts.Tick.prototype, 'getMarkPath', function (proceed) {
  729. var path = proceed.apply(this, [].slice.call(arguments, 1));
  730. // Do not do this if the chart is not 3D
  731. if (!this.axis.chart.is3d()) {
  732. return path;
  733. }
  734. var pArr = [
  735. this.axis.swapZ({x: path[1], y: path[2], z: 0}),
  736. this.axis.swapZ({x: path[4], y: path[5], z: 0})
  737. ];
  738. pArr = perspective(pArr, this.axis.chart, false);
  739. path = [
  740. 'M', pArr[0].x, pArr[0].y,
  741. 'L', pArr[1].x, pArr[1].y
  742. ];
  743. return path;
  744. });
  745. Highcharts.wrap(Highcharts.Tick.prototype, 'getLabelPosition', function (proceed) {
  746. var pos = proceed.apply(this, [].slice.call(arguments, 1));
  747. // Do not do this if the chart is not 3D
  748. if (!this.axis.chart.is3d()) {
  749. return pos;
  750. }
  751. var new_pos = perspective([this.axis.swapZ({x: pos.x, y: pos.y, z: 0})], this.axis.chart, false)[0];
  752. new_pos.x = new_pos.x - (!this.axis.horiz && this.axis.opposite ? this.axis.transA : 0); //#3788
  753. new_pos.old = pos;
  754. return new_pos;
  755. });
  756. Highcharts.wrap(Highcharts.Tick.prototype, 'handleOverflow', function (proceed, xy) {
  757. if (this.axis.chart.is3d()) {
  758. xy = xy.old;
  759. }
  760. return proceed.call(this, xy);
  761. });
  762. Highcharts.wrap(Highcharts.Axis.prototype, 'getTitlePosition', function (proceed) {
  763. var pos = proceed.apply(this, [].slice.call(arguments, 1));
  764. // Do not do this if the chart is not 3D
  765. if (!this.chart.is3d()) {
  766. return pos;
  767. }
  768. pos = perspective([this.swapZ({x: pos.x, y: pos.y, z: 0})], this.chart, false)[0];
  769. return pos;
  770. });
  771. Highcharts.wrap(Highcharts.Axis.prototype, 'drawCrosshair', function (proceed) {
  772. var args = arguments;
  773. if (this.chart.is3d()) {
  774. if (args[2]) {
  775. args[2] = {
  776. plotX: args[2].plotXold || args[2].plotX,
  777. plotY: args[2].plotYold || args[2].plotY
  778. };
  779. }
  780. }
  781. proceed.apply(this, [].slice.call(args, 1));
  782. });
  783. /***
  784. Z-AXIS
  785. ***/
  786. Highcharts.Axis.prototype.swapZ = function (p, insidePlotArea) {
  787. if (this.isZAxis) {
  788. var plotLeft = insidePlotArea ? 0 : this.chart.plotLeft;
  789. var chart = this.chart;
  790. return {
  791. x: plotLeft + (chart.yAxis[0].opposite ? p.z : chart.xAxis[0].width - p.z),
  792. y: p.y,
  793. z: p.x - plotLeft
  794. };
  795. } else {
  796. return p;
  797. }
  798. };
  799. var ZAxis = Highcharts.ZAxis = function () {
  800. this.isZAxis = true;
  801. this.init.apply(this, arguments);
  802. };
  803. Highcharts.extend(ZAxis.prototype, Highcharts.Axis.prototype);
  804. Highcharts.extend(ZAxis.prototype, {
  805. setOptions: function (userOptions) {
  806. userOptions = Highcharts.merge({
  807. offset: 0,
  808. lineWidth: 0
  809. }, userOptions);
  810. Highcharts.Axis.prototype.setOptions.call(this, userOptions);
  811. this.coll = 'zAxis';
  812. },
  813. setAxisSize: function () {
  814. Highcharts.Axis.prototype.setAxisSize.call(this);
  815. this.width = this.len = this.chart.options.chart.options3d.depth;
  816. this.right = this.chart.chartWidth - this.width - this.left;
  817. },
  818. getSeriesExtremes: function () {
  819. var axis = this,
  820. chart = axis.chart;
  821. axis.hasVisibleSeries = false;
  822. // Reset properties in case we're redrawing (#3353)
  823. axis.dataMin = axis.dataMax = axis.ignoreMinPadding = axis.ignoreMaxPadding = null;
  824. if (axis.buildStacks) {
  825. axis.buildStacks();
  826. }
  827. // loop through this axis' series
  828. Highcharts.each(axis.series, function (series) {
  829. if (series.visible || !chart.options.chart.ignoreHiddenSeries) {
  830. var seriesOptions = series.options,
  831. zData,
  832. threshold = seriesOptions.threshold;
  833. axis.hasVisibleSeries = true;
  834. // Validate threshold in logarithmic axes
  835. if (axis.isLog && threshold <= 0) {
  836. threshold = null;
  837. }
  838. zData = series.zData;
  839. if (zData.length) {
  840. axis.dataMin = Math.min(pick(axis.dataMin, zData[0]), Math.min.apply(null, zData));
  841. axis.dataMax = Math.max(pick(axis.dataMax, zData[0]), Math.max.apply(null, zData));
  842. }
  843. }
  844. });
  845. }
  846. });
  847. /**
  848. * Extend the chart getAxes method to also get the color axis
  849. */
  850. Highcharts.wrap(Highcharts.Chart.prototype, 'getAxes', function (proceed) {
  851. var chart = this,
  852. options = this.options,
  853. zAxisOptions = options.zAxis = Highcharts.splat(options.zAxis || {});
  854. proceed.call(this);
  855. if (!chart.is3d()) {
  856. return;
  857. }
  858. this.zAxis = [];
  859. Highcharts.each(zAxisOptions, function (axisOptions, i) {
  860. axisOptions.index = i;
  861. axisOptions.isX = true; //Z-Axis is shown horizontally, so it's kind of a X-Axis
  862. var zAxis = new ZAxis(chart, axisOptions);
  863. zAxis.setScale();
  864. });
  865. });
  866. /***
  867. EXTENSION FOR 3D COLUMNS
  868. ***/
  869. Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'translate', function (proceed) {
  870. proceed.apply(this, [].slice.call(arguments, 1));
  871. // Do not do this if the chart is not 3D
  872. if (!this.chart.is3d()) {
  873. return;
  874. }
  875. var series = this,
  876. chart = series.chart,
  877. seriesOptions = series.options,
  878. depth = seriesOptions.depth || 25;
  879. var stack = seriesOptions.stacking ? (seriesOptions.stack || 0) : series._i;
  880. var z = stack * (depth + (seriesOptions.groupZPadding || 1));
  881. if (seriesOptions.grouping !== false) { z = 0; }
  882. z += (seriesOptions.groupZPadding || 1);
  883. Highcharts.each(series.data, function (point) {
  884. if (point.y !== null) {
  885. var shapeArgs = point.shapeArgs,
  886. tooltipPos = point.tooltipPos;
  887. point.shapeType = 'cuboid';
  888. shapeArgs.z = z;
  889. shapeArgs.depth = depth;
  890. shapeArgs.insidePlotArea = true;
  891. // Translate the tooltip position in 3d space
  892. tooltipPos = perspective([{ x: tooltipPos[0], y: tooltipPos[1], z: z }], chart, false)[0];
  893. point.tooltipPos = [tooltipPos.x, tooltipPos.y];
  894. }
  895. });
  896. // store for later use #4067
  897. series.z = z;
  898. });
  899. Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'animate', function (proceed) {
  900. if (!this.chart.is3d()) {
  901. proceed.apply(this, [].slice.call(arguments, 1));
  902. } else {
  903. var args = arguments,
  904. init = args[1],
  905. yAxis = this.yAxis,
  906. series = this,
  907. reversed = this.yAxis.reversed;
  908. if (Highcharts.svg) { // VML is too slow anyway
  909. if (init) {
  910. Highcharts.each(series.data, function (point) {
  911. if (point.y !== null) {
  912. point.height = point.shapeArgs.height;
  913. point.shapey = point.shapeArgs.y; //#2968
  914. point.shapeArgs.height = 1;
  915. if (!reversed) {
  916. if (point.stackY) {
  917. point.shapeArgs.y = point.plotY + yAxis.translate(point.stackY);
  918. } else {
  919. point.shapeArgs.y = point.plotY + (point.negative ? -point.height : point.height);
  920. }
  921. }
  922. }
  923. });
  924. } else { // run the animation
  925. Highcharts.each(series.data, function (point) {
  926. if (point.y !== null) {
  927. point.shapeArgs.height = point.height;
  928. point.shapeArgs.y = point.shapey; //#2968
  929. // null value do not have a graphic
  930. if (point.graphic) {
  931. point.graphic.animate(point.shapeArgs, series.options.animation);
  932. }
  933. }
  934. });
  935. // redraw datalabels to the correct position
  936. this.drawDataLabels();
  937. // delete this function to allow it only once
  938. series.animate = null;
  939. }
  940. }
  941. }
  942. });
  943. Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'init', function (proceed) {
  944. proceed.apply(this, [].slice.call(arguments, 1));
  945. if (this.chart.is3d()) {
  946. var seriesOptions = this.options,
  947. grouping = seriesOptions.grouping,
  948. stacking = seriesOptions.stacking,
  949. z = 0;
  950. if (!(grouping !== undefined && !grouping)) {
  951. var stacks = this.chart.retrieveStacks(stacking),
  952. stack = seriesOptions.stack || 0,
  953. i; // position within the stack
  954. for (i = 0; i < stacks[stack].series.length; i++) {
  955. if (stacks[stack].series[i] === this) {
  956. break;
  957. }
  958. }
  959. z = (stacks.totalStacks * 10) - (10 * (stacks.totalStacks - stacks[stack].position)) - i;
  960. }
  961. seriesOptions.zIndex = z;
  962. }
  963. });
  964. function draw3DPoints(proceed) {
  965. // Do not do this if the chart is not 3D
  966. if (this.chart.is3d()) {
  967. var grouping = this.chart.options.plotOptions.column.grouping;
  968. if (grouping !== undefined && !grouping && this.group.zIndex !== undefined && !this.zIndexSet) {
  969. this.group.attr({zIndex : (this.group.zIndex * 10)});
  970. this.zIndexSet = true; // #4062 set zindex only once
  971. }
  972. var options = this.options,
  973. states = this.options.states;
  974. this.borderWidth = options.borderWidth = defined(options.edgeWidth) ? options.edgeWidth : 1; //#4055
  975. Highcharts.each(this.data, function (point) {
  976. if (point.y !== null) {
  977. var pointAttr = point.pointAttr;
  978. // Set the border color to the fill color to provide a smooth edge
  979. this.borderColor = Highcharts.pick(options.edgeColor, pointAttr[''].fill);
  980. pointAttr[''].stroke = this.borderColor;
  981. pointAttr.hover.stroke = Highcharts.pick(states.hover.edgeColor, this.borderColor);
  982. pointAttr.select.stroke = Highcharts.pick(states.select.edgeColor, this.borderColor);
  983. }
  984. });
  985. }
  986. proceed.apply(this, [].slice.call(arguments, 1));
  987. }
  988. Highcharts.wrap(Highcharts.Series.prototype, 'alignDataLabel', function (proceed) {
  989. // Only do this for 3D columns and columnranges
  990. if (this.chart.is3d() && (this.type === 'column' || this.type === 'columnrange')) {
  991. var series = this,
  992. chart = series.chart;
  993. var args = arguments,
  994. alignTo = args[4];
  995. var pos = ({x: alignTo.x, y: alignTo.y, z: series.z});
  996. pos = perspective([pos], chart, true)[0];
  997. alignTo.x = pos.x;
  998. alignTo.y = pos.y;
  999. }
  1000. proceed.apply(this, [].slice.call(arguments, 1));
  1001. });
  1002. if (Highcharts.seriesTypes.columnrange) {
  1003. Highcharts.wrap(Highcharts.seriesTypes.columnrange.prototype, 'drawPoints', draw3DPoints);
  1004. }
  1005. Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'drawPoints', draw3DPoints);
  1006. /***
  1007. EXTENSION FOR 3D CYLINDRICAL COLUMNS
  1008. Not supported
  1009. ***/
  1010. /*
  1011. var defaultOptions = Highcharts.getOptions();
  1012. defaultOptions.plotOptions.cylinder = Highcharts.merge(defaultOptions.plotOptions.column);
  1013. var CylinderSeries = Highcharts.extendClass(Highcharts.seriesTypes.column, {
  1014. type: 'cylinder'
  1015. });
  1016. Highcharts.seriesTypes.cylinder = CylinderSeries;
  1017. Highcharts.wrap(Highcharts.seriesTypes.cylinder.prototype, 'translate', function (proceed) {
  1018. proceed.apply(this, [].slice.call(arguments, 1));
  1019. // Do not do this if the chart is not 3D
  1020. if (!this.chart.is3d()) {
  1021. return;
  1022. }
  1023. var series = this,
  1024. chart = series.chart,
  1025. options = chart.options,
  1026. cylOptions = options.plotOptions.cylinder,
  1027. options3d = options.chart.options3d,
  1028. depth = cylOptions.depth || 0,
  1029. origin = {
  1030. x: chart.inverted ? chart.plotHeight / 2 : chart.plotWidth / 2,
  1031. y: chart.inverted ? chart.plotWidth / 2 : chart.plotHeight / 2,
  1032. z: options3d.depth,
  1033. vd: options3d.viewDistance
  1034. },
  1035. alpha = options3d.alpha;
  1036. var z = cylOptions.stacking ? (this.options.stack || 0) * depth : series._i * depth;
  1037. z += depth / 2;
  1038. if (cylOptions.grouping !== false) { z = 0; }
  1039. Highcharts.each(series.data, function (point) {
  1040. var shapeArgs = point.shapeArgs;
  1041. point.shapeType = 'arc3d';
  1042. shapeArgs.x += depth / 2;
  1043. shapeArgs.z = z;
  1044. shapeArgs.start = 0;
  1045. shapeArgs.end = 2 * PI;
  1046. shapeArgs.r = depth * 0.95;
  1047. shapeArgs.innerR = 0;
  1048. shapeArgs.depth = shapeArgs.height * (1 / sin((90 - alpha) * deg2rad)) - z;
  1049. shapeArgs.alpha = 90 - alpha;
  1050. shapeArgs.beta = 0;
  1051. shapeArgs.origin = origin;
  1052. });
  1053. });
  1054. *//***
  1055. EXTENSION FOR 3D PIES
  1056. ***/
  1057. Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'translate', function (proceed) {
  1058. proceed.apply(this, [].slice.call(arguments, 1));
  1059. // Do not do this if the chart is not 3D
  1060. if (!this.chart.is3d()) {
  1061. return;
  1062. }
  1063. var series = this,
  1064. chart = series.chart,
  1065. options = chart.options,
  1066. seriesOptions = series.options,
  1067. depth = seriesOptions.depth || 0,
  1068. options3d = options.chart.options3d,
  1069. origin = {
  1070. x: chart.plotWidth / 2,
  1071. y: chart.plotHeight / 2,
  1072. z: options3d.depth
  1073. },
  1074. alpha = options3d.alpha,
  1075. beta = options3d.beta,
  1076. z = seriesOptions.stacking ? (seriesOptions.stack || 0) * depth : series._i * depth;
  1077. z += depth / 2;
  1078. if (seriesOptions.grouping !== false) { z = 0; }
  1079. Highcharts.each(series.data, function (point) {
  1080. var shapeArgs = point.shapeArgs,
  1081. angle;
  1082. point.shapeType = 'arc3d';
  1083. shapeArgs.z = z;
  1084. shapeArgs.depth = depth * 0.75;
  1085. shapeArgs.origin = origin;
  1086. shapeArgs.alpha = alpha;
  1087. shapeArgs.beta = beta;
  1088. shapeArgs.center = series.center;
  1089. angle = (shapeArgs.end + shapeArgs.start) / 2;
  1090. point.slicedTranslation = {
  1091. translateX : round(cos(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad)),
  1092. translateY : round(sin(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad))
  1093. };
  1094. });
  1095. });
  1096. Highcharts.wrap(Highcharts.seriesTypes.pie.prototype.pointClass.prototype, 'haloPath', function (proceed) {
  1097. var args = arguments;
  1098. return this.series.chart.is3d() ? [] : proceed.call(this, args[1]);
  1099. });
  1100. Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'drawPoints', function (proceed) {
  1101. var seriesGroup = this.group,
  1102. options = this.options,
  1103. states = options.states;
  1104. // Do not do this if the chart is not 3D
  1105. if (this.chart.is3d()) {
  1106. // Set the border color to the fill color to provide a smooth edge
  1107. this.borderWidth = options.borderWidth = options.edgeWidth || 1;
  1108. this.borderColor = options.edgeColor = Highcharts.pick(options.edgeColor, options.borderColor, undefined);
  1109. states.hover.borderColor = Highcharts.pick(states.hover.edgeColor, this.borderColor);
  1110. states.hover.borderWidth = Highcharts.pick(states.hover.edgeWidth, this.borderWidth);
  1111. states.select.borderColor = Highcharts.pick(states.select.edgeColor, this.borderColor);
  1112. states.select.borderWidth = Highcharts.pick(states.select.edgeWidth, this.borderWidth);
  1113. Highcharts.each(this.data, function (point) {
  1114. var pointAttr = point.pointAttr;
  1115. pointAttr[''].stroke = point.series.borderColor || point.color;
  1116. pointAttr['']['stroke-width'] = point.series.borderWidth;
  1117. pointAttr.hover.stroke = states.hover.borderColor;
  1118. pointAttr.hover['stroke-width'] = states.hover.borderWidth;
  1119. pointAttr.select.stroke = states.select.borderColor;
  1120. pointAttr.select['stroke-width'] = states.select.borderWidth;
  1121. });
  1122. }
  1123. proceed.apply(this, [].slice.call(arguments, 1));
  1124. if (this.chart.is3d()) {
  1125. Highcharts.each(this.points, function (point) {
  1126. var graphic = point.graphic;
  1127. graphic.out.add(seriesGroup);
  1128. graphic.inn.add(seriesGroup);
  1129. graphic.side1.add(seriesGroup);
  1130. graphic.side2.add(seriesGroup);
  1131. // Hide null or 0 points (#3006, 3650)
  1132. graphic[point.y ? 'show' : 'hide']();
  1133. });
  1134. }
  1135. });
  1136. Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'drawDataLabels', function (proceed) {
  1137. if (this.chart.is3d()) {
  1138. var series = this;
  1139. Highcharts.each(series.data, function (point) {
  1140. var shapeArgs = point.shapeArgs,
  1141. r = shapeArgs.r,
  1142. d = shapeArgs.depth,
  1143. a1 = (shapeArgs.alpha || series.chart.options.chart.options3d.alpha) * deg2rad, //#3240 issue with datalabels for 0 and null values
  1144. a2 = (shapeArgs.start + shapeArgs.end) / 2,
  1145. labelPos = point.labelPos;
  1146. labelPos[1] += (-r * (1 - cos(a1)) * sin(a2)) + (sin(a2) > 0 ? sin(a1) * d : 0);
  1147. labelPos[3] += (-r * (1 - cos(a1)) * sin(a2)) + (sin(a2) > 0 ? sin(a1) * d : 0);
  1148. labelPos[5] += (-r * (1 - cos(a1)) * sin(a2)) + (sin(a2) > 0 ? sin(a1) * d : 0);
  1149. });
  1150. }
  1151. proceed.apply(this, [].slice.call(arguments, 1));
  1152. });
  1153. Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'addPoint', function (proceed) {
  1154. proceed.apply(this, [].slice.call(arguments, 1));
  1155. if (this.chart.is3d()) {
  1156. // destroy (and rebuild) everything!!!
  1157. this.update(this.userOptions, true); // #3845 pass the old options
  1158. }
  1159. });
  1160. Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'animate', function (proceed) {
  1161. if (!this.chart.is3d()) {
  1162. proceed.apply(this, [].slice.call(arguments, 1));
  1163. } else {
  1164. var args = arguments,
  1165. init = args[1],
  1166. animation = this.options.animation,
  1167. attribs,
  1168. center = this.center,
  1169. group = this.group,
  1170. markerGroup = this.markerGroup;
  1171. if (Highcharts.svg) { // VML is too slow anyway
  1172. if (animation === true) {
  1173. animation = {};
  1174. }
  1175. // Initialize the animation
  1176. if (init) {
  1177. // Scale down the group and place it in the center
  1178. group.oldtranslateX = group.translateX;
  1179. group.oldtranslateY = group.translateY;
  1180. attribs = {
  1181. translateX: center[0],
  1182. translateY: center[1],
  1183. scaleX: 0.001, // #1499
  1184. scaleY: 0.001
  1185. };
  1186. group.attr(attribs);
  1187. if (markerGroup) {
  1188. markerGroup.attrSetters = group.attrSetters;
  1189. markerGroup.attr(attribs);
  1190. }
  1191. // Run the animation
  1192. } else {
  1193. attribs = {
  1194. translateX: group.oldtranslateX,
  1195. translateY: group.oldtranslateY,
  1196. scaleX: 1,
  1197. scaleY: 1
  1198. };
  1199. group.animate(attribs, animation);
  1200. if (markerGroup) {
  1201. markerGroup.animate(attribs, animation);
  1202. }
  1203. // Delete this function to allow it only once
  1204. this.animate = null;
  1205. }
  1206. }
  1207. }
  1208. });/***
  1209. EXTENSION FOR 3D SCATTER CHART
  1210. ***/
  1211. Highcharts.wrap(Highcharts.seriesTypes.scatter.prototype, 'translate', function (proceed) {
  1212. //function translate3d(proceed) {
  1213. proceed.apply(this, [].slice.call(arguments, 1));
  1214. if (!this.chart.is3d()) {
  1215. return;
  1216. }
  1217. var series = this,
  1218. chart = series.chart,
  1219. zAxis = Highcharts.pick(series.zAxis, chart.options.zAxis[0]);
  1220. var raw_points = [],
  1221. raw_point,
  1222. projected_points,
  1223. projected_point,
  1224. i;
  1225. for (i = 0; i < series.data.length; i++) {
  1226. raw_point = series.data[i];
  1227. raw_point.isInside = raw_point.isInside ? (raw_point.z >= zAxis.min && raw_point.z <= zAxis.max) : false;
  1228. raw_points.push({
  1229. x: raw_point.plotX,
  1230. y: raw_point.plotY,
  1231. z: zAxis.translate(raw_point.z)
  1232. });
  1233. }
  1234. projected_points = perspective(raw_points, chart, true);
  1235. for (i = 0; i < series.data.length; i++) {
  1236. raw_point = series.data[i];
  1237. projected_point = projected_points[i];
  1238. raw_point.plotXold = raw_point.plotX;
  1239. raw_point.plotYold = raw_point.plotY;
  1240. raw_point.plotX = projected_point.x;
  1241. raw_point.plotY = projected_point.y;
  1242. raw_point.plotZ = projected_point.z;
  1243. }
  1244. });
  1245. Highcharts.wrap(Highcharts.seriesTypes.scatter.prototype, 'init', function (proceed, chart, options) {
  1246. if (chart.is3d()) {
  1247. // add a third coordinate
  1248. this.axisTypes = ['xAxis', 'yAxis', 'zAxis'];
  1249. this.pointArrayMap = ['x', 'y', 'z'];
  1250. this.parallelArrays = ['x', 'y', 'z'];
  1251. }
  1252. var result = proceed.apply(this, [chart, options]);
  1253. if (this.chart.is3d()) {
  1254. // Set a new default tooltip formatter
  1255. var default3dScatterTooltip = 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>z: <b>{point.z}</b><br/>';
  1256. if (this.userOptions.tooltip) {
  1257. this.tooltipOptions.pointFormat = this.userOptions.tooltip.pointFormat || default3dScatterTooltip;
  1258. } else {
  1259. this.tooltipOptions.pointFormat = default3dScatterTooltip;
  1260. }
  1261. }
  1262. return result;
  1263. });
  1264. /**
  1265. * Extension to the VML Renderer
  1266. */
  1267. if (Highcharts.VMLRenderer) {
  1268. Highcharts.setOptions({animate: false});
  1269. Highcharts.VMLRenderer.prototype.cuboid = Highcharts.SVGRenderer.prototype.cuboid;
  1270. Highcharts.VMLRenderer.prototype.cuboidPath = Highcharts.SVGRenderer.prototype.cuboidPath;
  1271. Highcharts.VMLRenderer.prototype.toLinePath = Highcharts.SVGRenderer.prototype.toLinePath;
  1272. Highcharts.VMLRenderer.prototype.createElement3D = Highcharts.SVGRenderer.prototype.createElement3D;
  1273. Highcharts.VMLRenderer.prototype.arc3d = function (shapeArgs) {
  1274. var result = Highcharts.SVGRenderer.prototype.arc3d.call(this, shapeArgs);
  1275. result.css({zIndex: result.zIndex});
  1276. return result;
  1277. };
  1278. Highcharts.VMLRenderer.prototype.arc3dPath = Highcharts.SVGRenderer.prototype.arc3dPath;
  1279. Highcharts.wrap(Highcharts.Axis.prototype, 'render', function (proceed) {
  1280. proceed.apply(this, [].slice.call(arguments, 1));
  1281. // VML doesn't support a negative z-index
  1282. if (this.sideFrame) {
  1283. this.sideFrame.css({zIndex: 0});
  1284. this.sideFrame.front.attr({fill: this.sideFrame.color});
  1285. }
  1286. if (this.bottomFrame) {
  1287. this.bottomFrame.css({zIndex: 1});
  1288. this.bottomFrame.front.attr({fill: this.bottomFrame.color});
  1289. }
  1290. if (this.backFrame) {
  1291. this.backFrame.css({zIndex: 0});
  1292. this.backFrame.front.attr({fill: this.backFrame.color});
  1293. }
  1294. });
  1295. }
  1296. }(Highcharts));