Make legend appearance consistent with chart elements (#5621)

This commit is contained in:
Akihiko Kusanagi 2019-05-09 21:33:19 +08:00 committed by Simon Brunel
parent f093c36574
commit feeda5d034
15 changed files with 548 additions and 391 deletions

View File

@ -82,7 +82,10 @@ Items passed to the legend `onClick` function are the ones returned from `labels
strokeStyle: Color,
// Point style of the legend box (only used if usePointStyle is true)
pointStyle: string
pointStyle: string | Image,
// Rotation of the point in degrees (only used if usePointStyle is true)
rotation: number
}
```

View File

@ -5,8 +5,6 @@ var defaults = require('../core/core.defaults');
var elements = require('../elements/index');
var helpers = require('../helpers/index');
var resolve = helpers.options.resolve;
defaults._set('bar', {
hover: {
mode: 'label'
@ -120,6 +118,16 @@ module.exports = DatasetController.extend({
dataElementType: elements.Rectangle,
/**
* @private
*/
_dataElementOptions: [
'backgroundColor',
'borderColor',
'borderSkipped',
'borderWidth'
],
initialize: function() {
var me = this;
var meta;
@ -147,7 +155,7 @@ module.exports = DatasetController.extend({
var me = this;
var meta = me.getMeta();
var dataset = me.getDataset();
var options = me._resolveElementOptions(rectangle, index);
var options = me._resolveDataElementOptions(rectangle, index);
rectangle._xScale = me.getScaleForId(meta.xAxisID);
rectangle._yScale = me.getScaleForId(meta.yAxisID);
@ -372,46 +380,5 @@ module.exports = DatasetController.extend({
}
helpers.canvas.unclipArea(chart.ctx);
},
/**
* @private
*/
_resolveElementOptions: function(rectangle, index) {
var me = this;
var chart = me.chart;
var datasets = chart.data.datasets;
var dataset = datasets[me.index];
var datasetOpts = me._config;
var custom = rectangle.custom || {};
var options = chart.options.elements.rectangle;
var values = {};
var i, ilen, key;
// Scriptable options
var context = {
chart: chart,
dataIndex: index,
dataset: dataset,
datasetIndex: me.index
};
var keys = [
'backgroundColor',
'borderColor',
'borderSkipped',
'borderWidth'
];
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
options[key]
], context, index);
}
return values;
}
});

View File

@ -47,6 +47,22 @@ module.exports = DatasetController.extend({
*/
dataElementType: elements.Point,
/**
* @private
*/
_dataElementOptions: [
'backgroundColor',
'borderColor',
'borderWidth',
'hoverBackgroundColor',
'hoverBorderColor',
'hoverBorderWidth',
'hoverRadius',
'hitRadius',
'pointStyle',
'rotation'
],
/**
* @protected
*/
@ -70,7 +86,7 @@ module.exports = DatasetController.extend({
var custom = point.custom || {};
var xScale = me.getScaleForId(meta.xAxisID);
var yScale = me.getScaleForId(meta.yAxisID);
var options = me._resolveElementOptions(point, index);
var options = me._resolveDataElementOptions(point, index);
var data = me.getDataset().data[index];
var dsIndex = me.index;
@ -122,17 +138,13 @@ module.exports = DatasetController.extend({
/**
* @private
*/
_resolveElementOptions: function(point, index) {
_resolveDataElementOptions: function(point, index) {
var me = this;
var chart = me.chart;
var datasets = chart.data.datasets;
var dataset = datasets[me.index];
var datasetOpts = me._config;
var dataset = me.getDataset();
var custom = point.custom || {};
var options = chart.options.elements.point;
var data = dataset.data[index];
var values = {};
var i, ilen, key;
var data = dataset.data[index] || {};
var values = DatasetController.prototype._resolveDataElementOptions.apply(me, arguments);
// Scriptable options
var context = {
@ -142,34 +154,12 @@ module.exports = DatasetController.extend({
datasetIndex: me.index
};
var keys = [
'backgroundColor',
'borderColor',
'borderWidth',
'hoverBackgroundColor',
'hoverBorderColor',
'hoverBorderWidth',
'hoverRadius',
'hitRadius',
'pointStyle',
'rotation'
];
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
options[key]
], context, index);
}
// Custom radius resolution
values.radius = resolve([
custom.radius,
data ? data.r : undefined,
dataset.radius,
options.radius
data.r,
me._config.radius,
chart.options.elements.point.radius
], context, index);
return values;

View File

@ -5,7 +5,6 @@ var defaults = require('../core/core.defaults');
var elements = require('../elements/index');
var helpers = require('../helpers/index');
var resolve = helpers.options.resolve;
var valueOrDefault = helpers.valueOrDefault;
var PI = Math.PI;
@ -50,20 +49,14 @@ defaults._set('doughnut', {
if (data.labels.length && data.datasets.length) {
return data.labels.map(function(label, i) {
var meta = chart.getDatasetMeta(0);
var ds = data.datasets[0];
var arc = meta.data[i];
var custom = arc && arc.custom || {};
var arcOpts = chart.options.elements.arc;
var fill = resolve([custom.backgroundColor, ds.backgroundColor, arcOpts.backgroundColor], undefined, i);
var stroke = resolve([custom.borderColor, ds.borderColor, arcOpts.borderColor], undefined, i);
var bw = resolve([custom.borderWidth, ds.borderWidth, arcOpts.borderWidth], undefined, i);
var style = meta.controller.getStyle(i);
return {
text: label,
fillStyle: fill,
strokeStyle: stroke,
lineWidth: bw,
hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
// Extra data used for toggling the correct item
index: i
@ -131,6 +124,19 @@ module.exports = DatasetController.extend({
linkScales: helpers.noop,
/**
* @private
*/
_dataElementOptions: [
'backgroundColor',
'borderColor',
'borderWidth',
'borderAlign',
'hoverBackgroundColor',
'hoverBorderColor',
'hoverBorderWidth',
],
// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
getRingIndex: function(datasetIndex) {
var ringIndex = 0;
@ -184,7 +190,7 @@ module.exports = DatasetController.extend({
}
for (i = 0, ilen = arcs.length; i < ilen; ++i) {
arcs[i]._options = me._resolveElementOptions(arcs[i], i);
arcs[i]._options = me._resolveDataElementOptions(arcs[i], i);
}
chart.borderWidth = me.getMaxBorderWidth();
@ -317,7 +323,7 @@ module.exports = DatasetController.extend({
arc = arcs[i];
if (controller) {
controller._configure();
options = controller._resolveElementOptions(arc, i);
options = controller._resolveDataElementOptions(arc, i);
} else {
options = arc._options;
}
@ -351,49 +357,6 @@ module.exports = DatasetController.extend({
model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth);
},
/**
* @private
*/
_resolveElementOptions: function(arc, index) {
var me = this;
var chart = me.chart;
var dataset = me.getDataset();
var datasetOpts = me._config;
var custom = arc.custom || {};
var options = chart.options.elements.arc;
var values = {};
var i, ilen, key;
// Scriptable options
var context = {
chart: chart,
dataIndex: index,
dataset: dataset,
datasetIndex: me.index
};
var keys = [
'backgroundColor',
'borderColor',
'borderWidth',
'borderAlign',
'hoverBackgroundColor',
'hoverBorderColor',
'hoverBorderWidth',
];
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
options[key]
], context, index);
}
return values;
},
/**
* Get radius length offset of the dataset in relation to the visible datasets weights. This allows determining the inner and outer radius correctly
* @private

View File

@ -35,6 +35,38 @@ module.exports = DatasetController.extend({
dataElementType: elements.Point,
/**
* @private
*/
_datasetElementOptions: [
'backgroundColor',
'borderCapStyle',
'borderColor',
'borderDash',
'borderDashOffset',
'borderJoinStyle',
'borderWidth',
'cubicInterpolationMode',
'fill'
],
/**
* @private
*/
_dataElementOptions: {
backgroundColor: 'pointBackgroundColor',
borderColor: 'pointBorderColor',
borderWidth: 'pointBorderWidth',
hitRadius: 'pointHitRadius',
hoverBackgroundColor: 'pointHoverBackgroundColor',
hoverBorderColor: 'pointHoverBorderColor',
hoverBorderWidth: 'pointHoverBorderWidth',
hoverRadius: 'pointHoverRadius',
pointStyle: 'pointStyle',
radius: 'pointRadius',
rotation: 'pointRotation'
},
update: function(reset) {
var me = this;
var meta = me.getMeta();
@ -61,7 +93,7 @@ module.exports = DatasetController.extend({
// Data
line._children = points;
// Model
line._model = me._resolveLineOptions(line);
line._model = me._resolveDatasetElementOptions(line);
line.pivot();
}
@ -93,7 +125,7 @@ module.exports = DatasetController.extend({
var lineModel = meta.dataset._model;
var x, y;
var options = me._resolvePointOptions(point, index);
var options = me._resolveDataElementOptions(point, index);
x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex);
y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);
@ -127,101 +159,20 @@ module.exports = DatasetController.extend({
/**
* @private
*/
_resolvePointOptions: function(element, index) {
_resolveDatasetElementOptions: function(element) {
var me = this;
var chart = me.chart;
var dataset = chart.data.datasets[me.index];
var datasetOpts = me._config;
var custom = element.custom || {};
var options = chart.options.elements.point;
var values = {};
var i, ilen, key;
// Scriptable options
var context = {
chart: chart,
dataIndex: index,
dataset: dataset,
datasetIndex: me.index
};
var ELEMENT_OPTIONS = {
backgroundColor: 'pointBackgroundColor',
borderColor: 'pointBorderColor',
borderWidth: 'pointBorderWidth',
hitRadius: 'pointHitRadius',
hoverBackgroundColor: 'pointHoverBackgroundColor',
hoverBorderColor: 'pointHoverBorderColor',
hoverBorderWidth: 'pointHoverBorderWidth',
hoverRadius: 'pointHoverRadius',
pointStyle: 'pointStyle',
radius: 'pointRadius',
rotation: 'pointRotation'
};
var keys = Object.keys(ELEMENT_OPTIONS);
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[ELEMENT_OPTIONS[key]],
datasetOpts[key],
options[key]
], context, index);
}
return values;
},
/**
* @private
*/
_resolveLineOptions: function(element) {
var me = this;
var chart = me.chart;
var datasetIndex = me.index;
var dataset = chart.data.datasets[datasetIndex];
var datasetOpts = me._config;
var custom = element.custom || {};
var options = chart.options;
var elementOptions = options.elements.line;
var values = {};
var i, ilen, key;
// Scriptable options
var context = {
chart: chart,
dataset: dataset,
datasetIndex: datasetIndex
};
var keys = [
'backgroundColor',
'borderCapStyle',
'borderColor',
'borderDash',
'borderDashOffset',
'borderJoinStyle',
'borderWidth',
'cubicInterpolationMode',
'fill'
];
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
elementOptions[key]
], context);
}
var options = me.chart.options;
var lineOptions = options.elements.line;
var values = DatasetController.prototype._resolveDatasetElementOptions.apply(me, arguments);
// The default behavior of lines is to break at null values, according
// to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
// This option gives lines the ability to span gaps
values.spanGaps = valueOrDefault(datasetOpts.spanGaps, options.spanGaps);
values.tension = valueOrDefault(datasetOpts.lineTension, elementOptions.tension);
values.steppedLine = resolve([custom.steppedLine, datasetOpts.steppedLine, elementOptions.stepped]);
values.tension = valueOrDefault(datasetOpts.lineTension, lineOptions.tension);
values.steppedLine = resolve([custom.steppedLine, datasetOpts.steppedLine, lineOptions.stepped]);
return values;
},

View File

@ -59,20 +59,14 @@ defaults._set('polarArea', {
if (data.labels.length && data.datasets.length) {
return data.labels.map(function(label, i) {
var meta = chart.getDatasetMeta(0);
var ds = data.datasets[0];
var arc = meta.data[i];
var custom = arc.custom || {};
var arcOpts = chart.options.elements.arc;
var fill = resolve([custom.backgroundColor, ds.backgroundColor, arcOpts.backgroundColor], undefined, i);
var stroke = resolve([custom.borderColor, ds.borderColor, arcOpts.borderColor], undefined, i);
var bw = resolve([custom.borderWidth, ds.borderWidth, arcOpts.borderWidth], undefined, i);
var style = meta.controller.getStyle(i);
return {
text: label,
fillStyle: fill,
strokeStyle: stroke,
lineWidth: bw,
hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
// Extra data used for toggling the correct item
index: i
@ -116,6 +110,19 @@ module.exports = DatasetController.extend({
linkScales: helpers.noop,
/**
* @private
*/
_dataElementOptions: [
'backgroundColor',
'borderColor',
'borderWidth',
'borderAlign',
'hoverBackgroundColor',
'hoverBorderColor',
'hoverBorderWidth',
],
update: function(reset) {
var me = this;
var dataset = me.getDataset();
@ -138,7 +145,7 @@ module.exports = DatasetController.extend({
}
for (i = 0, ilen = arcs.length; i < ilen; ++i) {
arcs[i]._options = me._resolveElementOptions(arcs[i], i);
arcs[i]._options = me._resolveDataElementOptions(arcs[i], i);
me.updateElement(arcs[i], i, reset);
}
},
@ -241,49 +248,6 @@ module.exports = DatasetController.extend({
model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth);
},
/**
* @private
*/
_resolveElementOptions: function(arc, index) {
var me = this;
var chart = me.chart;
var dataset = me.getDataset();
var datasetOpts = me._config;
var custom = arc.custom || {};
var options = chart.options.elements.arc;
var values = {};
var i, ilen, key;
// Scriptable options
var context = {
chart: chart,
dataIndex: index,
dataset: dataset,
datasetIndex: me.index
};
var keys = [
'backgroundColor',
'borderColor',
'borderWidth',
'borderAlign',
'hoverBackgroundColor',
'hoverBorderColor',
'hoverBorderWidth',
];
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
options[key]
], context, index);
}
return values;
},
/**
* @private
*/

View File

@ -6,7 +6,6 @@ var elements = require('../elements/index');
var helpers = require('../helpers/index');
var valueOrDefault = helpers.valueOrDefault;
var resolve = helpers.options.resolve;
defaults._set('radar', {
scale: {
@ -33,6 +32,37 @@ module.exports = DatasetController.extend({
linkScales: helpers.noop,
/**
* @private
*/
_datasetElementOptions: [
'backgroundColor',
'borderWidth',
'borderColor',
'borderCapStyle',
'borderDash',
'borderDashOffset',
'borderJoinStyle',
'fill'
],
/**
* @private
*/
_dataElementOptions: {
backgroundColor: 'pointBackgroundColor',
borderColor: 'pointBorderColor',
borderWidth: 'pointBorderWidth',
hitRadius: 'pointHitRadius',
hoverBackgroundColor: 'pointHoverBackgroundColor',
hoverBorderColor: 'pointHoverBorderColor',
hoverBorderWidth: 'pointHoverBorderWidth',
hoverRadius: 'pointHoverRadius',
pointStyle: 'pointStyle',
radius: 'pointRadius',
rotation: 'pointRotation'
},
update: function(reset) {
var me = this;
var meta = me.getMeta();
@ -54,7 +84,7 @@ module.exports = DatasetController.extend({
line._children = points;
line._loop = true;
// Model
line._model = me._resolveLineOptions(line);
line._model = me._resolveDatasetElementOptions(line);
line.pivot();
@ -78,7 +108,7 @@ module.exports = DatasetController.extend({
var dataset = me.getDataset();
var scale = me.chart.scale;
var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
var options = me._resolvePointOptions(point, index);
var options = me._resolveDataElementOptions(point, index);
var lineModel = me.getMeta().dataset._model;
var x = reset ? scale.xCenter : pointPosition.x;
var y = reset ? scale.yCenter : pointPosition.y;
@ -111,86 +141,11 @@ module.exports = DatasetController.extend({
/**
* @private
*/
_resolvePointOptions: function(element, index) {
_resolveDatasetElementOptions: function() {
var me = this;
var chart = me.chart;
var dataset = chart.data.datasets[me.index];
var datasetOpts = me._config;
var custom = element.custom || {};
var options = chart.options.elements.point;
var values = {};
var i, ilen, key;
var values = DatasetController.prototype._resolveDatasetElementOptions.apply(me, arguments);
// Scriptable options
var context = {
chart: chart,
dataIndex: index,
dataset: dataset,
datasetIndex: me.index
};
var ELEMENT_OPTIONS = {
backgroundColor: 'pointBackgroundColor',
borderColor: 'pointBorderColor',
borderWidth: 'pointBorderWidth',
hitRadius: 'pointHitRadius',
hoverBackgroundColor: 'pointHoverBackgroundColor',
hoverBorderColor: 'pointHoverBorderColor',
hoverBorderWidth: 'pointHoverBorderWidth',
hoverRadius: 'pointHoverRadius',
pointStyle: 'pointStyle',
radius: 'pointRadius',
rotation: 'pointRotation'
};
var keys = Object.keys(ELEMENT_OPTIONS);
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[ELEMENT_OPTIONS[key]],
datasetOpts[key],
options[key]
], context, index);
}
return values;
},
/**
* @private
*/
_resolveLineOptions: function(element) {
var me = this;
var chart = me.chart;
var dataset = chart.data.datasets[me.index];
var datasetOpts = me._config;
var custom = element.custom || {};
var options = chart.options.elements.line;
var values = {};
var i, ilen, key;
var keys = [
'backgroundColor',
'borderWidth',
'borderColor',
'borderCapStyle',
'borderDash',
'borderDashOffset',
'borderJoinStyle',
'fill'
];
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
options[key]
]);
}
values.tension = valueOrDefault(dataset.lineTension, options.tension);
values.tension = valueOrDefault(me._config.lineTension, me.chart.options.elements.line.tension);
return values;
},

View File

@ -94,6 +94,35 @@ helpers.extend(DatasetController.prototype, {
*/
dataElementType: null,
/**
* Dataset element option keys to be resolved in _resolveDatasetElementOptions.
* A derived controller may override this to resolve controller-specific options.
* The keys defined here are for backward compatibility for legend styles.
* @private
*/
_datasetElementOptions: [
'backgroundColor',
'borderCapStyle',
'borderColor',
'borderDash',
'borderDashOffset',
'borderJoinStyle',
'borderWidth'
],
/**
* Data element option keys to be resolved in _resolveDataElementOptions.
* A derived controller may override this to resolve controller-specific options.
* The keys defined here are for backward compatibility for legend styles.
* @private
*/
_dataElementOptions: [
'backgroundColor',
'borderColor',
'borderWidth',
'pointStyle'
],
initialize: function(chart, datasetIndex) {
var me = this;
me.chart = chart;
@ -293,6 +322,111 @@ helpers.extend(DatasetController.prototype, {
}
},
/**
* Returns a set of predefined style properties that should be used to represent the dataset
* or the data if the index is specified
* @param {number} index - data index
* @return {IStyleInterface} style object
*/
getStyle: function(index) {
var me = this;
var meta = me.getMeta();
var dataset = meta.dataset;
var style;
me._configure();
if (dataset && index === undefined) {
style = me._resolveDatasetElementOptions(dataset || {});
} else {
index = index || 0;
style = me._resolveDataElementOptions(meta.data[index] || {}, index);
}
if (style.fill === false || style.fill === null) {
style.backgroundColor = 'rgba(0,0,0,0)';
}
return style;
},
/**
* @private
*/
_resolveDatasetElementOptions: function(element) {
var me = this;
var chart = me.chart;
var datasetOpts = me._config;
var custom = element.custom || {};
var options = chart.options.elements[me.datasetElementType.prototype._type] || {};
var elementOptions = me._datasetElementOptions;
var values = {};
var i, ilen, key;
// Scriptable options
var context = {
chart: chart,
dataset: me.getDataset(),
datasetIndex: me.index
};
for (i = 0, ilen = elementOptions.length; i < ilen; ++i) {
key = elementOptions[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
options[key]
], context);
}
return values;
},
/**
* @private
*/
_resolveDataElementOptions: function(element, index) {
var me = this;
var chart = me.chart;
var datasetOpts = me._config;
var custom = element.custom || {};
var options = chart.options.elements[me.dataElementType.prototype._type] || {};
var elementOptions = me._dataElementOptions;
var values = {};
var keys, i, ilen, key;
// Scriptable options
var context = {
chart: chart,
dataIndex: index,
dataset: me.getDataset(),
datasetIndex: me.index
};
if (helpers.isArray(elementOptions)) {
for (i = 0, ilen = elementOptions.length; i < ilen; ++i) {
key = elementOptions[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
options[key]
], context, index);
}
} else {
keys = Object.keys(elementOptions);
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
datasetOpts[elementOptions[key]],
datasetOpts[key],
options[key]
], context, index);
}
}
return values;
},
removeHoverStyle: function(element) {
helpers.merge(element._model, element.$previousStyle || {});
delete element.$previousStyle;

View File

@ -58,6 +58,7 @@ var Element = function(configuration) {
};
helpers.extend(Element.prototype, {
_type: undefined,
initialize: function() {
this.hidden = false;

View File

@ -92,6 +92,8 @@ function drawBorder(ctx, vm, arc) {
}
module.exports = Element.extend({
_type: 'arc',
inLabelRange: function(mouseX) {
var vm = this._view;

View File

@ -26,6 +26,8 @@ defaults._set('global', {
});
module.exports = Element.extend({
_type: 'line',
draw: function() {
var me = this;
var vm = me._view;

View File

@ -35,6 +35,8 @@ function yRange(mouseY) {
}
module.exports = Element.extend({
_type: 'point',
inRange: function(mouseX, mouseY) {
var vm = this._view;
return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;

View File

@ -131,6 +131,8 @@ function inRange(vm, x, y) {
}
module.exports = Element.extend({
_type: 'rectangle',
draw: function() {
var ctx = this._chart.ctx;
var vm = this._view;

View File

@ -49,18 +49,25 @@ defaults._set('global', {
// lineWidth :
generateLabels: function(chart) {
var data = chart.data;
var options = chart.options.legend || {};
var usePointStyle = options.labels && options.labels.usePointStyle;
return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {
var meta = chart.getDatasetMeta(i);
var style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
return {
text: dataset.label,
fillStyle: (!helpers.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]),
fillStyle: style.backgroundColor,
hidden: !chart.isDatasetVisible(i),
lineCap: dataset.borderCapStyle,
lineDash: dataset.borderDash,
lineDashOffset: dataset.borderDashOffset,
lineJoin: dataset.borderJoinStyle,
lineWidth: dataset.borderWidth,
strokeStyle: dataset.borderColor,
pointStyle: dataset.pointStyle,
lineCap: style.borderCapStyle,
lineDash: style.borderDash,
lineDashOffset: style.borderDashOffset,
lineJoin: style.borderJoinStyle,
lineWidth: style.borderWidth,
strokeStyle: style.borderColor,
pointStyle: style.pointStyle,
rotation: style.rotation,
// Below is extra data used for toggling the datasets
datasetIndex: i
@ -377,7 +384,7 @@ var Legend = Element.extend({
ctx.setLineDash(valueOrDefault(legendItem.lineDash, lineDefault.borderDash));
}
if (opts.labels && opts.labels.usePointStyle) {
if (labelOpts && labelOpts.usePointStyle) {
// Recalculate x and y for drawPoint() because its expecting
// x and y to be center of figure (instead of top left)
var radius = boxWidth * Math.SQRT2 / 2;
@ -385,13 +392,13 @@ var Legend = Element.extend({
var centerY = y + fontSize / 2;
// Draw pointStyle as legend symbol
helpers.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY);
helpers.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY, legendItem.rotation);
} else {
// Draw box as legend symbol
ctx.fillRect(x, y, boxWidth, fontSize);
if (lineWidth !== 0) {
ctx.strokeRect(x, y, boxWidth, fontSize);
}
ctx.fillRect(x, y, boxWidth, fontSize);
}
ctx.restore();

View File

@ -24,7 +24,7 @@ describe('Legend block tests', function() {
});
});
it('should update correctly', function() {
it('should update bar chart correctly', function() {
var chart = window.acquireChart({
type: 'bar',
data: {
@ -55,29 +55,31 @@ describe('Legend block tests', function() {
text: 'dataset1',
fillStyle: '#f31',
hidden: false,
lineCap: 'butt',
lineDash: [2, 2],
lineDashOffset: 5.5,
lineCap: undefined,
lineDash: undefined,
lineDashOffset: undefined,
lineJoin: undefined,
lineWidth: undefined,
strokeStyle: undefined,
lineWidth: 0,
strokeStyle: 'rgba(0,0,0,0.1)',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 0
}, {
text: 'dataset2',
fillStyle: undefined,
fillStyle: 'rgba(0,0,0,0.1)',
hidden: true,
lineCap: undefined,
lineDash: undefined,
lineDashOffset: undefined,
lineJoin: 'miter',
lineWidth: undefined,
strokeStyle: undefined,
lineJoin: undefined,
lineWidth: 0,
strokeStyle: 'rgba(0,0,0,0.1)',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 1
}, {
text: 'dataset3',
fillStyle: undefined,
fillStyle: 'rgba(0,0,0,0.1)',
hidden: false,
lineCap: undefined,
lineDash: undefined,
@ -85,7 +87,78 @@ describe('Legend block tests', function() {
lineJoin: undefined,
lineWidth: 10,
strokeStyle: 'green',
pointStyle: 'crossRot',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 2
}]);
});
it('should update line chart correctly', function() {
var chart = window.acquireChart({
type: 'line',
data: {
datasets: [{
label: 'dataset1',
backgroundColor: '#f31',
borderCapStyle: 'round',
borderDash: [2, 2],
borderDashOffset: 5.5,
data: []
}, {
label: 'dataset2',
hidden: true,
borderJoinStyle: 'round',
data: []
}, {
label: 'dataset3',
borderWidth: 10,
borderColor: 'green',
pointStyle: 'crossRot',
fill: false,
data: []
}],
labels: []
}
});
expect(chart.legend.legendItems).toEqual([{
text: 'dataset1',
fillStyle: '#f31',
hidden: false,
lineCap: 'round',
lineDash: [2, 2],
lineDashOffset: 5.5,
lineJoin: 'miter',
lineWidth: 3,
strokeStyle: 'rgba(0,0,0,0.1)',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 0
}, {
text: 'dataset2',
fillStyle: 'rgba(0,0,0,0.1)',
hidden: true,
lineCap: 'butt',
lineDash: [],
lineDashOffset: 0,
lineJoin: 'round',
lineWidth: 3,
strokeStyle: 'rgba(0,0,0,0.1)',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 1
}, {
text: 'dataset3',
fillStyle: 'rgba(0,0,0,0)',
hidden: false,
lineCap: 'butt',
lineDash: [],
lineDashOffset: 0,
lineJoin: 'miter',
lineWidth: 10,
strokeStyle: 'green',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 2
}]);
});
@ -132,17 +205,18 @@ describe('Legend block tests', function() {
text: 'dataset1',
fillStyle: '#f31',
hidden: false,
lineCap: 'butt',
lineDash: [2, 2],
lineDashOffset: 5.5,
lineCap: undefined,
lineDash: undefined,
lineDashOffset: undefined,
lineJoin: undefined,
lineWidth: undefined,
strokeStyle: undefined,
lineWidth: 0,
strokeStyle: 'rgba(0,0,0,0.1)',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 0
}, {
text: 'dataset3',
fillStyle: undefined,
fillStyle: 'rgba(0,0,0,0.1)',
hidden: false,
lineCap: undefined,
lineDash: undefined,
@ -150,7 +224,8 @@ describe('Legend block tests', function() {
lineJoin: undefined,
lineWidth: 10,
strokeStyle: 'green',
pointStyle: 'crossRot',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 2
}]);
});
@ -217,6 +292,145 @@ describe('Legend block tests', function() {
});
});
it('should pick up the first item when the property is an array', function() {
var chart = window.acquireChart({
type: 'bar',
data: {
datasets: [{
label: 'dataset1',
backgroundColor: ['#f31', '#666', '#14e'],
borderWidth: [5, 10, 15],
borderColor: ['red', 'green', 'blue'],
data: []
}],
labels: []
}
});
expect(chart.legend.legendItems).toEqual([{
text: 'dataset1',
fillStyle: '#f31',
hidden: false,
lineCap: undefined,
lineDash: undefined,
lineDashOffset: undefined,
lineJoin: undefined,
lineWidth: 5,
strokeStyle: 'red',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 0
}]);
});
it('should use the value for the first item when the property is a function', function() {
var helpers = window.Chart.helpers;
var chart = window.acquireChart({
type: 'bar',
data: {
datasets: [{
label: 'dataset1',
backgroundColor: function(ctx) {
var value = ctx.dataset.data[ctx.dataIndex] || 0;
return helpers.color({r: value * 10, g: 0, b: 0}).rgbString();
},
borderWidth: function(ctx) {
var value = ctx.dataset.data[ctx.dataIndex] || 0;
return value;
},
borderColor: function(ctx) {
var value = ctx.dataset.data[ctx.dataIndex] || 0;
return helpers.color({r: 255 - value * 10, g: 0, b: 0}).rgbString();
},
data: [5, 10, 15, 20]
}],
labels: ['A', 'B', 'C', 'D']
}
});
expect(chart.legend.legendItems).toEqual([{
text: 'dataset1',
fillStyle: 'rgb(50, 0, 0)',
hidden: false,
lineCap: undefined,
lineDash: undefined,
lineDashOffset: undefined,
lineJoin: undefined,
lineWidth: 5,
strokeStyle: 'rgb(205, 0, 0)',
pointStyle: undefined,
rotation: undefined,
datasetIndex: 0
}]);
});
it('should draw correctly when usePointStyle is true', function() {
var chart = window.acquireChart({
type: 'line',
data: {
datasets: [{
label: 'dataset1',
backgroundColor: '#f31',
borderCapStyle: 'butt',
borderDash: [2, 2],
borderDashOffset: 5.5,
borderWidth: 0,
borderColor: '#f31',
pointStyle: 'crossRot',
pointBackgroundColor: 'rgba(0,0,0,0.1)',
pointBorderWidth: 5,
pointBorderColor: 'green',
data: []
}, {
label: 'dataset2',
backgroundColor: '#f31',
borderJoinStyle: 'miter',
borderWidth: 2,
borderColor: '#f31',
pointStyle: 'crossRot',
pointRotation: 15,
data: []
}],
labels: []
},
options: {
legend: {
labels: {
usePointStyle: true
}
}
}
});
expect(chart.legend.legendItems).toEqual([{
text: 'dataset1',
fillStyle: 'rgba(0,0,0,0.1)',
hidden: false,
lineCap: undefined,
lineDash: undefined,
lineDashOffset: undefined,
lineJoin: undefined,
lineWidth: 5,
strokeStyle: 'green',
pointStyle: 'crossRot',
rotation: undefined,
datasetIndex: 0
}, {
text: 'dataset2',
fillStyle: '#f31',
hidden: false,
lineCap: undefined,
lineDash: undefined,
lineDashOffset: undefined,
lineJoin: undefined,
lineWidth: 2,
strokeStyle: '#f31',
pointStyle: 'crossRot',
rotation: 15,
datasetIndex: 1
}]);
});
describe('config update', function() {
it ('should update the options', function() {
var chart = acquireChart({