tilemap.src.js 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391
  1. /**
  2. * @license Highcharts JS v7.0.2 (2019-01-17)
  3. * Tilemap module
  4. *
  5. * (c) 2010-2019 Highsoft AS
  6. *
  7. * License: www.highcharts.com/license
  8. */
  9. 'use strict';
  10. (function (factory) {
  11. if (typeof module === 'object' && module.exports) {
  12. factory['default'] = factory;
  13. module.exports = factory;
  14. } else if (typeof define === 'function' && define.amd) {
  15. define(function () {
  16. return factory;
  17. });
  18. } else {
  19. factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
  20. }
  21. }(function (Highcharts) {
  22. (function (H) {
  23. /**
  24. * (c) 2010-2019 Torstein Honsi
  25. *
  26. * License: www.highcharts.com/license
  27. */
  28. var defined = H.defined,
  29. noop = H.noop,
  30. seriesTypes = H.seriesTypes;
  31. /**
  32. * Mixin for maps and heatmaps
  33. *
  34. * @private
  35. * @mixin Highcharts.colorPointMixin
  36. */
  37. H.colorPointMixin = {
  38. /**
  39. * Color points have a value option that determines whether or not it is
  40. * a null point
  41. *
  42. * @function Highcharts.colorPointMixin.isValid
  43. *
  44. * @return {boolean}
  45. */
  46. isValid: function () {
  47. // undefined is allowed
  48. return (
  49. this.value !== null &&
  50. this.value !== Infinity &&
  51. this.value !== -Infinity
  52. );
  53. },
  54. /**
  55. * Set the visibility of a single point
  56. *
  57. * @function Highcharts.colorPointMixin.setVisible
  58. *
  59. * @param {boolean} visible
  60. */
  61. setVisible: function (vis) {
  62. var point = this,
  63. method = vis ? 'show' : 'hide';
  64. point.visible = Boolean(vis);
  65. // Show and hide associated elements
  66. ['graphic', 'dataLabel'].forEach(function (key) {
  67. if (point[key]) {
  68. point[key][method]();
  69. }
  70. });
  71. },
  72. /**
  73. * @function Highcharts.colorPointMixin.setState
  74. *
  75. * @param {string} state
  76. */
  77. setState: function (state) {
  78. H.Point.prototype.setState.call(this, state);
  79. if (this.graphic) {
  80. this.graphic.attr({
  81. zIndex: state === 'hover' ? 1 : 0
  82. });
  83. }
  84. }
  85. };
  86. /**
  87. * @private
  88. * @mixin Highcharts.colorSeriesMixin
  89. */
  90. H.colorSeriesMixin = {
  91. pointArrayMap: ['value'],
  92. axisTypes: ['xAxis', 'yAxis', 'colorAxis'],
  93. optionalAxis: 'colorAxis',
  94. trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
  95. getSymbol: noop,
  96. parallelArrays: ['x', 'y', 'value'],
  97. colorKey: 'value',
  98. pointAttribs: seriesTypes.column.prototype.pointAttribs,
  99. /**
  100. * In choropleth maps, the color is a result of the value, so this needs
  101. * translation too
  102. *
  103. * @function Highcharts.colorSeriesMixin.translateColors
  104. */
  105. translateColors: function () {
  106. var series = this,
  107. nullColor = this.options.nullColor,
  108. colorAxis = this.colorAxis,
  109. colorKey = this.colorKey;
  110. this.data.forEach(function (point) {
  111. var value = point[colorKey],
  112. color;
  113. color = point.options.color ||
  114. (
  115. point.isNull ?
  116. nullColor :
  117. (colorAxis && value !== undefined) ?
  118. colorAxis.toColor(value, point) :
  119. point.color || series.color
  120. );
  121. if (color) {
  122. point.color = color;
  123. }
  124. });
  125. },
  126. /**
  127. * Get the color attibutes to apply on the graphic
  128. *
  129. * @function Highcharts.colorSeriesMixin.colorAttribs
  130. *
  131. * @param {Highcharts.Point} point
  132. *
  133. * @return {Highcharts.Dictionary<Highcharts.ColorString>}
  134. */
  135. colorAttribs: function (point) {
  136. var ret = {};
  137. if (defined(point.color)) {
  138. ret[this.colorProp || 'fill'] = point.color;
  139. }
  140. return ret;
  141. }
  142. };
  143. }(Highcharts));
  144. (function (H) {
  145. /**
  146. * (c) 2010-2019 Torstein Honsi
  147. *
  148. * License: www.highcharts.com/license
  149. */
  150. var colorPointMixin = H.colorPointMixin,
  151. colorSeriesMixin = H.colorSeriesMixin,
  152. LegendSymbolMixin = H.LegendSymbolMixin,
  153. merge = H.merge,
  154. noop = H.noop,
  155. pick = H.pick,
  156. Series = H.Series,
  157. seriesType = H.seriesType,
  158. seriesTypes = H.seriesTypes;
  159. /**
  160. * @private
  161. * @class
  162. * @name Highcharts.seriesTypes.heatmap
  163. *
  164. * @augments Highcharts.Series
  165. */
  166. seriesType(
  167. 'heatmap',
  168. 'scatter'
  169. /**
  170. * A heatmap is a graphical representation of data where the individual
  171. * values contained in a matrix are represented as colors.
  172. *
  173. * @sample highcharts/demo/heatmap/
  174. * Simple heatmap
  175. * @sample highcharts/demo/heatmap-canvas/
  176. * Heavy heatmap
  177. *
  178. * @extends plotOptions.scatter
  179. * @excluding animationLimit, connectEnds, connectNulls, dashStyle,
  180. * findNearestPointBy, getExtremesFromAll, jitter, linecap,
  181. * lineWidth, marker, pointInterval, pointIntervalUnit,
  182. * pointRange, pointStart, shadow, softThreshold, stacking,
  183. * step, threshold
  184. * @product highcharts highmaps
  185. * @optionparent plotOptions.heatmap
  186. */
  187. , {
  188. /**
  189. * Animation is disabled by default on the heatmap series.
  190. */
  191. animation: false,
  192. /**
  193. * The border width for each heat map item.
  194. */
  195. borderWidth: 0,
  196. /**
  197. * Padding between the points in the heatmap.
  198. *
  199. * @type {number}
  200. * @default 0
  201. * @since 6.0
  202. * @apioption plotOptions.heatmap.pointPadding
  203. */
  204. /**
  205. * The main color of the series. In heat maps this color is rarely used,
  206. * as we mostly use the color to denote the value of each point. Unless
  207. * options are set in the [colorAxis](#colorAxis), the default value
  208. * is pulled from the [options.colors](#colors) array.
  209. *
  210. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  211. * @since 4.0
  212. * @product highcharts
  213. * @apioption plotOptions.heatmap.color
  214. */
  215. /**
  216. * The column size - how many X axis units each column in the heatmap
  217. * should span.
  218. *
  219. * @sample {highcharts} maps/demo/heatmap/
  220. * One day
  221. * @sample {highmaps} maps/demo/heatmap/
  222. * One day
  223. *
  224. * @type {number}
  225. * @default 1
  226. * @since 4.0
  227. * @product highcharts highmaps
  228. * @apioption plotOptions.heatmap.colsize
  229. */
  230. /**
  231. * The row size - how many Y axis units each heatmap row should span.
  232. *
  233. * @sample {highcharts} maps/demo/heatmap/
  234. * 1 by default
  235. * @sample {highmaps} maps/demo/heatmap/
  236. * 1 by default
  237. *
  238. * @type {number}
  239. * @default 1
  240. * @since 4.0
  241. * @product highcharts highmaps
  242. * @apioption plotOptions.heatmap.rowsize
  243. */
  244. /**
  245. * The color applied to null points. In styled mode, a general CSS class
  246. * is applied instead.
  247. *
  248. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  249. */
  250. nullColor: '#f7f7f7',
  251. dataLabels: {
  252. formatter: function () { // #2945
  253. return this.point.value;
  254. },
  255. inside: true,
  256. verticalAlign: 'middle',
  257. crop: false,
  258. overflow: false,
  259. padding: 0 // #3837
  260. },
  261. /** @ignore */
  262. marker: null,
  263. /**
  264. * @ignore
  265. */
  266. pointRange: null, // dynamically set to colsize by default
  267. tooltip: {
  268. pointFormat: '{point.x}, {point.y}: {point.value}<br/>'
  269. },
  270. states: {
  271. hover: {
  272. /** @ignore */
  273. halo: false, // #3406, halo is disabled on heatmaps by default
  274. /**
  275. * How much to brighten the point on interaction. Requires the main
  276. * color to be defined in hex or rgb(a) format.
  277. *
  278. * In styled mode, the hover brightening is by default replaced with
  279. * a fill-opacity set in the `.highcharts-point:hover` rule.
  280. */
  281. brightness: 0.2
  282. }
  283. }
  284. }, merge(colorSeriesMixin, {
  285. pointArrayMap: ['y', 'value'],
  286. hasPointSpecificOptions: true,
  287. getExtremesFromAll: true,
  288. directTouch: true,
  289. /**
  290. * Override the init method to add point ranges on both axes.
  291. *
  292. * @private
  293. * @function Highcharts.seriesTypes.heatmap#init
  294. */
  295. init: function () {
  296. var options;
  297. seriesTypes.scatter.prototype.init.apply(this, arguments);
  298. options = this.options;
  299. // #3758, prevent resetting in setData
  300. options.pointRange = pick(options.pointRange, options.colsize || 1);
  301. // general point range
  302. this.yAxis.axisPointRange = options.rowsize || 1;
  303. },
  304. /**
  305. * @private
  306. * @function Highcharts.seriesTypes.heatmap#translate
  307. */
  308. translate: function () {
  309. var series = this,
  310. options = series.options,
  311. xAxis = series.xAxis,
  312. yAxis = series.yAxis,
  313. seriesPointPadding = options.pointPadding || 0,
  314. between = function (x, a, b) {
  315. return Math.min(Math.max(a, x), b);
  316. },
  317. pointPlacement = series.pointPlacementToXValue(); // #7860
  318. series.generatePoints();
  319. series.points.forEach(function (point) {
  320. var xPad = (options.colsize || 1) / 2,
  321. yPad = (options.rowsize || 1) / 2,
  322. x1 = between(
  323. Math.round(
  324. xAxis.len -
  325. xAxis.translate(point.x - xPad,
  326. 0,
  327. 1,
  328. 0,
  329. 1,
  330. -pointPlacement)
  331. ),
  332. -xAxis.len, 2 * xAxis.len
  333. ),
  334. x2 = between(
  335. Math.round(
  336. xAxis.len -
  337. xAxis.translate(point.x + xPad,
  338. 0,
  339. 1,
  340. 0,
  341. 1,
  342. -pointPlacement)
  343. ),
  344. -xAxis.len, 2 * xAxis.len
  345. ),
  346. y1 = between(
  347. Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)),
  348. -yAxis.len, 2 * yAxis.len
  349. ),
  350. y2 = between(
  351. Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1)),
  352. -yAxis.len, 2 * yAxis.len
  353. ),
  354. pointPadding = pick(point.pointPadding, seriesPointPadding);
  355. // Set plotX and plotY for use in K-D-Tree and more
  356. point.plotX = point.clientX = (x1 + x2) / 2;
  357. point.plotY = (y1 + y2) / 2;
  358. point.shapeType = 'rect';
  359. point.shapeArgs = {
  360. x: Math.min(x1, x2) + pointPadding,
  361. y: Math.min(y1, y2) + pointPadding,
  362. width: Math.abs(x2 - x1) - pointPadding * 2,
  363. height: Math.abs(y2 - y1) - pointPadding * 2
  364. };
  365. });
  366. series.translateColors();
  367. },
  368. /**
  369. * @private
  370. * @function Highcharts.seriesTypes.heatmap#drawPoints
  371. */
  372. drawPoints: function () {
  373. // In styled mode, use CSS, otherwise the fill used in the style
  374. // sheet will take precedence over the fill attribute.
  375. var func = this.chart.styledMode ? 'css' : 'attr';
  376. seriesTypes.column.prototype.drawPoints.call(this);
  377. this.points.forEach(function (point) {
  378. point.graphic[func](this.colorAttribs(point));
  379. }, this);
  380. },
  381. /**
  382. * @ignore
  383. * @deprecated
  384. * @function Highcharts.seriesTypes.heatmap#animate
  385. */
  386. animate: noop,
  387. /**
  388. * @ignore
  389. * @deprecated
  390. * @function Highcharts.seriesTypes.heatmap#getBox
  391. */
  392. getBox: noop,
  393. /**
  394. * @private
  395. * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.heatmap#drawLegendSymbol
  396. */
  397. drawLegendSymbol: LegendSymbolMixin.drawRectangle,
  398. /**
  399. * @private
  400. * @borrows Highcharts.seriesTypes.column#alignDataLabel as Highcharts.seriesTypes.heatmap#alignDataLabel
  401. */
  402. alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
  403. /**
  404. * @private
  405. * @function Highcharts.seriesTypes.heatmap#getExtremes
  406. */
  407. getExtremes: function () {
  408. // Get the extremes from the value data
  409. Series.prototype.getExtremes.call(this, this.valueData);
  410. this.valueMin = this.dataMin;
  411. this.valueMax = this.dataMax;
  412. // Get the extremes from the y data
  413. Series.prototype.getExtremes.call(this);
  414. }
  415. }), H.extend({
  416. /**
  417. * @private
  418. * @function Highcharts.Point#haloPath
  419. *
  420. * @param {number} size
  421. *
  422. * @return {Highcharts.SVGPathArray}
  423. */
  424. haloPath: function (size) {
  425. if (!size) {
  426. return [];
  427. }
  428. var rect = this.shapeArgs;
  429. return [
  430. 'M', rect.x - size, rect.y - size,
  431. 'L', rect.x - size, rect.y + rect.height + size,
  432. rect.x + rect.width + size, rect.y + rect.height + size,
  433. rect.x + rect.width + size, rect.y - size,
  434. 'Z'
  435. ];
  436. }
  437. }, colorPointMixin)
  438. );
  439. /**
  440. * A `heatmap` series. If the [type](#series.heatmap.type) option is
  441. * not specified, it is inherited from [chart.type](#chart.type).
  442. *
  443. * @extends series,plotOptions.heatmap
  444. * @excluding dataParser, dataURL, marker, pointRange, stack
  445. * @product highcharts highmaps
  446. * @apioption series.heatmap
  447. */
  448. /**
  449. * An array of data points for the series. For the `heatmap` series
  450. * type, points can be given in the following ways:
  451. *
  452. * 1. An array of arrays with 3 or 2 values. In this case, the values
  453. * correspond to `x,y,value`. If the first value is a string, it is
  454. * applied as the name of the point, and the `x` value is inferred.
  455. * The `x` value can also be omitted, in which case the inner arrays
  456. * should be of length 2\. Then the `x` value is automatically calculated,
  457. * either starting at 0 and incremented by 1, or from `pointStart`
  458. * and `pointInterval` given in the series options.
  459. *
  460. * ```js
  461. * data: [
  462. * [0, 9, 7],
  463. * [1, 10, 4],
  464. * [2, 6, 3]
  465. * ]
  466. * ```
  467. *
  468. * 2. An array of objects with named values. The following snippet shows only a
  469. * few settings, see the complete options set below. If the total number of data
  470. * points exceeds the series' [turboThreshold](#series.heatmap.turboThreshold),
  471. * this option is not available.
  472. *
  473. * ```js
  474. * data: [{
  475. * x: 1,
  476. * y: 3,
  477. * value: 10,
  478. * name: "Point2",
  479. * color: "#00FF00"
  480. * }, {
  481. * x: 1,
  482. * y: 7,
  483. * value: 10,
  484. * name: "Point1",
  485. * color: "#FF00FF"
  486. * }]
  487. * ```
  488. *
  489. * @sample {highcharts} highcharts/chart/reflow-true/
  490. * Numerical values
  491. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  492. * Arrays of numeric x and y
  493. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  494. * Arrays of datetime x and y
  495. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  496. * Arrays of point.name and y
  497. * @sample {highcharts} highcharts/series/data-array-of-objects/
  498. * Config objects
  499. *
  500. * @type {Array<Array<number>|*>}
  501. * @extends series.line.data
  502. * @excluding marker
  503. * @product highcharts highmaps
  504. * @apioption series.heatmap.data
  505. */
  506. /**
  507. * The color of the point. In heat maps the point color is rarely set
  508. * explicitly, as we use the color to denote the `value`. Options for
  509. * this are set in the [colorAxis](#colorAxis) configuration.
  510. *
  511. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  512. * @product highcharts highmaps
  513. * @apioption series.heatmap.data.color
  514. */
  515. /**
  516. * The value of the point, resulting in a color controled by options
  517. * as set in the [colorAxis](#colorAxis) configuration.
  518. *
  519. * @type {number}
  520. * @product highcharts highmaps
  521. * @apioption series.heatmap.data.value
  522. */
  523. /**
  524. * The x value of the point. For datetime axes,
  525. * the X value is the timestamp in milliseconds since 1970.
  526. *
  527. * @type {number}
  528. * @product highcharts highmaps
  529. * @apioption series.heatmap.data.x
  530. */
  531. /**
  532. * The y value of the point.
  533. *
  534. * @type {number}
  535. * @product highcharts highmaps
  536. * @apioption series.heatmap.data.y
  537. */
  538. /**
  539. * Point padding for a single point.
  540. *
  541. * @sample maps/plotoptions/tilemap-pointpadding
  542. * Point padding on tiles
  543. *
  544. * @type {number}
  545. * @product highcharts highmaps
  546. * @apioption series.heatmap.data.pointPadding
  547. */
  548. }(Highcharts));
  549. (function (H) {
  550. /* *
  551. * Tilemaps module
  552. *
  553. * (c) 2010-2017 Highsoft AS
  554. * Author: Øystein Moseng
  555. *
  556. * License: www.highcharts.com/license
  557. */
  558. var seriesType = H.seriesType,
  559. pick = H.pick,
  560. // Utility func to get the middle number of 3
  561. between = function (x, a, b) {
  562. return Math.min(Math.max(a, x), b);
  563. },
  564. // Utility func to get padding definition from tile size division
  565. tilePaddingFromTileSize = function (series, xDiv, yDiv) {
  566. var options = series.options;
  567. return {
  568. xPad: (options.colsize || 1) / -xDiv,
  569. yPad: (options.rowsize || 1) / -yDiv
  570. };
  571. };
  572. // Map of shape types.
  573. H.tileShapeTypes = {
  574. // Hexagon shape type.
  575. hexagon: {
  576. alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel,
  577. getSeriesPadding: function (series) {
  578. return tilePaddingFromTileSize(series, 3, 2);
  579. },
  580. haloPath: function (size) {
  581. if (!size) {
  582. return [];
  583. }
  584. var hexagon = this.tileEdges;
  585. return [
  586. 'M', hexagon.x2 - size, hexagon.y1 + size,
  587. 'L', hexagon.x3 + size, hexagon.y1 + size,
  588. hexagon.x4 + size * 1.5, hexagon.y2,
  589. hexagon.x3 + size, hexagon.y3 - size,
  590. hexagon.x2 - size, hexagon.y3 - size,
  591. hexagon.x1 - size * 1.5, hexagon.y2,
  592. 'Z'
  593. ];
  594. },
  595. translate: function () {
  596. var series = this,
  597. options = series.options,
  598. xAxis = series.xAxis,
  599. yAxis = series.yAxis,
  600. seriesPointPadding = options.pointPadding || 0,
  601. xPad = (options.colsize || 1) / 3,
  602. yPad = (options.rowsize || 1) / 2,
  603. yShift;
  604. series.generatePoints();
  605. series.points.forEach(function (point) {
  606. var x1 = between(
  607. Math.floor(
  608. xAxis.len -
  609. xAxis.translate(point.x - xPad * 2, 0, 1, 0, 1)
  610. ), -xAxis.len, 2 * xAxis.len
  611. ),
  612. x2 = between(
  613. Math.floor(
  614. xAxis.len -
  615. xAxis.translate(point.x - xPad, 0, 1, 0, 1)
  616. ), -xAxis.len, 2 * xAxis.len
  617. ),
  618. x3 = between(
  619. Math.floor(
  620. xAxis.len -
  621. xAxis.translate(point.x + xPad, 0, 1, 0, 1)
  622. ), -xAxis.len, 2 * xAxis.len
  623. ),
  624. x4 = between(
  625. Math.floor(
  626. xAxis.len -
  627. xAxis.translate(point.x + xPad * 2, 0, 1, 0, 1)
  628. ), -xAxis.len, 2 * xAxis.len
  629. ),
  630. y1 = between(
  631. Math.floor(yAxis.translate(point.y - yPad, 0, 1, 0, 1)),
  632. -yAxis.len,
  633. 2 * yAxis.len
  634. ),
  635. y2 = between(
  636. Math.floor(yAxis.translate(point.y, 0, 1, 0, 1)),
  637. -yAxis.len,
  638. 2 * yAxis.len
  639. ),
  640. y3 = between(
  641. Math.floor(yAxis.translate(point.y + yPad, 0, 1, 0, 1)),
  642. -yAxis.len,
  643. 2 * yAxis.len
  644. ),
  645. pointPadding = pick(point.pointPadding, seriesPointPadding),
  646. // We calculate the point padding of the midpoints to
  647. // preserve the angles of the shape.
  648. midPointPadding = pointPadding *
  649. Math.abs(x2 - x1) / Math.abs(y3 - y2),
  650. xMidPadding = xAxis.reversed ?
  651. -midPointPadding : midPointPadding,
  652. xPointPadding = xAxis.reversed ?
  653. -pointPadding : pointPadding,
  654. yPointPadding = yAxis.reversed ?
  655. -pointPadding : pointPadding;
  656. // Shift y-values for every second grid column
  657. if (point.x % 2) {
  658. yShift = yShift || Math.round(Math.abs(y3 - y1) / 2) *
  659. // We have to reverse the shift for reversed y-axes
  660. (yAxis.reversed ? -1 : 1);
  661. y1 += yShift;
  662. y2 += yShift;
  663. y3 += yShift;
  664. }
  665. // Set plotX and plotY for use in K-D-Tree and more
  666. point.plotX = point.clientX = (x2 + x3) / 2;
  667. point.plotY = y2;
  668. // Apply point padding to translated coordinates
  669. x1 += xMidPadding + xPointPadding;
  670. x2 += xPointPadding;
  671. x3 -= xPointPadding;
  672. x4 -= xMidPadding + xPointPadding;
  673. y1 -= yPointPadding;
  674. y3 += yPointPadding;
  675. // Store points for halo creation
  676. point.tileEdges = {
  677. x1: x1, x2: x2, x3: x3, x4: x4, y1: y1, y2: y2, y3: y3
  678. };
  679. // Finally set the shape for this point
  680. point.shapeType = 'path';
  681. point.shapeArgs = {
  682. d: [
  683. 'M', x2, y1,
  684. 'L', x3, y1,
  685. x4, y2,
  686. x3, y3,
  687. x2, y3,
  688. x1, y2,
  689. 'Z'
  690. ]
  691. };
  692. });
  693. series.translateColors();
  694. }
  695. },
  696. // Diamond shape type.
  697. diamond: {
  698. alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel,
  699. getSeriesPadding: function (series) {
  700. return tilePaddingFromTileSize(series, 2, 2);
  701. },
  702. haloPath: function (size) {
  703. if (!size) {
  704. return [];
  705. }
  706. var diamond = this.tileEdges;
  707. return [
  708. 'M', diamond.x2, diamond.y1 + size,
  709. 'L', diamond.x3 + size, diamond.y2,
  710. diamond.x2, diamond.y3 - size,
  711. diamond.x1 - size, diamond.y2,
  712. 'Z'
  713. ];
  714. },
  715. translate: function () {
  716. var series = this,
  717. options = series.options,
  718. xAxis = series.xAxis,
  719. yAxis = series.yAxis,
  720. seriesPointPadding = options.pointPadding || 0,
  721. xPad = (options.colsize || 1),
  722. yPad = (options.rowsize || 1) / 2,
  723. yShift;
  724. series.generatePoints();
  725. series.points.forEach(function (point) {
  726. var x1 = between(
  727. Math.round(
  728. xAxis.len -
  729. xAxis.translate(point.x - xPad, 0, 1, 0, 0)
  730. ), -xAxis.len, 2 * xAxis.len
  731. ),
  732. x2 = between(
  733. Math.round(
  734. xAxis.len -
  735. xAxis.translate(point.x, 0, 1, 0, 0)
  736. ), -xAxis.len, 2 * xAxis.len
  737. ),
  738. x3 = between(
  739. Math.round(
  740. xAxis.len -
  741. xAxis.translate(point.x + xPad, 0, 1, 0, 0)
  742. ), -xAxis.len, 2 * xAxis.len
  743. ),
  744. y1 = between(
  745. Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 0)),
  746. -yAxis.len,
  747. 2 * yAxis.len
  748. ),
  749. y2 = between(
  750. Math.round(yAxis.translate(point.y, 0, 1, 0, 0)),
  751. -yAxis.len,
  752. 2 * yAxis.len
  753. ),
  754. y3 = between(
  755. Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 0)),
  756. -yAxis.len,
  757. 2 * yAxis.len
  758. ),
  759. pointPadding = pick(point.pointPadding, seriesPointPadding),
  760. // We calculate the point padding of the midpoints to
  761. // preserve the angles of the shape.
  762. midPointPadding = pointPadding *
  763. Math.abs(x2 - x1) / Math.abs(y3 - y2),
  764. xPointPadding = xAxis.reversed ?
  765. -midPointPadding : midPointPadding,
  766. yPointPadding = yAxis.reversed ?
  767. -pointPadding : pointPadding;
  768. // Shift y-values for every second grid column
  769. // We have to reverse the shift for reversed y-axes
  770. if (point.x % 2) {
  771. yShift = Math.abs(y3 - y1) / 2 * (yAxis.reversed ? -1 : 1);
  772. y1 += yShift;
  773. y2 += yShift;
  774. y3 += yShift;
  775. }
  776. // Set plotX and plotY for use in K-D-Tree and more
  777. point.plotX = point.clientX = x2;
  778. point.plotY = y2;
  779. // Apply point padding to translated coordinates
  780. x1 += xPointPadding;
  781. x3 -= xPointPadding;
  782. y1 -= yPointPadding;
  783. y3 += yPointPadding;
  784. // Store points for halo creation
  785. point.tileEdges = {
  786. x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3
  787. };
  788. // Set this point's shape parameters
  789. point.shapeType = 'path';
  790. point.shapeArgs = {
  791. d: [
  792. 'M', x2, y1,
  793. 'L', x3, y2,
  794. x2, y3,
  795. x1, y2,
  796. 'Z'
  797. ]
  798. };
  799. });
  800. series.translateColors();
  801. }
  802. },
  803. // Circle shape type.
  804. circle: {
  805. alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel,
  806. getSeriesPadding: function (series) {
  807. return tilePaddingFromTileSize(series, 2, 2);
  808. },
  809. haloPath: function (size) {
  810. return H.seriesTypes.scatter.prototype.pointClass.prototype.haloPath
  811. .call(
  812. this,
  813. size + (size && this.radius)
  814. );
  815. },
  816. translate: function () {
  817. var series = this,
  818. options = series.options,
  819. xAxis = series.xAxis,
  820. yAxis = series.yAxis,
  821. seriesPointPadding = options.pointPadding || 0,
  822. yRadius = (options.rowsize || 1) / 2,
  823. colsize = (options.colsize || 1),
  824. colsizePx,
  825. yRadiusPx,
  826. xRadiusPx,
  827. radius,
  828. forceNextRadiusCompute = false;
  829. series.generatePoints();
  830. series.points.forEach(function (point) {
  831. var x = between(
  832. Math.round(
  833. xAxis.len -
  834. xAxis.translate(point.x, 0, 1, 0, 0)
  835. ), -xAxis.len, 2 * xAxis.len
  836. ),
  837. y = between(
  838. Math.round(yAxis.translate(point.y, 0, 1, 0, 0)),
  839. -yAxis.len,
  840. 2 * yAxis.len
  841. ),
  842. pointPadding = seriesPointPadding,
  843. hasPerPointPadding = false;
  844. // If there is point padding defined on a single point, add it
  845. if (point.pointPadding !== undefined) {
  846. pointPadding = point.pointPadding;
  847. hasPerPointPadding = true;
  848. forceNextRadiusCompute = true;
  849. }
  850. // Find radius if not found already.
  851. // Use the smallest one (x vs y) to avoid overlap.
  852. // Note that the radius will be recomputed for each series.
  853. // Ideal (max) x radius is dependent on y radius:
  854. /*
  855. * (circle 2)
  856. * (circle 3)
  857. | yRadiusPx
  858. (circle 1) *-------|
  859. colsizePx
  860. The distance between circle 1 and 3 (and circle 2 and 3) is
  861. 2r, which is the hypotenuse of the triangle created by
  862. colsizePx and yRadiusPx. If the distance between circle 2
  863. and circle 1 is less than 2r, we use half of that distance
  864. instead (yRadiusPx).
  865. */
  866. if (!radius || forceNextRadiusCompute) {
  867. colsizePx = Math.abs(
  868. between(
  869. Math.floor(
  870. xAxis.len -
  871. xAxis.translate(point.x + colsize, 0, 1, 0, 0)
  872. ), -xAxis.len, 2 * xAxis.len
  873. ) - x
  874. );
  875. yRadiusPx = Math.abs(
  876. between(
  877. Math.floor(
  878. yAxis.translate(point.y + yRadius, 0, 1, 0, 0)
  879. ), -yAxis.len, 2 * yAxis.len
  880. ) - y
  881. );
  882. xRadiusPx = Math.floor(
  883. Math.sqrt(
  884. (colsizePx * colsizePx + yRadiusPx * yRadiusPx)
  885. ) / 2
  886. );
  887. radius = Math.min(
  888. colsizePx, xRadiusPx, yRadiusPx
  889. ) - pointPadding;
  890. // If we have per point padding we need to always compute
  891. // the radius for this point and the next. If we used to
  892. // have per point padding but don't anymore, don't force
  893. // compute next radius.
  894. if (forceNextRadiusCompute && !hasPerPointPadding) {
  895. forceNextRadiusCompute = false;
  896. }
  897. }
  898. // Shift y-values for every second grid column.
  899. // Note that we always use the optimal y axis radius for this.
  900. // Also note: We have to reverse the shift for reversed y-axes.
  901. if (point.x % 2) {
  902. y += yRadiusPx * (yAxis.reversed ? -1 : 1);
  903. }
  904. // Set plotX and plotY for use in K-D-Tree and more
  905. point.plotX = point.clientX = x;
  906. point.plotY = y;
  907. // Save radius for halo
  908. point.radius = radius;
  909. // Set this point's shape parameters
  910. point.shapeType = 'circle';
  911. point.shapeArgs = {
  912. x: x,
  913. y: y,
  914. r: radius
  915. };
  916. });
  917. series.translateColors();
  918. }
  919. },
  920. // Square shape type.
  921. square: {
  922. alignDataLabel: H.seriesTypes.heatmap.prototype.alignDataLabel,
  923. translate: H.seriesTypes.heatmap.prototype.translate,
  924. getSeriesPadding: function () {
  925. },
  926. haloPath: H.seriesTypes.heatmap.prototype.pointClass.prototype.haloPath
  927. }
  928. };
  929. // Extension to add pixel padding for series. Uses getSeriesPixelPadding on each
  930. // series and adds the largest padding required. If no series has this function
  931. // defined, we add nothing.
  932. H.addEvent(H.Axis, 'afterSetAxisTranslation', function () {
  933. if (this.recomputingForTilemap) {
  934. return;
  935. }
  936. var axis = this,
  937. // Find which series' padding to use
  938. seriesPadding = axis.series
  939. .map(function (series) {
  940. return series.getSeriesPixelPadding &&
  941. series.getSeriesPixelPadding(axis);
  942. })
  943. .reduce(function (a, b) {
  944. return (a && a.padding) > (b && b.padding) ? a : b;
  945. }, undefined) ||
  946. {
  947. padding: 0,
  948. axisLengthFactor: 1
  949. },
  950. lengthPadding = Math.round(
  951. seriesPadding.padding * seriesPadding.axisLengthFactor
  952. );
  953. // Don't waste time on this if we're not adding extra padding
  954. if (seriesPadding.padding) {
  955. // Recompute translation with new axis length now (minus padding)
  956. axis.len -= lengthPadding;
  957. axis.recomputingForTilemap = true;
  958. axis.setAxisTranslation();
  959. delete axis.recomputingForTilemap;
  960. axis.minPixelPadding += seriesPadding.padding;
  961. axis.len += lengthPadding;
  962. }
  963. });
  964. /**
  965. * @private
  966. * @class
  967. * @name Highcharts.seriesTypes.tilemap
  968. *
  969. * @augments Highcharts.Series
  970. */
  971. seriesType('tilemap', 'heatmap'
  972. /**
  973. * A tilemap series is a type of heatmap where the tile shapes are configurable.
  974. *
  975. * @sample highcharts/demo/honeycomb-usa/
  976. * Honeycomb tilemap, USA
  977. * @sample maps/plotoptions/honeycomb-brazil/
  978. * Honeycomb tilemap, Brazil
  979. * @sample maps/plotoptions/honeycomb-china/
  980. * Honeycomb tilemap, China
  981. * @sample maps/plotoptions/honeycomb-europe/
  982. * Honeycomb tilemap, Europe
  983. * @sample maps/demo/circlemap-africa/
  984. * Circlemap tilemap, Africa
  985. * @sample maps/demo/diamondmap
  986. * Diamondmap tilemap
  987. *
  988. * @extends plotOptions.heatmap
  989. * @since 6.0.0
  990. * @excluding jitter, joinBy, shadow, allAreas, mapData, data
  991. * @product highcharts highmaps
  992. * @optionparent plotOptions.tilemap
  993. */
  994. , { // Default options
  995. states: {
  996. hover: {
  997. halo: {
  998. enabled: true,
  999. size: 2,
  1000. opacity: 0.5,
  1001. attributes: {
  1002. zIndex: 3
  1003. }
  1004. }
  1005. }
  1006. },
  1007. /**
  1008. * The padding between points in the tilemap.
  1009. *
  1010. * @sample maps/plotoptions/tilemap-pointpadding
  1011. * Point padding on tiles
  1012. */
  1013. pointPadding: 2,
  1014. /**
  1015. * The column size - how many X axis units each column in the tilemap
  1016. * should span. Works as in [Heatmaps](#plotOptions.heatmap.colsize).
  1017. *
  1018. * @sample {highcharts} maps/demo/heatmap/
  1019. * One day
  1020. * @sample {highmaps} maps/demo/heatmap/
  1021. * One day
  1022. *
  1023. * @type {number}
  1024. * @default 1
  1025. * @product highcharts highmaps
  1026. * @apioption plotOptions.tilemap.colsize
  1027. */
  1028. /**
  1029. * The row size - how many Y axis units each tilemap row should span.
  1030. * Analogous to [colsize](#plotOptions.tilemap.colsize).
  1031. *
  1032. * @sample {highcharts} maps/demo/heatmap/
  1033. * 1 by default
  1034. * @sample {highmaps} maps/demo/heatmap/
  1035. * 1 by default
  1036. *
  1037. * @type {number}
  1038. * @default 1
  1039. * @product highcharts highmaps
  1040. * @apioption plotOptions.tilemap.rowsize
  1041. */
  1042. /**
  1043. * The shape of the tiles in the tilemap. Possible values are `hexagon`,
  1044. * `circle`, `diamond`, and `square`.
  1045. *
  1046. * @sample maps/demo/circlemap-africa
  1047. * Circular tile shapes
  1048. * @sample maps/demo/diamondmap
  1049. * Diamond tile shapes
  1050. *
  1051. * @validvalue ["circle", "diamond", "hexagon", "square"]
  1052. */
  1053. tileShape: 'hexagon'
  1054. }, { // Prototype functions
  1055. // Set tile shape object on series
  1056. setOptions: function () {
  1057. // Call original function
  1058. var ret = H.seriesTypes.heatmap.prototype.setOptions.apply(
  1059. this,
  1060. Array.prototype.slice.call(arguments)
  1061. );
  1062. this.tileShape = H.tileShapeTypes[ret.tileShape];
  1063. return ret;
  1064. },
  1065. // Use the shape's defined data label alignment function
  1066. alignDataLabel: function () {
  1067. return this.tileShape.alignDataLabel.apply(
  1068. this,
  1069. Array.prototype.slice.call(arguments)
  1070. );
  1071. },
  1072. // Get metrics for padding of axis for this series
  1073. getSeriesPixelPadding: function (axis) {
  1074. var isX = axis.isXAxis,
  1075. padding = this.tileShape.getSeriesPadding(this),
  1076. coord1,
  1077. coord2;
  1078. // If the shape type does not require padding, return no-op padding
  1079. if (!padding) {
  1080. return {
  1081. padding: 0,
  1082. axisLengthFactor: 1
  1083. };
  1084. }
  1085. // Use translate to compute how far outside the points we
  1086. // draw, and use this difference as padding.
  1087. coord1 = Math.round(
  1088. axis.translate(
  1089. isX ?
  1090. padding.xPad * 2 :
  1091. padding.yPad,
  1092. 0, 1, 0, 1
  1093. )
  1094. );
  1095. coord2 = Math.round(
  1096. axis.translate(
  1097. isX ? padding.xPad : 0,
  1098. 0, 1, 0, 1
  1099. )
  1100. );
  1101. return {
  1102. padding: Math.abs(coord1 - coord2) || 0,
  1103. // Offset the yAxis length to compensate for shift. Setting the
  1104. // length factor to 2 would add the same margin to max as min.
  1105. // Now we only add a slight bit of the min margin to max, as we
  1106. // don't actually draw outside the max bounds. For the xAxis we
  1107. // draw outside on both sides so we add the same margin to min
  1108. // and max.
  1109. axisLengthFactor: isX ? 2 : 1.1
  1110. };
  1111. },
  1112. // Use translate from tileShape
  1113. translate: function () {
  1114. return this.tileShape.translate.apply(
  1115. this,
  1116. Array.prototype.slice.call(arguments)
  1117. );
  1118. }
  1119. }, H.extend({
  1120. /**
  1121. * @private
  1122. * @function Highcharts.Point#haloPath
  1123. *
  1124. * @return {Highcharts.SVGPathArray}
  1125. */
  1126. haloPath: function () {
  1127. return this.series.tileShape.haloPath.apply(
  1128. this,
  1129. Array.prototype.slice.call(arguments)
  1130. );
  1131. }
  1132. }, H.colorPointMixin));
  1133. /**
  1134. * A `tilemap` series. If the [type](#series.tilemap.type) option is
  1135. * not specified, it is inherited from [chart.type](#chart.type).
  1136. *
  1137. * @extends series,plotOptions.tilemap
  1138. * @excluding allAreas, dataParser, dataURL, joinBy, mapData, marker,
  1139. * pointRange, shadow, stack
  1140. * @product highcharts highmaps
  1141. * @apioption series.tilemap
  1142. */
  1143. /**
  1144. * An array of data points for the series. For the `tilemap` series
  1145. * type, points can be given in the following ways:
  1146. *
  1147. * 1. An array of arrays with 3 or 2 values. In this case, the values correspond
  1148. * to `x,y,value`. If the first value is a string, it is applied as the name
  1149. * of the point, and the `x` value is inferred. The `x` value can also be
  1150. * omitted, in which case the inner arrays should be of length 2\. Then the
  1151. * `x` value is automatically calculated, either starting at 0 and
  1152. * incremented by 1, or from `pointStart` and `pointInterval` given in the
  1153. * series options.
  1154. * ```js
  1155. * data: [
  1156. * [0, 9, 7],
  1157. * [1, 10, 4],
  1158. * [2, 6, 3]
  1159. * ]
  1160. * ```
  1161. *
  1162. * 2. An array of objects with named values. The objects are point configuration
  1163. * objects as seen below. If the total number of data points exceeds the
  1164. * series' [turboThreshold](#series.tilemap.turboThreshold), this option is
  1165. * not available.
  1166. * ```js
  1167. * data: [{
  1168. * x: 1,
  1169. * y: 3,
  1170. * value: 10,
  1171. * name: "Point2",
  1172. * color: "#00FF00"
  1173. * }, {
  1174. * x: 1,
  1175. * y: 7,
  1176. * value: 10,
  1177. * name: "Point1",
  1178. * color: "#FF00FF"
  1179. * }]
  1180. * ```
  1181. *
  1182. * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid
  1183. * coordinates are offset.
  1184. *
  1185. * @sample maps/series/tilemap-gridoffset
  1186. * Offset grid coordinates
  1187. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1188. * Arrays of numeric x and y
  1189. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1190. * Arrays of datetime x and y
  1191. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1192. * Arrays of point.name and y
  1193. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1194. * Config objects
  1195. *
  1196. * @type {Array<Array<(number|string),number>|Array<(number|string),number,number>|*>}
  1197. * @extends series.heatmap.data
  1198. * @excluding marker
  1199. * @product highcharts highmaps
  1200. * @apioption series.tilemap.data
  1201. */
  1202. /**
  1203. * The color of the point. In tilemaps the point color is rarely set
  1204. * explicitly, as we use the color to denote the `value`. Options for
  1205. * this are set in the [colorAxis](#colorAxis) configuration.
  1206. *
  1207. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  1208. * @product highcharts highmaps
  1209. * @apioption series.tilemap.data.color
  1210. */
  1211. /**
  1212. * The x coordinate of the point.
  1213. *
  1214. * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid
  1215. * coordinates are offset.
  1216. *
  1217. * @sample maps/series/tilemap-gridoffset
  1218. * Offset grid coordinates
  1219. *
  1220. * @type {number}
  1221. * @product highcharts highmaps
  1222. * @apioption series.tilemap.data.x
  1223. */
  1224. /**
  1225. * The y coordinate of the point.
  1226. *
  1227. * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid
  1228. * coordinates are offset.
  1229. *
  1230. * @sample maps/series/tilemap-gridoffset
  1231. * Offset grid coordinates
  1232. *
  1233. * @type {number}
  1234. * @product highcharts highmaps
  1235. * @apioption series.tilemap.data.y
  1236. */
  1237. }(Highcharts));
  1238. return (function () {
  1239. }());
  1240. }));