]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Bar chart performance improvements
authoretimberg <evert.timberg@gmail.com>
Fri, 14 Oct 2016 00:43:11 +0000 (20:43 -0400)
committerEvert Timberg <evert.timberg+github@gmail.com>
Fri, 14 Oct 2016 11:20:08 +0000 (06:20 -0500)
src/controllers/controller.bar.js
src/core/core.datasetController.js
src/core/core.scale.js
src/elements/element.rectangle.js

index f828eb79e912916ad9dc8d8df70c81b2a53ab3e3..e9a85aabd22a8c925e06949e9b0d092f6b051cef 100644 (file)
@@ -69,31 +69,29 @@ module.exports = function(Chart) {
                        var custom = rectangle.custom || {};
                        var dataset = me.getDataset();
 
-                       helpers.extend(rectangle, {
-                               // Utility
-                               _xScale: xScale,
-                               _yScale: yScale,
-                               _datasetIndex: me.index,
-                               _index: index,
-
-                               // Desired view properties
-                               _model: {
-                                       x: me.calculateBarX(index, me.index),
-                                       y: reset ? scaleBase : me.calculateBarY(index, me.index),
-
-                                       // Tooltip
-                                       label: me.chart.data.labels[index],
-                                       datasetLabel: dataset.label,
-
-                                       // Appearance
-                                       base: reset ? scaleBase : me.calculateBarBase(me.index, index),
-                                       width: me.calculateBarWidth(index),
-                                       backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
-                                       borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
-                                       borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
-                                       borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
-                               }
-                       });
+                       rectangle._xScale = xScale;
+                       rectangle._yScale = yScale;
+                       rectangle._datasetIndex = me.index;
+                       rectangle._index = index;
+
+                       var ruler = me.getRuler(index);
+                       rectangle._model = {
+                               x: me.calculateBarX(index, me.index, ruler),
+                               y: reset ? scaleBase : me.calculateBarY(index, me.index),
+
+                               // Tooltip
+                               label: me.chart.data.labels[index],
+                               datasetLabel: dataset.label,
+
+                               // Appearance
+                               base: reset ? scaleBase : me.calculateBarBase(me.index, index),
+                               width: me.calculateBarWidth(ruler),
+                               backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
+                               borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
+                               borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
+                               borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
+                       };
+
                        rectangle.pivot();
                },
 
@@ -160,12 +158,11 @@ module.exports = function(Chart) {
                        };
                },
 
