/base/000_base/bower_components/highcharts/modules/boost.src.js |
@@ -1,5 +1,5 @@ |
/** |
* @license Highcharts JS v5.0.10 (2017-03-31) |
* @license Highcharts JS v5.0.12 (2017-05-24) |
* Boost module |
* |
* (c) 2010-2017 Highsoft AS |
@@ -61,8 +61,8 @@ |
* |
* Settings |
* There are two ways of setting the boost threshold: |
* - Per. series: boost based on number of points in individual series |
* - Per. chart: boost based on the number of series |
* - Per. series: boost based on number of points in individual series |
* - Per. chart: boost based on the number of series |
* |
* To set the series boost threshold, set seriesBoostThreshold on the chart object. |
* To set the series-specific threshold, set boostThreshold on the series object. |
@@ -115,7 +115,7 @@ |
* @apioption series.boostThreshold |
*/ |
|
/* global Float32Array, Image */ |
/* global Float32Array */ |
|
|
var win = H.win, |
@@ -284,16 +284,61 @@ |
yellowgreen: '#9acd32' |
}; |
|
/** |
* Tolerant max() funciton |
* @return {number} max value |
*/ |
function patientMax() { |
var args = Array.prototype.slice.call(arguments), |
r = -Number.MAX_VALUE; |
|
each(args, function(t) { |
if (typeof t !== 'undefined' && typeof t.length !== 'undefined') { |
//r = r < t.length ? t.length : r; |
if (t.length > 0) { |
r = t.length; |
return true; |
} |
} |
}); |
|
return r; |
} |
|
/* |
* Returns true if we should force chart series boosting |
*/ |
function shouldForceChartSeriesBoosting(chart) { |
// If there are more than five series currently boosting, |
// we should boost the whole chart to avoid running out of webgl contexts. |
var sboostCount = 0, |
series; |
|
if (chart.series.length > 1) { |
for (var i = 0; i < chart.series.length; i++) { |
series = chart.series[i]; |
if (patientMax( |
series.processedXData, |
series.options.data, |
series.points |
) >= (series.options.boostThreshold || Number.MAX_VALUE)) { |
sboostCount++; |
} |
} |
} |
|
return sboostCount > 5; |
} |
|
/* |
* Returns true if the chart is in series boost mode |
* @param chart {Highchart.Chart} - the chart to check |
* @returns {Boolean} - true if the chart is in series boost mode |
*/ |
function isChartSeriesBoosting(chart) { |
return chart.series.length >= pick( |
chart.options.boost && chart.options.boost.seriesThreshold, // docs |
10 |
return shouldForceChartSeriesBoosting(chart) || chart.series.length >= pick( |
chart.options.boost && chart.options.boost.seriesThreshold, |
50 |
); |
} |
|
@@ -303,23 +348,6 @@ |
* @returns {boolean} - true if the series is in boost mode |
*/ |
function isSeriesBoosting(series) { |
function patientMax() { |
var args = Array.prototype.slice.call(arguments), |
r = -Number.MAX_VALUE; |
|
each(args, function(t) { |
if (typeof t !== 'undefined' && typeof t.length !== 'undefined') { |
//r = r < t.length ? t.length : r; |
if (t.length > 0) { |
r = t.length; |
return true; |
} |
} |
}); |
|
return r; |
} |
|
return isChartSeriesBoosting(series.chart) || |
patientMax( |
series.processedXData, |
@@ -1097,7 +1125,15 @@ |
minVal, |
color, |
scolor, |
sdata = isStacked ? series.data : (xData || rawData); |
sdata = isStacked ? series.data : (xData || rawData), |
closestLeft = { |
x: Number.MIN_VALUE, |
y: 0 |
}, |
closestRight = { |
x: Number.MIN_VALUE, |
y: 0 |
}; |
|
if (options.boostData && options.boostData.length > 0) { |
return; |
@@ -1176,10 +1212,12 @@ |
|
if (plotY !== undefined && !isNaN(plotY) && point.y !== null) { |
shapeArgs = point.shapeArgs; |
pointAttr = (point.pointAttr && point.pointAttr['']) || |
point.series.pointAttribs(point); |
swidth = pointAttr['stroke-width']; |
|
|
pointAttr = point.series.pointAttribs(point); |
|
swidth = pointAttr['stroke-width'] || 0; |
|
// Handle point colors |
color = H.color(pointAttr.fill).rgba; |
color[0] /= 255.0; |
@@ -1344,7 +1382,17 @@ |
isYInside = y >= yMin && y <= yMax; |
} |
|
if ((!y || !isYInside)) { |
if (x > xMax && closestRight.x < xMax) { |
closestRight.x = x; |
closestRight.y = y; |
} |
|
if (x < xMin && closestLeft.x < xMin) { |
closestLeft.x = x; |
closestLeft.y = y; |
} |
|
if (y !== 0 && (!y || !isYInside)) { |
return; |
} |
|
@@ -1427,6 +1475,30 @@ |
|
//return true; |
}); |
|
function pushSupplementPoint(point) { |
if (!settings.useGPUTranslations) { |
inst.skipTranslation = true; |
point.x = xAxis.toPixels(point.x, true); |
point.y = yAxis.toPixels(point.y, true); |
} |
|
// We should only do this for lines, and we should ignore markers |
// since there's no point here that would have a marker. |
|
vertice( |
point.x, |
point.y, |
0, |
2 |
); |
} |
|
if (!lastX) { |
// There are no points within the selected range |
pushSupplementPoint(closestLeft); |
pushSupplementPoint(closestRight); |
} |
} |
|
/* |
@@ -1566,7 +1638,9 @@ |
gl.viewport(0, 0, width, height); |
shader.setPMatrix(orthoMatrix(width, height)); |
|
gl.lineWidth(settings.lineWidth); |
if (settings.lineWidth > 1 && !H.isMS) { |
gl.lineWidth(settings.lineWidth); |
} |
|
vbuffer.build(exports.data, 'aVertexPosition', 4); |
vbuffer.bind(); |
@@ -1616,7 +1690,7 @@ |
} |
|
//Blending |
if (options.boostBlending === 'add') { // docs |
if (options.boostBlending === 'add') { |
gl.blendFunc(gl.SRC_ALPHA, gl.ONE); |
gl.blendEquation(gl.FUNC_ADD); |
|
@@ -1628,8 +1702,9 @@ |
gl.blendEquation(gl.FUNC_MIN); |
|
} else { |
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); //, gl.ONE, gl.ZERO); |
gl.blendEquation(gl.FUNC_ADD); |
//gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);//, gl.ONE, gl.ZERO); |
//gl.blendEquation(gl.FUNC_ADD); |
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); |
} |
|
shader.reset(); |
@@ -1737,7 +1812,6 @@ |
*/ |
function init(canvas, noFlush) { |
var i = 0, |
activeContext, |
contexts = [ |
'webgl', |
'experimental-webgl', |
@@ -1758,7 +1832,6 @@ |
for (; i < contexts.length; i++) { |
gl = canvas.getContext(contexts[i]); |
if (gl) { |
activeContext = contexts[i]; |
break; |
} |
} |
@@ -2230,6 +2303,25 @@ |
return false; |
} |
|
/* Used for treemap|heatmap.drawPoints */ |
function pointDrawHandler(proceed) { |
if (!isSeriesBoosting(this)) { |
return proceed.call(this); |
} |
|
//Make sure we have a valid OGL context |
var renderer = createAndAttachRenderer(this.chart, this); |
|
if (renderer) { |
allocateIfNotSeriesBoosting(renderer, this); |
renderer.pushSeries(this); |
} |
|
renderIfNotSeriesBoosting(renderer, this); |
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
// We're wrapped in a closure, so just return if there's no webgl support |
|
@@ -2240,404 +2332,390 @@ |
} else { |
H.error(26); |
} |
//eslint-disable |
return; |
//eslint-enable |
} |
} else { |
|
//////////////////////////////////////////////////////////////////////////////// |
// GL-SPECIFIC WRAPPINGS FOLLOWS |
//////////////////////////////////////////////////////////////////////////// |
// GL-SPECIFIC WRAPPINGS FOLLOWS |
|
/** If the series is a heatmap or treemap, or if the series is not boosting |
* do the default behaviour. Otherwise, process if the series has no |
* extremes. |
*/ |
wrap(Series.prototype, 'processData', function(proceed) { |
// If this is a heatmap, do default behaviour |
if (!isSeriesBoosting(this) || |
this.type === 'heatmap' || |
this.type === 'treemap') { |
proceed.apply(this, Array.prototype.slice.call(arguments, 1)); |
} |
/** If the series is a heatmap or treemap, or if the series is not boosting |
* do the default behaviour. Otherwise, process if the series has no |
* extremes. |
*/ |
wrap(Series.prototype, 'processData', function(proceed) { |
// If this is a heatmap, do default behaviour |
if (!isSeriesBoosting(this) || |
this.type === 'heatmap' || |
this.type === 'treemap') { |
proceed.apply(this, Array.prototype.slice.call(arguments, 1)); |
} |
|
if (!this.hasExtremes || !this.hasExtremes(true)) { |
proceed.apply(this, Array.prototype.slice.call(arguments, 1)); |
} |
}); |
if (!this.hasExtremes || !this.hasExtremes(true)) { |
proceed.apply(this, Array.prototype.slice.call(arguments, 1)); |
} |
}); |
|
H.extend(Series.prototype, { |
pointRange: 0, |
directTouch: false, |
allowDG: false, // No data grouping, let boost handle large data |
hasExtremes: function(checkX) { |
var options = this.options, |
data = options.data, |
xAxis = this.xAxis && this.xAxis.options, |
yAxis = this.yAxis && this.yAxis.options; |
H.extend(Series.prototype, { |
pointRange: 0, |
directTouch: false, |
allowDG: false, // No data grouping, let boost handle large data |
hasExtremes: function(checkX) { |
var options = this.options, |
data = options.data, |
xAxis = this.xAxis && this.xAxis.options, |
yAxis = this.yAxis && this.yAxis.options; |
|
return data.length > (options.boostThreshold || Number.MAX_VALUE) && |
isNumber(yAxis.min) && isNumber(yAxis.max) && |
(!checkX || (isNumber(xAxis.min) && isNumber(xAxis.max))); |
}, |
return data.length > (options.boostThreshold || Number.MAX_VALUE) && |
isNumber(yAxis.min) && isNumber(yAxis.max) && |
(!checkX || (isNumber(xAxis.min) && isNumber(xAxis.max))); |
}, |
|
/** |
* If implemented in the core, parts of this can probably be |
* shared with other similar methods in Highcharts. |
*/ |
destroyGraphics: function() { |
var series = this, |
points = this.points, |
point, |
i; |
/** |
* If implemented in the core, parts of this can probably be |
* shared with other similar methods in Highcharts. |
*/ |
destroyGraphics: function() { |
var series = this, |
points = this.points, |
point, |
i; |
|
if (points) { |
for (i = 0; i < points.length; i = i + 1) { |
point = points[i]; |
if (point && point.graphic) { |
point.graphic = point.graphic.destroy(); |
if (points) { |
for (i = 0; i < points.length; i = i + 1) { |
point = points[i]; |
if (point && point.graphic) { |
point.graphic = point.graphic.destroy(); |
} |
} |
} |
} |
|
each(['graph', 'area', 'tracker'], function(prop) { |
if (series[prop]) { |
series[prop] = series[prop].destroy(); |
} |
}); |
}, |
each(['graph', 'area', 'tracker'], function(prop) { |
if (series[prop]) { |
series[prop] = series[prop].destroy(); |
} |
}); |
}, |
|
renderCanvas: function() { |
var series = this, |
options = series.options || {}, |
renderer = false, |
chart = series.chart, |
xAxis = this.xAxis, |
yAxis = this.yAxis, |
//ctx, |
//c = 0, |
xData = options.xData || series.processedXData, |
yData = options.yData || series.processedYData, |
renderCanvas: function() { |
var series = this, |
options = series.options || {}, |
renderer = false, |
chart = series.chart, |
xAxis = this.xAxis, |
yAxis = this.yAxis, |
//ctx, |
//c = 0, |
xData = options.xData || series.processedXData, |
yData = options.yData || series.processedYData, |
|
rawData = options.data, |
xExtremes = xAxis.getExtremes(), |
xMin = xExtremes.min, |
xMax = xExtremes.max, |
yExtremes = yAxis.getExtremes(), |
yMin = yExtremes.min, |
yMax = yExtremes.max, |
pointTaken = {}, |
lastClientX, |
sampling = !!series.sampling, |
points, |
// r = options.marker && options.marker.radius, |
// cvsDrawPoint = this.cvsDrawPoint, |
// cvsLineTo = options.lineWidth ? this.cvsLineTo : false, |
// cvsMarker = r <= 1 ? this.cvsMarkerSquare : this.cvsMarkerCircle, |
enableMouseTracking = options.enableMouseTracking !== false, |
// lastPoint, |
threshold = options.threshold, |
yBottom = yAxis.getThreshold(threshold), |
hasThreshold = isNumber(threshold), |
// translatedThreshold = yBottom, |
// doFill = this.fill, |
isRange = series.pointArrayMap && |
series.pointArrayMap.join(',') === 'low,high', |
isStacked = !!options.stacking, |
cropStart = series.cropStart || 0, |
requireSorting = series.requireSorting, |
wasNull, |
connectNulls = options.connectNulls, |
useRaw = !xData, |
minVal, |
maxVal, |
minI, |
maxI, |
// fillColor = series.fillOpacity ? |
// new Color(series.color).setOpacity( |
// pick(options.fillOpacity, 0.75) |
// ).get() : series.color, |
rawData = options.data, |
xExtremes = xAxis.getExtremes(), |
xMin = xExtremes.min, |
xMax = xExtremes.max, |
yExtremes = yAxis.getExtremes(), |
yMin = yExtremes.min, |
yMax = yExtremes.max, |
pointTaken = {}, |
lastClientX, |
sampling = !!series.sampling, |
points, |
enableMouseTracking = options.enableMouseTracking !== false, |
threshold = options.threshold, |
yBottom = yAxis.getThreshold(threshold), |
isRange = series.pointArrayMap && |
series.pointArrayMap.join(',') === 'low,high', |
isStacked = !!options.stacking, |
cropStart = series.cropStart || 0, |
requireSorting = series.requireSorting, |
useRaw = !xData, |
minVal, |
maxVal, |
minI, |
maxI, |
|
addKDPoint = function(clientX, plotY, i) { |
//Shaves off about 60ms compared to repeated concatination |
index = clientX + ',' + plotY; |
addKDPoint = function(clientX, plotY, i) { |
//Shaves off about 60ms compared to repeated concatination |
index = clientX + ',' + plotY; |
|
// The k-d tree requires series points. |
// Reduce the amount of points, since the time to build the |
// tree increases exponentially. |
if (enableMouseTracking && !pointTaken[index]) { |
pointTaken[index] = true; |
// The k-d tree requires series points. |
// Reduce the amount of points, since the time to build the |
// tree increases exponentially. |
if (enableMouseTracking && !pointTaken[index]) { |
pointTaken[index] = true; |
|
if (chart.inverted) { |
clientX = xAxis.len - clientX; |
plotY = yAxis.len - plotY; |
if (chart.inverted) { |
clientX = xAxis.len - clientX; |
plotY = yAxis.len - plotY; |
} |
|
points.push({ |
clientX: clientX, |
plotX: clientX, |
plotY: plotY, |
i: cropStart + i |
}); |
} |
}; |
|
points.push({ |
clientX: clientX, |
plotX: clientX, |
plotY: plotY, |
i: cropStart + i |
// Get or create the renderer |
renderer = createAndAttachRenderer(chart, series); |
|
if (!this.visible) { |
if (!isChartSeriesBoosting(chart) && renderer) { |
renderer.clear(); |
this.image.attr({ |
href: '' |
}); |
} |
}; |
return; |
} |
|
// Get or create the renderer |
renderer = createAndAttachRenderer(chart, series); |
// If we are zooming out from SVG mode, destroy the graphics |
if (this.points || this.graph) { |
this.destroyGraphics(); |
} |
|
if (!this.visible) { |
if (!isChartSeriesBoosting(chart) && renderer) { |
renderer.clear(); |
this.image.attr({ |
href: '' |
}); |
// If we're rendering per. series we should create the marker groups |
// as usual. |
if (!isChartSeriesBoosting(chart)) { |
this.markerGroup = series.plotGroup( |
'markerGroup', |
'markers', |
true, |
1, |
chart.seriesGroup |
); |
} else { |
//Use a single group for the markers |
this.markerGroup = chart.markerGroup; |
} |
return; |
} |
|
// If we are zooming out from SVG mode, destroy the graphics |
if (this.points || this.graph) { |
this.destroyGraphics(); |
} |
points = this.points = []; |
|
// If we're rendering per. series we should create the marker groups |
// as usual. |
if (!isChartSeriesBoosting(chart)) { |
this.markerGroup = series.plotGroup( |
'markerGroup', |
'markers', |
true, |
1, |
chart.seriesGroup |
); |
} else { |
//Use a single group for the markers |
this.markerGroup = chart.markerGroup; |
} |
// Do not start building while drawing |
series.buildKDTree = noop; |
|
points = this.points = []; |
if (renderer) { |
allocateIfNotSeriesBoosting(renderer, this); |
renderer.pushSeries(series); |
// Perform the actual renderer if we're on series level |
renderIfNotSeriesBoosting(renderer, this, chart); |
//console.log(series, chart); |
} |
|
// Do not start building while drawing |
series.buildKDTree = noop; |
/* This builds the KD-tree */ |
function processPoint(d, i) { |
var x, |
y, |
clientX, |
plotY, |
isNull, |
low, |
chartDestroyed = typeof chart.index === 'undefined', |
isYInside = true; |
|
if (renderer) { |
allocateIfNotSeriesBoosting(renderer, this); |
renderer.pushSeries(series); |
// Perform the actual renderer if we're on series level |
renderIfNotSeriesBoosting(renderer, this, chart); |
//console.log(series, chart); |
} |
if (!chartDestroyed) { |
if (useRaw) { |
x = d[0]; |
y = d[1]; |
} else { |
x = d; |
y = yData[i]; |
} |
|
/* This builds the KD-tree */ |
function processPoint(d, i) { |
var x, |
y, |
clientX, |
plotY, |
isNull, |
low, |
chartDestroyed = typeof chart.index === 'undefined', |
isYInside = true; |
// Resolve low and high for range series |
if (isRange) { |
if (useRaw) { |
y = d.slice(1, 3); |
} |
low = y[0]; |
y = y[1]; |
} else if (isStacked) { |
x = d.x; |
y = d.stackY; |
low = y - d.y; |
} |
|
if (!chartDestroyed) { |
if (useRaw) { |
x = d[0]; |
y = d[1]; |
} else { |
x = d; |
y = yData[i]; |
} |
isNull = y === null; |
|
// Resolve low and high for range series |
if (isRange) { |
if (useRaw) { |
y = d.slice(1, 3); |
// Optimize for scatter zooming |
if (!requireSorting) { |
isYInside = y >= yMin && y <= yMax; |
} |
low = y[0]; |
y = y[1]; |
} else if (isStacked) { |
x = d.x; |
y = d.stackY; |
low = y - d.y; |
} |
|
isNull = y === null; |
if (!isNull && x >= xMin && x <= xMax && isYInside) { |
|
// Optimize for scatter zooming |
if (!requireSorting) { |
isYInside = y >= yMin && y <= yMax; |
} |
// We use ceil to allow the KD tree to work with sub |
// pixels, which can be used in boost to space pixels |
clientX = Math.ceil(xAxis.toPixels(x, true)); |
|
if (!isNull && x >= xMin && x <= xMax && isYInside) { |
if (sampling) { |
if (minI === undefined || clientX === lastClientX) { |
if (!isRange) { |
low = y; |
} |
if (maxI === undefined || y > maxVal) { |
maxVal = y; |
maxI = i; |
} |
if (minI === undefined || low < minVal) { |
minVal = low; |
minI = i; |
} |
|
// We use ceil to allow the KD tree to work with sub pixels, |
// which can be used in boost to space pixels |
clientX = Math.ceil(xAxis.toPixels(x, true)); |
|
if (sampling) { |
if (minI === undefined || clientX === lastClientX) { |
if (!isRange) { |
low = y; |
} |
if (maxI === undefined || y > maxVal) { |
maxVal = y; |
maxI = i; |
} |
if (minI === undefined || low < minVal) { |
minVal = low; |
minI = i; |
} |
if (clientX !== lastClientX) { // Add points and reset |
if (minI !== undefined) { // then maxI is also a number |
plotY = yAxis.toPixels(maxVal, true); |
yBottom = yAxis.toPixels(minVal, true); |
|
} |
if (clientX !== lastClientX) { // Add points and reset |
if (minI !== undefined) { // then maxI is also a number |
plotY = yAxis.toPixels(maxVal, true); |
yBottom = yAxis.toPixels(minVal, true); |
addKDPoint(clientX, plotY, maxI); |
if (yBottom !== plotY) { |
addKDPoint(clientX, yBottom, minI); |
} |
} |
|
addKDPoint(clientX, plotY, maxI); |
if (yBottom !== plotY) { |
addKDPoint(clientX, yBottom, minI); |
} |
minI = maxI = undefined; |
lastClientX = clientX; |
} |
|
minI = maxI = undefined; |
lastClientX = clientX; |
} else { |
plotY = Math.ceil(yAxis.toPixels(y, true)); |
addKDPoint(clientX, plotY, i); |
} |
} else { |
plotY = Math.ceil(yAxis.toPixels(y, true)); |
addKDPoint(clientX, plotY, i); |
} |
} |
wasNull = isNull && !connectNulls; |
|
return !chartDestroyed; |
} |
|
return !chartDestroyed; |
} |
function doneProcessing() { |
fireEvent(series, 'renderedCanvas'); |
// Pass tests in Pointer. |
// Replace this with a single property, and replace when zooming |
// in below boostThreshold. |
series.directTouch = false; |
series.options.stickyTracking = true; |
|
function doneProcessing() { |
fireEvent(series, 'renderedCanvas'); |
// Pass tests in Pointer. |
// Replace this with a single property, and replace when zooming in |
// below boostThreshold. |
series.directTouch = false; |
series.options.stickyTracking = true; |
// Go back to prototype, ready to build |
delete series.buildKDTree; |
series.buildKDTree(); |
} |
|
delete series.buildKDTree; // Go back to prototype, ready to build |
series.buildKDTree(); |
// Loop over the points to build the k-d tree |
eachAsync( |
isStacked ? series.data : (xData || rawData), |
processPoint, |
doneProcessing, |
chart.renderer.forExport ? Number.MAX_VALUE : undefined |
); |
} |
}); |
|
// Loop over the points to build the k-d tree |
eachAsync( |
isStacked ? series.data : (xData || rawData), |
processPoint, |
doneProcessing, |
chart.renderer.forExport ? Number.MAX_VALUE : undefined |
); |
} |
}); |
/* |
* We need to handle heatmaps separatly, since we can't perform the |
* size/color calculations in the shader easily. |
* |
* This likely needs future optimization. |
* |
*/ |
each(['heatmap', 'treemap'], |
function(t) { |
if (seriesTypes[t]) { |
wrap(seriesTypes[t].prototype, 'drawPoints', pointDrawHandler); |
seriesTypes[t].prototype.directTouch = false; // Use k-d-tree |
} |
} |
); |
|
/* Used for treemap|heatmap.drawPoints */ |
function pointDrawHandler(proceed) { |
if (!isSeriesBoosting(this)) { |
return proceed.call(this); |
} |
if (seriesTypes.bubble) { |
// By default, the bubble series does not use the KD-tree, so force it |
// to. |
delete seriesTypes.bubble.prototype.buildKDTree; |
seriesTypes.bubble.prototype.directTouch = false; |
|
//Make sure we have a valid OGL context |
var renderer = createAndAttachRenderer(this.chart, this); |
|
if (renderer) { |
allocateIfNotSeriesBoosting(renderer, this); |
renderer.pushSeries(this); |
// Needed for markers to work correctly |
wrap( |
seriesTypes.bubble.prototype, |
'markerAttribs', |
function(proceed) { |
if (isSeriesBoosting(this)) { |
return false; |
} |
return proceed.apply(this, [].slice.call(arguments, 1)); |
} |
); |
} |
|
renderIfNotSeriesBoosting(renderer, this); |
} |
seriesTypes.scatter.prototype.fill = true; |
|
/* |
* We need to handle heatmaps separatly, since we can't perform the size/color |
* calculations in the shader easily. |
* |
* This likely needs future optimization. |
* |
*/ |
each(['heatmap', 'treemap'], |
function(t) { |
if (seriesTypes[t]) { |
wrap(seriesTypes[t].prototype, 'drawPoints', pointDrawHandler); |
seriesTypes[t].prototype.directTouch = false; // Use k-d-tree |
} |
} |
); |
extend(seriesTypes.area.prototype, { |
fill: true, |
fillOpacity: true, |
sampling: true |
}); |
|
if (seriesTypes.bubble) { |
// By default, the bubble series does not use the KD-tree, so force it to. |
delete seriesTypes.bubble.prototype.buildKDTree; |
seriesTypes.bubble.prototype.directTouch = false; |
extend(seriesTypes.column.prototype, { |
fill: true, |
sampling: true |
}); |
|
// Needed for markers to work correctly |
wrap(seriesTypes.bubble.prototype, 'markerAttribs', function(proceed) { |
if (isSeriesBoosting(this)) { |
return false; |
wrap(Series.prototype, 'setVisible', function(proceed, vis) { |
proceed.call(this, vis, false); |
if (this.visible === false && this.ogl && this.canvas && this.image) { |
this.ogl.clear(); |
this.image.attr({ |
href: '' |
}); |
} else { |
this.chart.redraw(); |
} |
return proceed.apply(this, [].slice.call(arguments, 1)); |
}); |
} |
|
seriesTypes.scatter.prototype.fill = true; |
/** |
* Take care of the canvas blitting |
*/ |
H.Chart.prototype.callbacks.push(function(chart) { |
|
extend(seriesTypes.area.prototype, { |
fill: true, |
fillOpacity: true, |
sampling: true |
}); |
/* Convert chart-level canvas to image */ |
function canvasToSVG() { |
if (chart.ogl && isChartSeriesBoosting(chart)) { |
chart.ogl.render(chart); |
} |
} |
|
extend(seriesTypes.column.prototype, { |
fill: true, |
sampling: true |
}); |
/* Clear chart-level canvas */ |
function preRender() { |
|
wrap(Series.prototype, 'setVisible', function(proceed, vis) { |
proceed.call(this, vis, false); |
if (this.visible === false && this.ogl && this.canvas && this.image) { |
this.ogl.clear(); |
this.image.attr({ |
href: '' |
}); |
} else { |
this.chart.redraw(); |
} |
}); |
if (!isChartSeriesBoosting(chart) && chart.didBoost) { |
chart.didBoost = false; |
// Clear the canvas |
if (chart.image) { |
chart.image.attr({ |
href: '' |
}); |
} |
} |
|
/** |
* Take care of the canvas blitting |
*/ |
H.Chart.prototype.callbacks.push(function(chart) { |
if (chart.canvas && chart.ogl && isChartSeriesBoosting(chart)) { |
chart.didBoost = true; |
|
/* Convert chart-level canvas to image */ |
function canvasToSVG() { |
if (chart.ogl && isChartSeriesBoosting(chart)) { |
chart.ogl.render(chart); |
} |
} |
// Allocate |
chart.ogl.allocateBuffer(chart); |
} |
|
/* Clear chart-level canvas */ |
function preRender() { |
if (chart.canvas && chart.ogl && isChartSeriesBoosting(chart)) { |
// Allocate |
chart.ogl.allocateBuffer(chart); |
} |
//see #6518 + #6739 |
if (chart.markerGroup && chart.xAxis && chart.xAxis.length > 0 && chart.yAxis && chart.yAxis.length > 0) { |
chart.markerGroup.translate( |
chart.xAxis[0].pos, |
chart.yAxis[0].pos |
); |
} |
|
//see #6518 |
if (chart.markerGroup) { |
chart.markerGroup.translate( |
chart.xAxis[0].pos, |
chart.yAxis[0].pos |
); |
} |
} |
|
addEvent(chart, 'predraw', preRender); |
addEvent(chart, 'render', canvasToSVG); |
}); |
addEvent(chart, 'predraw', preRender); |
addEvent(chart, 'render', canvasToSVG); |
}); |
} // if hasCanvasSupport |
|
}(Highcharts)); |
})); |