292 lines
6.9 KiB
JavaScript
292 lines
6.9 KiB
JavaScript
'use strict';
|
|
|
|
var DatasetController = require('../core/core.datasetController');
|
|
var defaults = require('../core/core.defaults');
|
|
var elements = require('../elements/index');
|
|
var helpers = require('../helpers/index');
|
|
|
|
var resolve = helpers.options.resolve;
|
|
|
|
defaults._set('polarArea', {
|
|
scale: {
|
|
type: 'radialLinear',
|
|
angleLines: {
|
|
display: false
|
|
},
|
|
gridLines: {
|
|
circular: true
|
|
},
|
|
pointLabels: {
|
|
display: false
|
|
},
|
|
ticks: {
|
|
beginAtZero: true
|
|
}
|
|
},
|
|
|
|
// Boolean - Whether to animate the rotation of the chart
|
|
animation: {
|
|
animateRotate: true,
|
|
animateScale: true
|
|
},
|
|
|
|
startAngle: -0.5 * Math.PI,
|
|
legendCallback: function(chart) {
|
|
var list = document.createElement('ul');
|
|
var data = chart.data;
|
|
var datasets = data.datasets;
|
|
var labels = data.labels;
|
|
var i, ilen, listItem, listItemSpan;
|
|
|
|
list.setAttribute('class', chart.id + '-legend');
|
|
if (datasets.length) {
|
|
for (i = 0, ilen = datasets[0].data.length; i < ilen; ++i) {
|
|
listItem = list.appendChild(document.createElement('li'));
|
|
listItemSpan = listItem.appendChild(document.createElement('span'));
|
|
listItemSpan.style.backgroundColor = datasets[0].backgroundColor[i];
|
|
if (labels[i]) {
|
|
listItem.appendChild(document.createTextNode(labels[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
return list.outerHTML;
|
|
},
|
|
legend: {
|
|
labels: {
|
|
generateLabels: function(chart) {
|
|
var data = chart.data;
|
|
if (data.labels.length && data.datasets.length) {
|
|
return data.labels.map(function(label, i) {
|
|
var meta = chart.getDatasetMeta(0);
|
|
var style = meta.controller.getStyle(i);
|
|
|
|
return {
|
|
text: label,
|
|
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
|
|
};
|
|
});
|
|
}
|
|
return [];
|
|
}
|
|
},
|
|
|
|
onClick: function(e, legendItem) {
|
|
var index = legendItem.index;
|
|
var chart = this.chart;
|
|
var i, ilen, meta;
|
|
|
|
for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
|
|
meta = chart.getDatasetMeta(i);
|
|
meta.data[index].hidden = !meta.data[index].hidden;
|
|
}
|
|
|
|
chart.update();
|
|
}
|
|
},
|
|
|
|
// Need to override these to give a nice default
|
|
tooltips: {
|
|
callbacks: {
|
|
title: function() {
|
|
return '';
|
|
},
|
|
label: function(item, data) {
|
|
return data.labels[item.index] + ': ' + item.yLabel;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
module.exports = DatasetController.extend({
|
|
|
|
dataElementType: elements.Arc,
|
|
|
|
linkScales: helpers.noop,
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
_dataElementOptions: [
|
|
'backgroundColor',
|
|
'borderColor',
|
|
'borderWidth',
|
|
'borderAlign',
|
|
'hoverBackgroundColor',
|
|
'hoverBorderColor',
|
|
'hoverBorderWidth',
|
|
],
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
_getIndexScaleId: function() {
|
|
return this.chart.scale.id;
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
_getValueScaleId: function() {
|
|
return this.chart.scale.id;
|
|
},
|
|
|
|
update: function(reset) {
|
|
var me = this;
|
|
var dataset = me.getDataset();
|
|
var meta = me.getMeta();
|
|
var start = me.chart.options.startAngle || 0;
|
|
var starts = me._starts = [];
|
|
var angles = me._angles = [];
|
|
var arcs = meta.data;
|
|
var i, ilen, angle;
|
|
|
|
me._updateRadius();
|
|
|
|
meta.count = me.countVisibleElements();
|
|
|
|
for (i = 0, ilen = dataset.data.length; i < ilen; i++) {
|
|
starts[i] = start;
|
|
angle = me._computeAngle(i);
|
|
angles[i] = angle;
|
|
start += angle;
|
|
}
|
|
|
|
for (i = 0, ilen = arcs.length; i < ilen; ++i) {
|
|
arcs[i]._options = me._resolveDataElementOptions(arcs[i], i);
|
|
me.updateElement(arcs[i], i, reset);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
_updateRadius: function() {
|
|
var me = this;
|
|
var chart = me.chart;
|
|
var chartArea = chart.chartArea;
|
|
var opts = chart.options;
|
|
var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
|
|
|
|
chart.outerRadius = Math.max(minSize / 2, 0);
|
|
chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
|
|
chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
|
|
|
|
me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index);
|
|
me.innerRadius = me.outerRadius - chart.radiusLength;
|
|
},
|
|
|
|
updateElement: function(arc, index, reset) {
|
|
var me = this;
|
|
var chart = me.chart;
|
|
var dataset = me.getDataset();
|
|
var opts = chart.options;
|
|
var animationOpts = opts.animation;
|
|
var scale = chart.scale;
|
|
var labels = chart.data.labels;
|
|
|
|
var centerX = scale.xCenter;
|
|
var centerY = scale.yCenter;
|
|
|
|
// var negHalfPI = -0.5 * Math.PI;
|
|
var datasetStartAngle = opts.startAngle;
|
|
var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
|
|
var startAngle = me._starts[index];
|
|
var endAngle = startAngle + (arc.hidden ? 0 : me._angles[index]);
|
|
|
|
var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
|
|
var options = arc._options || {};
|
|
|
|
helpers.extend(arc, {
|
|
// Utility
|
|
_datasetIndex: me.index,
|
|
_index: index,
|
|
_scale: scale,
|
|
|
|
// Desired view properties
|
|
_model: {
|
|
backgroundColor: options.backgroundColor,
|
|
borderColor: options.borderColor,
|
|
borderWidth: options.borderWidth,
|
|
borderAlign: options.borderAlign,
|
|
x: centerX,
|
|
y: centerY,
|
|
innerRadius: 0,
|
|
outerRadius: reset ? resetRadius : distance,
|
|
startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle,
|
|
endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle,
|
|
label: helpers.valueAtIndexOrDefault(labels, index, labels[index])
|
|
}
|
|
});
|
|
|
|
arc.pivot();
|
|
},
|
|
|
|
countVisibleElements: function() {
|
|
var dataset = this.getDataset();
|
|
var meta = this.getMeta();
|
|
var count = 0;
|
|
|
|
helpers.each(meta.data, function(element, index) {
|
|
if (!isNaN(dataset.data[index]) && !element.hidden) {
|
|
count++;
|
|
}
|
|
});
|
|
|
|
return count;
|
|
},
|
|
|
|
/**
|
|
* @protected
|
|
*/
|
|
setHoverStyle: function(arc) {
|
|
var model = arc._model;
|
|
var options = arc._options;
|
|
var getHoverColor = helpers.getHoverColor;
|
|
var valueOrDefault = helpers.valueOrDefault;
|
|
|
|
arc.$previousStyle = {
|
|
backgroundColor: model.backgroundColor,
|
|
borderColor: model.borderColor,
|
|
borderWidth: model.borderWidth,
|
|
};
|
|
|
|
model.backgroundColor = valueOrDefault(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));
|
|
model.borderColor = valueOrDefault(options.hoverBorderColor, getHoverColor(options.borderColor));
|
|
model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth);
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
_computeAngle: function(index) {
|
|
var me = this;
|
|
var count = this.getMeta().count;
|
|
var dataset = me.getDataset();
|
|
var meta = me.getMeta();
|
|
|
|
if (isNaN(dataset.data[index]) || meta.data[index].hidden) {
|
|
return 0;
|
|
}
|
|
|
|
// Scriptable options
|
|
var context = {
|
|
chart: me.chart,
|
|
dataIndex: index,
|
|
dataset: dataset,
|
|
datasetIndex: me.index
|
|
};
|
|
|
|
return resolve([
|
|
me.chart.options.elements.arc.angle,
|
|
(2 * Math.PI) / count
|
|
], context, index);
|
|
}
|
|
});
|