-               calculateBarWidth: function(index) {
+               calculateBarWidth: function(ruler) {
                        var xScale = this.getScaleForId(this.getMeta().xAxisID);
                        if (xScale.options.barThickness) {
                                return xScale.options.barThickness;
                        }
-                       var ruler = this.getRuler(index);
                        return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;
                },
 
@@ -184,13 +181,11 @@ module.exports = function(Chart) {
                        return barIndex;
                },
 
-               calculateBarX: function(index, datasetIndex) {
+               calculateBarX: function(index, datasetIndex, ruler) {
                        var me = this;
                        var meta = me.getMeta();
                        var xScale = me.getScaleForId(meta.xAxisID);
                        var barIndex = me.getBarIndex(datasetIndex);
-
-                       var ruler = me.getRuler(index);
                        var leftTick = xScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);
                        leftTick -= me.chart.isCombo ? (ruler.tickWidth / 2) : 0;
 
@@ -242,12 +237,16 @@ module.exports = function(Chart) {
                draw: function(ease) {
                        var me = this;
                        var easingDecimal = ease || 1;
-                       helpers.each(me.getMeta().data, function(rectangle, index) {
-                               var d = me.getDataset().data[index];
+                       var metaData = me.getMeta().data;
+                       var dataset = me.getDataset();
+                       var i, len;
+
+                       for (i = 0, len = metaData.length; i < len; ++i) {
+                               var d = dataset.data[i];
                                if (d !== null && d !== undefined && !isNaN(d)) {
-                                       rectangle.transition(easingDecimal).draw();
+                                       metaData[i].transition(easingDecimal).draw();
                                }
-                       }, me);
+                       }
                },
 
                setHoverStyle: function(rectangle) {
@@ -342,88 +341,84 @@ module.exports = function(Chart) {
                        var dataset = me.getDataset();
                        var rectangleElementOptions = me.chart.options.elements.rectangle;
 
-                       helpers.extend(rectangle, {
-                               // Utility
-                               _xScale: xScale,
-                               _yScale: yScale,
-                               _datasetIndex: me.index,
-                               _index: index,
-
-                               // Desired view properties
-                               _model: {
-                                       x: reset ? scaleBase : me.calculateBarX(index, me.index),
-                                       y: me.calculateBarY(index, me.index),
-
-                                       // Tooltip
-                                       label: me.chart.data.labels[index],
-                                       datasetLabel: dataset.label,
-
-                                       // Appearance
-                                       base: reset ? scaleBase : me.calculateBarBase(me.index, index),
-                                       height: me.calculateBarHeight(index),
-                                       backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
-                                       borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
-                                       borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
-                                       borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
-                               },
+                       rectangle._xScale = xScale;
+                       rectangle._yScale = yScale;
+                       rectangle._datasetIndex = me.index;
+                       rectangle._index = index;
 
-                               draw: function() {
-                                       var ctx = this._chart.ctx;
-                                       var vm = this._view;
-
-                                       var halfHeight = vm.height / 2,
-                                               topY = vm.y - halfHeight,
-                                               bottomY = vm.y + halfHeight,
-                                               right = vm.base - (vm.base - vm.x),
-                                               halfStroke = vm.borderWidth / 2;
-
-                                       // Canvas doesn't allow us to stroke inside the width so we can
-                                       // adjust the sizes to fit if we're setting a stroke on the line
-                                       if (vm.borderWidth) {
-                                               topY += halfStroke;
-                                               bottomY -= halfStroke;
-                                               right += halfStroke;
-                                       }
+                       var ruler = me.getRuler(index);
+                       rectangle._model = {
+                               x: reset ? scaleBase : me.calculateBarX(index, me.index),
+                               y: me.calculateBarY(index, me.index, ruler),
+
+                               // Tooltip
+                               label: me.chart.data.labels[index],
+                               datasetLabel: dataset.label,
+
+                               // Appearance
+                               base: reset ? scaleBase : me.calculateBarBase(me.index, index),
+                               height: me.calculateBarHeight(ruler),
+                               backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
+                               borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
+                               borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
+                               borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
+                       };
+                       rectangle.draw = function() {
+                               var ctx = this._chart.ctx;
+                               var vm = this._view;
+
+                               var halfHeight = vm.height / 2,
+                                       topY = vm.y - halfHeight,
+                                       bottomY = vm.y + halfHeight,
+                                       right = vm.base - (vm.base - vm.x),
+                                       halfStroke = vm.borderWidth / 2;
+
+                               // Canvas doesn't allow us to stroke inside the width so we can
+                               // adjust the sizes to fit if we're setting a stroke on the line
+                               if (vm.borderWidth) {
+                                       topY += halfStroke;
+                                       bottomY -= halfStroke;
+                                       right += halfStroke;
+                               }
 
-                                       ctx.beginPath();
-
-                                       ctx.fillStyle = vm.backgroundColor;
-                                       ctx.strokeStyle = vm.borderColor;
-                                       ctx.lineWidth = vm.borderWidth;
-
-                                       // Corner points, from bottom-left to bottom-right clockwise
-                                       // | 1 2 |
-                                       // | 0 3 |
-                                       var corners = [
-                                               [vm.base, bottomY],
-                                               [vm.base, topY],
-                                               [right, topY],
-                                               [right, bottomY]
-                                       ];
-
-                                       // Find first (starting) corner with fallback to 'bottom'
-                                       var borders = ['bottom', 'left', 'top', 'right'];
-                                       var startCorner = borders.indexOf(vm.borderSkipped, 0);
-                                       if (startCorner === -1) {
-                                               startCorner = 0;
-                                       }
+                               ctx.beginPath();
+
+                               ctx.fillStyle = vm.backgroundColor;
+                               ctx.strokeStyle = vm.borderColor;
+                               ctx.lineWidth = vm.borderWidth;
+
+                               // Corner points, from bottom-left to bottom-right clockwise
+                               // | 1 2 |
+                               // | 0 3 |
+                               var corners = [
+                                       [vm.base, bottomY],
+                                       [vm.base, topY],
+                                       [right, topY],
+                                       [right, bottomY]
+                               ];
+
+                               // Find first (starting) corner with fallback to 'bottom'
+                               var borders = ['bottom', 'left', 'top', 'right'];
+                               var startCorner = borders.indexOf(vm.borderSkipped, 0);
+                               if (startCorner === -1) {
+                                       startCorner = 0;
+                               }
 
-                                       function cornerAt(cornerIndex) {
-                                               return corners[(startCorner + cornerIndex) % 4];
-                                       }
+                               function cornerAt(cornerIndex) {
+                                       return corners[(startCorner + cornerIndex) % 4];
+                               }
 
-                                       // Draw rectangle from 'startCorner'
-                                       ctx.moveTo.apply(ctx, cornerAt(0));
-                                       for (var i = 1; i < 4; i++) {
-                                               ctx.lineTo.apply(ctx, cornerAt(i));
-                                       }
+                               // Draw rectangle from 'startCorner'
+                               ctx.moveTo.apply(ctx, cornerAt(0));
+                               for (var i = 1; i < 4; i++) {
+                                       ctx.lineTo.apply(ctx, cornerAt(i));
+                               }
 
-                                       ctx.fill();
-                                       if (vm.borderWidth) {
-                                               ctx.stroke();
-                                       }
+                               ctx.fill();
+                               if (vm.borderWidth) {
+                                       ctx.stroke();
                                }
-                       });
+                       };
 
                        rectangle.pivot();
                },
@@ -490,13 +485,12 @@ module.exports = function(Chart) {
                        };
                },
 
-               calculateBarHeight: function(index) {
+               calculateBarHeight: function(ruler) {
                        var me = this;
                        var yScale = me.getScaleForId(me.getMeta().yAxisID);
                        if (yScale.options.barThickness) {
                                return yScale.options.barThickness;
                        }
-                       var ruler = me.getRuler(index);
                        return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;
                },
 
@@ -533,13 +527,11 @@ module.exports = function(Chart) {
                        return xScale.getPixelForValue(value);
                },
 
-               calculateBarY: function(index, datasetIndex) {
+               calculateBarY: function(index, datasetIndex, ruler) {
                        var me = this;
                        var meta = me.getMeta();
                        var yScale = me.getScaleForId(meta.yAxisID);
                        var barIndex = me.getBarIndex(datasetIndex);
-
-                       var ruler = me.getRuler(index);
                        var topTick = yScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);
                        topTick -= me.chart.isCombo ? (ruler.tickHeight / 2) : 0;
 
index 2faff1b6e9c0bcdd93f010de39c98c0eafd79b50..2e218dfe990e9fe1e49c388f48379b3c5b5264ce 100644 (file)
@@ -210,9 +210,11 @@ module.exports = function(Chart) {
 
                draw: function(ease) {
                        var easingDecimal = ease || 1;
-                       helpers.each(this.getMeta().data, function(element) {
-                               element.transition(easingDecimal).draw();
-                       });
+                       var i, len;
+                       var metaData = this.getMeta().data;
+                       for (i = 0, len = metaData.length; i < len; ++i) {
+                               metaData[i].transition(easingDecimal).draw();
+                       }
                },
 
                removeHoverStyle: function(element, elementOpts) {
index 890e04c42e3aa2d3df9ee13b54e1e7885cd1d939..e2d5f56bc8d809dfd578edde3706e06c8768b193 100644 (file)
@@ -167,13 +167,8 @@ module.exports = function(Chart) {
                convertTicksToLabels: function() {
                        var me = this;
                        // Convert ticks to strings
-                       me.ticks = me.ticks.map(function(numericalTick, index, ticks) {
-                               if (me.options.ticks.userCallback) {
-                                       return me.options.ticks.userCallback(numericalTick, index, ticks);
-                               }
-                               return me.options.ticks.callback(numericalTick, index, ticks);
-                       },
-                       me);
+                       var tickOpts = me.options.ticks;
+                       me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback);
                },
                afterTickToLabelConversion: function() {
                        helpers.callCallback(this.options.afterTickToLabelConversion, [this]);
index 3f4ea10f907e92816a83fc6e682ab416067b4718..427916791eda915f54cc4067c4f923646b929a7e 100644 (file)
@@ -95,9 +95,12 @@ module.exports = function(Chart) {
                        }
 
                        // Draw rectangle from 'startCorner'
-                       ctx.moveTo.apply(ctx, cornerAt(0));
+                       var corner = cornerAt(0);
+                       ctx.moveTo(corner[0], corner[1]);
+
                        for (var i = 1; i < 4; i++) {
-                               ctx.lineTo.apply(ctx, cornerAt(i));
+                               corner = cornerAt(i);
+                               ctx.lineTo(corner[0], corner[1]);
                        }
 
                        ctx.fill();