Map.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /* *
  2. *
  3. * (c) 2010-2019 Torstein Honsi
  4. *
  5. * License: www.highcharts.com/license
  6. *
  7. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  8. *
  9. * */
  10. 'use strict';
  11. import H from '../parts/Globals.js';
  12. import U from '../parts/Utilities.js';
  13. var extend = U.extend, pick = U.pick;
  14. import '../parts/Options.js';
  15. import '../parts/Chart.js';
  16. import '../parts/SvgRenderer.js';
  17. var Chart = H.Chart, defaultOptions = H.defaultOptions, merge = H.merge, Renderer = H.Renderer, SVGRenderer = H.SVGRenderer, VMLRenderer = H.VMLRenderer;
  18. // Add language
  19. extend(defaultOptions.lang, {
  20. zoomIn: 'Zoom in',
  21. zoomOut: 'Zoom out'
  22. });
  23. // Set the default map navigation options
  24. /**
  25. * @product highmaps
  26. * @optionparent mapNavigation
  27. */
  28. defaultOptions.mapNavigation = {
  29. /**
  30. * General options for the map navigation buttons. Individual options
  31. * can be given from the [mapNavigation.buttons](#mapNavigation.buttons)
  32. * option set.
  33. *
  34. * @sample {highmaps} maps/mapnavigation/button-theme/
  35. * Theming the navigation buttons
  36. */
  37. buttonOptions: {
  38. /**
  39. * What box to align the buttons to. Possible values are `plotBox`
  40. * and `spacingBox`.
  41. *
  42. * @type {Highcharts.ButtonRelativeToValue}
  43. */
  44. alignTo: 'plotBox',
  45. /**
  46. * The alignment of the navigation buttons.
  47. *
  48. * @type {Highcharts.AlignValue}
  49. */
  50. align: 'left',
  51. /**
  52. * The vertical alignment of the buttons. Individual alignment can
  53. * be adjusted by each button's `y` offset.
  54. *
  55. * @type {Highcharts.VerticalAlignValue}
  56. */
  57. verticalAlign: 'top',
  58. /**
  59. * The X offset of the buttons relative to its `align` setting.
  60. */
  61. x: 0,
  62. /**
  63. * The width of the map navigation buttons.
  64. */
  65. width: 18,
  66. /**
  67. * The pixel height of the map navigation buttons.
  68. */
  69. height: 18,
  70. /**
  71. * Padding for the navigation buttons.
  72. *
  73. * @since 5.0.0
  74. */
  75. padding: 5,
  76. /**
  77. * Text styles for the map navigation buttons.
  78. *
  79. * @type {Highcharts.CSSObject}
  80. * @default {"fontSize": "15px", "fontWeight": "bold"}
  81. */
  82. style: {
  83. /** @ignore */
  84. fontSize: '15px',
  85. /** @ignore */
  86. fontWeight: 'bold'
  87. },
  88. /**
  89. * A configuration object for the button theme. The object accepts
  90. * SVG properties like `stroke-width`, `stroke` and `fill`. Tri-state
  91. * button styles are supported by the `states.hover` and `states.select`
  92. * objects.
  93. *
  94. * @sample {highmaps} maps/mapnavigation/button-theme/
  95. * Themed navigation buttons
  96. *
  97. * @type {Highcharts.SVGAttributes}
  98. * @default {"stroke-width": 1, "text-align": "center"}
  99. */
  100. theme: {
  101. /** @ignore */
  102. 'stroke-width': 1,
  103. /** @ignore */
  104. 'text-align': 'center'
  105. }
  106. },
  107. /**
  108. * The individual buttons for the map navigation. This usually includes
  109. * the zoom in and zoom out buttons. Properties for each button is
  110. * inherited from
  111. * [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while
  112. * individual options can be overridden. But default, the `onclick`, `text`
  113. * and `y` options are individual.
  114. */
  115. buttons: {
  116. /**
  117. * Options for the zoom in button. Properties for the zoom in and zoom
  118. * out buttons are inherited from
  119. * [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while
  120. * individual options can be overridden. By default, the `onclick`,
  121. * `text` and `y` options are individual.
  122. *
  123. * @extends mapNavigation.buttonOptions
  124. */
  125. zoomIn: {
  126. // eslint-disable-next-line valid-jsdoc
  127. /**
  128. * Click handler for the button.
  129. *
  130. * @type {Function}
  131. * @default function () { this.mapZoom(0.5); }
  132. */
  133. onclick: function () {
  134. this.mapZoom(0.5);
  135. },
  136. /**
  137. * The text for the button. The tooltip (title) is a language option
  138. * given by [lang.zoomIn](#lang.zoomIn).
  139. */
  140. text: '+',
  141. /**
  142. * The position of the zoomIn button relative to the vertical
  143. * alignment.
  144. */
  145. y: 0
  146. },
  147. /**
  148. * Options for the zoom out button. Properties for the zoom in and
  149. * zoom out buttons are inherited from
  150. * [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while
  151. * individual options can be overridden. By default, the `onclick`,
  152. * `text` and `y` options are individual.
  153. *
  154. * @extends mapNavigation.buttonOptions
  155. */
  156. zoomOut: {
  157. // eslint-disable-next-line valid-jsdoc
  158. /**
  159. * Click handler for the button.
  160. *
  161. * @type {Function}
  162. * @default function () { this.mapZoom(2); }
  163. */
  164. onclick: function () {
  165. this.mapZoom(2);
  166. },
  167. /**
  168. * The text for the button. The tooltip (title) is a language option
  169. * given by [lang.zoomOut](#lang.zoomIn).
  170. */
  171. text: '-',
  172. /**
  173. * The position of the zoomOut button relative to the vertical
  174. * alignment.
  175. */
  176. y: 28
  177. }
  178. },
  179. /**
  180. * Whether to enable navigation buttons. By default it inherits the
  181. * [enabled](#mapNavigation.enabled) setting.
  182. *
  183. * @type {boolean}
  184. * @apioption mapNavigation.enableButtons
  185. */
  186. /**
  187. * Whether to enable map navigation. The default is not to enable
  188. * navigation, as many choropleth maps are simple and don't need it.
  189. * Additionally, when touch zoom and mousewheel zoom is enabled, it breaks
  190. * the default behaviour of these interactions in the website, and the
  191. * implementer should be aware of this.
  192. *
  193. * Individual interactions can be enabled separately, namely buttons,
  194. * multitouch zoom, double click zoom, double click zoom to element and
  195. * mousewheel zoom.
  196. *
  197. * @type {boolean}
  198. * @default false
  199. * @apioption mapNavigation.enabled
  200. */
  201. /**
  202. * Enables zooming in on an area on double clicking in the map. By default
  203. * it inherits the [enabled](#mapNavigation.enabled) setting.
  204. *
  205. * @type {boolean}
  206. * @apioption mapNavigation.enableDoubleClickZoom
  207. */
  208. /**
  209. * Whether to zoom in on an area when that area is double clicked.
  210. *
  211. * @sample {highmaps} maps/mapnavigation/doubleclickzoomto/
  212. * Enable double click zoom to
  213. *
  214. * @type {boolean}
  215. * @default false
  216. * @apioption mapNavigation.enableDoubleClickZoomTo
  217. */
  218. /**
  219. * Enables zooming by mouse wheel. By default it inherits the [enabled](
  220. * #mapNavigation.enabled) setting.
  221. *
  222. * @type {boolean}
  223. * @apioption mapNavigation.enableMouseWheelZoom
  224. */
  225. /**
  226. * Whether to enable multitouch zooming. Note that if the chart covers the
  227. * viewport, this prevents the user from using multitouch and touchdrag on
  228. * the web page, so you should make sure the user is not trapped inside the
  229. * chart. By default it inherits the [enabled](#mapNavigation.enabled)
  230. * setting.
  231. *
  232. * @type {boolean}
  233. * @apioption mapNavigation.enableTouchZoom
  234. */
  235. /**
  236. * Sensitivity of mouse wheel or trackpad scrolling. 1 is no sensitivity,
  237. * while with 2, one mousewheel delta will zoom in 50%.
  238. *
  239. * @since 4.2.4
  240. */
  241. mouseWheelSensitivity: 1.1
  242. // enabled: false,
  243. // enableButtons: null, // inherit from enabled
  244. // enableTouchZoom: null, // inherit from enabled
  245. // enableDoubleClickZoom: null, // inherit from enabled
  246. // enableDoubleClickZoomTo: false
  247. // enableMouseWheelZoom: null, // inherit from enabled
  248. };
  249. /* eslint-disable valid-jsdoc */
  250. /**
  251. * Utility for reading SVG paths directly.
  252. *
  253. * @requires modules/map
  254. *
  255. * @function Highcharts.splitPath
  256. *
  257. * @param {string} path
  258. *
  259. * @return {Highcharts.SVGPathArray}
  260. */
  261. H.splitPath = function (path) {
  262. var i;
  263. // Move letters apart
  264. path = path.replace(/([A-Za-z])/g, ' $1 ');
  265. // Trim
  266. path = path.replace(/^\s*/, '').replace(/\s*$/, '');
  267. // Split on spaces and commas
  268. // Extra comma to escape gulp.scripts task
  269. path = path.split(/[ ,]+/);
  270. // Parse numbers
  271. for (i = 0; i < path.length; i++) {
  272. if (!/[a-zA-Z]/.test(path[i])) {
  273. path[i] = parseFloat(path[i]);
  274. }
  275. }
  276. return path;
  277. };
  278. /**
  279. * Contains all loaded map data for Highmaps.
  280. *
  281. * @requires modules/map
  282. *
  283. * @name Highcharts.maps
  284. * @type {Highcharts.Dictionary<*>}
  285. */
  286. H.maps = {};
  287. /**
  288. * Create symbols for the zoom buttons
  289. * @private
  290. */
  291. function selectiveRoundedRect(x, y, w, h, rTopLeft, rTopRight, rBottomRight, rBottomLeft) {
  292. return [
  293. 'M', x + rTopLeft, y,
  294. // top side
  295. 'L', x + w - rTopRight, y,
  296. // top right corner
  297. 'C', x + w - rTopRight / 2,
  298. y, x + w,
  299. y + rTopRight / 2, x + w, y + rTopRight,
  300. // right side
  301. 'L', x + w, y + h - rBottomRight,
  302. // bottom right corner
  303. 'C', x + w, y + h - rBottomRight / 2,
  304. x + w - rBottomRight / 2, y + h,
  305. x + w - rBottomRight, y + h,
  306. // bottom side
  307. 'L', x + rBottomLeft, y + h,
  308. // bottom left corner
  309. 'C', x + rBottomLeft / 2, y + h,
  310. x, y + h - rBottomLeft / 2,
  311. x, y + h - rBottomLeft,
  312. // left side
  313. 'L', x, y + rTopLeft,
  314. // top left corner
  315. 'C', x, y + rTopLeft / 2,
  316. x + rTopLeft / 2, y,
  317. x + rTopLeft, y,
  318. 'Z'
  319. ];
  320. }
  321. SVGRenderer.prototype.symbols.topbutton = function (x, y, w, h, attr) {
  322. return selectiveRoundedRect(x - 1, y - 1, w, h, attr.r, attr.r, 0, 0);
  323. };
  324. SVGRenderer.prototype.symbols.bottombutton = function (x, y, w, h, attr) {
  325. return selectiveRoundedRect(x - 1, y - 1, w, h, 0, 0, attr.r, attr.r);
  326. };
  327. // The symbol callbacks are generated on the SVGRenderer object in all browsers.
  328. // Even VML browsers need this in order to generate shapes in export. Now share
  329. // them with the VMLRenderer.
  330. if (Renderer === VMLRenderer) {
  331. ['topbutton', 'bottombutton'].forEach(function (shape) {
  332. VMLRenderer.prototype.symbols[shape] =
  333. SVGRenderer.prototype.symbols[shape];
  334. });
  335. }
  336. /**
  337. * The factory function for creating new map charts. Creates a new {@link
  338. * Highcharts.Chart|Chart} object with different default options than the basic
  339. * Chart.
  340. *
  341. * @requires modules/map
  342. *
  343. * @function Highcharts.mapChart
  344. *
  345. * @param {string|Highcharts.HTMLDOMElement} [renderTo]
  346. * The DOM element to render to, or its id.
  347. *
  348. * @param {Highcharts.Options} options
  349. * The chart options structure as described in the
  350. * [options reference](https://api.highcharts.com/highstock).
  351. *
  352. * @param {Highcharts.ChartCallbackFunction} [callback]
  353. * A function to execute when the chart object is finished loading and
  354. * rendering. In most cases the chart is built in one thread, but in
  355. * Internet Explorer version 8 or less the chart is sometimes
  356. * initialized before the document is ready, and in these cases the
  357. * chart object will not be finished synchronously. As a consequence,
  358. * code that relies on the newly built Chart object should always run in
  359. * the callback. Defining a
  360. * [chart.events.load](https://api.highcharts.com/highstock/chart.events.load)
  361. * handler is equivalent.
  362. *
  363. * @return {Highcharts.Chart}
  364. * The chart object.
  365. */
  366. H.Map = H.mapChart = function (a, b, c) {
  367. var hasRenderToArg = typeof a === 'string' || a.nodeName, options = arguments[hasRenderToArg ? 1 : 0], userOptions = options, hiddenAxis = {
  368. endOnTick: false,
  369. visible: false,
  370. minPadding: 0,
  371. maxPadding: 0,
  372. startOnTick: false
  373. }, seriesOptions, defaultCreditsOptions = H.getOptions().credits;
  374. /* For visual testing
  375. hiddenAxis.gridLineWidth = 1;
  376. hiddenAxis.gridZIndex = 10;
  377. hiddenAxis.tickPositions = undefined;
  378. // */
  379. // Don't merge the data
  380. seriesOptions = options.series;
  381. options.series = null;
  382. options = merge({
  383. chart: {
  384. panning: 'xy',
  385. type: 'map'
  386. },
  387. credits: {
  388. mapText: pick(defaultCreditsOptions.mapText, ' \u00a9 <a href="{geojson.copyrightUrl}">' +
  389. '{geojson.copyrightShort}</a>'),
  390. mapTextFull: pick(defaultCreditsOptions.mapTextFull, '{geojson.copyright}')
  391. },
  392. tooltip: {
  393. followTouchMove: false
  394. },
  395. xAxis: hiddenAxis,
  396. yAxis: merge(hiddenAxis, { reversed: true })
  397. }, options, // user's options
  398. {
  399. chart: {
  400. inverted: false,
  401. alignTicks: false
  402. }
  403. });
  404. options.series = userOptions.series = seriesOptions;
  405. return hasRenderToArg ?
  406. new Chart(a, options, c) :
  407. new Chart(options, b);
  408. };