]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Reduce size of on-canvas legend
authorEvert Timberg <evert.timberg+github@gmail.com>
Wed, 4 May 2016 23:28:22 +0000 (19:28 -0400)
committerEvert Timberg <evert.timberg+github@gmail.com>
Wed, 4 May 2016 23:28:22 +0000 (19:28 -0400)
src/core/core.legend.js

index 62287ab707ffa8805a6aaad811feb86a5994d3b9..a7ef76c689b3b068cb257faee85f7a51ddafea71 100644 (file)
@@ -3,6 +3,7 @@
 module.exports = function(Chart) {
 
        var helpers = Chart.helpers;
+       var noop = helpers.noop;
 
        Chart.defaults.global.legend = {
 
@@ -14,13 +15,14 @@ module.exports = function(Chart) {
                // a callback that will handle
                onClick: function(e, legendItem) {
                        var index = legendItem.datasetIndex;
-                       var meta = this.chart.getDatasetMeta(index);
+                       var ci = this.chart;
+                       var meta = ci.getDatasetMeta(index);
 
                        // See controller.isDatasetVisible comment
-                       meta.hidden = meta.hidden === null? !this.chart.data.datasets[index].hidden : null;
+                       meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
 
                        // We hid a dataset ... rerender the chart
-                       this.chart.update();
+                       ci.update();
                },
 
                labels: {
@@ -75,7 +77,7 @@ module.exports = function(Chart) {
                // Any function defined here is inherited by all legend types.
                // Any function can be extended by the legend type
 
-               beforeUpdate: helpers.noop,
+               beforeUpdate: noop,
                update: function(maxWidth, maxHeight, margins) {
 
                        // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
@@ -104,11 +106,11 @@ module.exports = function(Chart) {
 
                        return this.minSize;
                },
-               afterUpdate: helpers.noop,
+               afterUpdate: noop,
 
                //
 
-               beforeSetDimensions: helpers.noop,
+               beforeSetDimensions: noop,
                setDimensions: function() {
                        // Set the unconstrained dimension before label rotation
                        if (this.isHorizontal()) {
@@ -136,90 +138,92 @@ module.exports = function(Chart) {
                                height: 0
                        };
                },
-               afterSetDimensions: helpers.noop,
+               afterSetDimensions: noop,
 
                //
 
-               beforeBuildLabels: helpers.noop,
+               beforeBuildLabels: noop,
                buildLabels: function() {
                        this.legendItems = this.options.labels.generateLabels.call(this, this.chart);
                        if(this.options.reverse){
                                this.legendItems.reverse();
                        }
                },
-               afterBuildLabels: helpers.noop,
+               afterBuildLabels: noop,
 
                //
 
-               beforeFit: helpers.noop,
+               beforeFit: noop,
                fit: function() {
+                       var opts = this.options;
+                       var labelOpts = opts.labels;
+                       var display = opts.display;
 
                        var ctx = this.ctx;
-                       var fontSize = helpers.getValueOrDefault(this.options.labels.fontSize, Chart.defaults.global.defaultFontSize);
-                       var fontStyle = helpers.getValueOrDefault(this.options.labels.fontStyle, Chart.defaults.global.defaultFontStyle);
-                       var fontFamily = helpers.getValueOrDefault(this.options.labels.fontFamily, Chart.defaults.global.defaultFontFamily);
-                       var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
+
+                       var globalDefault = Chart.defaults.global,
+                               itemOrDefault = helpers.getValueOrDefault,
+                               fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
+                               fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
+                               fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),
+                               labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
 
                        // Reset hit boxes
-                       this.legendHitBoxes = [];
+                       var hitboxes = this.legendHitBoxes = [];
 
-                       // Width
-                       if (this.isHorizontal()) {
-                               this.minSize.width = this.maxWidth; // fill all the width
-                       } else {
-                               this.minSize.width = this.options.display ? 10 : 0;
-                       }
+                       var minSize = this.minSize;
+                       var isHorizontal = this.isHorizontal();
 
-                       // height
-                       if (this.isHorizontal()) {
-                               this.minSize.height = this.options.display ? 10 : 0;
+                       if (isHorizontal) {
+                               minSize.width = this.maxWidth; // fill all the width
+                               minSize.height = display ? 10 : 0;
                        } else {
-                               this.minSize.height = this.maxHeight; // fill all the height
+                               minSize.width = display ? 10 : 0;
+                               minSize.height = this.maxHeight; // fill all the height
                        }
 
                        // Increase sizes here
-                       if (this.options.display) {
-                               if (this.isHorizontal()) {
+                       if (display) {
+                               if (isHorizontal) {
                                        // Labels
 
                                        // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
-                                       this.lineWidths = [0];
-                                       var totalHeight = this.legendItems.length ? fontSize + (this.options.labels.padding) : 0;
+                                       var lineWidths = this.lineWidths = [0];
+                                       var totalHeight = this.legendItems.length ? fontSize + (labelOpts.padding) : 0;
 
                                        ctx.textAlign = "left";
                                        ctx.textBaseline = 'top';
                                        ctx.font = labelFont;
 
                                        helpers.each(this.legendItems, function(legendItem, i) {
-                                               var width = this.options.labels.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
-                                               if (this.lineWidths[this.lineWidths.length - 1] + width + this.options.labels.padding >= this.width) {
-                                                       totalHeight += fontSize + (this.options.labels.padding);
-                                                       this.lineWidths[this.lineWidths.length] = this.left;
+                                               var width = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
+                                               if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= this.width) {
+                                                       totalHeight += fontSize + (labelOpts.padding);
+                                                       lineWidths[lineWidths.length] = this.left;
                                                }
 
                                                // Store the hitbox width and height here. Final position will be updated in `draw`
-                                               this.legendHitBoxes[i] = {
+                                               hitboxes[i] = {
                                                        left: 0,
                                                        top: 0,
                                                        width: width,
                                                        height: fontSize
                                                };
 
-                                               this.lineWidths[this.lineWidths.length - 1] += width + this.options.labels.padding;
+                                               lineWidths[lineWidths.length - 1] += width + labelOpts.padding;
                                        }, this);
 
-                                       this.minSize.height += totalHeight;
+                                       minSize.height += totalHeight;
 
                                } else {
                                        // TODO vertical
                                }
                        }
 
-                       this.width = this.minSize.width;
-                       this.height = this.minSize.height;
-
+                       this.width = minSize.width;
+                       this.height = minSize.height;
                },
-               afterFit: helpers.noop,
+               afterFit: noop,
 
                // Shared Methods
                isHorizontal: function() {
@@ -228,19 +232,26 @@ module.exports = function(Chart) {
 
                // Actualy draw the legend on the canvas
                draw: function() {
-                       if (this.options.display) {
-                               var ctx = this.ctx;
-                               var cursor = {
-                                       x: this.left + ((this.width - this.lineWidths[0]) / 2),
-                                       y: this.top + this.options.labels.padding,
-                                       line: 0
-                               };
-
-                               var fontColor = helpers.getValueOrDefault(this.options.labels.fontColor, Chart.defaults.global.defaultFontColor);
-                               var fontSize = helpers.getValueOrDefault(this.options.labels.fontSize, Chart.defaults.global.defaultFontSize);
-                               var fontStyle = helpers.getValueOrDefault(this.options.labels.fontStyle, Chart.defaults.global.defaultFontStyle);
-                               var fontFamily = helpers.getValueOrDefault(this.options.labels.fontFamily, Chart.defaults.global.defaultFontFamily);
-                               var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
+                       var opts = this.options;
+                       var labelOpts = opts.labels;
+                       var globalDefault = Chart.defaults.global,
+                               lineDefault = globalDefault.elements.line,
+                               legendWidth = this.width,
+                               lineWidths = this.lineWidths;
+
+                       if (opts.display) {
+                               var ctx = this.ctx,
+                                       cursor = {
+                                               x: this.left + ((legendWidth - lineWidths[0]) / 2),
+                                               y: this.top + labelOpts.padding,
+                                               line: 0
+                                       },
+                                       itemOrDefault = helpers.getValueOrDefault,
+                                       fontColor = itemOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor),
+                                       fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
+                                       fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
+                                       fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),
+                                       labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
 
                                // Horizontal
                                if (this.isHorizontal()) {
@@ -252,57 +263,58 @@ module.exports = function(Chart) {
                                        ctx.fillStyle = fontColor; // render in correct colour
                                        ctx.font = labelFont;
 
+                                       var boxWidth = labelOpts.boxWidth,
+                                               hitboxes = this.legendHitBoxes;
+
                                        helpers.each(this.legendItems, function(legendItem, i) {
-                                               var textWidth = ctx.measureText(legendItem.text).width;
-                                               var width = this.options.labels.boxWidth + (fontSize / 2) + textWidth;
+                                               var textWidth = ctx.measureText(legendItem.text).width,
+                                                       width = boxWidth + (fontSize / 2) + textWidth,
+                                                       x = cursor.x,
+                                                       y = cursor.y;
 
-                                               if (cursor.x + width >= this.width) {
-                                                       cursor.y += fontSize + (this.options.labels.padding);
+                                               if (x + width >= legendWidth) {
+                                                       cursor.y += fontSize + (labelOpts.padding);
                                                        cursor.line++;
-                                                       cursor.x = this.left + ((this.width - this.lineWidths[cursor.line]) / 2);
+                                                       cursor.x = this.left + ((legendWidth - lineWidths[cursor.line]) / 2);
                                                }
 
                                                // Set the ctx for the box
                                                ctx.save();
 
-                                               var itemOrDefault = function(item, defaulVal) {
-                                                       return item !== undefined ? item : defaulVal;
-                                               };
-
-                                               ctx.fillStyle = itemOrDefault(legendItem.fillStyle, Chart.defaults.global.defaultColor);
-                                               ctx.lineCap = itemOrDefault(legendItem.lineCap, Chart.defaults.global.elements.line.borderCapStyle);
-                                               ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, Chart.defaults.global.elements.line.borderDashOffset);
-                                               ctx.lineJoin = itemOrDefault(legendItem.lineJoin, Chart.defaults.global.elements.line.borderJoinStyle);
-                                               ctx.lineWidth = itemOrDefault(legendItem.lineWidth, Chart.defaults.global.elements.line.borderWidth);
-                                               ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, Chart.defaults.global.defaultColor);
+                                               ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor);
+                                               ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);
+                                               ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset);
+                                               ctx.lineJoin = itemOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle);
+                                               ctx.lineWidth = itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth);
+                                               ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, globalDefault.defaultColor);
 
                                                if (ctx.setLineDash) {
                                                        // IE 9 and 10 do not support line dash
-                                                       ctx.setLineDash(itemOrDefault(legendItem.lineDash, Chart.defaults.global.elements.line.borderDash));
+                                                       ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash));
                                                }
 
                                                // Draw the box
-                                               ctx.strokeRect(cursor.x, cursor.y, this.options.labels.boxWidth, fontSize);
-                                               ctx.fillRect(cursor.x, cursor.y, this.options.labels.boxWidth, fontSize);
+                                               ctx.strokeRect(x, y, boxWidth, fontSize);
+                                               ctx.fillRect(x, y, boxWidth, fontSize);
 
                                                ctx.restore();
 
-                                               this.legendHitBoxes[i].left = cursor.x;
-                                               this.legendHitBoxes[i].top = cursor.y;
+                                               hitboxes[i].left = x;
+                                               hitboxes[i].top = y;
 
                                                // Fill the actual label
-                                               ctx.fillText(legendItem.text, this.options.labels.boxWidth + (fontSize / 2) + cursor.x, cursor.y);
+                                               ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y);
 
                                                if (legendItem.hidden) {
                                                        // Strikethrough the text if hidden
                                                        ctx.beginPath();
                                                        ctx.lineWidth = 2;
-                                                       ctx.moveTo(this.options.labels.boxWidth + (fontSize / 2) + cursor.x, cursor.y + (fontSize / 2));
-                                                       ctx.lineTo(this.options.labels.boxWidth + (fontSize / 2) + cursor.x + textWidth, cursor.y + (fontSize / 2));
+                                                       ctx.moveTo(boxWidth + (fontSize / 2) + x, y + (fontSize / 2));
+                                                       ctx.lineTo(boxWidth + (fontSize / 2) + x + textWidth, y + (fontSize / 2));
                                                        ctx.stroke();
                                                }
 
-                                               cursor.x += width + (this.options.labels.padding);
+                                               cursor.x += width + (labelOpts.padding);
                                        }, this);
                                } else {
 
@@ -312,17 +324,21 @@ module.exports = function(Chart) {
 
                // Handle an event
                handleEvent: function(e) {
-                       var position = helpers.getRelativePosition(e, this.chart.chart);
+                       var position = helpers.getRelativePosition(e, this.chart.chart),
+                               x = position.x,
+                               y = position.y,
+                               opts = this.options;
 
-                       if (position.x >= this.left && position.x <= this.right && position.y >= this.top && position.y <= this.bottom) {
+                       if (x >= this.left && x <= this.right && y >= this.top && y <= this.bottom) {
                                // See if we are touching one of the dataset boxes
-                               for (var i = 0; i < this.legendHitBoxes.length; ++i) {
-                                       var hitBox = this.legendHitBoxes[i];
+                               var lh = this.legendHitBoxes;
+                               for (var i = 0; i < lh.length; ++i) {
+                                       var hitBox = lh[i];
 
-                                       if (position.x >= hitBox.left && position.x <= hitBox.left + hitBox.width && position.y >= hitBox.top && position.y <= hitBox.top + hitBox.height) {
+                                       if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
                                                // Touching an element
-                                               if (this.options.onClick) {
-                                                       this.options.onClick.call(this, e, this.legendItems[i]);
+                                               if (opts.onClick) {
+                                                       opts.onClick.call(this, e, this.legendItems[i]);
                                                }
                                                break;
                                        }