TreemapSeries.js 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  1. /* *
  2. *
  3. * (c) 2014-2021 Highsoft AS
  4. *
  5. * Authors: Jon Arild Nygard / Oystein Moseng
  6. *
  7. * License: www.highcharts.com/license
  8. *
  9. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  10. *
  11. * */
  12. 'use strict';
  13. var __extends = (this && this.__extends) || (function () {
  14. var extendStatics = function (d, b) {
  15. extendStatics = Object.setPrototypeOf ||
  16. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  17. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  18. return extendStatics(d, b);
  19. };
  20. return function (d, b) {
  21. extendStatics(d, b);
  22. function __() { this.constructor = d; }
  23. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  24. };
  25. })();
  26. import Color from '../../Core/Color/Color.js';
  27. var color = Color.parse;
  28. import ColorMapMixin from '../../Mixins/ColorMapSeries.js';
  29. var colorMapSeriesMixin = ColorMapMixin.colorMapSeriesMixin;
  30. import H from '../../Core/Globals.js';
  31. var noop = H.noop;
  32. import LegendSymbolMixin from '../../Mixins/LegendSymbol.js';
  33. import palette from '../../Core/Color/Palette.js';
  34. import SeriesRegistry from '../../Core/Series/SeriesRegistry.js';
  35. var Series = SeriesRegistry.series, _a = SeriesRegistry.seriesTypes, ColumnSeries = _a.column, HeatmapSeries = _a.heatmap, ScatterSeries = _a.scatter;
  36. import TreemapAlgorithmGroup from './TreemapAlgorithmGroup.js';
  37. import TreemapPoint from './TreemapPoint.js';
  38. import TreemapUtilities from './TreemapUtilities.js';
  39. import TreeSeriesMixin from '../../Mixins/TreeSeries.js';
  40. var getColor = TreeSeriesMixin.getColor, getLevelOptions = TreeSeriesMixin.getLevelOptions, updateRootId = TreeSeriesMixin.updateRootId;
  41. import U from '../../Core/Utilities.js';
  42. var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, error = U.error, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isObject = U.isObject, isString = U.isString, merge = U.merge, pick = U.pick, stableSort = U.stableSort;
  43. import './TreemapComposition.js';
  44. /* *
  45. *
  46. * Class
  47. *
  48. * */
  49. /**
  50. * @private
  51. * @class
  52. * @name Highcharts.seriesTypes.treemap
  53. *
  54. * @augments Highcharts.Series
  55. */
  56. var TreemapSeries = /** @class */ (function (_super) {
  57. __extends(TreemapSeries, _super);
  58. function TreemapSeries() {
  59. /* *
  60. *
  61. * Static Properties
  62. *
  63. * */
  64. var _this = _super !== null && _super.apply(this, arguments) || this;
  65. /* *
  66. *
  67. * Properties
  68. *
  69. * */
  70. _this.axisRatio = void 0;
  71. _this.data = void 0;
  72. _this.mapOptionsToLevel = void 0;
  73. _this.nodeMap = void 0;
  74. _this.options = void 0;
  75. _this.points = void 0;
  76. _this.rootNode = void 0;
  77. _this.tree = void 0;
  78. return _this;
  79. /* eslint-enable valid-jsdoc */
  80. }
  81. /* *
  82. *
  83. * Function
  84. *
  85. * */
  86. /* eslint-disable valid-jsdoc */
  87. TreemapSeries.prototype.algorithmCalcPoints = function (directionChange, last, group, childrenArea) {
  88. var pX, pY, pW, pH, gW = group.lW, gH = group.lH, plot = group.plot, keep, i = 0, end = group.elArr.length - 1;
  89. if (last) {
  90. gW = group.nW;
  91. gH = group.nH;
  92. }
  93. else {
  94. keep = group.elArr[group.elArr.length - 1];
  95. }
  96. group.elArr.forEach(function (p) {
  97. if (last || (i < end)) {
  98. if (group.direction === 0) {
  99. pX = plot.x;
  100. pY = plot.y;
  101. pW = gW;
  102. pH = p / pW;
  103. }
  104. else {
  105. pX = plot.x;
  106. pY = plot.y;
  107. pH = gH;
  108. pW = p / pH;
  109. }
  110. childrenArea.push({
  111. x: pX,
  112. y: pY,
  113. width: pW,
  114. height: correctFloat(pH)
  115. });
  116. if (group.direction === 0) {
  117. plot.y = plot.y + pH;
  118. }
  119. else {
  120. plot.x = plot.x + pW;
  121. }
  122. }
  123. i = i + 1;
  124. });
  125. // Reset variables
  126. group.reset();
  127. if (group.direction === 0) {
  128. group.width = group.width - gW;
  129. }
  130. else {
  131. group.height = group.height - gH;
  132. }
  133. plot.y = plot.parent.y + (plot.parent.height - group.height);
  134. plot.x = plot.parent.x + (plot.parent.width - group.width);
  135. if (directionChange) {
  136. group.direction = 1 - group.direction;
  137. }
  138. // If not last, then add uncalculated element
  139. if (!last) {
  140. group.addElement(keep);
  141. }
  142. };
  143. TreemapSeries.prototype.algorithmFill = function (directionChange, parent, children) {
  144. var childrenArea = [], pTot, direction = parent.direction, x = parent.x, y = parent.y, width = parent.width, height = parent.height, pX, pY, pW, pH;
  145. children.forEach(function (child) {
  146. pTot =
  147. (parent.width * parent.height) * (child.val / parent.val);
  148. pX = x;
  149. pY = y;
  150. if (direction === 0) {
  151. pH = height;
  152. pW = pTot / pH;
  153. width = width - pW;
  154. x = x + pW;
  155. }
  156. else {
  157. pW = width;
  158. pH = pTot / pW;
  159. height = height - pH;
  160. y = y + pH;
  161. }
  162. childrenArea.push({
  163. x: pX,
  164. y: pY,
  165. width: pW,
  166. height: pH
  167. });
  168. if (directionChange) {
  169. direction = 1 - direction;
  170. }
  171. });
  172. return childrenArea;
  173. };
  174. TreemapSeries.prototype.algorithmLowAspectRatio = function (directionChange, parent, children) {
  175. var childrenArea = [], series = this, pTot, plot = {
  176. x: parent.x,
  177. y: parent.y,
  178. parent: parent
  179. }, direction = parent.direction, i = 0, end = children.length - 1, group = new TreemapAlgorithmGroup(parent.height, parent.width, direction, plot);
  180. // Loop through and calculate all areas
  181. children.forEach(function (child) {
  182. pTot =
  183. (parent.width * parent.height) * (child.val / parent.val);
  184. group.addElement(pTot);
  185. if (group.lP.nR > group.lP.lR) {
  186. series.algorithmCalcPoints(directionChange, false, group, childrenArea, plot // @todo no supported
  187. );
  188. }
  189. // If last child, then calculate all remaining areas
  190. if (i === end) {
  191. series.algorithmCalcPoints(directionChange, true, group, childrenArea, plot // @todo not supported
  192. );
  193. }
  194. i = i + 1;
  195. });
  196. return childrenArea;
  197. };
  198. /**
  199. * Over the alignment method by setting z index.
  200. * @private
  201. */
  202. TreemapSeries.prototype.alignDataLabel = function (point, dataLabel, labelOptions) {
  203. var style = labelOptions.style;
  204. // #8160: Prevent the label from exceeding the point's
  205. // boundaries in treemaps by applying ellipsis overflow.
  206. // The issue was happening when datalabel's text contained a
  207. // long sequence of characters without a whitespace.
  208. if (style &&
  209. !defined(style.textOverflow) &&
  210. dataLabel.text &&
  211. dataLabel.getBBox().width > dataLabel.text.textWidth) {
  212. dataLabel.css({
  213. textOverflow: 'ellipsis',
  214. // unit (px) is required when useHTML is true
  215. width: style.width += 'px'
  216. });
  217. }
  218. ColumnSeries.prototype.alignDataLabel.apply(this, arguments);
  219. if (point.dataLabel) {
  220. // point.node.zIndex could be undefined (#6956)
  221. point.dataLabel.attr({ zIndex: (point.node.zIndex || 0) + 1 });
  222. }
  223. };
  224. TreemapSeries.prototype.buildNode = function (id, i, level, list, parent) {
  225. var series = this, children = [], point = series.points[i], height = 0, node, child;
  226. // Actions
  227. ((list[id] || [])).forEach(function (i) {
  228. child = series.buildNode(series.points[i].id, i, (level + 1), list, id);
  229. height = Math.max(child.height + 1, height);
  230. children.push(child);
  231. });
  232. node = {
  233. id: id,
  234. i: i,
  235. children: children,
  236. height: height,
  237. level: level,
  238. parent: parent,
  239. visible: false // @todo move this to better location
  240. };
  241. series.nodeMap[node.id] = node;
  242. if (point) {
  243. point.node = node;
  244. }
  245. return node;
  246. };
  247. /**
  248. * Recursive function which calculates the area for all children of a
  249. * node.
  250. *
  251. * @private
  252. * @function Highcharts.Series#calculateChildrenAreas
  253. *
  254. * @param {object} node
  255. * The node which is parent to the children.
  256. *
  257. * @param {object} area
  258. * The rectangular area of the parent.
  259. */
  260. TreemapSeries.prototype.calculateChildrenAreas = function (parent, area) {
  261. var series = this, options = series.options, mapOptionsToLevel = series.mapOptionsToLevel, level = mapOptionsToLevel[parent.level + 1], algorithm = pick((series[(level && level.layoutAlgorithm)] &&
  262. level.layoutAlgorithm), options.layoutAlgorithm), alternate = options.alternateStartingDirection, childrenValues = [], children;
  263. // Collect all children which should be included
  264. children = parent.children.filter(function (n) {
  265. return !n.ignore;
  266. });
  267. if (level && level.layoutStartingDirection) {
  268. area.direction = level.layoutStartingDirection === 'vertical' ?
  269. 0 :
  270. 1;
  271. }
  272. childrenValues = series[algorithm](area, children);
  273. children.forEach(function (child, index) {
  274. var values = childrenValues[index];
  275. child.values = merge(values, {
  276. val: child.childrenTotal,
  277. direction: (alternate ? 1 - area.direction : area.direction)
  278. });
  279. child.pointValues = merge(values, {
  280. x: (values.x / series.axisRatio),
  281. // Flip y-values to avoid visual regression with csvCoord in
  282. // Axis.translate at setPointValues. #12488
  283. y: TreemapUtilities.AXIS_MAX - values.y - values.height,
  284. width: (values.width / series.axisRatio)
  285. });
  286. // If node has children, then call method recursively
  287. if (child.children.length) {
  288. series.calculateChildrenAreas(child, child.values);
  289. }
  290. });
  291. };
  292. /**
  293. * Extend drawDataLabels with logic to handle custom options related to
  294. * the treemap series:
  295. *
  296. * - Points which is not a leaf node, has dataLabels disabled by
  297. * default.
  298. *
  299. * - Options set on series.levels is merged in.
  300. *
  301. * - Width of the dataLabel is set to match the width of the point
  302. * shape.
  303. *
  304. * @private
  305. */
  306. TreemapSeries.prototype.drawDataLabels = function () {
  307. var series = this, mapOptionsToLevel = series.mapOptionsToLevel, points = series.points.filter(function (n) {
  308. return n.node.visible;
  309. }), options, level;
  310. points.forEach(function (point) {
  311. level = mapOptionsToLevel[point.node.level];
  312. // Set options to new object to avoid problems with scope
  313. options = { style: {} };
  314. // If not a leaf, then label should be disabled as default
  315. if (!point.node.isLeaf) {
  316. options.enabled = false;
  317. }
  318. // If options for level exists, include them as well
  319. if (level && level.dataLabels) {
  320. options = merge(options, level.dataLabels);
  321. series._hasPointLabels = true;
  322. }
  323. // Set dataLabel width to the width of the point shape.
  324. if (point.shapeArgs) {
  325. options.style.width = point.shapeArgs.width;
  326. if (point.dataLabel) {
  327. point.dataLabel.css({
  328. width: point.shapeArgs.width + 'px'
  329. });
  330. }
  331. }
  332. // Merge custom options with point options
  333. point.dlOptions = merge(options, point.options.dataLabels);
  334. });
  335. Series.prototype.drawDataLabels.call(this);
  336. };
  337. /**
  338. * Override drawPoints
  339. * @private
  340. */
  341. TreemapSeries.prototype.drawPoints = function () {
  342. var series = this, chart = series.chart, renderer = chart.renderer, points = series.points, styledMode = chart.styledMode, options = series.options, shadow = styledMode ? {} : options.shadow, borderRadius = options.borderRadius, withinAnimationLimit = chart.pointCount < options.animationLimit, allowTraversingTree = options.allowTraversingTree;
  343. points.forEach(function (point) {
  344. var levelDynamic = point.node.levelDynamic, animatableAttribs = {}, attribs = {}, css = {}, groupKey = 'level-group-' + point.node.level, hasGraphic = !!point.graphic, shouldAnimate = withinAnimationLimit && hasGraphic, shapeArgs = point.shapeArgs;
  345. // Don't bother with calculate styling if the point is not drawn
  346. if (point.shouldDraw()) {
  347. point.isInside = true;
  348. if (borderRadius) {
  349. attribs.r = borderRadius;
  350. }
  351. merge(true, // Extend object
  352. // Which object to extend
  353. shouldAnimate ? animatableAttribs : attribs,
  354. // Add shapeArgs to animate/attr if graphic exists
  355. hasGraphic ? shapeArgs : {},
  356. // Add style attribs if !styleMode
  357. styledMode ?
  358. {} :
  359. series.pointAttribs(point, point.selected ? 'select' : void 0));
  360. // In styled mode apply point.color. Use CSS, otherwise the
  361. // fill used in the style sheet will take precedence over
  362. // the fill attribute.
  363. if (series.colorAttribs && styledMode) {
  364. // Heatmap is loaded
  365. extend(css, series.colorAttribs(point));
  366. }
  367. if (!series[groupKey]) {
  368. series[groupKey] = renderer.g(groupKey)
  369. .attr({
  370. // @todo Set the zIndex based upon the number of
  371. // levels, instead of using 1000
  372. zIndex: 1000 - (levelDynamic || 0)
  373. })
  374. .add(series.group);
  375. series[groupKey].survive = true;
  376. }
  377. }
  378. // Draw the point
  379. point.draw({
  380. animatableAttribs: animatableAttribs,
  381. attribs: attribs,
  382. css: css,
  383. group: series[groupKey],
  384. renderer: renderer,
  385. shadow: shadow,
  386. shapeArgs: shapeArgs,
  387. shapeType: 'rect'
  388. });
  389. // If setRootNode is allowed, set a point cursor on clickables &
  390. // add drillId to point
  391. if (allowTraversingTree && point.graphic) {
  392. point.drillId = options.interactByLeaf ?
  393. series.drillToByLeaf(point) :
  394. series.drillToByGroup(point);
  395. }
  396. });
  397. };
  398. /**
  399. * Finds the drill id for a parent node. Returns false if point should
  400. * not have a click event.
  401. * @private
  402. */
  403. TreemapSeries.prototype.drillToByGroup = function (point) {
  404. var series = this, drillId = false;
  405. if ((point.node.level - series.nodeMap[series.rootNode].level) ===
  406. 1 &&
  407. !point.node.isLeaf) {
  408. drillId = point.id;
  409. }
  410. return drillId;
  411. };
  412. /**
  413. * Finds the drill id for a leaf node. Returns false if point should not
  414. * have a click event
  415. * @private
  416. */
  417. TreemapSeries.prototype.drillToByLeaf = function (point) {
  418. var series = this, drillId = false, nodeParent;
  419. if ((point.node.parent !== series.rootNode) &&
  420. point.node.isLeaf) {
  421. nodeParent = point.node;
  422. while (!drillId) {
  423. nodeParent = series.nodeMap[nodeParent.parent];
  424. if (nodeParent.parent === series.rootNode) {
  425. drillId = nodeParent.id;
  426. }
  427. }
  428. }
  429. return drillId;
  430. };
  431. /**
  432. * @todo remove this function at a suitable version.
  433. * @private
  434. */
  435. TreemapSeries.prototype.drillToNode = function (id, redraw) {
  436. error(32, false, void 0, { 'treemap.drillToNode': 'use treemap.setRootNode' });
  437. this.setRootNode(id, redraw);
  438. };
  439. TreemapSeries.prototype.drillUp = function () {
  440. var series = this, node = series.nodeMap[series.rootNode];
  441. if (node && isString(node.parent)) {
  442. series.setRootNode(node.parent, true, { trigger: 'traverseUpButton' });
  443. }
  444. };
  445. TreemapSeries.prototype.getExtremes = function () {
  446. // Get the extremes from the value data
  447. var _a = Series.prototype.getExtremes
  448. .call(this, this.colorValueData), dataMin = _a.dataMin, dataMax = _a.dataMax;
  449. this.valueMin = dataMin;
  450. this.valueMax = dataMax;
  451. // Get the extremes from the y data
  452. return Series.prototype.getExtremes.call(this);
  453. };
  454. /**
  455. * Creates an object map from parent id to childrens index.
  456. *
  457. * @private
  458. * @function Highcharts.Series#getListOfParents
  459. *
  460. * @param {Highcharts.SeriesTreemapDataOptions} [data]
  461. * List of points set in options.
  462. *
  463. * @param {Array<string>} [existingIds]
  464. * List of all point ids.
  465. *
  466. * @return {object}
  467. * Map from parent id to children index in data.
  468. */
  469. TreemapSeries.prototype.getListOfParents = function (data, existingIds) {
  470. var arr = isArray(data) ? data : [], ids = isArray(existingIds) ? existingIds : [], listOfParents = arr.reduce(function (prev, curr, i) {
  471. var parent = pick(curr.parent, '');
  472. if (typeof prev[parent] === 'undefined') {
  473. prev[parent] = [];
  474. }
  475. prev[parent].push(i);
  476. return prev;
  477. }, {
  478. '': [] // Root of tree
  479. });
  480. // If parent does not exist, hoist parent to root of tree.
  481. TreemapUtilities.eachObject(listOfParents, function (children, parent, list) {
  482. if ((parent !== '') && (ids.indexOf(parent) === -1)) {
  483. children.forEach(function (child) {
  484. list[''].push(child);
  485. });
  486. delete list[parent];
  487. }
  488. });
  489. return listOfParents;
  490. };
  491. /**
  492. * Creates a tree structured object from the series points.
  493. * @private
  494. */
  495. TreemapSeries.prototype.getTree = function () {
  496. var series = this, allIds = this.data.map(function (d) {
  497. return d.id;
  498. }), parentList = series.getListOfParents(this.data, allIds);
  499. series.nodeMap = {};
  500. return series.buildNode('', -1, 0, parentList);
  501. };
  502. /**
  503. * Define hasData function for non-cartesian series. Returns true if the
  504. * series has points at all.
  505. * @private
  506. */
  507. TreemapSeries.prototype.hasData = function () {
  508. return !!this.processedXData.length; // != 0
  509. };
  510. TreemapSeries.prototype.init = function (chart, options) {
  511. var series = this, setOptionsEvent;
  512. // If color series logic is loaded, add some properties
  513. if (colorMapSeriesMixin) {
  514. this.colorAttribs = colorMapSeriesMixin.colorAttribs;
  515. }
  516. setOptionsEvent = addEvent(series, 'setOptions', function (event) {
  517. var options = event.userOptions;
  518. if (defined(options.allowDrillToNode) &&
  519. !defined(options.allowTraversingTree)) {
  520. options.allowTraversingTree = options.allowDrillToNode;
  521. delete options.allowDrillToNode;
  522. }
  523. if (defined(options.drillUpButton) &&
  524. !defined(options.traverseUpButton)) {
  525. options.traverseUpButton = options.drillUpButton;
  526. delete options.drillUpButton;
  527. }
  528. });
  529. Series.prototype.init.call(series, chart, options);
  530. // Treemap's opacity is a different option from other series
  531. delete series.opacity;
  532. // Handle deprecated options.
  533. series.eventsToUnbind.push(setOptionsEvent);
  534. if (series.options.allowTraversingTree) {
  535. series.eventsToUnbind.push(addEvent(series, 'click', series.onClickDrillToNode));
  536. }
  537. };
  538. /**
  539. * Add drilling on the suitable points.
  540. * @private
  541. */
  542. TreemapSeries.prototype.onClickDrillToNode = function (event) {
  543. var series = this, point = event.point, drillId = point && point.drillId;
  544. // If a drill id is returned, add click event and cursor.
  545. if (isString(drillId)) {
  546. point.setState(''); // Remove hover
  547. series.setRootNode(drillId, true, { trigger: 'click' });
  548. }
  549. };
  550. /**
  551. * Get presentational attributes
  552. * @private
  553. */
  554. TreemapSeries.prototype.pointAttribs = function (point, state) {
  555. var series = this, mapOptionsToLevel = (isObject(series.mapOptionsToLevel) ?
  556. series.mapOptionsToLevel :
  557. {}), level = point && mapOptionsToLevel[point.node.level] || {}, options = this.options, attr, stateOptions = (state && options.states[state]) || {}, className = (point && point.getClassName()) || '', opacity;
  558. // Set attributes by precedence. Point trumps level trumps series.
  559. // Stroke width uses pick because it can be 0.
  560. attr = {
  561. 'stroke': (point && point.borderColor) ||
  562. level.borderColor ||
  563. stateOptions.borderColor ||
  564. options.borderColor,
  565. 'stroke-width': pick(point && point.borderWidth, level.borderWidth, stateOptions.borderWidth, options.borderWidth),
  566. 'dashstyle': (point && point.borderDashStyle) ||
  567. level.borderDashStyle ||
  568. stateOptions.borderDashStyle ||
  569. options.borderDashStyle,
  570. 'fill': (point && point.color) || this.color
  571. };
  572. // Hide levels above the current view
  573. if (className.indexOf('highcharts-above-level') !== -1) {
  574. attr.fill = 'none';
  575. attr['stroke-width'] = 0;
  576. // Nodes with children that accept interaction
  577. }
  578. else if (className.indexOf('highcharts-internal-node-interactive') !== -1) {
  579. opacity = pick(stateOptions.opacity, options.opacity);
  580. attr.fill = color(attr.fill).setOpacity(opacity).get();
  581. attr.cursor = 'pointer';
  582. // Hide nodes that have children
  583. }
  584. else if (className.indexOf('highcharts-internal-node') !== -1) {
  585. attr.fill = 'none';
  586. }
  587. else if (state) {
  588. // Brighten and hoist the hover nodes
  589. attr.fill = color(attr.fill)
  590. .brighten(stateOptions.brightness)
  591. .get();
  592. }
  593. return attr;
  594. };
  595. TreemapSeries.prototype.renderTraverseUpButton = function (rootId) {
  596. var series = this, nodeMap = series.nodeMap, node = nodeMap[rootId], name = node.name, buttonOptions = series.options.traverseUpButton, backText = pick(buttonOptions.text, name, '◁ Back'), attr, states;
  597. if (rootId === '' || (series.is('sunburst') &&
  598. series.tree.children.length === 1 &&
  599. rootId === series.tree.children[0].id)) {
  600. if (series.drillUpButton) {
  601. series.drillUpButton = series.drillUpButton.destroy();
  602. }
  603. }
  604. else if (!this.drillUpButton) {
  605. attr = buttonOptions.theme;
  606. states = attr && attr.states;
  607. this.drillUpButton = this.chart.renderer
  608. .button(backText, 0, 0, function () {
  609. series.drillUp();
  610. }, attr, states && states.hover, states && states.select)
  611. .addClass('highcharts-drillup-button')
  612. .attr({
  613. align: buttonOptions.position.align,
  614. zIndex: 7
  615. })
  616. .add()
  617. .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox');
  618. }
  619. else {
  620. this.drillUpButton.placed = false;
  621. this.drillUpButton.attr({
  622. text: backText
  623. })
  624. .align();
  625. }
  626. };
  627. /**
  628. * Set the node's color recursively, from the parent down.
  629. * @private
  630. */
  631. TreemapSeries.prototype.setColorRecursive = function (node, parentColor, colorIndex, index, siblings) {
  632. var series = this, chart = series && series.chart, colors = chart && chart.options && chart.options.colors, colorInfo, point;
  633. if (node) {
  634. colorInfo = getColor(node, {
  635. colors: colors,
  636. index: index,
  637. mapOptionsToLevel: series.mapOptionsToLevel,
  638. parentColor: parentColor,
  639. parentColorIndex: colorIndex,
  640. series: series,
  641. siblings: siblings
  642. });
  643. point = series.points[node.i];
  644. if (point) {
  645. point.color = colorInfo.color;
  646. point.colorIndex = colorInfo.colorIndex;
  647. }
  648. // Do it all again with the children
  649. (node.children || []).forEach(function (child, i) {
  650. series.setColorRecursive(child, colorInfo.color, colorInfo.colorIndex, i, node.children.length);
  651. });
  652. }
  653. };
  654. TreemapSeries.prototype.setPointValues = function () {
  655. var series = this;
  656. var points = series.points, xAxis = series.xAxis, yAxis = series.yAxis;
  657. var styledMode = series.chart.styledMode;
  658. // Get the crisp correction in classic mode. For this to work in
  659. // styled mode, we would need to first add the shape (without x,
  660. // y, width and height), then read the rendered stroke width
  661. // using point.graphic.strokeWidth(), then modify and apply the
  662. // shapeArgs. This applies also to column series, but the
  663. // downside is performance and code complexity.
  664. var getCrispCorrection = function (point) { return (styledMode ?
  665. 0 :
  666. ((series.pointAttribs(point)['stroke-width'] || 0) % 2) / 2); };
  667. points.forEach(function (point) {
  668. var _a = point.node, values = _a.pointValues, visible = _a.visible;
  669. // Points which is ignored, have no values.
  670. if (values && visible) {
  671. var height = values.height, width = values.width, x = values.x, y = values.y;
  672. var crispCorr = getCrispCorrection(point);
  673. var x1 = Math.round(xAxis.toPixels(x, true)) - crispCorr;
  674. var x2 = Math.round(xAxis.toPixels(x + width, true)) - crispCorr;
  675. var y1 = Math.round(yAxis.toPixels(y, true)) - crispCorr;
  676. var y2 = Math.round(yAxis.toPixels(y + height, true)) - crispCorr;
  677. // Set point values
  678. var shapeArgs = {
  679. x: Math.min(x1, x2),
  680. y: Math.min(y1, y2),
  681. width: Math.abs(x2 - x1),
  682. height: Math.abs(y2 - y1)
  683. };
  684. point.plotX = shapeArgs.x + (shapeArgs.width / 2);
  685. point.plotY = shapeArgs.y + (shapeArgs.height / 2);
  686. point.shapeArgs = shapeArgs;
  687. }
  688. else {
  689. // Reset visibility
  690. delete point.plotX;
  691. delete point.plotY;
  692. }
  693. });
  694. };
  695. /**
  696. * Sets a new root node for the series.
  697. *
  698. * @private
  699. * @function Highcharts.Series#setRootNode
  700. *
  701. * @param {string} id
  702. * The id of the new root node.
  703. *
  704. * @param {boolean} [redraw=true]
  705. * Wether to redraw the chart or not.
  706. *
  707. * @param {object} [eventArguments]
  708. * Arguments to be accessed in event handler.
  709. *
  710. * @param {string} [eventArguments.newRootId]
  711. * Id of the new root.
  712. *
  713. * @param {string} [eventArguments.previousRootId]
  714. * Id of the previous root.
  715. *
  716. * @param {boolean} [eventArguments.redraw]
  717. * Wether to redraw the chart after.
  718. *
  719. * @param {object} [eventArguments.series]
  720. * The series to update the root of.
  721. *
  722. * @param {string} [eventArguments.trigger]
  723. * The action which triggered the event. Undefined if the setRootNode is
  724. * called directly.
  725. *
  726. * @fires Highcharts.Series#event:setRootNode
  727. */
  728. TreemapSeries.prototype.setRootNode = function (id, redraw, eventArguments) {
  729. var series = this, eventArgs = extend({
  730. newRootId: id,
  731. previousRootId: series.rootNode,
  732. redraw: pick(redraw, true),
  733. series: series
  734. }, eventArguments);
  735. /**
  736. * The default functionality of the setRootNode event.
  737. *
  738. * @private
  739. * @param {object} args The event arguments.
  740. * @param {string} args.newRootId Id of the new root.
  741. * @param {string} args.previousRootId Id of the previous root.
  742. * @param {boolean} args.redraw Wether to redraw the chart after.
  743. * @param {object} args.series The series to update the root of.
  744. * @param {string} [args.trigger=undefined] The action which
  745. * triggered the event. Undefined if the setRootNode is called
  746. * directly.
  747. * @return {void}
  748. */
  749. var defaultFn = function (args) {
  750. var series = args.series;
  751. // Store previous and new root ids on the series.
  752. series.idPreviousRoot = args.previousRootId;
  753. series.rootNode = args.newRootId;
  754. // Redraw the chart
  755. series.isDirty = true; // Force redraw
  756. if (args.redraw) {
  757. series.chart.redraw();
  758. }
  759. };
  760. // Fire setRootNode event.
  761. fireEvent(series, 'setRootNode', eventArgs, defaultFn);
  762. };
  763. /**
  764. * Workaround for `inactive` state. Since `series.opacity` option is
  765. * already reserved, don't use that state at all by disabling
  766. * `inactiveOtherPoints` and not inheriting states by points.
  767. * @private
  768. */
  769. TreemapSeries.prototype.setState = function (state) {
  770. this.options.inactiveOtherPoints = true;
  771. Series.prototype.setState.call(this, state, false);
  772. this.options.inactiveOtherPoints = false;
  773. };
  774. TreemapSeries.prototype.setTreeValues = function (tree) {
  775. var series = this, options = series.options, idRoot = series.rootNode, mapIdToNode = series.nodeMap, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (TreemapUtilities.isBoolean(options.levelIsConstant) ?
  776. options.levelIsConstant :
  777. true), childrenTotal = 0, children = [], val, point = series.points[tree.i];
  778. // First give the children some values
  779. tree.children.forEach(function (child) {
  780. child = series.setTreeValues(child);
  781. children.push(child);
  782. if (!child.ignore) {
  783. childrenTotal += child.val;
  784. }
  785. });
  786. // Sort the children
  787. stableSort(children, function (a, b) {
  788. return (a.sortIndex || 0) - (b.sortIndex || 0);
  789. });
  790. // Set the values
  791. val = pick(point && point.options.value, childrenTotal);
  792. if (point) {
  793. point.value = val;
  794. }
  795. extend(tree, {
  796. children: children,
  797. childrenTotal: childrenTotal,
  798. // Ignore this node if point is not visible
  799. ignore: !(pick(point && point.visible, true) && (val > 0)),
  800. isLeaf: tree.visible && !childrenTotal,
  801. levelDynamic: (tree.level - (levelIsConstant ? 0 : nodeRoot.level)),
  802. name: pick(point && point.name, ''),
  803. sortIndex: pick(point && point.sortIndex, -val),
  804. val: val
  805. });
  806. return tree;
  807. };
  808. TreemapSeries.prototype.sliceAndDice = function (parent, children) {
  809. return this.algorithmFill(true, parent, children);
  810. };
  811. TreemapSeries.prototype.squarified = function (parent, children) {
  812. return this.algorithmLowAspectRatio(true, parent, children);
  813. };
  814. TreemapSeries.prototype.strip = function (parent, children) {
  815. return this.algorithmLowAspectRatio(false, parent, children);
  816. };
  817. TreemapSeries.prototype.stripes = function (parent, children) {
  818. return this.algorithmFill(false, parent, children);
  819. };
  820. TreemapSeries.prototype.translate = function () {
  821. var series = this, options = series.options,
  822. // NOTE: updateRootId modifies series.
  823. rootId = updateRootId(series), rootNode, pointValues, seriesArea, tree, val;
  824. // Call prototype function
  825. Series.prototype.translate.call(series);
  826. // @todo Only if series.isDirtyData is true
  827. tree = series.tree = series.getTree();
  828. rootNode = series.nodeMap[rootId];
  829. if (rootId !== '' &&
  830. (!rootNode || !rootNode.children.length)) {
  831. series.setRootNode('', false);
  832. rootId = series.rootNode;
  833. rootNode = series.nodeMap[rootId];
  834. }
  835. series.renderTraverseUpButton(rootId);
  836. series.mapOptionsToLevel = getLevelOptions({
  837. from: rootNode.level + 1,
  838. levels: options.levels,
  839. to: tree.height,
  840. defaults: {
  841. levelIsConstant: series.options.levelIsConstant,
  842. colorByPoint: options.colorByPoint
  843. }
  844. });
  845. // Parents of the root node is by default visible
  846. TreemapUtilities.recursive(series.nodeMap[series.rootNode], function (node) {
  847. var next = false, p = node.parent;
  848. node.visible = true;
  849. if (p || p === '') {
  850. next = series.nodeMap[p];
  851. }
  852. return next;
  853. });
  854. // Children of the root node is by default visible
  855. TreemapUtilities.recursive(series.nodeMap[series.rootNode].children, function (children) {
  856. var next = false;
  857. children.forEach(function (child) {
  858. child.visible = true;
  859. if (child.children.length) {
  860. next = (next || []).concat(child.children);
  861. }
  862. });
  863. return next;
  864. });
  865. series.setTreeValues(tree);
  866. // Calculate plotting values.
  867. series.axisRatio = (series.xAxis.len / series.yAxis.len);
  868. series.nodeMap[''].pointValues = pointValues = {
  869. x: 0,
  870. y: 0,
  871. width: TreemapUtilities.AXIS_MAX,
  872. height: TreemapUtilities.AXIS_MAX
  873. };
  874. series.nodeMap[''].values = seriesArea = merge(pointValues, {
  875. width: (pointValues.width * series.axisRatio),
  876. direction: (options.layoutStartingDirection === 'vertical' ? 0 : 1),
  877. val: tree.val
  878. });
  879. series.calculateChildrenAreas(tree, seriesArea);
  880. // Logic for point colors
  881. if (!series.colorAxis &&
  882. !options.colorByPoint) {
  883. series.setColorRecursive(series.tree);
  884. }
  885. // Update axis extremes according to the root node.
  886. if (options.allowTraversingTree) {
  887. val = rootNode.pointValues;
  888. series.xAxis.setExtremes(val.x, val.x + val.width, false);
  889. series.yAxis.setExtremes(val.y, val.y + val.height, false);
  890. series.xAxis.setScale();
  891. series.yAxis.setScale();
  892. }
  893. // Assign values to points.
  894. series.setPointValues();
  895. };
  896. /**
  897. * A treemap displays hierarchical data using nested rectangles. The data
  898. * can be laid out in varying ways depending on options.
  899. *
  900. * @sample highcharts/demo/treemap-large-dataset/
  901. * Treemap
  902. *
  903. * @extends plotOptions.scatter
  904. * @excluding dragDrop, marker, jitter, dataSorting
  905. * @product highcharts
  906. * @requires modules/treemap
  907. * @optionparent plotOptions.treemap
  908. */
  909. TreemapSeries.defaultOptions = merge(ScatterSeries.defaultOptions, {
  910. /**
  911. * When enabled the user can click on a point which is a parent and
  912. * zoom in on its children. Deprecated and replaced by
  913. * [allowTraversingTree](#plotOptions.treemap.allowTraversingTree).
  914. *
  915. * @sample {highcharts} highcharts/plotoptions/treemap-allowdrilltonode/
  916. * Enabled
  917. *
  918. * @deprecated
  919. * @type {boolean}
  920. * @default false
  921. * @since 4.1.0
  922. * @product highcharts
  923. * @apioption plotOptions.treemap.allowDrillToNode
  924. */
  925. /**
  926. * When enabled the user can click on a point which is a parent and
  927. * zoom in on its children.
  928. *
  929. * @sample {highcharts} highcharts/plotoptions/treemap-allowtraversingtree/
  930. * Enabled
  931. *
  932. * @since 7.0.3
  933. * @product highcharts
  934. */
  935. allowTraversingTree: false,
  936. animationLimit: 250,
  937. /**
  938. * When the series contains less points than the crop threshold, all
  939. * points are drawn, event if the points fall outside the visible plot
  940. * area at the current zoom. The advantage of drawing all points
  941. * (including markers and columns), is that animation is performed on
  942. * updates. On the other hand, when the series contains more points than
  943. * the crop threshold, the series data is cropped to only contain points
  944. * that fall within the plot area. The advantage of cropping away
  945. * invisible points is to increase performance on large series.
  946. *
  947. * @type {number}
  948. * @default 300
  949. * @since 4.1.0
  950. * @product highcharts
  951. * @apioption plotOptions.treemap.cropThreshold
  952. */
  953. /**
  954. * Fires on a request for change of root node for the tree, before the
  955. * update is made. An event object is passed to the function, containing
  956. * additional properties `newRootId`, `previousRootId`, `redraw` and
  957. * `trigger`.
  958. *
  959. * @type {function}
  960. * @default undefined
  961. * @sample {highcharts} highcharts/plotoptions/treemap-events-setrootnode/
  962. * Alert update information on setRootNode event.
  963. * @since 7.0.3
  964. * @product highcharts
  965. * @apioption plotOptions.treemap.events.setRootNode
  966. */
  967. /**
  968. * This option decides if the user can interact with the parent nodes
  969. * or just the leaf nodes. When this option is undefined, it will be
  970. * true by default. However when allowTraversingTree is true, then it
  971. * will be false by default.
  972. *
  973. * @sample {highcharts} highcharts/plotoptions/treemap-interactbyleaf-false/
  974. * False
  975. * @sample {highcharts} highcharts/plotoptions/treemap-interactbyleaf-true-and-allowtraversingtree/
  976. * InteractByLeaf and allowTraversingTree is true
  977. *
  978. * @type {boolean}
  979. * @since 4.1.2
  980. * @product highcharts
  981. * @apioption plotOptions.treemap.interactByLeaf
  982. */
  983. /**
  984. * The sort index of the point inside the treemap level.
  985. *
  986. * @sample {highcharts} highcharts/plotoptions/treemap-sortindex/
  987. * Sort by years
  988. *
  989. * @type {number}
  990. * @since 4.1.10
  991. * @product highcharts
  992. * @apioption plotOptions.treemap.sortIndex
  993. */
  994. /**
  995. * A series specific or series type specific color set to apply instead
  996. * of the global [colors](#colors) when
  997. * [colorByPoint](#plotOptions.treemap.colorByPoint) is true.
  998. *
  999. * @type {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
  1000. * @since 3.0
  1001. * @product highcharts
  1002. * @apioption plotOptions.treemap.colors
  1003. */
  1004. /**
  1005. * Whether to display this series type or specific series item in the
  1006. * legend.
  1007. */
  1008. showInLegend: false,
  1009. /**
  1010. * @ignore-option
  1011. */
  1012. marker: void 0,
  1013. /**
  1014. * When using automatic point colors pulled from the `options.colors`
  1015. * collection, this option determines whether the chart should receive
  1016. * one color per series or one color per point.
  1017. *
  1018. * @see [series colors](#plotOptions.treemap.colors)
  1019. *
  1020. * @since 2.0
  1021. * @product highcharts
  1022. * @apioption plotOptions.treemap.colorByPoint
  1023. */
  1024. colorByPoint: false,
  1025. /**
  1026. * @since 4.1.0
  1027. */
  1028. dataLabels: {
  1029. defer: false,
  1030. enabled: true,
  1031. formatter: function () {
  1032. var point = this && this.point ?
  1033. this.point :
  1034. {}, name = isString(point.name) ? point.name : '';
  1035. return name;
  1036. },
  1037. inside: true,
  1038. verticalAlign: 'middle'
  1039. },
  1040. tooltip: {
  1041. headerFormat: '',
  1042. pointFormat: '<b>{point.name}</b>: {point.value}<br/>'
  1043. },
  1044. /**
  1045. * Whether to ignore hidden points when the layout algorithm runs.
  1046. * If `false`, hidden points will leave open spaces.
  1047. *
  1048. * @since 5.0.8
  1049. */
  1050. ignoreHiddenPoint: true,
  1051. /**
  1052. * This option decides which algorithm is used for setting position
  1053. * and dimensions of the points.
  1054. *
  1055. * @see [How to write your own algorithm](https://www.highcharts.com/docs/chart-and-series-types/treemap)
  1056. *
  1057. * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-sliceanddice/
  1058. * SliceAndDice by default
  1059. * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-stripes/
  1060. * Stripes
  1061. * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-squarified/
  1062. * Squarified
  1063. * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-strip/
  1064. * Strip
  1065. *
  1066. * @since 4.1.0
  1067. * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"]
  1068. */
  1069. layoutAlgorithm: 'sliceAndDice',
  1070. /**
  1071. * Defines which direction the layout algorithm will start drawing.
  1072. *
  1073. * @since 4.1.0
  1074. * @validvalue ["vertical", "horizontal"]
  1075. */
  1076. layoutStartingDirection: 'vertical',
  1077. /**
  1078. * Enabling this option will make the treemap alternate the drawing
  1079. * direction between vertical and horizontal. The next levels starting
  1080. * direction will always be the opposite of the previous.
  1081. *
  1082. * @sample {highcharts} highcharts/plotoptions/treemap-alternatestartingdirection-true/
  1083. * Enabled
  1084. *
  1085. * @since 4.1.0
  1086. */
  1087. alternateStartingDirection: false,
  1088. /**
  1089. * Used together with the levels and allowTraversingTree options. When
  1090. * set to false the first level visible to be level one, which is
  1091. * dynamic when traversing the tree. Otherwise the level will be the
  1092. * same as the tree structure.
  1093. *
  1094. * @since 4.1.0
  1095. */
  1096. levelIsConstant: true,
  1097. /**
  1098. * Options for the button appearing when drilling down in a treemap.
  1099. * Deprecated and replaced by
  1100. * [traverseUpButton](#plotOptions.treemap.traverseUpButton).
  1101. *
  1102. * @deprecated
  1103. */
  1104. drillUpButton: {
  1105. /**
  1106. * The position of the button.
  1107. *
  1108. * @deprecated
  1109. */
  1110. position: {
  1111. /**
  1112. * Vertical alignment of the button.
  1113. *
  1114. * @deprecated
  1115. * @type {Highcharts.VerticalAlignValue}
  1116. * @default top
  1117. * @product highcharts
  1118. * @apioption plotOptions.treemap.drillUpButton.position.verticalAlign
  1119. */
  1120. /**
  1121. * Horizontal alignment of the button.
  1122. *
  1123. * @deprecated
  1124. * @type {Highcharts.AlignValue}
  1125. */
  1126. align: 'right',
  1127. /**
  1128. * Horizontal offset of the button.
  1129. *
  1130. * @deprecated
  1131. */
  1132. x: -10,
  1133. /**
  1134. * Vertical offset of the button.
  1135. *
  1136. * @deprecated
  1137. */
  1138. y: 10
  1139. }
  1140. },
  1141. /**
  1142. * Options for the button appearing when traversing down in a treemap.
  1143. */
  1144. traverseUpButton: {
  1145. /**
  1146. * The position of the button.
  1147. */
  1148. position: {
  1149. /**
  1150. * Vertical alignment of the button.
  1151. *
  1152. * @type {Highcharts.VerticalAlignValue}
  1153. * @default top
  1154. * @product highcharts
  1155. * @apioption plotOptions.treemap.traverseUpButton.position.verticalAlign
  1156. */
  1157. /**
  1158. * Horizontal alignment of the button.
  1159. *
  1160. * @type {Highcharts.AlignValue}
  1161. */
  1162. align: 'right',
  1163. /**
  1164. * Horizontal offset of the button.
  1165. */
  1166. x: -10,
  1167. /**
  1168. * Vertical offset of the button.
  1169. */
  1170. y: 10
  1171. }
  1172. },
  1173. /**
  1174. * Set options on specific levels. Takes precedence over series options,
  1175. * but not point options.
  1176. *
  1177. * @sample {highcharts} highcharts/plotoptions/treemap-levels/
  1178. * Styling dataLabels and borders
  1179. * @sample {highcharts} highcharts/demo/treemap-with-levels/
  1180. * Different layoutAlgorithm
  1181. *
  1182. * @type {Array<*>}
  1183. * @since 4.1.0
  1184. * @product highcharts
  1185. * @apioption plotOptions.treemap.levels
  1186. */
  1187. /**
  1188. * Can set a `borderColor` on all points which lies on the same level.
  1189. *
  1190. * @type {Highcharts.ColorString}
  1191. * @since 4.1.0
  1192. * @product highcharts
  1193. * @apioption plotOptions.treemap.levels.borderColor
  1194. */
  1195. /**
  1196. * Set the dash style of the border of all the point which lies on the
  1197. * level. See
  1198. * [plotOptions.scatter.dashStyle](#plotoptions.scatter.dashstyle)
  1199. * for possible options.
  1200. *
  1201. * @type {Highcharts.DashStyleValue}
  1202. * @since 4.1.0
  1203. * @product highcharts
  1204. * @apioption plotOptions.treemap.levels.borderDashStyle
  1205. */
  1206. /**
  1207. * Can set the borderWidth on all points which lies on the same level.
  1208. *
  1209. * @type {number}
  1210. * @since 4.1.0
  1211. * @product highcharts
  1212. * @apioption plotOptions.treemap.levels.borderWidth
  1213. */
  1214. /**
  1215. * Can set a color on all points which lies on the same level.
  1216. *
  1217. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  1218. * @since 4.1.0
  1219. * @product highcharts
  1220. * @apioption plotOptions.treemap.levels.color
  1221. */
  1222. /**
  1223. * A configuration object to define how the color of a child varies from
  1224. * the parent's color. The variation is distributed among the children
  1225. * of node. For example when setting brightness, the brightness change
  1226. * will range from the parent's original brightness on the first child,
  1227. * to the amount set in the `to` setting on the last node. This allows a
  1228. * gradient-like color scheme that sets children out from each other
  1229. * while highlighting the grouping on treemaps and sectors on sunburst
  1230. * charts.
  1231. *
  1232. * @sample highcharts/demo/sunburst/
  1233. * Sunburst with color variation
  1234. *
  1235. * @since 6.0.0
  1236. * @product highcharts
  1237. * @apioption plotOptions.treemap.levels.colorVariation
  1238. */
  1239. /**
  1240. * The key of a color variation. Currently supports `brightness` only.
  1241. *
  1242. * @type {string}
  1243. * @since 6.0.0
  1244. * @product highcharts
  1245. * @validvalue ["brightness"]
  1246. * @apioption plotOptions.treemap.levels.colorVariation.key
  1247. */
  1248. /**
  1249. * The ending value of a color variation. The last sibling will receive
  1250. * this value.
  1251. *
  1252. * @type {number}
  1253. * @since 6.0.0
  1254. * @product highcharts
  1255. * @apioption plotOptions.treemap.levels.colorVariation.to
  1256. */
  1257. /**
  1258. * Can set the options of dataLabels on each point which lies on the
  1259. * level.
  1260. * [plotOptions.treemap.dataLabels](#plotOptions.treemap.dataLabels) for
  1261. * possible values.
  1262. *
  1263. * @extends plotOptions.treemap.dataLabels
  1264. * @since 4.1.0
  1265. * @product highcharts
  1266. * @apioption plotOptions.treemap.levels.dataLabels
  1267. */
  1268. /**
  1269. * Can set the layoutAlgorithm option on a specific level.
  1270. *
  1271. * @type {string}
  1272. * @since 4.1.0
  1273. * @product highcharts
  1274. * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"]
  1275. * @apioption plotOptions.treemap.levels.layoutAlgorithm
  1276. */
  1277. /**
  1278. * Can set the layoutStartingDirection option on a specific level.
  1279. *
  1280. * @type {string}
  1281. * @since 4.1.0
  1282. * @product highcharts
  1283. * @validvalue ["vertical", "horizontal"]
  1284. * @apioption plotOptions.treemap.levels.layoutStartingDirection
  1285. */
  1286. /**
  1287. * Decides which level takes effect from the options set in the levels
  1288. * object.
  1289. *
  1290. * @sample {highcharts} highcharts/plotoptions/treemap-levels/
  1291. * Styling of both levels
  1292. *
  1293. * @type {number}
  1294. * @since 4.1.0
  1295. * @product highcharts
  1296. * @apioption plotOptions.treemap.levels.level
  1297. */
  1298. // Presentational options
  1299. /**
  1300. * The color of the border surrounding each tree map item.
  1301. *
  1302. * @type {Highcharts.ColorString}
  1303. */
  1304. borderColor: palette.neutralColor10,
  1305. /**
  1306. * The width of the border surrounding each tree map item.
  1307. */
  1308. borderWidth: 1,
  1309. colorKey: 'colorValue',
  1310. /**
  1311. * The opacity of a point in treemap. When a point has children, the
  1312. * visibility of the children is determined by the opacity.
  1313. *
  1314. * @since 4.2.4
  1315. */
  1316. opacity: 0.15,
  1317. /**
  1318. * A wrapper object for all the series options in specific states.
  1319. *
  1320. * @extends plotOptions.heatmap.states
  1321. */
  1322. states: {
  1323. /**
  1324. * Options for the hovered series
  1325. *
  1326. * @extends plotOptions.heatmap.states.hover
  1327. * @excluding halo
  1328. */
  1329. hover: {
  1330. /**
  1331. * The border color for the hovered state.
  1332. */
  1333. borderColor: palette.neutralColor40,
  1334. /**
  1335. * Brightness for the hovered point. Defaults to 0 if the
  1336. * heatmap series is loaded first, otherwise 0.1.
  1337. *
  1338. * @type {number}
  1339. * @default undefined
  1340. */
  1341. brightness: HeatmapSeries ? 0 : 0.1,
  1342. /**
  1343. * @extends plotOptions.heatmap.states.hover.halo
  1344. */
  1345. halo: false,
  1346. /**
  1347. * The opacity of a point in treemap. When a point has children,
  1348. * the visibility of the children is determined by the opacity.
  1349. *
  1350. * @since 4.2.4
  1351. */
  1352. opacity: 0.75,
  1353. /**
  1354. * The shadow option for hovered state.
  1355. */
  1356. shadow: false
  1357. }
  1358. }
  1359. });
  1360. return TreemapSeries;
  1361. }(ScatterSeries));
  1362. extend(TreemapSeries.prototype, {
  1363. buildKDTree: noop,
  1364. colorKey: 'colorValue',
  1365. directTouch: true,
  1366. drawLegendSymbol: LegendSymbolMixin.drawRectangle,
  1367. getExtremesFromAll: true,
  1368. getSymbol: noop,
  1369. optionalAxis: 'colorAxis',
  1370. parallelArrays: ['x', 'y', 'value', 'colorValue'],
  1371. pointArrayMap: ['value'],
  1372. pointClass: TreemapPoint,
  1373. trackerGroups: ['group', 'dataLabelsGroup'],
  1374. utils: {
  1375. recursive: TreemapUtilities.recursive
  1376. }
  1377. });
  1378. SeriesRegistry.registerSeriesType('treemap', TreemapSeries);
  1379. /* *
  1380. *
  1381. * Default Export
  1382. *
  1383. * */
  1384. export default TreemapSeries;
  1385. /* *
  1386. *
  1387. * API Options
  1388. *
  1389. * */
  1390. /**
  1391. * A `treemap` series. If the [type](#series.treemap.type) option is
  1392. * not specified, it is inherited from [chart.type](#chart.type).
  1393. *
  1394. * @extends series,plotOptions.treemap
  1395. * @excluding dataParser, dataURL, stack, dataSorting
  1396. * @product highcharts
  1397. * @requires modules/treemap
  1398. * @apioption series.treemap
  1399. */
  1400. /**
  1401. * An array of data points for the series. For the `treemap` series
  1402. * type, points can be given in the following ways:
  1403. *
  1404. * 1. An array of numerical values. In this case, the numerical values will be
  1405. * interpreted as `value` options. Example:
  1406. * ```js
  1407. * data: [0, 5, 3, 5]
  1408. * ```
  1409. *
  1410. * 2. An array of objects with named values. The following snippet shows only a
  1411. * few settings, see the complete options set below. If the total number of
  1412. * data points exceeds the series'
  1413. * [turboThreshold](#series.treemap.turboThreshold),
  1414. * this option is not available.
  1415. * ```js
  1416. * data: [{
  1417. * value: 9,
  1418. * name: "Point2",
  1419. * color: "#00FF00"
  1420. * }, {
  1421. * value: 6,
  1422. * name: "Point1",
  1423. * color: "#FF00FF"
  1424. * }]
  1425. * ```
  1426. *
  1427. * @sample {highcharts} highcharts/chart/reflow-true/
  1428. * Numerical values
  1429. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1430. * Config objects
  1431. *
  1432. * @type {Array<number|null|*>}
  1433. * @extends series.heatmap.data
  1434. * @excluding x, y
  1435. * @product highcharts
  1436. * @apioption series.treemap.data
  1437. */
  1438. /**
  1439. * The value of the point, resulting in a relative area of the point
  1440. * in the treemap.
  1441. *
  1442. * @type {number|null}
  1443. * @product highcharts
  1444. * @apioption series.treemap.data.value
  1445. */
  1446. /**
  1447. * Serves a purpose only if a `colorAxis` object is defined in the chart
  1448. * options. This value will decide which color the point gets from the
  1449. * scale of the colorAxis.
  1450. *
  1451. * @type {number}
  1452. * @since 4.1.0
  1453. * @product highcharts
  1454. * @apioption series.treemap.data.colorValue
  1455. */
  1456. /**
  1457. * Only for treemap. Use this option to build a tree structure. The
  1458. * value should be the id of the point which is the parent. If no points
  1459. * has a matching id, or this option is undefined, then the parent will
  1460. * be set to the root.
  1461. *
  1462. * @sample {highcharts} highcharts/point/parent/
  1463. * Point parent
  1464. * @sample {highcharts} highcharts/demo/treemap-with-levels/
  1465. * Example where parent id is not matching
  1466. *
  1467. * @type {string}
  1468. * @since 4.1.0
  1469. * @product highcharts
  1470. * @apioption series.treemap.data.parent
  1471. */
  1472. ''; // adds doclets above to transpiled file