From d440af7f9eabfb2eb46264c081203c087952a057 Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Mon, 18 Nov 2019 09:48:28 +0200 Subject: [PATCH 1/3] Improve stacking speed and footprint --- src/core/core.datasetController.js | 96 +++++++++++++++++------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index 213c1a553c3..516f5bc1237 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -192,6 +192,45 @@ function getUserBounds(scale) { max: maxDefined ? max : Number.POSITIVE_INFINITY }; } + +function getOrCreateStack(stacks, stackKey, indexValue) { + const subStack = stacks[stackKey] || (stacks[stackKey] = {}); + return subStack[indexValue] || (subStack[indexValue] = {}); +} + +function updateStacks(controller, parsed) { + const chart = controller.chart; + const meta = controller._cachedMeta; + const stacks = chart._stacks || (chart._stacks = {}); // map structure is {stackKey: {datasetIndex: value}} + const xScale = meta.xScale; + const yScale = meta.yScale; + const xId = xScale.id; + const yId = yScale.id; + const xStacked = isStacked(xScale, meta); + const yStacked = isStacked(yScale, meta); + const xKey = yStacked && getStackKey(xScale, yScale, meta); + const yKey = xStacked && getStackKey(yScale, xScale, meta); + const ilen = parsed.length; + const datasetIndex = meta.index; + let stack; + + for (let i = 0; i < ilen; ++i) { + const item = parsed[i]; + const x = item[xId]; + const y = item[yId]; + const itemStacks = item._stacks || (item._stacks = {}); + + if (yStacked) { + stack = itemStacks[yId] = getOrCreateStack(stacks, xKey, x); + stack[datasetIndex] = y; + } + if (xStacked) { + stack = itemStacks[xId] = getOrCreateStack(stacks, yKey, y); + stack[datasetIndex] = x; + } + } +} + // Base class for all dataset controllers (line, bar, etc) var DatasetController = function(chart, datasetIndex) { this.initialize(chart, datasetIndex); @@ -257,12 +296,14 @@ helpers.extend(DatasetController.prototype, { }, linkScales: function() { - var chart = this.chart; - var meta = this._cachedMeta; - var dataset = this.getDataset(); - - meta.xAxisID = dataset.xAxisID || getFirstScaleId(chart, 'x'); - meta.yAxisID = dataset.yAxisID || getFirstScaleId(chart, 'y'); + const me = this; + const chart = me.chart; + const meta = me._cachedMeta; + const dataset = me.getDataset(); + const xid = meta.xAxisID = dataset.xAxisID || getFirstScaleId(chart, 'x'); + const yid = meta.yAxisID = dataset.yAxisID || getFirstScaleId(chart, 'y'); + meta.xScale = me.getScaleForId(xid); + meta.yScale = me.getScaleForId(yid); }, getDataset: function() { @@ -444,20 +485,12 @@ helpers.extend(DatasetController.prototype, { */ _parse: function(start, count) { const me = this; - const chart = me.chart; const meta = me._cachedMeta; const data = me._data; - const stacks = chart._stacks || (chart._stacks = {}); // map structure is {stackKey: {datasetIndex: value}} const xScale = me._getIndexScale(); const yScale = me._getValueScale(); - const xId = xScale.id; - const yId = yScale.id; - const xStacked = isStacked(xScale, meta); - const yStacked = isStacked(yScale, meta); - const xKey = yStacked && getStackKey(xScale, yScale, meta); - const yKey = xStacked && getStackKey(yScale, xScale, meta); - const stacked = xStacked || yStacked; - var i, ilen, parsed, stack, item, x, y; + const stacked = isStacked(xScale, meta) || isStacked(yScale, meta); + var i, ilen, parsed; if (helpers.isArray(data[start])) { parsed = me._parseArrayData(meta, data, start, count); @@ -467,29 +500,11 @@ helpers.extend(DatasetController.prototype, { parsed = me._parsePrimitiveData(meta, data, start, count); } - function storeStack(stackKey, indexValue, scaleId, value) { - stackKey += '.' + indexValue; - item._stackKeys[scaleId] = stackKey; - stack = stacks[stackKey] || (stacks[stackKey] = {}); - stack[meta.index] = value; - } - for (i = 0, ilen = parsed.length; i < ilen; ++i) { - item = parsed[i]; - meta.data[start + i]._parsed = item; - - if (stacked) { - item._stackKeys = {}; - x = item[xId]; - y = item[yId]; - - if (yStacked) { - storeStack(xKey, x, yId, y); - } - if (xStacked) { - storeStack(yKey, y, xId, x); - } - } + meta.data[start + i]._parsed = parsed[i]; + } + if (stacked) { + updateStacks(me, parsed); } xScale._invalidateCaches(); @@ -598,7 +613,7 @@ helpers.extend(DatasetController.prototype, { var value = parsed[scale.id]; var stack = { keys: getSortedDatasetIndices(chart, true), - values: chart._stacks[parsed._stackKeys[scale.id]] + values: parsed._stacks[scale.id] }; return applyStack(stack, value, meta.index); }, @@ -611,7 +626,6 @@ helpers.extend(DatasetController.prototype, { var meta = this._cachedMeta; var metaData = meta.data; var ilen = metaData.length; - var stacks = chart._stacks || (chart._stacks = {}); var max = Number.NEGATIVE_INFINITY; var stacked = canStack && meta._stacked; var indices = getSortedDatasetIndices(chart, true); @@ -633,7 +647,7 @@ helpers.extend(DatasetController.prototype, { if (stacked) { stack = { keys: indices, - values: stacks[parsed._stackKeys[scale.id]] + values: parsed._stacks[scale.id] }; value = applyStack(stack, value, meta.index, true); } From f276252f3db01df0fa62370b5f8fa5723da58a69 Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Mon, 18 Nov 2019 10:09:30 +0200 Subject: [PATCH 2/3] Better utilization of caches --- src/controllers/controller.bubble.js | 26 ++++++++++++------------- src/controllers/controller.line.js | 21 +++++++++----------- src/core/core.datasetController.js | 29 ++++++++++++++-------------- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/controllers/controller.bubble.js b/src/controllers/controller.bubble.js index 726f86b81ba..5752ccf3793 100644 --- a/src/controllers/controller.bubble.js +++ b/src/controllers/controller.bubble.js @@ -59,9 +59,9 @@ module.exports = DatasetController.extend({ * @private */ _parseObjectData: function(meta, data, start, count) { - var xScale = this.getScaleForId(meta.xAxisID); - var yScale = this.getScaleForId(meta.yAxisID); - var parsed = []; + const xScale = meta.xScale; + const yScale = meta.yScale; + const parsed = []; var i, ilen, item, obj; for (i = start, ilen = start + count; i < ilen; ++i) { obj = data[i]; @@ -95,8 +95,8 @@ module.exports = DatasetController.extend({ _getLabelAndValue: function(index) { const me = this; const meta = me._cachedMeta; - const xScale = me.getScaleForId(meta.xAxisID); - const yScale = me.getScaleForId(meta.yAxisID); + const xScale = meta.xScale; + const yScale = meta.yScale; const parsed = me._getParsed(index); const x = xScale.getLabelForValue(parsed[xScale.id]); const y = yScale.getLabelForValue(parsed[yScale.id]); @@ -126,14 +126,14 @@ module.exports = DatasetController.extend({ * @protected */ updateElement: function(point, index, reset) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var yScale = me.getScaleForId(meta.yAxisID); - var options = me._resolveDataElementOptions(index); - var parsed = !reset && me._getParsed(index); - var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(parsed[xScale.id]); - var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(parsed[yScale.id]); + const me = this; + const meta = me._cachedMeta; + const xScale = meta.xScale; + const yScale = meta.yScale; + const options = me._resolveDataElementOptions(index); + const parsed = !reset && me._getParsed(index); + const x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(parsed[xScale.id]); + const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(parsed[yScale.id]); point._options = options; point._model = { diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index 7a89514fc3d..273f89d783a 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -77,9 +77,6 @@ module.exports = DatasetController.extend({ var showLine = me._showLine = valueOrDefault(config.showLine, options.showLines); var i, ilen; - me._xScale = me.getScaleForId(meta.xAxisID); - me._yScale = me.getScaleForId(meta.yAxisID); - // Update Line if (showLine) { // Data @@ -106,15 +103,15 @@ module.exports = DatasetController.extend({ }, updateElement: function(point, index, reset) { - var me = this; - var meta = me.getMeta(); - var xScale = me._xScale; - var yScale = me._yScale; - var stacked = meta._stacked; - var parsed = me._getParsed(index); - var options = me._resolveDataElementOptions(index); - var x = xScale.getPixelForValue(parsed[xScale.id]); - var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(stacked ? me._applyStack(yScale, parsed) : parsed[yScale.id]); + const me = this; + const meta = me._cachedMeta; + const xScale = meta.xScale; + const yScale = meta.yScale; + const stacked = meta._stacked; + const parsed = me._getParsed(index); + const options = me._resolveDataElementOptions(index); + const x = xScale.getPixelForValue(parsed[xScale.id]); + const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(stacked ? me._applyStack(yScale, parsed) : parsed[yScale.id]); // Utility point._options = options; diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index 516f5bc1237..e8c35e6ea2f 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -487,9 +487,9 @@ helpers.extend(DatasetController.prototype, { const me = this; const meta = me._cachedMeta; const data = me._data; - const xScale = me._getIndexScale(); - const yScale = me._getValueScale(); - const stacked = isStacked(xScale, meta) || isStacked(yScale, meta); + const iScale = me._getIndexScale(); + const vScale = me._getValueScale(); + const stacked = isStacked(iScale, meta) || isStacked(vScale, meta); var i, ilen, parsed; if (helpers.isArray(data[start])) { @@ -507,9 +507,9 @@ helpers.extend(DatasetController.prototype, { updateStacks(me, parsed); } - xScale._invalidateCaches(); - if (yScale !== xScale) { - yScale._invalidateCaches(); + iScale._invalidateCaches(); + if (vScale !== iScale) { + vScale._invalidateCaches(); } }, @@ -553,9 +553,9 @@ helpers.extend(DatasetController.prototype, { * @private */ _parseArrayData: function(meta, data, start, count) { - var xScale = this.getScaleForId(meta.xAxisID); - var yScale = this.getScaleForId(meta.yAxisID); - var parsed = []; + const xScale = meta.xScale; + const yScale = meta.yScale; + const parsed = []; var i, ilen, item, arr; for (i = start, ilen = start + count; i < ilen; ++i) { arr = data[i]; @@ -579,9 +579,9 @@ helpers.extend(DatasetController.prototype, { * @private */ _parseObjectData: function(meta, data, start, count) { - var xScale = this.getScaleForId(meta.xAxisID); - var yScale = this.getScaleForId(meta.yAxisID); - var parsed = []; + const xScale = meta.xScale; + const yScale = meta.yScale; + const parsed = []; var i, ilen, item, obj; for (i = start, ilen = start + count; i < ilen; ++i) { obj = data[i]; @@ -736,11 +736,12 @@ helpers.extend(DatasetController.prototype, { * @private */ _update: function(reset) { - var me = this; + const me = this; + const meta = me._cachedMeta; me._configure(); me._cachedDataOpts = null; me.update(reset); - me._cachedMeta._clip = toClip(helpers.valueOrDefault(me._config.clip, defaultClip(me._xScale, me._yScale, me._getMaxOverflow()))); + meta._clip = toClip(helpers.valueOrDefault(me._config.clip, defaultClip(meta.xScale, meta.yScale, me._getMaxOverflow()))); me._cacheScaleStackStatus(); }, From 241870a729fe21b27498dabf69f5611bb3030ccc Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Mon, 18 Nov 2019 22:47:41 +0200 Subject: [PATCH 3/3] Chore --- src/controllers/controller.bar.js | 134 ++++++------ src/controllers/controller.bubble.js | 5 +- src/controllers/controller.doughnut.js | 10 +- src/controllers/controller.horizontalBar.js | 4 +- src/controllers/controller.line.js | 6 +- src/controllers/controller.polarArea.js | 8 +- src/controllers/controller.radar.js | 10 +- src/core/core.datasetController.js | 229 ++++++++++---------- 8 files changed, 205 insertions(+), 201 deletions(-) diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index 8d7e01f71e3..804746f5243 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -153,12 +153,12 @@ function parseFloatBar(arr, item, vScale, i) { } function parseArrayOrPrimitive(meta, data, start, count) { - var iScale = this._getIndexScale(); - var vScale = this._getValueScale(); - var labels = iScale._getLabels(); - var singleScale = iScale === vScale; - var parsed = []; - var i, ilen, item, entry; + const iScale = meta.iScale; + const vScale = meta.vScale; + const labels = iScale._getLabels(); + const singleScale = iScale === vScale; + const parsed = []; + let i, ilen, item, entry; for (i = start, ilen = start + count; i < ilen; ++i) { entry = data[i]; @@ -219,11 +219,11 @@ module.exports = DatasetController.extend({ * @private */ _parseObjectData: function(meta, data, start, count) { - var iScale = this._getIndexScale(); - var vScale = this._getValueScale(); - var vProp = vScale._getAxis(); - var parsed = []; - var i, ilen, item, obj, value; + const iScale = meta.iScale; + const vScale = meta.vScale; + const vProp = vScale._getAxis(); + const parsed = []; + let i, ilen, item, obj, value; for (i = start, ilen = start + count; i < ilen; ++i) { obj = data[i]; item = {}; @@ -244,8 +244,9 @@ module.exports = DatasetController.extend({ */ _getLabelAndValue: function(index) { const me = this; - const indexScale = me._getIndexScale(); - const valueScale = me._getValueScale(); + const meta = me._cachedMeta; + const indexScale = meta.iScale; + const valueScale = meta.vScale; const parsed = me._getParsed(index); const custom = parsed._custom; const value = custom @@ -264,14 +265,14 @@ module.exports = DatasetController.extend({ DatasetController.prototype.initialize.apply(me, arguments); - meta = me.getMeta(); + meta = me._cachedMeta; meta.stack = me.getDataset().stack; meta.bar = true; }, update: function(reset) { var me = this; - var rects = me.getMeta().data; + var rects = me._cachedMeta.data; var i, ilen; me._ruler = me.getRuler(); @@ -306,14 +307,15 @@ module.exports = DatasetController.extend({ * @private */ _updateElementGeometry: function(rectangle, index, reset, options) { - var me = this; - var model = rectangle._model; - var vscale = me._getValueScale(); - var base = vscale.getBasePixel(); - var horizontal = vscale.isHorizontal(); - var ruler = me._ruler || me.getRuler(); - var vpixels = me.calculateBarValuePixels(index, options); - var ipixels = me.calculateBarIndexPixels(index, ruler, options); + const me = this; + const meta = me._cachedMeta; + const model = rectangle._model; + const vScale = meta.vScale; + const base = vScale.getBasePixel(); + const horizontal = vScale.isHorizontal(); + const ruler = me._ruler || me.getRuler(); + const vpixels = me.calculateBarValuePixels(index, options); + const ipixels = me.calculateBarIndexPixels(index, ruler, options); model.horizontal = horizontal; model.base = reset ? base : vpixels.base; @@ -330,26 +332,27 @@ module.exports = DatasetController.extend({ * @private */ _getStacks: function(last) { - var me = this; - var scale = me._getIndexScale(); - var metasets = scale._getMatchingVisibleMetas(me._type); - var stacked = scale.options.stacked; - var ilen = metasets.length; - var stacks = []; - var i, meta; + const me = this; + const meta = me._cachedMeta; + const iScale = meta.iScale; + const metasets = iScale._getMatchingVisibleMetas(me._type); + const stacked = iScale.options.stacked; + const ilen = metasets.length; + const stacks = []; + let i, item; for (i = 0; i < ilen; ++i) { - meta = metasets[i]; + item = metasets[i]; // stacked | meta.stack // | found | not found | undefined // false | x | x | x // true | | x | // undefined | | x | x - if (stacked === false || stacks.indexOf(meta.stack) === -1 || - (stacked === undefined && meta.stack === undefined)) { - stacks.push(meta.stack); + if (stacked === false || stacks.indexOf(item.stack) === -1 || + (stacked === undefined && item.stack === undefined)) { + stacks.push(item.stack); } - if (meta.index === last) { + if (item.index === last) { break; } } @@ -387,21 +390,22 @@ module.exports = DatasetController.extend({ * @private */ getRuler: function() { - var me = this; - var scale = me._getIndexScale(); - var pixels = []; - var i, ilen; + const me = this; + const meta = me._cachedMeta; + const iScale = meta.iScale; + const pixels = []; + let i, ilen; - for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) { - pixels.push(scale.getPixelForValue(me._getParsed(i)[scale.id])); + for (i = 0, ilen = meta.data.length; i < ilen; ++i) { + pixels.push(iScale.getPixelForValue(me._getParsed(i)[iScale.id])); } return { - pixels: pixels, - start: scale._startPixel, - end: scale._endPixel, + pixels, + start: iScale._startPixel, + end: iScale._endPixel, stackCount: me.getStackCount(), - scale: scale + scale: iScale }; }, @@ -410,15 +414,16 @@ module.exports = DatasetController.extend({ * @private */ calculateBarValuePixels: function(index, options) { - var me = this; - var valueScale = me._getValueScale(); - var minBarLength = options.minBarLength; - var start = 0; - var parsed = me._getParsed(index); - var value = parsed[valueScale.id]; - var custom = parsed._custom; - var length = me._cachedMeta._stacked ? me._applyStack(valueScale, parsed) : parsed[valueScale.id]; - var base, head, size; + const me = this; + const meta = me._cachedMeta; + const vScale = meta.vScale; + const minBarLength = options.minBarLength; + const parsed = me._getParsed(index); + const custom = parsed._custom; + let value = parsed[vScale.id]; + let start = 0; + let length = meta._stacked ? me._applyStack(vScale, parsed) : parsed[vScale.id]; + let base, head, size; if (length !== value) { start = length - value; @@ -435,8 +440,8 @@ module.exports = DatasetController.extend({ start += value; } - base = valueScale.getPixelForValue(start); - head = valueScale.getPixelForValue(start + length); + base = vScale.getPixelForValue(start); + head = vScale.getPixelForValue(start + length); size = head - base; if (minBarLength !== undefined && Math.abs(size) < minBarLength) { @@ -461,7 +466,7 @@ module.exports = DatasetController.extend({ ? computeFlexCategoryTraits(index, ruler, options) : computeFitCategoryTraits(index, ruler, options); - var stackIndex = me.getStackIndex(me.index, me.getMeta().stack); + var stackIndex = me.getStackIndex(me.index, me._cachedMeta.stack); var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2); var size = Math.min( valueOrDefault(options.maxBarThickness, Infinity), @@ -476,17 +481,18 @@ module.exports = DatasetController.extend({ }, draw: function() { - var me = this; - var chart = me.chart; - var scale = me._getValueScale(); - var rects = me.getMeta().data; - var ilen = rects.length; - var i = 0; + const me = this; + const chart = me.chart; + const meta = me._cachedMeta; + const vScale = meta.vScale; + const rects = meta.data; + const ilen = rects.length; + let i = 0; helpers.canvas.clipArea(chart.ctx, chart.chartArea); for (; i < ilen; ++i) { - if (!isNaN(me._getParsed(i)[scale.id])) { + if (!isNaN(me._getParsed(i)[vScale.id])) { rects[i].draw(); } } diff --git a/src/controllers/controller.bubble.js b/src/controllers/controller.bubble.js index 5752ccf3793..c1b58f8dd73 100644 --- a/src/controllers/controller.bubble.js +++ b/src/controllers/controller.bubble.js @@ -112,9 +112,8 @@ module.exports = DatasetController.extend({ * @protected */ update: function(reset) { - var me = this; - var meta = me.getMeta(); - var points = meta.data; + const me = this; + const points = me._cachedMeta.data; // Update Points helpers.each(points, function(point, index) { diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index e3bf0aa2315..b98331b76ad 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -140,7 +140,7 @@ module.exports = DatasetController.extend({ */ _parse: function(start, count) { var data = this.getDataset().data; - var metaData = this.getMeta().data; + var metaData = this._cachedMeta.data; var i, ilen; for (i = start, ilen = start + count; i < ilen; ++i) { metaData[i]._parsed = +data[i]; @@ -169,7 +169,7 @@ module.exports = DatasetController.extend({ var ratioY = 1; var offsetX = 0; var offsetY = 0; - var meta = me.getMeta(); + var meta = me._cachedMeta; var arcs = meta.data; var cutout = opts.cutoutPercentage / 100 || 0; var circumference = opts.circumference; @@ -261,7 +261,7 @@ module.exports = DatasetController.extend({ if (index === 0) { model.startAngle = opts.rotation; } else { - model.startAngle = me.getMeta().data[index - 1]._model.endAngle; + model.startAngle = me._cachedMeta.data[index - 1]._model.endAngle; } model.endAngle = model.startAngle + model.circumference; @@ -271,7 +271,7 @@ module.exports = DatasetController.extend({ }, calculateTotal: function() { - var metaData = this.getMeta().data; + var metaData = this._cachedMeta.data; var total = 0; var value; @@ -290,7 +290,7 @@ module.exports = DatasetController.extend({ }, calculateCircumference: function(value) { - var total = this.getMeta().total; + var total = this._cachedMeta.total; if (total > 0 && !isNaN(value)) { return DOUBLE_PI * (Math.abs(value) / total); } diff --git a/src/controllers/controller.horizontalBar.js b/src/controllers/controller.horizontalBar.js index 7b11bcc6627..6ee66000d0f 100644 --- a/src/controllers/controller.horizontalBar.js +++ b/src/controllers/controller.horizontalBar.js @@ -51,13 +51,13 @@ module.exports = BarController.extend({ * @private */ _getValueScaleId: function() { - return this.getMeta().xAxisID; + return this._cachedMeta.xAxisID; }, /** * @private */ _getIndexScaleId: function() { - return this.getMeta().yAxisID; + return this._cachedMeta.yAxisID; } }); diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index 273f89d783a..0d46f369669 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -69,7 +69,7 @@ module.exports = DatasetController.extend({ update: function(reset) { var me = this; - var meta = me.getMeta(); + var meta = me._cachedMeta; var line = meta.dataset; var points = meta.data || []; var options = me.chart.options; @@ -172,7 +172,7 @@ module.exports = DatasetController.extend({ updateBezierControlPoints: function() { var me = this; var chart = me.chart; - var meta = me.getMeta(); + var meta = me._cachedMeta; var lineModel = meta.dataset._model; var area = chart.chartArea; var points = meta.data || []; @@ -227,7 +227,7 @@ module.exports = DatasetController.extend({ draw: function() { var me = this; var chart = me.chart; - var meta = me.getMeta(); + var meta = me._cachedMeta; var points = meta.data || []; var area = chart.chartArea; var i = 0; diff --git a/src/controllers/controller.polarArea.js b/src/controllers/controller.polarArea.js index 4bd83c9d97a..a2fd5a1a43b 100644 --- a/src/controllers/controller.polarArea.js +++ b/src/controllers/controller.polarArea.js @@ -136,7 +136,7 @@ module.exports = DatasetController.extend({ update: function(reset) { var me = this; var dataset = me.getDataset(); - var meta = me.getMeta(); + var meta = me._cachedMeta; var start = me.chart.options.startAngle || 0; var starts = me._starts = []; var angles = me._angles = []; @@ -219,7 +219,7 @@ module.exports = DatasetController.extend({ countVisibleElements: function() { var dataset = this.getDataset(); - var meta = this.getMeta(); + var meta = this._cachedMeta; var count = 0; helpers.each(meta.data, function(element, index) { @@ -256,9 +256,9 @@ module.exports = DatasetController.extend({ */ _computeAngle: function(index) { var me = this; - var count = this.getMeta().count; + var meta = me._cachedMeta; + var count = meta.count; var dataset = me.getDataset(); - var meta = me.getMeta(); if (isNaN(dataset.data[index]) || meta.data[index].hidden) { return 0; diff --git a/src/controllers/controller.radar.js b/src/controllers/controller.radar.js index 99857a17c24..6b9d24468b7 100644 --- a/src/controllers/controller.radar.js +++ b/src/controllers/controller.radar.js @@ -82,18 +82,18 @@ module.exports = DatasetController.extend({ */ _getLabelAndValue: function(index) { const me = this; - const scale = me._getValueScale(); + const vScale = me._cachedMeta.vScale; const parsed = me._getParsed(index); return { - label: scale._getLabels()[index], - value: '' + scale.getLabelForValue(parsed[scale.id]) + label: vScale._getLabels()[index], + value: '' + vScale.getLabelForValue(parsed[vScale.id]) }; }, update: function(reset) { var me = this; - var meta = me.getMeta(); + var meta = me._cachedMeta; var line = meta.dataset; var points = meta.data || []; var animationsDisabled = me.chart._animationsDisabled; @@ -168,7 +168,7 @@ module.exports = DatasetController.extend({ updateBezierControlPoints: function() { var me = this; - var meta = me.getMeta(); + var meta = me._cachedMeta; var lineModel = meta.dataset._model; var area = me.chart.chartArea; var points = meta.data || []; diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index e8c35e6ea2f..79139bfd355 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -280,14 +280,14 @@ helpers.extend(DatasetController.prototype, { ], initialize: function(chart, datasetIndex) { - var me = this; - var meta; + const me = this; + let meta; me.chart = chart; me.index = datasetIndex; me._cachedMeta = meta = me.getMeta(); me._type = meta.type; me.linkScales(); - meta._stacked = isStacked(me._getValueScale(), meta); + meta._stacked = isStacked(meta.vScale, meta); me.addElements(); }, @@ -304,6 +304,8 @@ helpers.extend(DatasetController.prototype, { const yid = meta.yAxisID = dataset.yAxisID || getFirstScaleId(chart, 'y'); meta.xScale = me.getScaleForId(xid); meta.yScale = me.getScaleForId(yid); + meta.iScale = me._getIndexScale(); + meta.vScale = me._getValueScale(); }, getDataset: function() { @@ -350,9 +352,10 @@ helpers.extend(DatasetController.prototype, { * @private */ _getOtherScale: function(scale) { - return scale.id === this._getIndexScaleId() - ? this._getValueScale() - : this._getIndexScale(); + const meta = this._cachedMeta; + return scale === meta.iScale + ? meta.vScale + : meta.iScale; }, reset: function() { @@ -419,9 +422,9 @@ helpers.extend(DatasetController.prototype, { * @private */ _labelCheck: function() { - var me = this; - var scale = me._getIndexScale(); - var labels = scale ? scale._getLabels() : me.chart.data.labels; + const me = this; + const iScale = me._cachedMeta.iScale; + const labels = iScale ? iScale._getLabels() : me.chart.data.labels; if (me._labels === labels) { return false; @@ -448,14 +451,14 @@ helpers.extend(DatasetController.prototype, { }, buildOrUpdateElements: function() { - var me = this; - var dataChanged = me._dataCheck(); - var labelsChanged = me._labelCheck(); - var scaleChanged = me._scaleCheck(); - var meta = me._cachedMeta; + const me = this; + const dataChanged = me._dataCheck(); + const labelsChanged = me._labelCheck(); + const scaleChanged = me._scaleCheck(); + const meta = me._cachedMeta; // make sure cached _stacked status is current - meta._stacked = isStacked(me._getValueScale(), meta); + meta._stacked = isStacked(meta.vScale, meta); // Re-sync meta data in case the user replaced the data array or if we missed // any updates and so make sure that we handle number of datapoints changing. @@ -467,7 +470,7 @@ helpers.extend(DatasetController.prototype, { * @private */ _configure: function() { - var me = this; + const me = this; me._config = helpers.merge({}, [ me.chart.options.datasets[me._type], me.getDataset(), @@ -487,10 +490,10 @@ helpers.extend(DatasetController.prototype, { const me = this; const meta = me._cachedMeta; const data = me._data; - const iScale = me._getIndexScale(); - const vScale = me._getValueScale(); + const iScale = meta.iScale; + const vScale = meta.vScale; const stacked = isStacked(iScale, meta) || isStacked(vScale, meta); - var i, ilen, parsed; + let i, ilen, parsed; if (helpers.isArray(data[start])) { parsed = me._parseArrayData(meta, data, start, count); @@ -525,12 +528,12 @@ helpers.extend(DatasetController.prototype, { * @private */ _parsePrimitiveData: function(meta, data, start, count) { - var iScale = this._getIndexScale(); - var vScale = this._getValueScale(); - var labels = iScale._getLabels(); - var singleScale = iScale === vScale; - var parsed = []; - var i, ilen, item; + const iScale = meta.iScale; + const vScale = meta.vScale; + const labels = iScale._getLabels(); + const singleScale = iScale === vScale; + const parsed = []; + let i, ilen, item; for (i = start, ilen = start + count; i < ilen; ++i) { item = {}; @@ -556,7 +559,7 @@ helpers.extend(DatasetController.prototype, { const xScale = meta.xScale; const yScale = meta.yScale; const parsed = []; - var i, ilen, item, arr; + let i, ilen, item, arr; for (i = start, ilen = start + count; i < ilen; ++i) { arr = data[i]; item = {}; @@ -582,7 +585,7 @@ helpers.extend(DatasetController.prototype, { const xScale = meta.xScale; const yScale = meta.yScale; const parsed = []; - var i, ilen, item, obj; + let i, ilen, item, obj; for (i = start, ilen = start + count; i < ilen; ++i) { obj = data[i]; item = {}; @@ -597,7 +600,7 @@ helpers.extend(DatasetController.prototype, { * @private */ _getParsed: function(index) { - var data = this._cachedMeta.data; + const data = this._cachedMeta.data; if (index < 0 || index >= data.length) { return; } @@ -608,10 +611,10 @@ helpers.extend(DatasetController.prototype, { * @private */ _applyStack: function(scale, parsed) { - var chart = this.chart; - var meta = this._cachedMeta; - var value = parsed[scale.id]; - var stack = { + const chart = this.chart; + const meta = this._cachedMeta; + const value = parsed[scale.id]; + const stack = { keys: getSortedDatasetIndices(chart, true), values: parsed._stacks[scale.id] }; @@ -622,16 +625,16 @@ helpers.extend(DatasetController.prototype, { * @private */ _getMinMax: function(scale, canStack) { - var chart = this.chart; - var meta = this._cachedMeta; - var metaData = meta.data; - var ilen = metaData.length; - var max = Number.NEGATIVE_INFINITY; - var stacked = canStack && meta._stacked; - var indices = getSortedDatasetIndices(chart, true); - var otherScale = this._getOtherScale(scale); - var {min: otherMin, max: otherMax} = getUserBounds(otherScale); - var i, item, value, parsed, stack, min, minPositive, otherValue; + const chart = this.chart; + const meta = this._cachedMeta; + const metaData = meta.data; + const ilen = metaData.length; + const stacked = canStack && meta._stacked; + const indices = getSortedDatasetIndices(chart, true); + const otherScale = this._getOtherScale(scale); + let max = Number.NEGATIVE_INFINITY; + let {min: otherMin, max: otherMax} = getUserBounds(otherScale); + let i, item, value, parsed, stack, min, minPositive, otherValue; min = minPositive = Number.POSITIVE_INFINITY; @@ -668,10 +671,10 @@ helpers.extend(DatasetController.prototype, { * @private */ _getAllParsedValues: function(scale) { - var meta = this._cachedMeta; - var metaData = meta.data; - var values = []; - var i, ilen, value; + const meta = this._cachedMeta; + const metaData = meta.data; + const values = []; + let i, ilen, value; for (i = 0, ilen = metaData.length; i < ilen; ++i) { value = metaData[i]._parsed[scale.id]; @@ -686,13 +689,14 @@ helpers.extend(DatasetController.prototype, { * @private */ _cacheScaleStackStatus: function() { - var me = this; - var indexScale = me._getIndexScale(); - var valueScale = me._getValueScale(); - var cache = me._scaleStacked = {}; - if (indexScale && valueScale) { - cache[indexScale.id] = indexScale.options.stacked; - cache[valueScale.id] = valueScale.options.stacked; + const me = this; + const meta = me._cachedMeta; + const iScale = meta.iScale; + const vScale = meta.vScale; + const cache = me._scaleStacked = {}; + if (iScale && vScale) { + cache[iScale.id] = iScale.options.stacked; + cache[vScale.id] = vScale.options.stacked; } }, @@ -700,15 +704,16 @@ helpers.extend(DatasetController.prototype, { * @private */ _scaleCheck: function() { - var me = this; - var indexScale = me._getIndexScale(); - var valueScale = me._getValueScale(); - var cache = me._scaleStacked; + const me = this; + const meta = me._cachedMeta; + const iScale = meta.iScale; + const vScale = meta.vScale; + const cache = me._scaleStacked; return !cache || - !indexScale || - !valueScale || - cache[indexScale.id] !== indexScale.options.stacked || - cache[valueScale.id] !== valueScale.options.stacked; + !iScale || + !vScale || + cache[iScale.id] !== iScale.options.stacked || + cache[vScale.id] !== vScale.options.stacked; }, /** @@ -723,12 +728,13 @@ helpers.extend(DatasetController.prototype, { */ _getLabelAndValue: function(index) { const me = this; - const indexScale = me._getIndexScale(); - const valueScale = me._getValueScale(); + const meta = me._cachedMeta; + const iScale = meta.iScale; + const vScale = meta.vScale; const parsed = me._getParsed(index); return { - label: indexScale ? '' + indexScale.getLabelForValue(parsed[indexScale.id]) : '', - value: valueScale ? '' + valueScale.getLabelForValue(parsed[valueScale.id]) : '' + label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.id]) : '', + value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.id]) : '' }; }, @@ -748,10 +754,10 @@ helpers.extend(DatasetController.prototype, { update: helpers.noop, transition: function(easingValue) { - var meta = this._cachedMeta; - var elements = meta.data || []; - var ilen = elements.length; - var i = 0; + const meta = this._cachedMeta; + const elements = meta.data || []; + const ilen = elements.length; + let i = 0; for (; i < ilen; ++i) { elements[i].transition(easingValue); @@ -763,10 +769,10 @@ helpers.extend(DatasetController.prototype, { }, draw: function() { - var meta = this._cachedMeta; - var elements = meta.data || []; - var ilen = elements.length; - var i = 0; + const meta = this._cachedMeta; + const elements = meta.data || []; + const ilen = elements.length; + let i = 0; if (meta.dataset) { meta.dataset.draw(); @@ -784,10 +790,10 @@ helpers.extend(DatasetController.prototype, { * @return {IStyleInterface} style object */ getStyle: function(index) { - var me = this; - var meta = me._cachedMeta; - var dataset = meta.dataset; - var style; + const me = this; + const meta = me._cachedMeta; + const dataset = meta.dataset; + let style; me._configure(); if (dataset && index === undefined) { @@ -808,21 +814,19 @@ helpers.extend(DatasetController.prototype, { * @private */ _resolveDatasetElementOptions: function(active) { - var me = this; - var chart = me.chart; - var datasetOpts = me._config; - var options = chart.options.elements[me.datasetElementType.prototype._type] || {}; - var elementOptions = me._datasetElementOptions; - var values = {}; - var i, ilen, key, readKey; - - // Scriptable options - var context = { + const me = this; + const chart = me.chart; + const datasetOpts = me._config; + const options = chart.options.elements[me.datasetElementType.prototype._type] || {}; + const elementOptions = me._datasetElementOptions; + const values = {}; + const context = { chart, dataset: me.getDataset(), datasetIndex: me.index, active }; + let i, ilen, key, readKey; for (i = 0, ilen = elementOptions.length; i < ilen; ++i) { key = elementOptions[i]; @@ -840,29 +844,24 @@ helpers.extend(DatasetController.prototype, { * @private */ _resolveDataElementOptions: function(index) { - var me = this; - var cached = me._cachedDataOpts; + const me = this; + const cached = me._cachedDataOpts; if (cached) { return cached; } - var chart = me.chart; - var datasetOpts = me._config; - var options = chart.options.elements[me.dataElementType.prototype._type] || {}; - var elementOptions = me._dataElementOptions; - var values = {}; - - // Scriptable options - var context = { + const chart = me.chart; + const datasetOpts = me._config; + const options = chart.options.elements[me.dataElementType.prototype._type] || {}; + const elementOptions = me._dataElementOptions; + const values = {}; + const context = { chart: chart, dataIndex: index, dataset: me.getDataset(), datasetIndex: me.index }; - - // `resolve` sets cacheable to `false` if any option is indexed or scripted - var info = {cacheable: true}; - - var keys, i, ilen, key; + const info = {cacheable: true}; + let keys, i, ilen, key; if (helpers.isArray(elementOptions)) { for (i = 0, ilen = elementOptions.length; i < ilen; ++i) { @@ -897,9 +896,9 @@ helpers.extend(DatasetController.prototype, { }, setHoverStyle: function(element, datasetIndex, index) { - var dataset = this.chart.data.datasets[datasetIndex]; - var model = element._model; - var getHoverColor = helpers.getHoverColor; + const dataset = this.chart.data.datasets[datasetIndex]; + const model = element._model; + const getHoverColor = helpers.getHoverColor; element.$previousStyle = { backgroundColor: model.backgroundColor, @@ -916,7 +915,7 @@ helpers.extend(DatasetController.prototype, { * @private */ _removeDatasetHoverStyle: function() { - var element = this.getMeta().dataset; + const element = this._cachedMeta.dataset; if (element) { this.removeHoverStyle(element); @@ -927,9 +926,9 @@ helpers.extend(DatasetController.prototype, { * @private */ _setDatasetHoverStyle: function() { - var element = this.getMeta().dataset; - var prev = {}; - var i, ilen, key, keys, hoverOptions, model; + const element = this._cachedMeta.dataset; + const prev = {}; + let i, ilen, key, keys, hoverOptions, model; if (!element) { return; @@ -952,10 +951,10 @@ helpers.extend(DatasetController.prototype, { * @private */ resyncElements: function(changed) { - var me = this; - var meta = me._cachedMeta; - var numMeta = meta.data.length; - var numData = me._data.length; + const me = this; + const meta = me._cachedMeta; + const numMeta = meta.data.length; + const numData = me._data.length; if (numData > numMeta) { me.insertElements(numMeta, numData - numMeta); @@ -973,7 +972,7 @@ helpers.extend(DatasetController.prototype, { insertElements: function(start, count) { const me = this; const elements = []; - var i; + let i; for (i = start; i < start + count; ++i) { elements.push(me.createElement(me.dataElementType)); } @@ -988,7 +987,7 @@ helpers.extend(DatasetController.prototype, { * @private */ onDataPush: function() { - var count = arguments.length; + const count = arguments.length; this.insertElements(this.getDataset().data.length - count, count); },