tilemap.src.js 41 KB

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