123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- /* *
- *
- * (c) 2010-2021 Torstein Honsi
- *
- * License: www.highcharts.com/license
- *
- * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
- *
- * */
- 'use strict';
- import Chart from '../Core/Chart/Chart.js';
- import F from '../Core/FormatUtilities.js';
- var format = F.format;
- import H from '../Core/Globals.js';
- var win = H.win;
- import U from '../Core/Utilities.js';
- var error = U.error, extend = U.extend, merge = U.merge, wrap = U.wrap;
- /**
- * Represents the loose structure of a geographic JSON file.
- *
- * @interface Highcharts.GeoJSON
- */ /**
- * Full copyright note of the geographic data.
- * @name Highcharts.GeoJSON#copyright
- * @type {string|undefined}
- */ /**
- * Short copyright note of the geographic data suitable for watermarks.
- * @name Highcharts.GeoJSON#copyrightShort
- * @type {string|undefined}
- */ /**
- * Additional meta information based on the coordinate reference system.
- * @name Highcharts.GeoJSON#crs
- * @type {Highcharts.Dictionary<any>|undefined}
- */ /**
- * Data sets of geographic features.
- * @name Highcharts.GeoJSON#features
- * @type {Array<Highcharts.GeoJSONFeature>}
- */ /**
- * Map projections and transformations to be used when calculating between
- * lat/lon and chart values. Required for lat/lon support on maps. Allows
- * resizing, rotating, and moving portions of a map within its projected
- * coordinate system while still retaining lat/lon support. If using lat/lon
- * on a portion of the map that does not match a `hitZone`, the definition with
- * the key `default` is used.
- * @name Highcharts.GeoJSON#hc-transform
- * @type {Highcharts.Dictionary<Highcharts.GeoJSONTranslation>|undefined}
- */ /**
- * Title of the geographic data.
- * @name Highcharts.GeoJSON#title
- * @type {string|undefined}
- */ /**
- * Type of the geographic data. Type of an optimized map collection is
- * `FeatureCollection`.
- * @name Highcharts.GeoJSON#type
- * @type {string|undefined}
- */ /**
- * Version of the geographic data.
- * @name Highcharts.GeoJSON#version
- * @type {string|undefined}
- */
- /**
- * Data set of a geographic feature.
- * @interface Highcharts.GeoJSONFeature
- * @extends Highcharts.Dictionary<*>
- */ /**
- * Data type of the geographic feature.
- * @name Highcharts.GeoJSONFeature#type
- * @type {string}
- */
- /**
- * Describes the map projection and transformations applied to a portion of
- * a map.
- * @interface Highcharts.GeoJSONTranslation
- */ /**
- * The coordinate reference system used to generate this portion of the map.
- * @name Highcharts.GeoJSONTranslation#crs
- * @type {string}
- */ /**
- * Define the portion of the map that this defintion applies to. Defined as a
- * GeoJSON polygon feature object, with `type` and `coordinates` properties.
- * @name Highcharts.GeoJSONTranslation#hitZone
- * @type {Highcharts.Dictionary<*>|undefined}
- */ /**
- * Property for internal use for maps generated by Highsoft.
- * @name Highcharts.GeoJSONTranslation#jsonmarginX
- * @type {number|undefined}
- */ /**
- * Property for internal use for maps generated by Highsoft.
- * @name Highcharts.GeoJSONTranslation#jsonmarginY
- * @type {number|undefined}
- */ /**
- * Property for internal use for maps generated by Highsoft.
- * @name Highcharts.GeoJSONTranslation#jsonres
- * @type {number|undefined}
- */ /**
- * Specifies clockwise rotation of the coordinates after the projection, but
- * before scaling and panning. Defined in radians, relative to the coordinate
- * system origin.
- * @name Highcharts.GeoJSONTranslation#rotation
- * @type {number|undefined}
- */ /**
- * The scaling factor applied to the projected coordinates.
- * @name Highcharts.GeoJSONTranslation#scale
- * @type {number|undefined}
- */ /**
- * Property for internal use for maps generated by Highsoft.
- * @name Highcharts.GeoJSONTranslation#xoffset
- * @type {number|undefined}
- */ /**
- * X offset of projected coordinates after scaling.
- * @name Highcharts.GeoJSONTranslation#xpan
- * @type {number|undefined}
- */ /**
- * Property for internal use for maps generated by Highsoft.
- * @name Highcharts.GeoJSONTranslation#yoffset
- * @type {number|undefined}
- */ /**
- * Y offset of projected coordinates after scaling.
- * @name Highcharts.GeoJSONTranslation#ypan
- * @type {number|undefined}
- */
- /**
- * Result object of a map transformation.
- *
- * @interface Highcharts.MapCoordinateObject
- */ /**
- * X coordinate on the map.
- * @name Highcharts.MapCoordinateObject#x
- * @type {number}
- */ /**
- * Y coordinate on the map.
- * @name Highcharts.MapCoordinateObject#y
- * @type {number|null}
- */
- /**
- * A latitude/longitude object.
- *
- * @interface Highcharts.MapLatLonObject
- */ /**
- * The latitude.
- * @name Highcharts.MapLatLonObject#lat
- * @type {number}
- */ /**
- * The longitude.
- * @name Highcharts.MapLatLonObject#lon
- * @type {number}
- */
- ''; // detach doclets above
- /* eslint-disable no-invalid-this, valid-jsdoc */
- /**
- * Test for point in polygon. Polygon defined as array of [x,y] points.
- * @private
- */
- function pointInPolygon(point, polygon) {
- var i, j, rel1, rel2, c = false, x = point.x, y = point.y;
- for (i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
- rel1 = polygon[i][1] > y;
- rel2 = polygon[j][1] > y;
- if (rel1 !== rel2 &&
- (x < (polygon[j][0] -
- polygon[i][0]) * (y - polygon[i][1]) /
- (polygon[j][1] - polygon[i][1]) +
- polygon[i][0])) {
- c = !c;
- }
- }
- return c;
- }
- /**
- * Highmaps only. Get point from latitude and longitude using specified
- * transform definition.
- *
- * @requires modules/map
- *
- * @sample maps/series/latlon-transform/
- * Use specific transformation for lat/lon
- *
- * @function Highcharts.Chart#transformFromLatLon
- *
- * @param {Highcharts.MapLatLonObject} latLon
- * A latitude/longitude object.
- *
- * @param {*} transform
- * The transform definition to use as explained in the
- * {@link https://www.highcharts.com/docs/maps/latlon|documentation}.
- *
- * @return {Highcharts.MapCoordinateObject}
- * An object with `x` and `y` properties.
- */
- Chart.prototype.transformFromLatLon = function (latLon, transform) {
- /**
- * Allows to manually load the proj4 library from Highcharts options
- * instead of the `window`.
- * In case of loading the library from a `script` tag,
- * this option is not needed, it will be loaded from there by default.
- *
- * @type {function}
- * @product highmaps
- * @apioption chart.proj4
- */
- var proj4 = (this.userOptions.chart &&
- this.userOptions.chart.proj4 ||
- win.proj4);
- if (!proj4) {
- error(21, false, this);
- return {
- x: 0,
- y: null
- };
- }
- var projected = proj4(transform.crs, [latLon.lon, latLon.lat]), cosAngle = transform.cosAngle ||
- (transform.rotation && Math.cos(transform.rotation)), sinAngle = transform.sinAngle ||
- (transform.rotation && Math.sin(transform.rotation)), rotated = transform.rotation ? [
- projected[0] * cosAngle + projected[1] * sinAngle,
- -projected[0] * sinAngle + projected[1] * cosAngle
- ] : projected;
- return {
- x: ((rotated[0] - (transform.xoffset || 0)) * (transform.scale || 1) +
- (transform.xpan || 0)) * (transform.jsonres || 1) +
- (transform.jsonmarginX || 0),
- y: (((transform.yoffset || 0) - rotated[1]) * (transform.scale || 1) +
- (transform.ypan || 0)) * (transform.jsonres || 1) -
- (transform.jsonmarginY || 0)
- };
- };
- /**
- * Highmaps only. Get latLon from point using specified transform definition.
- * The method returns an object with the numeric properties `lat` and `lon`.
- *
- * @requires modules/map
- *
- * @sample maps/series/latlon-transform/
- * Use specific transformation for lat/lon
- *
- * @function Highcharts.Chart#transformToLatLon
- *
- * @param {Highcharts.Point|Highcharts.MapCoordinateObject} point
- * A `Point` instance, or any object containing the properties `x` and
- * `y` with numeric values.
- *
- * @param {*} transform
- * The transform definition to use as explained in the
- * {@link https://www.highcharts.com/docs/maps/latlon|documentation}.
- *
- * @return {Highcharts.MapLatLonObject|undefined}
- * An object with `lat` and `lon` properties.
- */
- Chart.prototype.transformToLatLon = function (point, transform) {
- if (typeof win.proj4 === 'undefined') {
- error(21, false, this);
- return;
- }
- var normalized = {
- x: ((point.x -
- (transform.jsonmarginX || 0)) / (transform.jsonres || 1) -
- (transform.xpan || 0)) / (transform.scale || 1) +
- (transform.xoffset || 0),
- y: ((-point.y - (transform.jsonmarginY || 0)) / (transform.jsonres || 1) +
- (transform.ypan || 0)) / (transform.scale || 1) +
- (transform.yoffset || 0)
- }, cosAngle = transform.cosAngle ||
- (transform.rotation && Math.cos(transform.rotation)), sinAngle = transform.sinAngle ||
- (transform.rotation && Math.sin(transform.rotation)),
- // Note: Inverted sinAngle to reverse rotation direction
- projected = win.proj4(transform.crs, 'WGS84', transform.rotation ? {
- x: normalized.x * cosAngle + normalized.y * -sinAngle,
- y: normalized.x * sinAngle + normalized.y * cosAngle
- } : normalized);
- return { lat: projected.y, lon: projected.x };
- };
- /**
- * Highmaps only. Calculate latitude/longitude values for a point. Returns an
- * object with the numeric properties `lat` and `lon`.
- *
- * @requires modules/map
- *
- * @sample maps/demo/latlon-advanced/
- * Advanced lat/lon demo
- *
- * @function Highcharts.Chart#fromPointToLatLon
- *
- * @param {Highcharts.Point|Highcharts.MapCoordinateObject} point
- * A `Point` instance or anything containing `x` and `y` properties with
- * numeric values.
- *
- * @return {Highcharts.MapLatLonObject|undefined}
- * An object with `lat` and `lon` properties.
- */
- Chart.prototype.fromPointToLatLon = function (point) {
- var transforms = this.mapTransforms, transform;
- if (!transforms) {
- error(22, false, this);
- return;
- }
- for (transform in transforms) {
- if (Object.hasOwnProperty.call(transforms, transform) &&
- transforms[transform].hitZone &&
- pointInPolygon({ x: point.x, y: -point.y }, transforms[transform].hitZone.coordinates[0])) {
- return this.transformToLatLon(point, transforms[transform]);
- }
- }
- return this.transformToLatLon(point, transforms['default'] // eslint-disable-line dot-notation
- );
- };
- /**
- * Highmaps only. Get chart coordinates from latitude/longitude. Returns an
- * object with x and y values corresponding to the `xAxis` and `yAxis`.
- *
- * @requires modules/map
- *
- * @sample maps/series/latlon-to-point/
- * Find a point from lat/lon
- *
- * @function Highcharts.Chart#fromLatLonToPoint
- *
- * @param {Highcharts.MapLatLonObject} latLon
- * Coordinates.
- *
- * @return {Highcharts.MapCoordinateObject}
- * X and Y coordinates in terms of chart axis values.
- */
- Chart.prototype.fromLatLonToPoint = function (latLon) {
- var transforms = this.mapTransforms, transform, coords;
- if (!transforms) {
- error(22, false, this);
- return {
- x: 0,
- y: null
- };
- }
- for (transform in transforms) {
- if (Object.hasOwnProperty.call(transforms, transform) &&
- transforms[transform].hitZone) {
- coords = this.transformFromLatLon(latLon, transforms[transform]);
- if (pointInPolygon({ x: coords.x, y: -coords.y }, transforms[transform].hitZone.coordinates[0])) {
- return coords;
- }
- }
- }
- return this.transformFromLatLon(latLon, transforms['default'] // eslint-disable-line dot-notation
- );
- };
- /**
- * Highmaps only. Restructure a GeoJSON object in preparation to be read
- * directly by the
- * {@link https://api.highcharts.com/highmaps/plotOptions.series.mapData|series.mapData}
- * option. The GeoJSON will be broken down to fit a specific Highcharts type,
- * either `map`, `mapline` or `mappoint`. Meta data in GeoJSON's properties
- * object will be copied directly over to {@link Point.properties} in Highmaps.
- *
- * @requires modules/map
- *
- * @sample maps/demo/geojson/
- * Simple areas
- * @sample maps/demo/geojson-multiple-types/
- * Multiple types
- *
- * @function Highcharts.geojson
- *
- * @param {Highcharts.GeoJSON} geojson
- * The GeoJSON structure to parse, represented as a JavaScript object
- * rather than a JSON string.
- *
- * @param {string} [hType=map]
- * The Highmaps series type to prepare for. Setting "map" will return
- * GeoJSON polygons and multipolygons. Setting "mapline" will return
- * GeoJSON linestrings and multilinestrings. Setting "mappoint" will
- * return GeoJSON points and multipoints.
- *
- * @return {Array<*>}
- * An object ready for the `mapData` option.
- */
- H.geojson = function (geojson, hType, series) {
- var mapData = [], path = [], polygonToPath = function (polygon) {
- polygon.forEach(function (point, i) {
- if (i === 0) {
- path.push(['M', point[0], -point[1]]);
- }
- else {
- path.push(['L', point[0], -point[1]]);
- }
- });
- };
- hType = hType || 'map';
- geojson.features.forEach(function (feature) {
- var geometry = feature.geometry, type = geometry.type, coordinates = geometry.coordinates, properties = feature.properties, point;
- path = [];
- if (hType === 'map' || hType === 'mapbubble') {
- if (type === 'Polygon') {
- coordinates.forEach(polygonToPath);
- path.push(['Z']);
- }
- else if (type === 'MultiPolygon') {
- coordinates.forEach(function (items) {
- items.forEach(polygonToPath);
- });
- path.push(['Z']);
- }
- if (path.length) {
- point = { path: path };
- }
- }
- else if (hType === 'mapline') {
- if (type === 'LineString') {
- polygonToPath(coordinates);
- }
- else if (type === 'MultiLineString') {
- coordinates.forEach(polygonToPath);
- }
- if (path.length) {
- point = { path: path };
- }
- }
- else if (hType === 'mappoint') {
- if (type === 'Point') {
- point = {
- x: coordinates[0],
- y: -coordinates[1]
- };
- }
- }
- if (point) {
- mapData.push(extend(point, {
- name: properties.name || properties.NAME,
- /**
- * In Highmaps, when data is loaded from GeoJSON, the GeoJSON
- * item's properies are copied over here.
- *
- * @requires modules/map
- * @name Highcharts.Point#properties
- * @type {*}
- */
- properties: properties
- }));
- }
- });
- // Create a credits text that includes map source, to be picked up in
- // Chart.addCredits
- if (series && geojson.copyrightShort) {
- series.chart.mapCredits = format(series.chart.options.credits.mapText, { geojson: geojson });
- series.chart.mapCreditsFull = format(series.chart.options.credits.mapTextFull, { geojson: geojson });
- }
- return mapData;
- };
- // Override addCredits to include map source by default
- wrap(Chart.prototype, 'addCredits', function (proceed, credits) {
- credits = merge(true, this.options.credits, credits);
- // Disable credits link if map credits enabled. This to allow for in-text
- // anchors.
- if (this.mapCredits) {
- credits.href = null;
- }
- proceed.call(this, credits);
- // Add full map credits to hover
- if (this.credits && this.mapCreditsFull) {
- this.credits.attr({
- title: this.mapCreditsFull
- });
- }
- });
|