You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
541 lines
16 KiB
541 lines
16 KiB
/*
|
|
Map plugin v0.1 for Highcharts
|
|
|
|
(c) 2011-2013 Torstein Hønsi
|
|
|
|
License: www.highcharts.com/license
|
|
*/
|
|
(function (g) {
|
|
function x(a, b, c) {
|
|
for (var d = 4, e = []; d--; ) e[d] = Math.round(b.rgba[d] + (a.rgba[d] - b.rgba[d]) * (1 - c));
|
|
return 'rgba(' + e.join(',') + ')';
|
|
}
|
|
var r = g.Axis,
|
|
y = g.Chart,
|
|
s = g.Point,
|
|
z = g.Pointer,
|
|
l = g.each,
|
|
v = g.extend,
|
|
p = g.merge,
|
|
n = g.pick,
|
|
A = g.numberFormat,
|
|
B = g.getOptions(),
|
|
k = g.seriesTypes,
|
|
q = B.plotOptions,
|
|
t = g.wrap,
|
|
u = g.Color,
|
|
w = function () {};
|
|
B.mapNavigation = {
|
|
buttonOptions: {
|
|
align: 'right',
|
|
verticalAlign: 'bottom',
|
|
x: 0,
|
|
width: 18,
|
|
height: 18,
|
|
style: { fontSize: '15px', fontWeight: 'bold', textAlign: 'center' },
|
|
},
|
|
buttons: {
|
|
zoomIn: {
|
|
onclick: function () {
|
|
this.mapZoom(0.5);
|
|
},
|
|
text: '+',
|
|
y: -32,
|
|
},
|
|
zoomOut: {
|
|
onclick: function () {
|
|
this.mapZoom(2);
|
|
},
|
|
text: '-',
|
|
y: 0,
|
|
},
|
|
},
|
|
};
|
|
g.splitPath = function (a) {
|
|
var b,
|
|
a = a.replace(/([A-Za-z])/g, ' $1 '),
|
|
a = a.replace(/^\s*/, '').replace(/\s*$/, ''),
|
|
a = a.split(/[ ,]+/);
|
|
for (b = 0; b < a.length; b++) /[a-zA-Z]/.test(a[b]) || (a[b] = parseFloat(a[b]));
|
|
return a;
|
|
};
|
|
g.maps = {};
|
|
t(r.prototype, 'getSeriesExtremes', function (a) {
|
|
var b = this.isXAxis,
|
|
c,
|
|
d,
|
|
e = [];
|
|
l(this.series, function (a, b) {
|
|
if (a.useMapGeometry) (e[b] = a.xData), (a.xData = []);
|
|
});
|
|
a.call(this);
|
|
c = n(this.dataMin, Number.MAX_VALUE);
|
|
d = n(this.dataMax, Number.MIN_VALUE);
|
|
l(this.series, function (a, i) {
|
|
if (a.useMapGeometry)
|
|
(c = Math.min(c, a[b ? 'minX' : 'minY'])),
|
|
(d = Math.max(d, a[b ? 'maxX' : 'maxY'])),
|
|
(a.xData = e[i]);
|
|
});
|
|
this.dataMin = c;
|
|
this.dataMax = d;
|
|
});
|
|
t(r.prototype, 'setAxisTranslation', function (a) {
|
|
var b = this.chart,
|
|
c = b.plotWidth / b.plotHeight,
|
|
d = this.isXAxis,
|
|
e = b.xAxis[0];
|
|
a.call(this);
|
|
if (b.options.chart.type === 'map' && !d && e.transA !== void 0)
|
|
(this.transA = e.transA = Math.min(this.transA, e.transA)),
|
|
(a = (e.max - e.min) / (this.max - this.min)),
|
|
(e = a > c ? this : e),
|
|
(c = (e.max - e.min) * e.transA),
|
|
(e.minPixelPadding = (e.len - c) / 2);
|
|
});
|
|
t(y.prototype, 'render', function (a) {
|
|
var b = this,
|
|
c = b.options.mapNavigation;
|
|
a.call(b);
|
|
b.renderMapNavigation();
|
|
c.zoomOnDoubleClick &&
|
|
g.addEvent(b.container, 'dblclick', function (a) {
|
|
b.pointer.onContainerDblClick(a);
|
|
});
|
|
c.zoomOnMouseWheel &&
|
|
g.addEvent(
|
|
b.container,
|
|
document.onmousewheel === void 0 ? 'DOMMouseScroll' : 'mousewheel',
|
|
function (a) {
|
|
b.pointer.onContainerMouseWheel(a);
|
|
},
|
|
);
|
|
});
|
|
v(z.prototype, {
|
|
onContainerDblClick: function (a) {
|
|
var b = this.chart,
|
|
a = this.normalize(a);
|
|
b.isInsidePlot(a.chartX - b.plotLeft, a.chartY - b.plotTop) &&
|
|
b.mapZoom(0.5, b.xAxis[0].toValue(a.chartX), b.yAxis[0].toValue(a.chartY));
|
|
},
|
|
onContainerMouseWheel: function (a) {
|
|
var b = this.chart,
|
|
c,
|
|
a = this.normalize(a);
|
|
c = a.detail || -(a.wheelDelta / 120);
|
|
b.isInsidePlot(a.chartX - b.plotLeft, a.chartY - b.plotTop) &&
|
|
b.mapZoom(c > 0 ? 2 : 0.5, b.xAxis[0].toValue(a.chartX), b.yAxis[0].toValue(a.chartY));
|
|
},
|
|
});
|
|
t(z.prototype, 'init', function (a, b, c) {
|
|
a.call(this, b, c);
|
|
if (c.mapNavigation.enableTouchZoom)
|
|
this.pinchX = this.pinchHor = this.pinchY = this.pinchVert = !0;
|
|
});
|
|
v(y.prototype, {
|
|
renderMapNavigation: function () {
|
|
var a = this,
|
|
b = this.options.mapNavigation,
|
|
c = b.buttons,
|
|
d,
|
|
e,
|
|
f,
|
|
i = function () {
|
|
this.handler.call(a);
|
|
};
|
|
if (b.enableButtons)
|
|
for (d in c)
|
|
if (c.hasOwnProperty(d))
|
|
(f = p(b.buttonOptions, c[d])),
|
|
(e = a.renderer
|
|
.button(f.text, 0, 0, i)
|
|
.attr({ width: f.width, height: f.height })
|
|
.css(f.style)
|
|
.add()),
|
|
(e.handler = f.onclick),
|
|
e.align(v(f, { width: e.width, height: e.height }), null, 'spacingBox');
|
|
},
|
|
fitToBox: function (a, b) {
|
|
l(
|
|
[
|
|
['x', 'width'],
|
|
['y', 'height'],
|
|
],
|
|
function (c) {
|
|
var d = c[0],
|
|
c = c[1];
|
|
a[d] + a[c] > b[d] + b[c] &&
|
|
(a[c] > b[c] ? ((a[c] = b[c]), (a[d] = b[d])) : (a[d] = b[d] + b[c] - a[c]));
|
|
a[c] > b[c] && (a[c] = b[c]);
|
|
a[d] < b[d] && (a[d] = b[d]);
|
|
},
|
|
);
|
|
return a;
|
|
},
|
|
mapZoom: function (a, b, c) {
|
|
if (!this.isMapZooming) {
|
|
var d = this,
|
|
e = d.xAxis[0],
|
|
f = e.max - e.min,
|
|
i = n(b, e.min + f / 2),
|
|
b = f * a,
|
|
f = d.yAxis[0],
|
|
h = f.max - f.min,
|
|
c = n(c, f.min + h / 2);
|
|
a *= h;
|
|
i -= b / 2;
|
|
h = c - a / 2;
|
|
c = n(d.options.chart.animation, !0);
|
|
b = d.fitToBox(
|
|
{ x: i, y: h, width: b, height: a },
|
|
{
|
|
x: e.dataMin,
|
|
y: f.dataMin,
|
|
width: e.dataMax - e.dataMin,
|
|
height: f.dataMax - f.dataMin,
|
|
},
|
|
);
|
|
e.setExtremes(b.x, b.x + b.width, !1);
|
|
f.setExtremes(b.y, b.y + b.height, !1);
|
|
if ((e = c ? c.duration || 500 : 0))
|
|
(d.isMapZooming = !0),
|
|
setTimeout(function () {
|
|
d.isMapZooming = !1;
|
|
}, e);
|
|
d.redraw();
|
|
}
|
|
},
|
|
});
|
|
q.map = p(q.scatter, {
|
|
animation: !1,
|
|
nullColor: '#F8F8F8',
|
|
borderColor: 'silver',
|
|
borderWidth: 1,
|
|
marker: null,
|
|
stickyTracking: !1,
|
|
dataLabels: { verticalAlign: 'middle' },
|
|
turboThreshold: 0,
|
|
tooltip: { followPointer: !0, pointFormat: '{point.name}: {point.y}<br/>' },
|
|
states: { normal: { animation: !0 } },
|
|
});
|
|
r = g.extendClass(s, {
|
|
applyOptions: function (a, b) {
|
|
var c = s.prototype.applyOptions.call(this, a, b);
|
|
if (c.path && typeof c.path === 'string') c.path = c.options.path = g.splitPath(c.path);
|
|
return c;
|
|
},
|
|
onMouseOver: function () {
|
|
clearTimeout(this.colorInterval);
|
|
s.prototype.onMouseOver.call(this);
|
|
},
|
|
onMouseOut: function () {
|
|
var a = this,
|
|
b = +new Date(),
|
|
c = u(a.options.color),
|
|
d = u(a.pointAttr.hover.fill),
|
|
e = a.series.options.states.normal.animation,
|
|
f = e && (e.duration || 500);
|
|
if (f && c.rgba.length === 4 && d.rgba.length === 4)
|
|
delete a.pointAttr[''].fill,
|
|
clearTimeout(a.colorInterval),
|
|
(a.colorInterval = setInterval(function () {
|
|
var e = (new Date() - b) / f,
|
|
h = a.graphic;
|
|
e > 1 && (e = 1);
|
|
h && h.attr('fill', x(d, c, e));
|
|
e >= 1 && clearTimeout(a.colorInterval);
|
|
}, 13));
|
|
s.prototype.onMouseOut.call(a);
|
|
},
|
|
});
|
|
k.map = g.extendClass(k.scatter, {
|
|
type: 'map',
|
|
pointAttrToOptions: { stroke: 'borderColor', 'stroke-width': 'borderWidth', fill: 'color' },
|
|
colorKey: 'y',
|
|
pointClass: r,
|
|
trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
|
|
getSymbol: w,
|
|
supportsDrilldown: !0,
|
|
getExtremesFromAll: !0,
|
|
useMapGeometry: !0,
|
|
init: function (a) {
|
|
var b = this,
|
|
c = a.options.legend.valueDecimals,
|
|
d = [],
|
|
e,
|
|
f,
|
|
i,
|
|
h,
|
|
j,
|
|
o,
|
|
m;
|
|
o = a.options.legend.layout === 'horizontal';
|
|
g.Series.prototype.init.apply(this, arguments);
|
|
j = b.options.colorRange;
|
|
if ((h = b.options.valueRanges))
|
|
l(h, function (a) {
|
|
f = a.from;
|
|
i = a.to;
|
|
e = '';
|
|
f === void 0 ? (e = '< ') : i === void 0 && (e = '> ');
|
|
f !== void 0 && (e += A(f, c));
|
|
f !== void 0 && i !== void 0 && (e += ' - ');
|
|
i !== void 0 && (e += A(i, c));
|
|
d.push(
|
|
g.extend(
|
|
{
|
|
chart: b.chart,
|
|
name: e,
|
|
options: {},
|
|
drawLegendSymbol: k.area.prototype.drawLegendSymbol,
|
|
visible: !0,
|
|
setState: function () {},
|
|
setVisible: function () {},
|
|
},
|
|
a,
|
|
),
|
|
);
|
|
}),
|
|
(b.legendItems = d);
|
|
else if (j)
|
|
(f = j.from),
|
|
(i = j.to),
|
|
(h = j.fromLabel),
|
|
(j = j.toLabel),
|
|
(m = o ? [0, 0, 1, 0] : [0, 1, 0, 0]),
|
|
o || ((o = h), (h = j), (j = o)),
|
|
(o = {
|
|
linearGradient: { x1: m[0], y1: m[1], x2: m[2], y2: m[3] },
|
|
stops: [
|
|
[0, f],
|
|
[1, i],
|
|
],
|
|
}),
|
|
(d = [
|
|
{
|
|
chart: b.chart,
|
|
options: {},
|
|
fromLabel: h,
|
|
toLabel: j,
|
|
color: o,
|
|
drawLegendSymbol: this.drawLegendSymbolGradient,
|
|
visible: !0,
|
|
setState: function () {},
|
|
setVisible: function () {},
|
|
},
|
|
]),
|
|
(b.legendItems = d);
|
|
},
|
|
drawLegendSymbol: k.area.prototype.drawLegendSymbol,
|
|
drawLegendSymbolGradient: function (a, b) {
|
|
var c = a.options.symbolPadding,
|
|
d = n(a.options.padding, 8),
|
|
e,
|
|
f,
|
|
i = this.chart.renderer.fontMetrics(a.options.itemStyle.fontSize).h,
|
|
h = a.options.layout === 'horizontal',
|
|
j;
|
|
j = n(a.options.rectangleLength, 200);
|
|
h ? ((e = -(c / 2)), (f = 0)) : ((e = -j + a.baseline - c / 2), (f = d + i));
|
|
b.fromText = this.chart.renderer
|
|
.text(b.fromLabel, f, e)
|
|
.attr({ zIndex: 2 })
|
|
.add(b.legendGroup);
|
|
f = b.fromText.getBBox();
|
|
b.legendSymbol = this.chart.renderer
|
|
.rect(h ? f.x + f.width + c : f.x - i - c, f.y, h ? j : i, h ? i : j, 2)
|
|
.attr({ zIndex: 1 })
|
|
.add(b.legendGroup);
|
|
j = b.legendSymbol.getBBox();
|
|
b.toText = this.chart.renderer
|
|
.text(b.toLabel, j.x + j.width + c, h ? e : j.y + j.height - c)
|
|
.attr({ zIndex: 2 })
|
|
.add(b.legendGroup);
|
|
e = b.toText.getBBox();
|
|
h
|
|
? ((a.offsetWidth = f.width + j.width + e.width + c * 2 + d), (a.itemY = i + d))
|
|
: ((a.offsetWidth = Math.max(f.width, e.width) + c + j.width + d),
|
|
(a.itemY = j.height + d),
|
|
(a.itemX = c));
|
|
},
|
|
getBox: function (a) {
|
|
var b = Number.MIN_VALUE,
|
|
c = Number.MAX_VALUE,
|
|
d = Number.MIN_VALUE,
|
|
e = Number.MAX_VALUE;
|
|
l(a || this.options.data, function (a) {
|
|
for (
|
|
var i = a.path,
|
|
h = i.length,
|
|
j = !1,
|
|
g = Number.MIN_VALUE,
|
|
m = Number.MAX_VALUE,
|
|
k = Number.MIN_VALUE,
|
|
l = Number.MAX_VALUE;
|
|
h--;
|
|
|
|
)
|
|
typeof i[h] === 'number' &&
|
|
!isNaN(i[h]) &&
|
|
(j
|
|
? ((g = Math.max(g, i[h])), (m = Math.min(m, i[h])))
|
|
: ((k = Math.max(k, i[h])), (l = Math.min(l, i[h]))),
|
|
(j = !j));
|
|
a._maxX = g;
|
|
a._minX = m;
|
|
a._maxY = k;
|
|
a._minY = l;
|
|
b = Math.max(b, g);
|
|
c = Math.min(c, m);
|
|
d = Math.max(d, k);
|
|
e = Math.min(e, l);
|
|
});
|
|
this.minY = e;
|
|
this.maxY = d;
|
|
this.minX = c;
|
|
this.maxX = b;
|
|
},
|
|
translatePath: function (a) {
|
|
var b = !1,
|
|
c = this.xAxis,
|
|
d = this.yAxis,
|
|
e,
|
|
a = [].concat(a);
|
|
for (e = a.length; e--; )
|
|
typeof a[e] === 'number' &&
|
|
((a[e] = b ? Math.round(c.translate(a[e])) : Math.round(d.len - d.translate(a[e]))),
|
|
(b = !b));
|
|
return a;
|
|
},
|
|
setData: function () {
|
|
g.Series.prototype.setData.apply(this, arguments);
|
|
this.getBox();
|
|
},
|
|
translate: function () {
|
|
var a = this,
|
|
b = Number.MAX_VALUE,
|
|
c = Number.MIN_VALUE;
|
|
a.generatePoints();
|
|
l(a.data, function (d) {
|
|
d.shapeType = 'path';
|
|
d.shapeArgs = { d: a.translatePath(d.path) };
|
|
if (typeof d.y === 'number')
|
|
if (d.y > c) c = d.y;
|
|
else if (d.y < b) b = d.y;
|
|
});
|
|
a.translateColors(b, c);
|
|
},
|
|
translateColors: function (a, b) {
|
|
var c = this.options,
|
|
d = c.valueRanges,
|
|
e = c.colorRange,
|
|
f = this.colorKey,
|
|
i,
|
|
h;
|
|
e && ((i = u(e.from)), (h = u(e.to)));
|
|
l(this.data, function (g) {
|
|
var k = g[f],
|
|
m,
|
|
l,
|
|
n;
|
|
if (d)
|
|
for (n = d.length; n--; ) {
|
|
if (
|
|
((m = d[n]),
|
|
(i = m.from),
|
|
(h = m.to),
|
|
(i === void 0 || k >= i) && (h === void 0 || k <= h))
|
|
) {
|
|
l = m.color;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
e &&
|
|
k !== void 0 &&
|
|
((m = 1 - (b - k) / (b - a)), (l = k === null ? c.nullColor : x(i, h, m)));
|
|
if (l) (g.color = null), (g.options.color = l);
|
|
});
|
|
},
|
|
drawGraph: w,
|
|
drawDataLabels: w,
|
|
drawPoints: function () {
|
|
var a = this.xAxis,
|
|
b = this.yAxis,
|
|
c = this.colorKey;
|
|
l(this.data, function (a) {
|
|
a.plotY = 1;
|
|
if (a[c] === null) (a[c] = 0), (a.isNull = !0);
|
|
});
|
|
k.column.prototype.drawPoints.apply(this);
|
|
l(this.data, function (d) {
|
|
var e = d.dataLabels,
|
|
f = a.toPixels(d._minX, !0),
|
|
g = a.toPixels(d._maxX, !0),
|
|
h = b.toPixels(d._minY, !0),
|
|
j = b.toPixels(d._maxY, !0);
|
|
d.plotX = Math.round(f + (g - f) * n(e && e.anchorX, 0.5));
|
|
d.plotY = Math.round(h + (j - h) * n(e && e.anchorY, 0.5));
|
|
d.isNull && (d[c] = null);
|
|
});
|
|
g.Series.prototype.drawDataLabels.call(this);
|
|
},
|
|
animateDrilldown: function (a) {
|
|
var b = this.chart.plotBox,
|
|
c = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1],
|
|
d = c.bBox,
|
|
e = this.chart.options.drilldown.animation;
|
|
if (!a)
|
|
(a = Math.min(d.width / b.width, d.height / b.height)),
|
|
(c.shapeArgs = { scaleX: a, scaleY: a, translateX: d.x, translateY: d.y }),
|
|
l(this.points, function (a) {
|
|
a.graphic
|
|
.attr(c.shapeArgs)
|
|
.animate({ scaleX: 1, scaleY: 1, translateX: 0, translateY: 0 }, e);
|
|
}),
|
|
delete this.animate;
|
|
},
|
|
animateDrillupFrom: function (a) {
|
|
k.column.prototype.animateDrillupFrom.call(this, a);
|
|
},
|
|
animateDrillupTo: function (a) {
|
|
k.column.prototype.animateDrillupTo.call(this, a);
|
|
},
|
|
});
|
|
q.mapline = p(q.map, { lineWidth: 1, backgroundColor: 'none' });
|
|
k.mapline = g.extendClass(k.map, {
|
|
type: 'mapline',
|
|
pointAttrToOptions: { stroke: 'color', 'stroke-width': 'lineWidth', fill: 'backgroundColor' },
|
|
drawLegendSymbol: k.line.prototype.drawLegendSymbol,
|
|
});
|
|
q.mappoint = p(q.scatter, {
|
|
dataLabels: {
|
|
enabled: !0,
|
|
format: '{point.name}',
|
|
color: 'black',
|
|
style: { textShadow: '0 0 5px white' },
|
|
},
|
|
});
|
|
k.mappoint = g.extendClass(k.scatter, { type: 'mappoint' });
|
|
g.Map = function (a, b) {
|
|
var c = {
|
|
endOnTick: !1,
|
|
gridLineWidth: 0,
|
|
labels: { enabled: !1 },
|
|
lineWidth: 0,
|
|
minPadding: 0,
|
|
maxPadding: 0,
|
|
startOnTick: !1,
|
|
tickWidth: 0,
|
|
title: null,
|
|
},
|
|
d;
|
|
d = a.series;
|
|
a.series = null;
|
|
a = p({ chart: { type: 'map', panning: 'xy' }, xAxis: c, yAxis: p(c, { reversed: !0 }) }, a, {
|
|
chart: { inverted: !1 },
|
|
});
|
|
a.series = d;
|
|
return new g.Chart(a, b);
|
|
};
|
|
})(Highcharts);
|
|
|