package.es-modules.Maps.GeoJSONComposition.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of highcharts Show documentation
Show all versions of highcharts Show documentation
JavaScript charting framework
The newest version!
/* *
*
* (c) 2010-2024 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
'use strict';
import H from '../Core/Globals.js';
const { win } = H;
import T from '../Core/Templating.js';
const { format } = T;
import U from '../Core/Utilities.js';
const { error, extend, merge, wrap } = U;
/* *
*
* Composition
*
* */
var GeoJSONComposition;
(function (GeoJSONComposition) {
/* *
*
* Functions
*
* */
/**
* Deprecated. Use `MapView.lonLatToProjectedUnits` instead.
*
* @deprecated
*
* @requires modules/map
*
* @function Highcharts.Chart#fromLatLonToPoint
*
* @param {Highcharts.MapLonLatObject} lonLat
* Coordinates.
*
* @return {Highcharts.ProjectedXY}
* X and Y coordinates in terms of projected values
*/
function chartFromLatLonToPoint(lonLat) {
return this.mapView && this.mapView.lonLatToProjectedUnits(lonLat);
}
/**
* Deprecated. Use `MapView.projectedUnitsToLonLat` instead.
*
* @deprecated
*
* @requires modules/map
*
* @function Highcharts.Chart#fromPointToLatLon
*
* @param {Highcharts.Point|Highcharts.ProjectedXY} point
* A `Point` instance or anything containing `x` and `y` properties
* with numeric values.
*
* @return {Highcharts.MapLonLatObject|undefined}
* An object with `lat` and `lon` properties.
*/
function chartFromPointToLatLon(point) {
return this.mapView && this.mapView.projectedUnitsToLonLat(point);
}
/**
* Highcharts Maps 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.MapLonLatObject} 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 {ProjectedXY}
* An object with `x` and `y` properties.
*/
function chartTransformFromLatLon(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
*/
const proj4 = this.options.chart.proj4 || win.proj4;
if (!proj4) {
error(21, false, this);
return;
}
const { jsonmarginX = 0, jsonmarginY = 0, jsonres = 1, scale = 1, xoffset = 0, xpan = 0, yoffset = 0, ypan = 0 } = transform;
const 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] - xoffset) * scale + xpan) * jsonres + jsonmarginX,
y: -(((yoffset - rotated[1]) * scale + ypan) * jsonres - jsonmarginY)
};
}
/**
* Highcharts Maps 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.ProjectedXY} 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.MapLonLatObject|undefined}
* An object with `lat` and `lon` properties.
*/
function chartTransformToLatLon(point, transform) {
const proj4 = this.options.chart.proj4 || win.proj4;
if (!proj4) {
error(21, false, this);
return;
}
if (point.y === null) {
return;
}
const { jsonmarginX = 0, jsonmarginY = 0, jsonres = 1, scale = 1, xoffset = 0, xpan = 0, yoffset = 0, ypan = 0 } = transform;
const normalized = {
x: ((point.x - jsonmarginX) / jsonres - xpan) / scale + xoffset,
y: ((point.y - jsonmarginY) / jsonres + ypan) / scale + yoffset
}, 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 = 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 };
}
/** @private */
function compose(ChartClass) {
const chartProto = ChartClass.prototype;
if (!chartProto.transformFromLatLon) {
chartProto.fromLatLonToPoint = chartFromLatLonToPoint;
chartProto.fromPointToLatLon = chartFromPointToLatLon;
chartProto.transformFromLatLon = chartTransformFromLatLon;
chartProto.transformToLatLon = chartTransformToLatLon;
wrap(chartProto, 'addCredits', wrapChartAddCredit);
}
}
GeoJSONComposition.compose = compose;
/**
* Highcharts Maps only. Restructure a GeoJSON or TopoJSON object in
* preparation to be read directly by the
* {@link https://api.highcharts.com/highmaps/plotOptions.series.mapData|series.mapData}
* option. The object 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
* Highcharts Maps.
*
* @requires modules/map
*
* @sample maps/demo/geojson/ Simple areas
* @sample maps/demo/mapline-mappoint/ Multiple types
* @sample maps/series/mapdata-multiple/ Multiple map sources
*
* @function Highcharts.geojson
*
* @param {Highcharts.GeoJSON|Highcharts.TopoJSON} json
* The GeoJSON or TopoJSON structure to parse, represented as a
* JavaScript object.
*
* @param {string} [hType=map]
* The Highcharts Maps 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.
*/
function geojson(json, hType = 'map', series) {
const mapData = [];
const geojson = json.type === 'Topology' ? topo2geo(json) : json, features = geojson.features;
for (let i = 0, iEnd = features.length; i < iEnd; ++i) {
const feature = features[i], geometry = feature.geometry || {}, type = geometry.type, coordinates = geometry.coordinates, properties = feature.properties;
let pointOptions;
if ((hType === 'map' || hType === 'mapbubble') &&
(type === 'Polygon' || type === 'MultiPolygon')) {
if (coordinates.length) {
pointOptions = { geometry: { coordinates, type } };
}
}
else if (hType === 'mapline' &&
(type === 'LineString' ||
type === 'MultiLineString')) {
if (coordinates.length) {
pointOptions = { geometry: { coordinates, type } };
}
}
else if (hType === 'mappoint' && type === 'Point') {
if (coordinates.length) {
pointOptions = { geometry: { coordinates, type } };
}
}
if (pointOptions) {
const name = properties && (properties.name || properties.NAME), lon = properties && properties.lon, lat = properties && properties.lat;
mapData.push(extend(pointOptions, {
lat: typeof lat === 'number' ? lat : void 0,
lon: typeof lon === 'number' ? lon : void 0,
name: typeof name === 'string' ? name : void 0,
/**
* In Highcharts Maps, when data is loaded from GeoJSON, the
* GeoJSON item's properies are copied over here.
*
* @requires modules/map
* @name Highcharts.Point#properties
* @type {*}
*/
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;
}
GeoJSONComposition.geojson = geojson;
/**
* Convert a TopoJSON topology to GeoJSON. By default the first object is
* handled.
* Based on https://github.com/topojson/topojson-specification
*/
function topo2geo(topology, objectName) {
// Decode first object/feature as default
if (!objectName) {
objectName = Object.keys(topology.objects)[0];
}
const obj = topology.objects[objectName];
// Already decoded with the same title => return cache
if (obj['hc-decoded-geojson'] &&
obj['hc-decoded-geojson'].title === topology.title) {
return obj['hc-decoded-geojson'];
}
// Do the initial transform
let arcsArray = topology.arcs;
if (topology.transform) {
const arcs = topology.arcs, { scale, translate } = topology.transform;
let positionArray, x, y;
arcsArray = [];
for (let i = 0, iEnd = arcs.length; i < iEnd; ++i) {
const positions = arcs[i];
arcsArray.push(positionArray = []);
x = 0;
y = 0;
for (let j = 0, jEnd = positions.length; j < jEnd; ++j) {
positionArray.push([
(x += positions[j][0]) * scale[0] + translate[0],
(y += positions[j][1]) * scale[1] + translate[1]
]);
}
}
}
// Recurse down any depth of multi-dimensional arrays of arcs and insert
// the coordinates
const arcsToCoordinates = (arcs) => {
if (typeof arcs[0] === 'number') {
return arcs.reduce((coordinates, arcNo, i) => {
let arc = arcNo < 0 ? arcsArray[~arcNo] : arcsArray[arcNo];
// The first point of an arc is always identical to the last
// point of the previes arc, so slice it off to save further
// processing.
if (arcNo < 0) {
arc = arc.slice(0, i === 0 ? arc.length : arc.length - 1);
arc.reverse();
}
else if (i) {
arc = arc.slice(1);
}
return coordinates.concat(arc);
}, []);
}
return arcs.map(arcsToCoordinates);
};
const geometries = obj.geometries, features = [];
for (let i = 0, iEnd = geometries.length; i < iEnd; ++i) {
features.push({
type: 'Feature',
properties: geometries[i].properties,
geometry: {
type: geometries[i].type,
coordinates: geometries[i].coordinates ||
arcsToCoordinates(geometries[i].arcs)
}
});
}
const geojson = {
type: 'FeatureCollection',
copyright: topology.copyright,
copyrightShort: topology.copyrightShort,
copyrightUrl: topology.copyrightUrl,
features,
'hc-recommended-mapview': obj['hc-recommended-mapview'],
bbox: topology.bbox,
title: topology.title
};
obj['hc-decoded-geojson'] = geojson;
return geojson;
}
GeoJSONComposition.topo2geo = topo2geo;
/**
* Override addCredits to include map source by default.
* @private
*/
function wrapChartAddCredit(proceed, credits) {
credits = merge(true, this.options.credits, credits);
proceed.call(this, credits);
// Add full map credits to hover
if (this.credits && this.mapCreditsFull) {
this.credits.attr({
title: this.mapCreditsFull
});
}
}
})(GeoJSONComposition || (GeoJSONComposition = {}));
/* *
*
* Default Export
*
* */
export default GeoJSONComposition;
/* *
*
* API Declarations
*
* */
/**
* 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|undefined}
*/ /**
* Data sets of geographic features.
* @name Highcharts.GeoJSON#features
* @type {Array}
*/ /**
* 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|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 definition 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.ProjectedXY
*/ /**
* X coordinate in projected units.
* @name Highcharts.ProjectedXY#x
* @type {number}
*/ /**
* Y coordinate in projected units
* @name Highcharts.ProjectedXY#y
* @type {number}
*/
/**
* A latitude/longitude object.
*
* @interface Highcharts.MapLonLatObject
*/ /**
* The latitude.
* @name Highcharts.MapLonLatObject#lat
* @type {number}
*/ /**
* The longitude.
* @name Highcharts.MapLonLatObject#lon
* @type {number}
*/
/**
* An array of longitude, latitude.
*
* @typedef {Array} Highcharts.LonLatArray
*/
/**
* An array of GeoJSON or TopoJSON objects or strings used as map data for
* series.
*
* @typedef {Array<*>|GeoJSON|TopoJSON|string} Highcharts.MapDataType
*/
/**
* A TopoJSON object, see description on the
* [project's GitHub page](https://github.com/topojson/topojson).
*
* @typedef {Object} Highcharts.TopoJSON
*/
''; // Detach doclets above