From b0f69a1092f2bf38dcb42d3d9a788881f1a6aaba Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Mon, 7 Dec 2015 19:11:54 -0500 Subject: [PATCH] Generate nice legend boxes for all current chart types --- src/controllers/controller.doughnut.js | 10 +++- src/controllers/controller.polarArea.js | 10 +++- src/core/core.legend.js | 73 ++++++++++++++++--------- 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index 250279a56..d65d10d39 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -37,7 +37,15 @@ legend: { labels: { generateLabels: function(data) { - return data.labels.slice(); + return data.labels.map(function(label, i) { + return { + text: label, + fillStyle: data.datasets[0].backgroundColor[i], + + // Extra data used for toggling the correct item + index: i + }; + }); } } }, diff --git a/src/controllers/controller.polarArea.js b/src/controllers/controller.polarArea.js index 06847a31b..b19b225e1 100644 --- a/src/controllers/controller.polarArea.js +++ b/src/controllers/controller.polarArea.js @@ -39,7 +39,15 @@ legend: { labels: { generateLabels: function(data) { - return data.labels.slice(); + return data.labels.map(function(label, i) { + return { + text: label, + fillStyle: data.datasets[0].backgroundColor[i], + + // Extra data used for toggling the correct item + index: i + }; + }); } } }, diff --git a/src/core/core.legend.js b/src/core/core.legend.js index 1ce764742..3793aae36 100644 --- a/src/core/core.legend.js +++ b/src/core/core.legend.js @@ -24,9 +24,32 @@ }, // Generates labels shown in the legend + // Valid properties to return: + // text : text to display + // fillStyle : fill of coloured box + // strokeStyle: stroke of coloured box + // hidden : if this legend item refers to a hidden item + // lineCap : cap style for line + // lineDash + // lineDashOffset : + // lineJoin : + // lineWidth : generateLabels: function(data) { - return data.datasets.map(function(dataset) { - return this.options.labels.callback.call(this, dataset); + return data.datasets.map(function(dataset, i) { + return { + text: this.options.labels.callback.call(this, dataset), + fillStyle: dataset.backgroundColor, + hidden: dataset.hidden, + lineCap: dataset.borderCapStyle, + lineDash: dataset.borderDash, + lineDashOffset: dataset.borderDashOffset, + lineJoin: dataset.borderJoinStyle, + lineWidth: dataset.borderWidth, + strokeStyle: dataset.borderColor, + + // Below is extra data used for toggling the datasets + datasetIndex: i + }; }, this); } }, @@ -116,7 +139,7 @@ beforeBuildLabels: helpers.noop, buildLabels: function() { - this.labels = this.options.labels.generateLabels.call(this, this.chart.data); + this.legendItems = this.options.labels.generateLabels.call(this, this.chart.data); }, afterBuildLabels: helpers.noop, @@ -151,14 +174,14 @@ // 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.labels.length ? this.options.labels.fontSize + (this.options.labels.padding) : 0; + var totalHeight = this.legendItems.length ? this.options.labels.fontSize + (this.options.labels.padding) : 0; ctx.textAlign = "left"; ctx.textBaseline = 'top'; ctx.font = labelFont; - helpers.each(this.labels, function(label, i) { - var width = this.options.labels.boxWidth + (this.options.labels.fontSize / 2) + ctx.measureText(label).width; + helpers.each(this.legendItems, function(legendItem, i) { + var width = this.options.labels.boxWidth + (this.options.labels.fontSize / 2) + ctx.measureText(legendItem.text).width; if (this.lineWidths[this.lineWidths.length - 1] + width >= this.width) { totalHeight += this.options.labels.fontSize + (this.options.labels.padding); this.lineWidths[this.lineWidths.length] = this.left; @@ -214,12 +237,8 @@ ctx.fillStyle = this.options.labels.fontColor; // render in correct colour ctx.font = labelFont; - helpers.each(this.labels, function(label, i) { - var dataset = this.chart.data.datasets[i]; - var backgroundColor = dataset.backgroundColor; - var borderColor = dataset.borderColor; - - var textWidth = ctx.measureText(label).width; + helpers.each(this.legendItems, function(legendItem, i) { + var textWidth = ctx.measureText(legendItem.text).width; var width = this.options.labels.boxWidth + (this.options.labels.fontSize / 2) + textWidth; if (cursor.x + width >= this.width) { @@ -231,20 +250,20 @@ // Set the ctx for the box ctx.save(); - ctx.strokeStyle = dataset.borderColor || Chart.defaults.global.defaultColor; - ctx.fillStyle = dataset.backgroundColor || Chart.defaults.global.defaultColor; - - if (dataset.metaDataset) { - // Is this a line-like element? If so, stroke the box - if (ctx.setLineDash) { - // IE 9 and 10 do not support line dash - ctx.setLineDash(dataset.borderDash || Chart.defaults.global.elements.line.borderDash); - } + var itemOrDefault = function(item, defaulVal) { + return item !== undefined ? item : defaulVal; + }; - ctx.lineCap = dataset.borderCapStyle || Chart.defaults.global.elements.line.borderCapStyle; - ctx.lineDashOffset = dataset.borderDashOffset || Chart.defaults.global.elements.line.borderDashOffset; - ctx.lineJoin = dataset.borderJoinStyle || Chart.defaults.global.elements.line.borderJoinStyle; - ctx.lineWidth = dataset.borderWidth || Chart.defaults.global.elements.line.borderWidth; + 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); + + if (ctx.setLineDash) { + // IE 9 and 10 do not support line dash + ctx.setLineDash(itemOrDefault(legendItem.lineDash, Chart.defaults.global.elements.line.borderDash)); } // Draw the box @@ -257,9 +276,9 @@ this.legendHitBoxes[i].top = cursor.y; // Fill the actual label - ctx.fillText(label, this.options.labels.boxWidth + (this.options.labels.fontSize / 2) + cursor.x, cursor.y); + ctx.fillText(legendItem.text, this.options.labels.boxWidth + (this.options.labels.fontSize / 2) + cursor.x, cursor.y); - if (dataset.hidden) { + if (legendItem.hidden) { // Strikethrough the text if hidden ctx.beginPath(); ctx.lineWidth = 2;