initial commit
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
|
||||
var defined = H.defined,
|
||||
noop = H.noop,
|
||||
seriesTypes = H.seriesTypes;
|
||||
|
||||
/**
|
||||
* Mixin for maps and heatmaps
|
||||
*
|
||||
* @private
|
||||
* @mixin Highcharts.colorPointMixin
|
||||
*/
|
||||
H.colorPointMixin = {
|
||||
/**
|
||||
* Color points have a value option that determines whether or not it is
|
||||
* a null point
|
||||
*
|
||||
* @function Highcharts.colorPointMixin.isValid
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
isValid: function () {
|
||||
// undefined is allowed
|
||||
return (
|
||||
this.value !== null &&
|
||||
this.value !== Infinity &&
|
||||
this.value !== -Infinity
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the visibility of a single point
|
||||
*
|
||||
* @function Highcharts.colorPointMixin.setVisible
|
||||
*
|
||||
* @param {boolean} visible
|
||||
*/
|
||||
setVisible: function (vis) {
|
||||
var point = this,
|
||||
method = vis ? 'show' : 'hide';
|
||||
|
||||
point.visible = Boolean(vis);
|
||||
|
||||
// Show and hide associated elements
|
||||
['graphic', 'dataLabel'].forEach(function (key) {
|
||||
if (point[key]) {
|
||||
point[key][method]();
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @function Highcharts.colorPointMixin.setState
|
||||
*
|
||||
* @param {string} state
|
||||
*/
|
||||
setState: function (state) {
|
||||
H.Point.prototype.setState.call(this, state);
|
||||
if (this.graphic) {
|
||||
this.graphic.attr({
|
||||
zIndex: state === 'hover' ? 1 : 0
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @mixin Highcharts.colorSeriesMixin
|
||||
*/
|
||||
H.colorSeriesMixin = {
|
||||
pointArrayMap: ['value'],
|
||||
axisTypes: ['xAxis', 'yAxis', 'colorAxis'],
|
||||
optionalAxis: 'colorAxis',
|
||||
trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
|
||||
getSymbol: noop,
|
||||
parallelArrays: ['x', 'y', 'value'],
|
||||
colorKey: 'value',
|
||||
|
||||
pointAttribs: seriesTypes.column.prototype.pointAttribs,
|
||||
|
||||
/**
|
||||
* In choropleth maps, the color is a result of the value, so this needs
|
||||
* translation too
|
||||
*
|
||||
* @function Highcharts.colorSeriesMixin.translateColors
|
||||
*/
|
||||
translateColors: function () {
|
||||
var series = this,
|
||||
nullColor = this.options.nullColor,
|
||||
colorAxis = this.colorAxis,
|
||||
colorKey = this.colorKey;
|
||||
|
||||
this.data.forEach(function (point) {
|
||||
var value = point[colorKey],
|
||||
color;
|
||||
|
||||
color = point.options.color ||
|
||||
(
|
||||
point.isNull ?
|
||||
nullColor :
|
||||
(colorAxis && value !== undefined) ?
|
||||
colorAxis.toColor(value, point) :
|
||||
point.color || series.color
|
||||
);
|
||||
|
||||
if (color) {
|
||||
point.color = color;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the color attibutes to apply on the graphic
|
||||
*
|
||||
* @function Highcharts.colorSeriesMixin.colorAttribs
|
||||
*
|
||||
* @param {Highcharts.Point} point
|
||||
*
|
||||
* @return {Highcharts.Dictionary<Highcharts.ColorString>}
|
||||
*/
|
||||
colorAttribs: function (point) {
|
||||
var ret = {};
|
||||
|
||||
if (defined(point.color)) {
|
||||
ret[this.colorProp || 'fill'] = point.color;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,435 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* A latitude/longitude object.
|
||||
*
|
||||
* @interface Highcharts.MapLatLonObject
|
||||
*//**
|
||||
* The latitude.
|
||||
* @name Highcharts.MapLatLonObject#lat
|
||||
* @type {number}
|
||||
*//**
|
||||
* The longitude.
|
||||
* @name Highcharts.MapLatLonObject#lon
|
||||
* @type {number}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Options.js';
|
||||
import '../parts/Chart.js';
|
||||
|
||||
var Chart = H.Chart,
|
||||
extend = H.extend,
|
||||
format = H.format,
|
||||
merge = H.merge,
|
||||
win = H.win,
|
||||
wrap = H.wrap;
|
||||
|
||||
/* *
|
||||
* Test for point in polygon. Polygon defined as array of [x,y] points.
|
||||
*/
|
||||
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 module: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 {object} 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) {
|
||||
if (win.proj4 === undefined) {
|
||||
H.error(21, false, this);
|
||||
return {
|
||||
x: 0,
|
||||
y: null
|
||||
};
|
||||
}
|
||||
|
||||
var projected = win.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 module: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 {object} transform
|
||||
* The transform definition to use as explained in the
|
||||
* {@link https://www.highcharts.com/docs/maps/latlon|documentation}.
|
||||
*
|
||||
* @return {Highcharts.MapLatLonObject}
|
||||
* An object with `lat` and `lon` properties.
|
||||
*/
|
||||
Chart.prototype.transformToLatLon = function (point, transform) {
|
||||
if (win.proj4 === undefined) {
|
||||
H.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 module: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}
|
||||
* An object with `lat` and `lon` properties.
|
||||
*/
|
||||
Chart.prototype.fromPointToLatLon = function (point) {
|
||||
var transforms = this.mapTransforms,
|
||||
transform;
|
||||
|
||||
if (!transforms) {
|
||||
H.error(22, false, this);
|
||||
return;
|
||||
}
|
||||
|
||||
for (transform in transforms) {
|
||||
if (
|
||||
transforms.hasOwnProperty(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 module: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) {
|
||||
H.error(22, false, this);
|
||||
return {
|
||||
x: 0,
|
||||
y: null
|
||||
};
|
||||
}
|
||||
|
||||
for (transform in transforms) {
|
||||
if (
|
||||
transforms.hasOwnProperty(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 module:modules/map
|
||||
*
|
||||
* @sample maps/demo/geojson/
|
||||
* Simple areas
|
||||
* @sample maps/demo/geojson-multiple-types/
|
||||
* Multiple types
|
||||
*
|
||||
* @function Highcharts.geojson
|
||||
*
|
||||
* @param {object} 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<object>}
|
||||
* An object ready for the `mapData` option.
|
||||
*/
|
||||
H.geojson = function (geojson, hType, series) {
|
||||
var mapData = [],
|
||||
path = [],
|
||||
polygonToPath = function (polygon) {
|
||||
var i,
|
||||
len = polygon.length;
|
||||
|
||||
path.push('M');
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i === 1) {
|
||||
path.push('L');
|
||||
}
|
||||
path.push(polygon[i][0], -polygon[i][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 module: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
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,474 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Options.js';
|
||||
import '../parts/Point.js';
|
||||
import '../parts/Series.js';
|
||||
import '../parts/Legend.js';
|
||||
import './ColorSeriesMixin.js';
|
||||
|
||||
var colorPointMixin = H.colorPointMixin,
|
||||
colorSeriesMixin = H.colorSeriesMixin,
|
||||
LegendSymbolMixin = H.LegendSymbolMixin,
|
||||
merge = H.merge,
|
||||
noop = H.noop,
|
||||
pick = H.pick,
|
||||
Series = H.Series,
|
||||
seriesType = H.seriesType,
|
||||
seriesTypes = H.seriesTypes;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @class
|
||||
* @name Highcharts.seriesTypes.heatmap
|
||||
*
|
||||
* @augments Highcharts.Series
|
||||
*/
|
||||
seriesType(
|
||||
'heatmap',
|
||||
'scatter',
|
||||
|
||||
/**
|
||||
* A heatmap is a graphical representation of data where the individual
|
||||
* values contained in a matrix are represented as colors.
|
||||
*
|
||||
* @sample highcharts/demo/heatmap/
|
||||
* Simple heatmap
|
||||
* @sample highcharts/demo/heatmap-canvas/
|
||||
* Heavy heatmap
|
||||
*
|
||||
* @extends plotOptions.scatter
|
||||
* @excluding animationLimit, connectEnds, connectNulls, dashStyle,
|
||||
* findNearestPointBy, getExtremesFromAll, jitter, linecap,
|
||||
* lineWidth, marker, pointInterval, pointIntervalUnit,
|
||||
* pointRange, pointStart, shadow, softThreshold, stacking,
|
||||
* step, threshold
|
||||
* @product highcharts highmaps
|
||||
* @optionparent plotOptions.heatmap
|
||||
*/
|
||||
{
|
||||
|
||||
/**
|
||||
* Animation is disabled by default on the heatmap series.
|
||||
*/
|
||||
animation: false,
|
||||
|
||||
/**
|
||||
* The border width for each heat map item.
|
||||
*/
|
||||
borderWidth: 0,
|
||||
|
||||
/**
|
||||
* Padding between the points in the heatmap.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
* @since 6.0
|
||||
* @apioption plotOptions.heatmap.pointPadding
|
||||
*/
|
||||
|
||||
/**
|
||||
* The main color of the series. In heat maps this color is rarely used,
|
||||
* as we mostly use the color to denote the value of each point. Unless
|
||||
* options are set in the [colorAxis](#colorAxis), the default value
|
||||
* is pulled from the [options.colors](#colors) array.
|
||||
*
|
||||
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
|
||||
* @since 4.0
|
||||
* @product highcharts
|
||||
* @apioption plotOptions.heatmap.color
|
||||
*/
|
||||
|
||||
/**
|
||||
* The column size - how many X axis units each column in the heatmap
|
||||
* should span.
|
||||
*
|
||||
* @sample {highcharts} maps/demo/heatmap/
|
||||
* One day
|
||||
* @sample {highmaps} maps/demo/heatmap/
|
||||
* One day
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
* @since 4.0
|
||||
* @product highcharts highmaps
|
||||
* @apioption plotOptions.heatmap.colsize
|
||||
*/
|
||||
|
||||
/**
|
||||
* The row size - how many Y axis units each heatmap row should span.
|
||||
*
|
||||
* @sample {highcharts} maps/demo/heatmap/
|
||||
* 1 by default
|
||||
* @sample {highmaps} maps/demo/heatmap/
|
||||
* 1 by default
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
* @since 4.0
|
||||
* @product highcharts highmaps
|
||||
* @apioption plotOptions.heatmap.rowsize
|
||||
*/
|
||||
|
||||
/**
|
||||
* The color applied to null points. In styled mode, a general CSS class
|
||||
* is applied instead.
|
||||
*
|
||||
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
|
||||
*/
|
||||
nullColor: '#f7f7f7',
|
||||
|
||||
dataLabels: {
|
||||
formatter: function () { // #2945
|
||||
return this.point.value;
|
||||
},
|
||||
inside: true,
|
||||
verticalAlign: 'middle',
|
||||
crop: false,
|
||||
overflow: false,
|
||||
padding: 0 // #3837
|
||||
},
|
||||
|
||||
/** @ignore */
|
||||
marker: null,
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
pointRange: null, // dynamically set to colsize by default
|
||||
|
||||
tooltip: {
|
||||
pointFormat: '{point.x}, {point.y}: {point.value}<br/>'
|
||||
},
|
||||
|
||||
states: {
|
||||
|
||||
hover: {
|
||||
|
||||
/** @ignore */
|
||||
halo: false, // #3406, halo is disabled on heatmaps by default
|
||||
|
||||
/**
|
||||
* How much to brighten the point on interaction. Requires the main
|
||||
* color to be defined in hex or rgb(a) format.
|
||||
*
|
||||
* In styled mode, the hover brightening is by default replaced with
|
||||
* a fill-opacity set in the `.highcharts-point:hover` rule.
|
||||
*/
|
||||
brightness: 0.2
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}, merge(colorSeriesMixin, {
|
||||
|
||||
pointArrayMap: ['y', 'value'],
|
||||
hasPointSpecificOptions: true,
|
||||
getExtremesFromAll: true,
|
||||
directTouch: true,
|
||||
|
||||
/**
|
||||
* Override the init method to add point ranges on both axes.
|
||||
*
|
||||
* @private
|
||||
* @function Highcharts.seriesTypes.heatmap#init
|
||||
*/
|
||||
init: function () {
|
||||
var options;
|
||||
|
||||
seriesTypes.scatter.prototype.init.apply(this, arguments);
|
||||
|
||||
options = this.options;
|
||||
// #3758, prevent resetting in setData
|
||||
options.pointRange = pick(options.pointRange, options.colsize || 1);
|
||||
// general point range
|
||||
this.yAxis.axisPointRange = options.rowsize || 1;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @function Highcharts.seriesTypes.heatmap#translate
|
||||
*/
|
||||
translate: function () {
|
||||
var series = this,
|
||||
options = series.options,
|
||||
xAxis = series.xAxis,
|
||||
yAxis = series.yAxis,
|
||||
seriesPointPadding = options.pointPadding || 0,
|
||||
between = function (x, a, b) {
|
||||
return Math.min(Math.max(a, x), b);
|
||||
},
|
||||
pointPlacement = series.pointPlacementToXValue(); // #7860
|
||||
|
||||
series.generatePoints();
|
||||
|
||||
series.points.forEach(function (point) {
|
||||
var xPad = (options.colsize || 1) / 2,
|
||||
yPad = (options.rowsize || 1) / 2,
|
||||
x1 = between(
|
||||
Math.round(
|
||||
xAxis.len -
|
||||
xAxis.translate(point.x - xPad,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
-pointPlacement)
|
||||
),
|
||||
-xAxis.len, 2 * xAxis.len
|
||||
),
|
||||
x2 = between(
|
||||
Math.round(
|
||||
xAxis.len -
|
||||
xAxis.translate(point.x + xPad,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
-pointPlacement)
|
||||
),
|
||||
-xAxis.len, 2 * xAxis.len
|
||||
),
|
||||
y1 = between(
|
||||
Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)),
|
||||
-yAxis.len, 2 * yAxis.len
|
||||
),
|
||||
y2 = between(
|
||||
Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1)),
|
||||
-yAxis.len, 2 * yAxis.len
|
||||
),
|
||||
pointPadding = pick(point.pointPadding, seriesPointPadding);
|
||||
|
||||
// Set plotX and plotY for use in K-D-Tree and more
|
||||
point.plotX = point.clientX = (x1 + x2) / 2;
|
||||
point.plotY = (y1 + y2) / 2;
|
||||
|
||||
point.shapeType = 'rect';
|
||||
point.shapeArgs = {
|
||||
x: Math.min(x1, x2) + pointPadding,
|
||||
y: Math.min(y1, y2) + pointPadding,
|
||||
width: Math.abs(x2 - x1) - pointPadding * 2,
|
||||
height: Math.abs(y2 - y1) - pointPadding * 2
|
||||
};
|
||||
});
|
||||
|
||||
series.translateColors();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @function Highcharts.seriesTypes.heatmap#drawPoints
|
||||
*/
|
||||
drawPoints: function () {
|
||||
|
||||
// In styled mode, use CSS, otherwise the fill used in the style
|
||||
// sheet will take precedence over the fill attribute.
|
||||
var func = this.chart.styledMode ? 'css' : 'attr';
|
||||
|
||||
seriesTypes.column.prototype.drawPoints.call(this);
|
||||
|
||||
this.points.forEach(function (point) {
|
||||
point.graphic[func](this.colorAttribs(point));
|
||||
}, this);
|
||||
},
|
||||
|
||||
// Override to also allow null points, used when building the k-d-tree
|
||||
// for tooltips in boost mode.
|
||||
getValidPoints: function (points, insideOnly) {
|
||||
return Series.prototype.getValidPoints.call(
|
||||
this,
|
||||
points,
|
||||
insideOnly,
|
||||
true
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @deprecated
|
||||
* @function Highcharts.seriesTypes.heatmap#animate
|
||||
*/
|
||||
animate: noop,
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @deprecated
|
||||
* @function Highcharts.seriesTypes.heatmap#getBox
|
||||
*/
|
||||
getBox: noop,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.heatmap#drawLegendSymbol
|
||||
*/
|
||||
drawLegendSymbol: LegendSymbolMixin.drawRectangle,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @borrows Highcharts.seriesTypes.column#alignDataLabel as Highcharts.seriesTypes.heatmap#alignDataLabel
|
||||
*/
|
||||
alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @function Highcharts.seriesTypes.heatmap#getExtremes
|
||||
*/
|
||||
getExtremes: function () {
|
||||
// Get the extremes from the value data
|
||||
Series.prototype.getExtremes.call(this, this.valueData);
|
||||
this.valueMin = this.dataMin;
|
||||
this.valueMax = this.dataMax;
|
||||
|
||||
// Get the extremes from the y data
|
||||
Series.prototype.getExtremes.call(this);
|
||||
}
|
||||
|
||||
}), H.extend({
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @function Highcharts.Point#haloPath
|
||||
*
|
||||
* @param {number} size
|
||||
*
|
||||
* @return {Highcharts.SVGPathArray}
|
||||
*/
|
||||
haloPath: function (size) {
|
||||
if (!size) {
|
||||
return [];
|
||||
}
|
||||
var rect = this.shapeArgs;
|
||||
|
||||
return [
|
||||
'M', rect.x - size, rect.y - size,
|
||||
'L', rect.x - size, rect.y + rect.height + size,
|
||||
rect.x + rect.width + size, rect.y + rect.height + size,
|
||||
rect.x + rect.width + size, rect.y - size,
|
||||
'Z'
|
||||
];
|
||||
}
|
||||
}, colorPointMixin)
|
||||
);
|
||||
|
||||
/**
|
||||
* A `heatmap` series. If the [type](#series.heatmap.type) option is
|
||||
* not specified, it is inherited from [chart.type](#chart.type).
|
||||
*
|
||||
* @extends series,plotOptions.heatmap
|
||||
* @excluding dataParser, dataURL, marker, pointRange, stack
|
||||
* @product highcharts highmaps
|
||||
* @apioption series.heatmap
|
||||
*/
|
||||
|
||||
/**
|
||||
* An array of data points for the series. For the `heatmap` series
|
||||
* type, points can be given in the following ways:
|
||||
*
|
||||
* 1. An array of arrays with 3 or 2 values. In this case, the values
|
||||
* correspond to `x,y,value`. If the first value is a string, it is
|
||||
* applied as the name of the point, and the `x` value is inferred.
|
||||
* The `x` value can also be omitted, in which case the inner arrays
|
||||
* should be of length 2\. Then the `x` value is automatically calculated,
|
||||
* either starting at 0 and incremented by 1, or from `pointStart`
|
||||
* and `pointInterval` given in the series options.
|
||||
*
|
||||
* ```js
|
||||
* data: [
|
||||
* [0, 9, 7],
|
||||
* [1, 10, 4],
|
||||
* [2, 6, 3]
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* 2. An array of objects with named values. The following snippet shows only a
|
||||
* few settings, see the complete options set below. If the total number of data
|
||||
* points exceeds the series' [turboThreshold](#series.heatmap.turboThreshold),
|
||||
* this option is not available.
|
||||
*
|
||||
* ```js
|
||||
* data: [{
|
||||
* x: 1,
|
||||
* y: 3,
|
||||
* value: 10,
|
||||
* name: "Point2",
|
||||
* color: "#00FF00"
|
||||
* }, {
|
||||
* x: 1,
|
||||
* y: 7,
|
||||
* value: 10,
|
||||
* name: "Point1",
|
||||
* color: "#FF00FF"
|
||||
* }]
|
||||
* ```
|
||||
*
|
||||
* @sample {highcharts} highcharts/chart/reflow-true/
|
||||
* Numerical values
|
||||
* @sample {highcharts} highcharts/series/data-array-of-arrays/
|
||||
* Arrays of numeric x and y
|
||||
* @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
|
||||
* Arrays of datetime x and y
|
||||
* @sample {highcharts} highcharts/series/data-array-of-name-value/
|
||||
* Arrays of point.name and y
|
||||
* @sample {highcharts} highcharts/series/data-array-of-objects/
|
||||
* Config objects
|
||||
*
|
||||
* @type {Array<Array<number>|*>}
|
||||
* @extends series.line.data
|
||||
* @excluding marker
|
||||
* @product highcharts highmaps
|
||||
* @apioption series.heatmap.data
|
||||
*/
|
||||
|
||||
/**
|
||||
* The color of the point. In heat maps the point color is rarely set
|
||||
* explicitly, as we use the color to denote the `value`. Options for
|
||||
* this are set in the [colorAxis](#colorAxis) configuration.
|
||||
*
|
||||
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
|
||||
* @product highcharts highmaps
|
||||
* @apioption series.heatmap.data.color
|
||||
*/
|
||||
|
||||
/**
|
||||
* The value of the point, resulting in a color controled by options
|
||||
* as set in the [colorAxis](#colorAxis) configuration.
|
||||
*
|
||||
* @type {number}
|
||||
* @product highcharts highmaps
|
||||
* @apioption series.heatmap.data.value
|
||||
*/
|
||||
|
||||
/**
|
||||
* The x value of the point. For datetime axes,
|
||||
* the X value is the timestamp in milliseconds since 1970.
|
||||
*
|
||||
* @type {number}
|
||||
* @product highcharts highmaps
|
||||
* @apioption series.heatmap.data.x
|
||||
*/
|
||||
|
||||
/**
|
||||
* The y value of the point.
|
||||
*
|
||||
* @type {number}
|
||||
* @product highcharts highmaps
|
||||
* @apioption series.heatmap.data.y
|
||||
*/
|
||||
|
||||
/**
|
||||
* Point padding for a single point.
|
||||
*
|
||||
* @sample maps/plotoptions/tilemap-pointpadding
|
||||
* Point padding on tiles
|
||||
*
|
||||
* @type {number}
|
||||
* @product highcharts highmaps
|
||||
* @apioption series.heatmap.data.pointPadding
|
||||
*/
|
||||
@@ -0,0 +1,477 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Options.js';
|
||||
import '../parts/Chart.js';
|
||||
import '../parts/SvgRenderer.js';
|
||||
|
||||
var Chart = H.Chart,
|
||||
defaultOptions = H.defaultOptions,
|
||||
extend = H.extend,
|
||||
merge = H.merge,
|
||||
pick = H.pick,
|
||||
Renderer = H.Renderer,
|
||||
SVGRenderer = H.SVGRenderer,
|
||||
VMLRenderer = H.VMLRenderer;
|
||||
|
||||
// Add language
|
||||
extend(defaultOptions.lang, {
|
||||
zoomIn: 'Zoom in',
|
||||
zoomOut: 'Zoom out'
|
||||
});
|
||||
|
||||
// Set the default map navigation options
|
||||
|
||||
/**
|
||||
* @product highmaps
|
||||
* @optionparent mapNavigation
|
||||
*/
|
||||
defaultOptions.mapNavigation = {
|
||||
|
||||
/**
|
||||
* General options for the map navigation buttons. Individual options
|
||||
* can be given from the [mapNavigation.buttons](#mapNavigation.buttons)
|
||||
* option set.
|
||||
*
|
||||
* @sample {highmaps} maps/mapnavigation/button-theme/
|
||||
* Theming the navigation buttons
|
||||
*/
|
||||
buttonOptions: {
|
||||
|
||||
/**
|
||||
* What box to align the buttons to. Possible values are `plotBox`
|
||||
* and `spacingBox`.
|
||||
*
|
||||
* @validvalue ["plotBox", "spacingBox"]
|
||||
*/
|
||||
alignTo: 'plotBox',
|
||||
|
||||
/**
|
||||
* The alignment of the navigation buttons.
|
||||
*
|
||||
* @type {Highcharts.AlignType}
|
||||
*/
|
||||
align: 'left',
|
||||
|
||||
/**
|
||||
* The vertical alignment of the buttons. Individual alignment can
|
||||
* be adjusted by each button's `y` offset.
|
||||
*
|
||||
* @type {Highcharts.VerticalAlignType}
|
||||
*/
|
||||
verticalAlign: 'top',
|
||||
|
||||
/**
|
||||
* The X offset of the buttons relative to its `align` setting.
|
||||
*/
|
||||
x: 0,
|
||||
|
||||
/**
|
||||
* The width of the map navigation buttons.
|
||||
*/
|
||||
width: 18,
|
||||
|
||||
/**
|
||||
* The pixel height of the map navigation buttons.
|
||||
*/
|
||||
height: 18,
|
||||
|
||||
/**
|
||||
* Padding for the navigation buttons.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
padding: 5,
|
||||
|
||||
/**
|
||||
* Text styles for the map navigation buttons.
|
||||
*
|
||||
* @type {Highcharts.CSSObject}
|
||||
* @default {"fontSize": "15px", "fontWeight": "bold"}
|
||||
*/
|
||||
style: {
|
||||
/** @ignore */
|
||||
fontSize: '15px',
|
||||
/** @ignore */
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
|
||||
/**
|
||||
* A configuration object for the button theme. The object accepts
|
||||
* SVG properties like `stroke-width`, `stroke` and `fill`. Tri-state
|
||||
* button styles are supported by the `states.hover` and `states.select`
|
||||
* objects.
|
||||
*
|
||||
* @sample {highmaps} maps/mapnavigation/button-theme/
|
||||
* Themed navigation buttons
|
||||
*
|
||||
* @type {Highcharts.SVGAttributes}
|
||||
* @default {"stroke-width": 1, "text-align": "center"}
|
||||
*/
|
||||
theme: {
|
||||
/** @ignore */
|
||||
'stroke-width': 1,
|
||||
/** @ignore */
|
||||
'text-align': 'center'
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* The individual buttons for the map navigation. This usually includes
|
||||
* the zoom in and zoom out buttons. Properties for each button is
|
||||
* inherited from
|
||||
* [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while
|
||||
* individual options can be overridden. But default, the `onclick`, `text`
|
||||
* and `y` options are individual.
|
||||
*/
|
||||
buttons: {
|
||||
|
||||
/**
|
||||
* Options for the zoom in button. Properties for the zoom in and zoom
|
||||
* out buttons are inherited from
|
||||
* [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while
|
||||
* individual options can be overridden. By default, the `onclick`,
|
||||
* `text` and `y` options are individual.
|
||||
*
|
||||
* @extends mapNavigation.buttonOptions
|
||||
*/
|
||||
zoomIn: {
|
||||
|
||||
/**
|
||||
* Click handler for the button.
|
||||
*
|
||||
* @type {Function}
|
||||
* @default function () { this.mapZoom(0.5); }
|
||||
*/
|
||||
onclick: function () {
|
||||
this.mapZoom(0.5);
|
||||
},
|
||||
|
||||
/**
|
||||
* The text for the button. The tooltip (title) is a language option
|
||||
* given by [lang.zoomIn](#lang.zoomIn).
|
||||
*/
|
||||
text: '+',
|
||||
|
||||
/**
|
||||
* The position of the zoomIn button relative to the vertical
|
||||
* alignment.
|
||||
*/
|
||||
y: 0
|
||||
},
|
||||
|
||||
/**
|
||||
* Options for the zoom out button. Properties for the zoom in and
|
||||
* zoom out buttons are inherited from
|
||||
* [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while
|
||||
* individual options can be overridden. By default, the `onclick`,
|
||||
* `text` and `y` options are individual.
|
||||
*
|
||||
* @extends mapNavigation.buttonOptions
|
||||
*/
|
||||
zoomOut: {
|
||||
|
||||
/**
|
||||
* Click handler for the button.
|
||||
*
|
||||
* @type {Function}
|
||||
* @default function () { this.mapZoom(2); }
|
||||
*/
|
||||
onclick: function () {
|
||||
this.mapZoom(2);
|
||||
},
|
||||
|
||||
/**
|
||||
* The text for the button. The tooltip (title) is a language option
|
||||
* given by [lang.zoomOut](#lang.zoomIn).
|
||||
*/
|
||||
text: '-',
|
||||
|
||||
/**
|
||||
* The position of the zoomOut button relative to the vertical
|
||||
* alignment.
|
||||
*/
|
||||
y: 28
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether to enable navigation buttons. By default it inherits the
|
||||
* [enabled](#mapNavigation.enabled) setting.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @apioption mapNavigation.enableButtons
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether to enable map navigation. The default is not to enable
|
||||
* navigation, as many choropleth maps are simple and don't need it.
|
||||
* Additionally, when touch zoom and mousewheel zoom is enabled, it breaks
|
||||
* the default behaviour of these interactions in the website, and the
|
||||
* implementer should be aware of this.
|
||||
*
|
||||
* Individual interactions can be enabled separately, namely buttons,
|
||||
* multitouch zoom, double click zoom, double click zoom to element and
|
||||
* mousewheel zoom.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
* @apioption mapNavigation.enabled
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enables zooming in on an area on double clicking in the map. By default
|
||||
* it inherits the [enabled](#mapNavigation.enabled) setting.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @apioption mapNavigation.enableDoubleClickZoom
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether to zoom in on an area when that area is double clicked.
|
||||
*
|
||||
* @sample {highmaps} maps/mapnavigation/doubleclickzoomto/
|
||||
* Enable double click zoom to
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
* @apioption mapNavigation.enableDoubleClickZoomTo
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enables zooming by mouse wheel. By default it inherits the [enabled](
|
||||
* #mapNavigation.enabled) setting.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @apioption mapNavigation.enableMouseWheelZoom
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether to enable multitouch zooming. Note that if the chart covers the
|
||||
* viewport, this prevents the user from using multitouch and touchdrag on
|
||||
* the web page, so you should make sure the user is not trapped inside the
|
||||
* chart. By default it inherits the [enabled](#mapNavigation.enabled)
|
||||
* setting.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @apioption mapNavigation.enableTouchZoom
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sensitivity of mouse wheel or trackpad scrolling. 1 is no sensitivity,
|
||||
* while with 2, one mousewheel delta will zoom in 50%.
|
||||
*
|
||||
* @since 4.2.4
|
||||
*/
|
||||
mouseWheelSensitivity: 1.1
|
||||
|
||||
// enabled: false,
|
||||
// enableButtons: null, // inherit from enabled
|
||||
// enableTouchZoom: null, // inherit from enabled
|
||||
// enableDoubleClickZoom: null, // inherit from enabled
|
||||
// enableDoubleClickZoomTo: false
|
||||
// enableMouseWheelZoom: null, // inherit from enabled
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility for reading SVG paths directly.
|
||||
*
|
||||
* @requires module:modules/map
|
||||
*
|
||||
* @function Highcharts.splitPath
|
||||
*
|
||||
* @param {string} path
|
||||
*
|
||||
* @return {Highcharts.SVGPathArray}
|
||||
*/
|
||||
H.splitPath = function (path) {
|
||||
var i;
|
||||
|
||||
// Move letters apart
|
||||
path = path.replace(/([A-Za-z])/g, ' $1 ');
|
||||
// Trim
|
||||
path = path.replace(/^\s*/, '').replace(/\s*$/, '');
|
||||
|
||||
// Split on spaces and commas
|
||||
path = path.split(/[ ,]+/); // Extra comma to escape gulp.scripts task
|
||||
|
||||
// Parse numbers
|
||||
for (i = 0; i < path.length; i++) {
|
||||
if (!/[a-zA-Z]/.test(path[i])) {
|
||||
path[i] = parseFloat(path[i]);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains all loaded map data for Highmaps.
|
||||
*
|
||||
* @requires module:modules/map
|
||||
*
|
||||
* @name Highcharts.maps
|
||||
* @type {Highcharts.Dictionary<Highcharts.MapDataObject>}
|
||||
*/
|
||||
H.maps = {};
|
||||
|
||||
|
||||
// Create symbols for the zoom buttons
|
||||
function selectiveRoundedRect(
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
rTopLeft,
|
||||
rTopRight,
|
||||
rBottomRight,
|
||||
rBottomLeft
|
||||
) {
|
||||
return [
|
||||
'M', x + rTopLeft, y,
|
||||
// top side
|
||||
'L', x + w - rTopRight, y,
|
||||
// top right corner
|
||||
'C', x + w - rTopRight / 2,
|
||||
y, x + w,
|
||||
y + rTopRight / 2, x + w, y + rTopRight,
|
||||
// right side
|
||||
'L', x + w, y + h - rBottomRight,
|
||||
// bottom right corner
|
||||
'C', x + w, y + h - rBottomRight / 2,
|
||||
x + w - rBottomRight / 2, y + h,
|
||||
x + w - rBottomRight, y + h,
|
||||
// bottom side
|
||||
'L', x + rBottomLeft, y + h,
|
||||
// bottom left corner
|
||||
'C', x + rBottomLeft / 2, y + h,
|
||||
x, y + h - rBottomLeft / 2,
|
||||
x, y + h - rBottomLeft,
|
||||
// left side
|
||||
'L', x, y + rTopLeft,
|
||||
// top left corner
|
||||
'C', x, y + rTopLeft / 2,
|
||||
x + rTopLeft / 2, y,
|
||||
x + rTopLeft, y,
|
||||
'Z'
|
||||
];
|
||||
}
|
||||
SVGRenderer.prototype.symbols.topbutton = function (x, y, w, h, attr) {
|
||||
return selectiveRoundedRect(x - 1, y - 1, w, h, attr.r, attr.r, 0, 0);
|
||||
};
|
||||
SVGRenderer.prototype.symbols.bottombutton = function (x, y, w, h, attr) {
|
||||
return selectiveRoundedRect(x - 1, y - 1, w, h, 0, 0, attr.r, attr.r);
|
||||
};
|
||||
// The symbol callbacks are generated on the SVGRenderer object in all browsers.
|
||||
// Even VML browsers need this in order to generate shapes in export. Now share
|
||||
// them with the VMLRenderer.
|
||||
if (Renderer === VMLRenderer) {
|
||||
['topbutton', 'bottombutton'].forEach(function (shape) {
|
||||
VMLRenderer.prototype.symbols[shape] =
|
||||
SVGRenderer.prototype.symbols[shape];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The factory function for creating new map charts. Creates a new {@link
|
||||
* Highcharts.Chart|Chart} object with different default options than the basic
|
||||
* Chart.
|
||||
*
|
||||
* @requires module:modules/map
|
||||
*
|
||||
* @function Highcharts.mapChart
|
||||
*
|
||||
* @param {string|Highcharts.HTMLDOMElement} [renderTo]
|
||||
* The DOM element to render to, or its id.
|
||||
*
|
||||
* @param {Highcharts.Options} options
|
||||
* The chart options structure as described in the
|
||||
* [options reference](https://api.highcharts.com/highstock).
|
||||
*
|
||||
* @param {Highcharts.ChartCallbackFunction} [callback]
|
||||
* A function to execute when the chart object is finished loading and
|
||||
* rendering. In most cases the chart is built in one thread, but in
|
||||
* Internet Explorer version 8 or less the chart is sometimes
|
||||
* initialized before the document is ready, and in these cases the
|
||||
* chart object will not be finished synchronously. As a consequence,
|
||||
* code that relies on the newly built Chart object should always run in
|
||||
* the callback. Defining a
|
||||
* [chart.events.load](https://api.highcharts.com/highstock/chart.events.load)
|
||||
* handler is equivalent.
|
||||
*
|
||||
* @return {Highcharts.Chart}
|
||||
* The chart object.
|
||||
*/
|
||||
H.Map = H.mapChart = function (a, b, c) {
|
||||
|
||||
var hasRenderToArg = typeof a === 'string' || a.nodeName,
|
||||
options = arguments[hasRenderToArg ? 1 : 0],
|
||||
userOptions = options,
|
||||
hiddenAxis = {
|
||||
endOnTick: false,
|
||||
visible: false,
|
||||
minPadding: 0,
|
||||
maxPadding: 0,
|
||||
startOnTick: false
|
||||
},
|
||||
seriesOptions,
|
||||
defaultCreditsOptions = H.getOptions().credits;
|
||||
|
||||
/* For visual testing
|
||||
hiddenAxis.gridLineWidth = 1;
|
||||
hiddenAxis.gridZIndex = 10;
|
||||
hiddenAxis.tickPositions = undefined;
|
||||
// */
|
||||
|
||||
// Don't merge the data
|
||||
seriesOptions = options.series;
|
||||
options.series = null;
|
||||
|
||||
options = merge(
|
||||
{
|
||||
chart: {
|
||||
panning: 'xy',
|
||||
type: 'map'
|
||||
},
|
||||
credits: {
|
||||
mapText: pick(
|
||||
defaultCreditsOptions.mapText,
|
||||
' \u00a9 <a href="{geojson.copyrightUrl}">' +
|
||||
'{geojson.copyrightShort}</a>'
|
||||
),
|
||||
mapTextFull: pick(
|
||||
defaultCreditsOptions.mapTextFull,
|
||||
'{geojson.copyright}'
|
||||
)
|
||||
},
|
||||
tooltip: {
|
||||
followTouchMove: false
|
||||
},
|
||||
xAxis: hiddenAxis,
|
||||
yAxis: merge(hiddenAxis, { reversed: true })
|
||||
},
|
||||
options, // user's options
|
||||
|
||||
{ // forced options
|
||||
chart: {
|
||||
inverted: false,
|
||||
alignTicks: false
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
options.series = userOptions.series = seriesOptions;
|
||||
|
||||
|
||||
return hasRenderToArg ?
|
||||
new Chart(a, options, c) :
|
||||
new Chart(options, b);
|
||||
};
|
||||
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Axis.js';
|
||||
|
||||
var addEvent = H.addEvent,
|
||||
Axis = H.Axis,
|
||||
pick = H.pick;
|
||||
|
||||
// Override to use the extreme coordinates from the SVG shape, not the data
|
||||
// values
|
||||
addEvent(Axis, 'getSeriesExtremes', function () {
|
||||
var xData = [];
|
||||
|
||||
// Remove the xData array and cache it locally so that the proceed method
|
||||
// doesn't use it
|
||||
if (this.isXAxis) {
|
||||
this.series.forEach(function (series, i) {
|
||||
if (series.useMapGeometry) {
|
||||
xData[i] = series.xData;
|
||||
series.xData = [];
|
||||
}
|
||||
});
|
||||
this.seriesXData = xData;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
addEvent(Axis, 'afterGetSeriesExtremes', function () {
|
||||
|
||||
var xData = this.seriesXData,
|
||||
dataMin,
|
||||
dataMax,
|
||||
useMapGeometry;
|
||||
|
||||
// Run extremes logic for map and mapline
|
||||
if (this.isXAxis) {
|
||||
dataMin = pick(this.dataMin, Number.MAX_VALUE);
|
||||
dataMax = pick(this.dataMax, -Number.MAX_VALUE);
|
||||
this.series.forEach(function (series, i) {
|
||||
if (series.useMapGeometry) {
|
||||
dataMin = Math.min(dataMin, pick(series.minX, dataMin));
|
||||
dataMax = Math.max(dataMax, pick(series.maxX, dataMax));
|
||||
series.xData = xData[i]; // Reset xData array
|
||||
useMapGeometry = true;
|
||||
}
|
||||
});
|
||||
if (useMapGeometry) {
|
||||
this.dataMin = dataMin;
|
||||
this.dataMax = dataMax;
|
||||
}
|
||||
|
||||
delete this.seriesXData;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Override axis translation to make sure the aspect ratio is always kept
|
||||
addEvent(Axis, 'afterSetAxisTranslation', function () {
|
||||
var chart = this.chart,
|
||||
mapRatio,
|
||||
plotRatio = chart.plotWidth / chart.plotHeight,
|
||||
adjustedAxisLength,
|
||||
xAxis = chart.xAxis[0],
|
||||
padAxis,
|
||||
fixTo,
|
||||
fixDiff,
|
||||
preserveAspectRatio;
|
||||
|
||||
// Check for map-like series
|
||||
if (this.coll === 'yAxis' && xAxis.transA !== undefined) {
|
||||
this.series.forEach(function (series) {
|
||||
if (series.preserveAspectRatio) {
|
||||
preserveAspectRatio = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// On Y axis, handle both
|
||||
if (preserveAspectRatio) {
|
||||
|
||||
// Use the same translation for both axes
|
||||
this.transA = xAxis.transA = Math.min(this.transA, xAxis.transA);
|
||||
|
||||
mapRatio = plotRatio /
|
||||
((xAxis.max - xAxis.min) / (this.max - this.min));
|
||||
|
||||
// What axis to pad to put the map in the middle
|
||||
padAxis = mapRatio < 1 ? this : xAxis;
|
||||
|
||||
// Pad it
|
||||
adjustedAxisLength = (padAxis.max - padAxis.min) * padAxis.transA;
|
||||
padAxis.pixelPadding = padAxis.len - adjustedAxisLength;
|
||||
padAxis.minPixelPadding = padAxis.pixelPadding / 2;
|
||||
|
||||
fixTo = padAxis.fixTo;
|
||||
if (fixTo) {
|
||||
fixDiff = fixTo[1] - padAxis.toValue(fixTo[0], true);
|
||||
fixDiff *= padAxis.transA;
|
||||
if (
|
||||
Math.abs(fixDiff) > padAxis.minPixelPadding ||
|
||||
(
|
||||
padAxis.min === padAxis.dataMin &&
|
||||
padAxis.max === padAxis.dataMax
|
||||
)
|
||||
) { // zooming out again, keep within restricted area
|
||||
fixDiff = 0;
|
||||
}
|
||||
padAxis.minPixelPadding -= fixDiff;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Override Axis.render in order to delete the fixTo prop
|
||||
addEvent(Axis, 'render', function () {
|
||||
this.fixTo = null;
|
||||
});
|
||||
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Options.js';
|
||||
import '../parts/Point.js';
|
||||
import '../parts-more/BubbleSeries.js';
|
||||
|
||||
var merge = H.merge,
|
||||
Point = H.Point,
|
||||
seriesType = H.seriesType,
|
||||
seriesTypes = H.seriesTypes;
|
||||
|
||||
// The mapbubble series type
|
||||
if (seriesTypes.bubble) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @class
|
||||
* @name Highcharts.seriesTypes.mapbubble
|
||||
*
|
||||
* @augments Highcharts.Series
|
||||
*/
|
||||
seriesType('mapbubble', 'bubble'
|
||||
|
||||
/**
|
||||
* A map bubble series is a bubble series laid out on top of a map series,
|
||||
* where each bubble is tied to a specific map area.
|
||||
*
|
||||
* @sample maps/demo/map-bubble/
|
||||
* Map bubble chart
|
||||
*
|
||||
* @extends plotOptions.bubble
|
||||
* @product highmaps
|
||||
* @optionparent plotOptions.mapbubble
|
||||
*/
|
||||
, {
|
||||
|
||||
/**
|
||||
* The main color of the series. This color affects both the fill and
|
||||
* the stroke of the bubble. For enhanced control, use `marker` options.
|
||||
*
|
||||
* @sample {highmaps} maps/plotoptions/mapbubble-color/
|
||||
* Pink bubbles
|
||||
*
|
||||
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
|
||||
* @apioption plotOptions.mapbubble.color
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether to display negative sized bubbles. The threshold is given
|
||||
* by the [zThreshold](#plotOptions.mapbubble.zThreshold) option, and
|
||||
* negative bubbles can be visualized by setting [negativeColor](
|
||||
* #plotOptions.bubble.negativeColor).
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
* @apioption plotOptions.mapbubble.displayNegative
|
||||
*/
|
||||
|
||||
/**
|
||||
* @sample {highmaps} maps/demo/map-bubble/
|
||||
* Bubble size
|
||||
*
|
||||
* @apioption plotOptions.mapbubble.maxSize
|
||||
*/
|
||||
|
||||
/**
|
||||
* @sample {highmaps} maps/demo/map-bubble/
|
||||
* Bubble size
|
||||
*
|
||||
* @apioption plotOptions.mapbubble.minSize
|
||||
*/
|
||||
|
||||
/**
|
||||
* When a point's Z value is below the
|
||||
* [zThreshold](#plotOptions.mapbubble.zThreshold) setting, this color
|
||||
* is used.
|
||||
*
|
||||
* @sample {highmaps} maps/plotoptions/mapbubble-negativecolor/
|
||||
* Negative color below a threshold
|
||||
*
|
||||
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
|
||||
* @apioption plotOptions.mapbubble.negativeColor
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether the bubble's value should be represented by the area or the
|
||||
* width of the bubble. The default, `area`, corresponds best to the
|
||||
* human perception of the size of each bubble.
|
||||
*
|
||||
* @type {string}
|
||||
* @default area
|
||||
* @validvalue ["area", "width"]
|
||||
* @apioption plotOptions.mapbubble.sizeBy
|
||||
*/
|
||||
|
||||
/**
|
||||
* When this is true, the absolute value of z determines the size of
|
||||
* the bubble. This means that with the default `zThreshold` of 0, a
|
||||
* bubble of value -1 will have the same size as a bubble of value 1,
|
||||
* while a bubble of value 0 will have a smaller size according to
|
||||
* `minSize`.
|
||||
*
|
||||
* @sample {highmaps} highcharts/plotoptions/bubble-sizebyabsolutevalue/
|
||||
* Size by absolute value, various thresholds
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
* @since 1.1.9
|
||||
* @apioption plotOptions.mapbubble.sizeByAbsoluteValue
|
||||
*/
|
||||
|
||||
/**
|
||||
* The minimum for the Z value range. Defaults to the highest Z value
|
||||
* in the data.
|
||||
*
|
||||
* @see [zMax](#plotOptions.mapbubble.zMin)
|
||||
*
|
||||
* @sample {highmaps} highcharts/plotoptions/bubble-zmin-zmax/
|
||||
* Z has a possible range of 0-100
|
||||
*
|
||||
* @type {number}
|
||||
* @since 1.0.3
|
||||
* @apioption plotOptions.mapbubble.zMax
|
||||
*/
|
||||
|
||||
/**
|
||||
* The minimum for the Z value range. Defaults to the lowest Z value
|
||||
* in the data.
|
||||
*
|
||||
* @see [zMax](#plotOptions.mapbubble.zMax)
|
||||
*
|
||||
* @sample {highmaps} highcharts/plotoptions/bubble-zmin-zmax/
|
||||
* Z has a possible range of 0-100
|
||||
*
|
||||
* @type {number}
|
||||
* @since 1.0.3
|
||||
* @apioption plotOptions.mapbubble.zMin
|
||||
*/
|
||||
|
||||
/**
|
||||
* When [displayNegative](#plotOptions.mapbubble.displayNegative) is
|
||||
* `false`, bubbles with lower Z values are skipped. When
|
||||
* `displayNegative` is `true` and a [negativeColor](
|
||||
* #plotOptions.mapbubble.negativeColor) is given, points with lower Z
|
||||
* is colored.
|
||||
*
|
||||
* @sample {highmaps} maps/plotoptions/mapbubble-negativecolor/
|
||||
* Negative color below a threshold
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
* @apioption plotOptions.mapbubble.zThreshold
|
||||
*/
|
||||
|
||||
animationLimit: 500,
|
||||
|
||||
tooltip: {
|
||||
pointFormat: '{point.name}: {point.z}'
|
||||
}
|
||||
|
||||
// Prototype members
|
||||
}, {
|
||||
xyFromShape: true,
|
||||
type: 'mapbubble',
|
||||
// If one single value is passed, it is interpreted as z
|
||||
pointArrayMap: ['z'],
|
||||
// Return the map area identified by the dataJoinBy option
|
||||
getMapData: seriesTypes.map.prototype.getMapData,
|
||||
getBox: seriesTypes.map.prototype.getBox,
|
||||
setData: seriesTypes.map.prototype.setData
|
||||
|
||||
// Point class
|
||||
}, {
|
||||
applyOptions: function (options, x) {
|
||||
var point;
|
||||
|
||||
if (
|
||||
options &&
|
||||
options.lat !== undefined &&
|
||||
options.lon !== undefined
|
||||
) {
|
||||
point = Point.prototype.applyOptions.call(
|
||||
this,
|
||||
merge(
|
||||
options,
|
||||
this.series.chart.fromLatLonToPoint(options)
|
||||
),
|
||||
x
|
||||
);
|
||||
} else {
|
||||
point = seriesTypes.map.prototype.pointClass.prototype
|
||||
.applyOptions.call(this, options, x);
|
||||
}
|
||||
return point;
|
||||
},
|
||||
isValid: function () {
|
||||
return typeof this.z === 'number';
|
||||
},
|
||||
ttBelow: false
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A `mapbubble` series. If the [type](#series.mapbubble.type) option
|
||||
* is not specified, it is inherited from [chart.type](#chart.type).
|
||||
*
|
||||
* @extends series,plotOptions.mapbubble
|
||||
* @excluding dataParser, dataURL
|
||||
* @product highmaps
|
||||
* @apioption series.mapbubble
|
||||
*/
|
||||
|
||||
/**
|
||||
* An array of data points for the series. For the `mapbubble` series
|
||||
* type, points can be given in the following ways:
|
||||
*
|
||||
* 1. An array of numerical values. In this case, the numerical values
|
||||
* will be interpreted as `z` options. Example:
|
||||
*
|
||||
* ```js
|
||||
* data: [0, 5, 3, 5]
|
||||
* ```
|
||||
*
|
||||
* 2. An array of objects with named values. The following snippet shows only a
|
||||
* few settings, see the complete options set below. If the total number of data
|
||||
* points exceeds the series' [turboThreshold](
|
||||
* #series.mapbubble.turboThreshold),
|
||||
* this option is not available.
|
||||
*
|
||||
* ```js
|
||||
* data: [{
|
||||
* z: 9,
|
||||
* name: "Point2",
|
||||
* color: "#00FF00"
|
||||
* }, {
|
||||
* z: 10,
|
||||
* name: "Point1",
|
||||
* color: "#FF00FF"
|
||||
* }]
|
||||
* ```
|
||||
*
|
||||
* @type {Array<number|*>}
|
||||
* @extends series.mappoint.data
|
||||
* @excluding labelrank, middleX, middleY, path, value, x, y, lat, lon
|
||||
* @product highmaps
|
||||
* @apioption series.mapbubble.data
|
||||
*/
|
||||
|
||||
/**
|
||||
* While the `x` and `y` values of the bubble are determined by the
|
||||
* underlying map, the `z` indicates the actual value that gives the
|
||||
* size of the bubble.
|
||||
*
|
||||
* @sample {highmaps} maps/demo/map-bubble/
|
||||
* Bubble
|
||||
*
|
||||
* @type {number}
|
||||
* @product highmaps
|
||||
* @apioption series.mapbubble.data.z
|
||||
*/
|
||||
|
||||
/**
|
||||
* @excluding enabled, enabledThreshold, height, radius, width
|
||||
* @apioption series.mapbubble.marker
|
||||
*/
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Options.js';
|
||||
|
||||
var seriesType = H.seriesType,
|
||||
seriesTypes = H.seriesTypes;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @class
|
||||
* @name Highcharts.seriesTypes.mapline
|
||||
*
|
||||
* @augments Highcharts.Series
|
||||
*/
|
||||
seriesType('mapline', 'map'
|
||||
|
||||
/**
|
||||
* A mapline series is a special case of the map series where the value
|
||||
* colors are applied to the strokes rather than the fills. It can also be
|
||||
* used for freeform drawing, like dividers, in the map.
|
||||
*
|
||||
* @sample maps/demo/mapline-mappoint/
|
||||
* Mapline and map-point chart
|
||||
*
|
||||
* @extends plotOptions.map
|
||||
* @product highmaps
|
||||
* @optionparent plotOptions.mapline
|
||||
*/
|
||||
, {
|
||||
/**
|
||||
* The width of the map line.
|
||||
*/
|
||||
lineWidth: 1,
|
||||
|
||||
/**
|
||||
* Fill color for the map line shapes
|
||||
*
|
||||
* @type {Highcharts.ColorString}
|
||||
*/
|
||||
fillColor: 'none'
|
||||
}, {
|
||||
|
||||
type: 'mapline',
|
||||
|
||||
colorProp: 'stroke',
|
||||
|
||||
pointAttrToOptions: {
|
||||
'stroke': 'color',
|
||||
'stroke-width': 'lineWidth'
|
||||
},
|
||||
|
||||
/**
|
||||
* Get presentational attributes
|
||||
*
|
||||
* @private
|
||||
* @function Highcharts.seriesTypes.mapline#pointAttribs
|
||||
*
|
||||
* @param {Highcharts.Point} point
|
||||
*
|
||||
* @param {string} state
|
||||
*
|
||||
* @return {Highcharts.Dictionary<*>}
|
||||
*/
|
||||
pointAttribs: function (point, state) {
|
||||
var attr = seriesTypes.map.prototype.pointAttribs.call(
|
||||
this,
|
||||
point,
|
||||
state
|
||||
);
|
||||
|
||||
// The difference from a map series is that the stroke takes the
|
||||
// point color
|
||||
attr.fill = this.options.fillColor;
|
||||
|
||||
return attr;
|
||||
},
|
||||
|
||||
drawLegendSymbol: seriesTypes.line.prototype.drawLegendSymbol
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* A `mapline` series. If the [type](#series.mapline.type) option is
|
||||
* not specified, it is inherited from [chart.type](#chart.type).
|
||||
*
|
||||
* @extends series,plotOptions.mapline
|
||||
* @excluding dataParser, dataURL, marker
|
||||
* @product highmaps
|
||||
* @apioption series.mapline
|
||||
*/
|
||||
|
||||
/**
|
||||
* An array of data points for the series. For the `mapline` series type,
|
||||
* points can be given in the following ways:
|
||||
*
|
||||
* 1. An array of numerical values. In this case, the numerical values
|
||||
* will be interpreted as `value` options. Example:
|
||||
*
|
||||
* ```js
|
||||
* data: [0, 5, 3, 5]
|
||||
* ```
|
||||
*
|
||||
* 2. An array of arrays with 2 values. In this case, the values correspond
|
||||
* to `[hc-key, value]`. Example:
|
||||
*
|
||||
* ```js
|
||||
* data: [
|
||||
* ['us-ny', 0],
|
||||
* ['us-mi', 5],
|
||||
* ['us-tx', 3],
|
||||
* ['us-ak', 5]
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* 3. An array of objects with named values. The following snippet shows only a
|
||||
* few settings, see the complete options set below. If the total number of data
|
||||
* points exceeds the series' [turboThreshold](#series.map.turboThreshold),
|
||||
* this option is not available.
|
||||
*
|
||||
* ```js
|
||||
* data: [{
|
||||
* value: 6,
|
||||
* name: "Point2",
|
||||
* color: "#00FF00"
|
||||
* }, {
|
||||
* value: 6,
|
||||
* name: "Point1",
|
||||
* color: "#FF00FF"
|
||||
* }]
|
||||
* ```
|
||||
*
|
||||
* @type {Array<number|Array<string,number>|object>}
|
||||
* @product highmaps
|
||||
* @apioption series.mapline.data
|
||||
*/
|
||||
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Chart.js';
|
||||
|
||||
var addEvent = H.addEvent,
|
||||
Chart = H.Chart,
|
||||
doc = H.doc,
|
||||
extend = H.extend,
|
||||
merge = H.merge,
|
||||
pick = H.pick;
|
||||
|
||||
function stopEvent(e) {
|
||||
if (e) {
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
e.cancelBubble = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The MapNavigation handles buttons for navigation in addition to mousewheel
|
||||
* and doubleclick handlers for chart zooming.
|
||||
*
|
||||
* @private
|
||||
* @class
|
||||
* @name MapNavigation
|
||||
*
|
||||
* @param {Highcharts.Chart} chart
|
||||
* The Chart instance.
|
||||
*/
|
||||
function MapNavigation(chart) {
|
||||
this.init(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize function.
|
||||
*
|
||||
* @function MapNavigation#init
|
||||
*
|
||||
* @param {Highcharts.Chart} chart
|
||||
* The Chart instance.
|
||||
*/
|
||||
MapNavigation.prototype.init = function (chart) {
|
||||
this.chart = chart;
|
||||
chart.mapNavButtons = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the map navigation with new options. Calling this is the same as
|
||||
* calling `chart.update({ mapNavigation: {} })`.
|
||||
*
|
||||
* @function MapNavigation#update
|
||||
*
|
||||
* @param {Highcharts.MapNavigationOptions} options
|
||||
* New options for the map navigation.
|
||||
*/
|
||||
MapNavigation.prototype.update = function (options) {
|
||||
var chart = this.chart,
|
||||
o = chart.options.mapNavigation,
|
||||
buttonOptions,
|
||||
attr,
|
||||
states,
|
||||
hoverStates,
|
||||
selectStates,
|
||||
outerHandler = function (e) {
|
||||
this.handler.call(chart, e);
|
||||
stopEvent(e); // Stop default click event (#4444)
|
||||
},
|
||||
mapNavButtons = chart.mapNavButtons;
|
||||
|
||||
// Merge in new options in case of update, and register back to chart
|
||||
// options.
|
||||
if (options) {
|
||||
o = chart.options.mapNavigation =
|
||||
merge(chart.options.mapNavigation, options);
|
||||
}
|
||||
|
||||
// Destroy buttons in case of dynamic update
|
||||
while (mapNavButtons.length) {
|
||||
mapNavButtons.pop().destroy();
|
||||
}
|
||||
|
||||
if (pick(o.enableButtons, o.enabled) && !chart.renderer.forExport) {
|
||||
|
||||
H.objectEach(o.buttons, function (button, n) {
|
||||
buttonOptions = merge(o.buttonOptions, button);
|
||||
|
||||
// Presentational
|
||||
if (!chart.styledMode) {
|
||||
attr = buttonOptions.theme;
|
||||
attr.style = merge(
|
||||
buttonOptions.theme.style,
|
||||
buttonOptions.style // #3203
|
||||
);
|
||||
states = attr.states;
|
||||
hoverStates = states && states.hover;
|
||||
selectStates = states && states.select;
|
||||
}
|
||||
|
||||
button = chart.renderer.button(
|
||||
buttonOptions.text,
|
||||
0,
|
||||
0,
|
||||
outerHandler,
|
||||
attr,
|
||||
hoverStates,
|
||||
selectStates,
|
||||
0,
|
||||
n === 'zoomIn' ? 'topbutton' : 'bottombutton'
|
||||
)
|
||||
.addClass('highcharts-map-navigation highcharts-' + {
|
||||
zoomIn: 'zoom-in',
|
||||
zoomOut: 'zoom-out'
|
||||
}[n])
|
||||
.attr({
|
||||
width: buttonOptions.width,
|
||||
height: buttonOptions.height,
|
||||
title: chart.options.lang[n],
|
||||
padding: buttonOptions.padding,
|
||||
zIndex: 5
|
||||
})
|
||||
.add();
|
||||
button.handler = buttonOptions.onclick;
|
||||
button.align(
|
||||
extend(buttonOptions, {
|
||||
width: button.width,
|
||||
height: 2 * button.height
|
||||
}),
|
||||
null,
|
||||
buttonOptions.alignTo
|
||||
);
|
||||
// Stop double click event (#4444)
|
||||
addEvent(button.element, 'dblclick', stopEvent);
|
||||
|
||||
mapNavButtons.push(button);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
this.updateEvents(o);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update events, called internally from the update function. Add new event
|
||||
* handlers, or unbinds events if disabled.
|
||||
*
|
||||
* @function MapNavigation#updateEvents
|
||||
*
|
||||
* @param {Highcharts.MapNavigationOptions} options
|
||||
* Options for map navigation.
|
||||
*/
|
||||
MapNavigation.prototype.updateEvents = function (options) {
|
||||
var chart = this.chart;
|
||||
|
||||
// Add the double click event
|
||||
if (
|
||||
pick(options.enableDoubleClickZoom, options.enabled) ||
|
||||
options.enableDoubleClickZoomTo
|
||||
) {
|
||||
this.unbindDblClick = this.unbindDblClick || addEvent(
|
||||
chart.container,
|
||||
'dblclick',
|
||||
function (e) {
|
||||
chart.pointer.onContainerDblClick(e);
|
||||
}
|
||||
);
|
||||
} else if (this.unbindDblClick) {
|
||||
// Unbind and set unbinder to undefined
|
||||
this.unbindDblClick = this.unbindDblClick();
|
||||
}
|
||||
|
||||
// Add the mousewheel event
|
||||
if (pick(options.enableMouseWheelZoom, options.enabled)) {
|
||||
this.unbindMouseWheel = this.unbindMouseWheel || addEvent(
|
||||
chart.container,
|
||||
doc.onmousewheel === undefined ? 'DOMMouseScroll' : 'mousewheel',
|
||||
function (e) {
|
||||
chart.pointer.onContainerMouseWheel(e);
|
||||
// Issue #5011, returning false from non-jQuery event does
|
||||
// not prevent default
|
||||
stopEvent(e);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} else if (this.unbindMouseWheel) {
|
||||
// Unbind and set unbinder to undefined
|
||||
this.unbindMouseWheel = this.unbindMouseWheel();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Add events to the Chart object itself
|
||||
extend(Chart.prototype, /** @lends Chart.prototype */ {
|
||||
|
||||
/**
|
||||
* Fit an inner box to an outer. If the inner box overflows left or right,
|
||||
* align it to the sides of the outer. If it overflows both sides, fit it
|
||||
* within the outer. This is a pattern that occurs more places in
|
||||
* Highcharts, perhaps it should be elevated to a common utility function.
|
||||
*
|
||||
* @ignore
|
||||
* @function Highcharts.Chart#fitToBox
|
||||
*
|
||||
* @param {Highcharts.BBoxObject} inner
|
||||
*
|
||||
* @param {Highcharts.BBoxObject} outer
|
||||
*
|
||||
* @return {Highcharts.BBoxObject}
|
||||
* The inner box
|
||||
*/
|
||||
fitToBox: function (inner, outer) {
|
||||
[['x', 'width'], ['y', 'height']].forEach(function (dim) {
|
||||
var pos = dim[0],
|
||||
size = dim[1];
|
||||
|
||||
if (inner[pos] + inner[size] > outer[pos] + outer[size]) { // right
|
||||
// the general size is greater, fit fully to outer
|
||||
if (inner[size] > outer[size]) {
|
||||
inner[size] = outer[size];
|
||||
inner[pos] = outer[pos];
|
||||
} else { // align right
|
||||
inner[pos] = outer[pos] + outer[size] - inner[size];
|
||||
}
|
||||
}
|
||||
if (inner[size] > outer[size]) {
|
||||
inner[size] = outer[size];
|
||||
}
|
||||
if (inner[pos] < outer[pos]) {
|
||||
inner[pos] = outer[pos];
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return inner;
|
||||
},
|
||||
|
||||
/**
|
||||
* Highmaps only. Zoom in or out of the map. See also {@link Point#zoomTo}.
|
||||
* See {@link Chart#fromLatLonToPoint} for how to get the `centerX` and
|
||||
* `centerY` parameters for a geographic location.
|
||||
*
|
||||
* @function Highcharts.Chart#mapZoom
|
||||
*
|
||||
* @param {number} [howMuch]
|
||||
* How much to zoom the map. Values less than 1 zooms in. 0.5 zooms
|
||||
* in to half the current view. 2 zooms to twice the current view. If
|
||||
* omitted, the zoom is reset.
|
||||
*
|
||||
* @param {number} [centerX]
|
||||
* The X axis position to center around if available space.
|
||||
*
|
||||
* @param {number} [centerY]
|
||||
* The Y axis position to center around if available space.
|
||||
*
|
||||
* @param {number} [mouseX]
|
||||
* Fix the zoom to this position if possible. This is used for
|
||||
* example in mousewheel events, where the area under the mouse
|
||||
* should be fixed as we zoom in.
|
||||
*
|
||||
* @param {number} [mouseY]
|
||||
* Fix the zoom to this position if possible.
|
||||
*/
|
||||
mapZoom: function (howMuch, centerXArg, centerYArg, mouseX, mouseY) {
|
||||
var chart = this,
|
||||
xAxis = chart.xAxis[0],
|
||||
xRange = xAxis.max - xAxis.min,
|
||||
centerX = pick(centerXArg, xAxis.min + xRange / 2),
|
||||
newXRange = xRange * howMuch,
|
||||
yAxis = chart.yAxis[0],
|
||||
yRange = yAxis.max - yAxis.min,
|
||||
centerY = pick(centerYArg, yAxis.min + yRange / 2),
|
||||
newYRange = yRange * howMuch,
|
||||
fixToX = mouseX ? ((mouseX - xAxis.pos) / xAxis.len) : 0.5,
|
||||
fixToY = mouseY ? ((mouseY - yAxis.pos) / yAxis.len) : 0.5,
|
||||
newXMin = centerX - newXRange * fixToX,
|
||||
newYMin = centerY - newYRange * fixToY,
|
||||
newExt = chart.fitToBox({
|
||||
x: newXMin,
|
||||
y: newYMin,
|
||||
width: newXRange,
|
||||
height: newYRange
|
||||
}, {
|
||||
x: xAxis.dataMin,
|
||||
y: yAxis.dataMin,
|
||||
width: xAxis.dataMax - xAxis.dataMin,
|
||||
height: yAxis.dataMax - yAxis.dataMin
|
||||
}),
|
||||
zoomOut = newExt.x <= xAxis.dataMin &&
|
||||
newExt.width >= xAxis.dataMax - xAxis.dataMin &&
|
||||
newExt.y <= yAxis.dataMin &&
|
||||
newExt.height >= yAxis.dataMax - yAxis.dataMin;
|
||||
|
||||
// When mousewheel zooming, fix the point under the mouse
|
||||
if (mouseX) {
|
||||
xAxis.fixTo = [mouseX - xAxis.pos, centerXArg];
|
||||
}
|
||||
if (mouseY) {
|
||||
yAxis.fixTo = [mouseY - yAxis.pos, centerYArg];
|
||||
}
|
||||
|
||||
// Zoom
|
||||
if (howMuch !== undefined && !zoomOut) {
|
||||
xAxis.setExtremes(newExt.x, newExt.x + newExt.width, false);
|
||||
yAxis.setExtremes(newExt.y, newExt.y + newExt.height, false);
|
||||
|
||||
// Reset zoom
|
||||
} else {
|
||||
xAxis.setExtremes(undefined, undefined, false);
|
||||
yAxis.setExtremes(undefined, undefined, false);
|
||||
}
|
||||
|
||||
// Prevent zooming until this one is finished animating
|
||||
/*
|
||||
chart.holdMapZoom = true;
|
||||
setTimeout(function () {
|
||||
chart.holdMapZoom = false;
|
||||
}, 200);
|
||||
*/
|
||||
/*
|
||||
delay = animation ? animation.duration || 500 : 0;
|
||||
if (delay) {
|
||||
chart.isMapZooming = true;
|
||||
setTimeout(function () {
|
||||
chart.isMapZooming = false;
|
||||
if (chart.mapZoomQueue) {
|
||||
chart.mapZoom.apply(chart, chart.mapZoomQueue);
|
||||
}
|
||||
chart.mapZoomQueue = null;
|
||||
}, delay);
|
||||
}
|
||||
*/
|
||||
|
||||
chart.redraw();
|
||||
}
|
||||
});
|
||||
|
||||
// Extend the Chart.render method to add zooming and panning
|
||||
addEvent(Chart, 'beforeRender', function () {
|
||||
// Render the plus and minus buttons. Doing this before the shapes makes
|
||||
// getBBox much quicker, at least in Chrome.
|
||||
this.mapNavigation = new MapNavigation(this);
|
||||
this.mapNavigation.update();
|
||||
});
|
||||
|
||||
H.MapNavigation = MapNavigation;
|
||||
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Options.js';
|
||||
import '../parts/Point.js';
|
||||
import '../parts/ScatterSeries.js';
|
||||
|
||||
var merge = H.merge,
|
||||
Point = H.Point,
|
||||
seriesType = H.seriesType;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @class
|
||||
* @name Highcharts.seriesTypes.mappoint
|
||||
*
|
||||
* @augments Highcharts.Series
|
||||
*/
|
||||
seriesType(
|
||||
'mappoint',
|
||||
'scatter',
|
||||
/**
|
||||
* A mappoint series is a special form of scatter series where the points
|
||||
* can be laid out in map coordinates on top of a map.
|
||||
*
|
||||
* @sample maps/demo/mapline-mappoint/
|
||||
* Map-line and map-point series.
|
||||
*
|
||||
* @extends plotOptions.scatter
|
||||
* @product highmaps
|
||||
* @optionparent plotOptions.mappoint
|
||||
*/
|
||||
{
|
||||
dataLabels: {
|
||||
/**
|
||||
* @default {point.name}
|
||||
* @apioption plotOptions.mappoint.dataLabels.format
|
||||
*/
|
||||
enabled: true,
|
||||
formatter: function () { // #2945
|
||||
return this.point.name;
|
||||
},
|
||||
crop: false,
|
||||
defer: false,
|
||||
overflow: false,
|
||||
style: {
|
||||
color: '#000000'
|
||||
}
|
||||
}
|
||||
// Prototype members
|
||||
}, {
|
||||
type: 'mappoint',
|
||||
forceDL: true
|
||||
// Point class
|
||||
}, {
|
||||
applyOptions: function (options, x) {
|
||||
var mergedOptions = (
|
||||
options.lat !== undefined &&
|
||||
options.lon !== undefined ?
|
||||
merge(
|
||||
options, this.series.chart.fromLatLonToPoint(options)
|
||||
) :
|
||||
options
|
||||
);
|
||||
|
||||
return Point.prototype.applyOptions.call(this, mergedOptions, x);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* A `mappoint` series. If the [type](#series.mappoint.type) option
|
||||
* is not specified, it is inherited from [chart.type](#chart.type).
|
||||
*
|
||||
*
|
||||
* @extends series,plotOptions.mappoint
|
||||
* @excluding dataParser, dataURL
|
||||
* @product highmaps
|
||||
* @apioption series.mappoint
|
||||
*/
|
||||
|
||||
/**
|
||||
* An array of data points for the series. For the `mappoint` series
|
||||
* type, points can be given in the following ways:
|
||||
*
|
||||
* 1. An array of numerical values. In this case, the numerical values
|
||||
* will be interpreted as `y` options. The `x` values will be automatically
|
||||
* calculated, either starting at 0 and incremented by 1, or from `pointStart`
|
||||
* and `pointInterval` given in the series options. If the axis has
|
||||
* categories, these will be used. Example:
|
||||
*
|
||||
* ```js
|
||||
* data: [0, 5, 3, 5]
|
||||
* ```
|
||||
*
|
||||
* 2. An array of arrays with 2 values. In this case, the values correspond
|
||||
* to `x,y`. If the first value is a string, it is applied as the name
|
||||
* of the point, and the `x` value is inferred.
|
||||
*
|
||||
* ```js
|
||||
* data: [
|
||||
* [0, 1],
|
||||
* [1, 8],
|
||||
* [2, 7]
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* 3. An array of objects with named values. The following snippet shows only a
|
||||
* few settings, see the complete options set below. If the total number of data
|
||||
* points exceeds the series' [turboThreshold](#series.mappoint.turboThreshold),
|
||||
* this option is not available.
|
||||
*
|
||||
* ```js
|
||||
* data: [{
|
||||
* x: 1,
|
||||
* y: 7,
|
||||
* name: "Point2",
|
||||
* color: "#00FF00"
|
||||
* }, {
|
||||
* x: 1,
|
||||
* y: 4,
|
||||
* name: "Point1",
|
||||
* color: "#FF00FF"
|
||||
* }]
|
||||
* ```
|
||||
*
|
||||
* @type {Array<number|Array<number,number>|*>}
|
||||
* @extends series.map.data
|
||||
* @excluding labelrank, middleX, middleY, path, value
|
||||
* @product highmaps
|
||||
* @apioption series.mappoint.data
|
||||
*/
|
||||
|
||||
/**
|
||||
* The latitude of the point. Must be combined with the `lon` option
|
||||
* to work. Overrides `x` and `y` values.
|
||||
*
|
||||
* @sample {highmaps} maps/demo/mappoint-latlon/
|
||||
* Point position by lat/lon
|
||||
*
|
||||
* @type {number}
|
||||
* @since 1.1.0
|
||||
* @product highmaps
|
||||
* @apioption series.mappoint.data.lat
|
||||
*/
|
||||
|
||||
/**
|
||||
* The longitude of the point. Must be combined with the `lon` option
|
||||
* to work. Overrides `x` and `y` values.
|
||||
*
|
||||
* @sample {highmaps} maps/demo/mappoint-latlon/
|
||||
* Point position by lat/lon
|
||||
*
|
||||
* @type {number}
|
||||
* @since 1.1.0
|
||||
* @product highmaps
|
||||
* @apioption series.mappoint.data.lon
|
||||
*/
|
||||
|
||||
/**
|
||||
* The x coordinate of the point in terms of the map path coordinates.
|
||||
*
|
||||
* @sample {highmaps} maps/demo/mapline-mappoint/
|
||||
* Map point demo
|
||||
*
|
||||
* @type {number}
|
||||
* @product highmaps
|
||||
* @apioption series.mappoint.data.x
|
||||
*/
|
||||
|
||||
/**
|
||||
* The x coordinate of the point in terms of the map path coordinates.
|
||||
*
|
||||
* @sample {highmaps} maps/demo/mapline-mappoint/
|
||||
* Map point demo
|
||||
*
|
||||
* @type {number}
|
||||
* @product highmaps
|
||||
* @apioption series.mappoint.data.y
|
||||
*/
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* (c) 2010-2019 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Pointer.js';
|
||||
|
||||
var extend = H.extend,
|
||||
pick = H.pick,
|
||||
Pointer = H.Pointer,
|
||||
wrap = H.wrap;
|
||||
|
||||
// Extend the Pointer
|
||||
extend(Pointer.prototype, {
|
||||
|
||||
// The event handler for the doubleclick event
|
||||
onContainerDblClick: function (e) {
|
||||
var chart = this.chart;
|
||||
|
||||
e = this.normalize(e);
|
||||
|
||||
if (chart.options.mapNavigation.enableDoubleClickZoomTo) {
|
||||
if (
|
||||
chart.pointer.inClass(e.target, 'highcharts-tracker') &&
|
||||
chart.hoverPoint
|
||||
) {
|
||||
chart.hoverPoint.zoomTo();
|
||||
}
|
||||
} else if (
|
||||
chart.isInsidePlot(
|
||||
e.chartX - chart.plotLeft,
|
||||
e.chartY - chart.plotTop
|
||||
)
|
||||
) {
|
||||
chart.mapZoom(
|
||||
0.5,
|
||||
chart.xAxis[0].toValue(e.chartX),
|
||||
chart.yAxis[0].toValue(e.chartY),
|
||||
e.chartX,
|
||||
e.chartY
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// The event handler for the mouse scroll event
|
||||
onContainerMouseWheel: function (e) {
|
||||
var chart = this.chart,
|
||||
delta;
|
||||
|
||||
e = this.normalize(e);
|
||||
|
||||
// Firefox uses e.detail, WebKit and IE uses wheelDelta
|
||||
delta = e.detail || -(e.wheelDelta / 120);
|
||||
if (chart.isInsidePlot(
|
||||
e.chartX - chart.plotLeft,
|
||||
e.chartY - chart.plotTop
|
||||
)) {
|
||||
chart.mapZoom(
|
||||
Math.pow(
|
||||
chart.options.mapNavigation.mouseWheelSensitivity,
|
||||
delta
|
||||
),
|
||||
chart.xAxis[0].toValue(e.chartX),
|
||||
chart.yAxis[0].toValue(e.chartY),
|
||||
e.chartX,
|
||||
e.chartY
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// The pinchType is inferred from mapNavigation options.
|
||||
wrap(Pointer.prototype, 'zoomOption', function (proceed) {
|
||||
|
||||
|
||||
var mapNavigation = this.chart.options.mapNavigation;
|
||||
|
||||
// Pinch status
|
||||
if (pick(mapNavigation.enableTouchZoom, mapNavigation.enabled)) {
|
||||
this.chart.options.chart.pinchType = 'xy';
|
||||
}
|
||||
|
||||
proceed.apply(this, [].slice.call(arguments, 1));
|
||||
|
||||
});
|
||||
|
||||
// Extend the pinchTranslate method to preserve fixed ratio when zooming
|
||||
wrap(
|
||||
Pointer.prototype,
|
||||
'pinchTranslate',
|
||||
function (
|
||||
proceed,
|
||||
pinchDown,
|
||||
touches,
|
||||
transform,
|
||||
selectionMarker,
|
||||
clip,
|
||||
lastValidTouch
|
||||
) {
|
||||
var xBigger;
|
||||
|
||||
proceed.call(
|
||||
this,
|
||||
pinchDown,
|
||||
touches,
|
||||
transform,
|
||||
selectionMarker,
|
||||
clip,
|
||||
lastValidTouch
|
||||
);
|
||||
|
||||
// Keep ratio
|
||||
if (this.chart.options.chart.type === 'map' && this.hasZoom) {
|
||||
xBigger = transform.scaleX > transform.scaleY;
|
||||
this.pinchTranslateDirection(
|
||||
!xBigger,
|
||||
pinchDown,
|
||||
touches,
|
||||
transform,
|
||||
selectionMarker,
|
||||
clip,
|
||||
lastValidTouch,
|
||||
xBigger ? transform.scaleX : transform.scaleY
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user