Files
Chart.js/src/controllers/controller.polarArea.js
Evert Timberg 3934935caa Enable pointStyle for doughnut, pie, and polar area charts (#9341)
* Enable pointStyle for doughnut, pie, and polar area charts

* Fix whitespace
2021-07-01 14:15:06 -04:00

217 lines
5.3 KiB
JavaScript

import DatasetController from '../core/core.datasetController';
import {toRadians, PI} from '../helpers/index';
import {formatNumber} from '../helpers/helpers.intl';
export default class PolarAreaController extends DatasetController {
constructor(chart, datasetIndex) {
super(chart, datasetIndex);
this.innerRadius = undefined;
this.outerRadius = undefined;
}
getLabelAndValue(index) {
const me = this;
const meta = me._cachedMeta;
const chart = me.chart;
const labels = chart.data.labels || [];
const value = formatNumber(meta._parsed[index].r, chart.options.locale);
return {
label: labels[index] || '',
value,
};
}
update(mode) {
const arcs = this._cachedMeta.data;
this._updateRadius();
this.updateElements(arcs, 0, arcs.length, mode);
}
/**
* @private
*/
_updateRadius() {
const me = this;
const chart = me.chart;
const chartArea = chart.chartArea;
const opts = chart.options;
const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
const outerRadius = Math.max(minSize / 2, 0);
const innerRadius = Math.max(opts.cutoutPercentage ? (outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount();
me.outerRadius = outerRadius - (radiusLength * me.index);
me.innerRadius = me.outerRadius - radiusLength;
}
updateElements(arcs, start, count, mode) {
const me = this;
const reset = mode === 'reset';
const chart = me.chart;
const dataset = me.getDataset();
const opts = chart.options;
const animationOpts = opts.animation;
const scale = me._cachedMeta.rScale;
const centerX = scale.xCenter;
const centerY = scale.yCenter;
const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * PI;
let angle = datasetStartAngle;
let i;
const defaultAngle = 360 / me.countVisibleElements();
for (i = 0; i < start; ++i) {
angle += me._computeAngle(i, mode, defaultAngle);
}
for (i = start; i < start + count; i++) {
const arc = arcs[i];
let startAngle = angle;
let endAngle = angle + me._computeAngle(i, mode, defaultAngle);
let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(dataset.data[i]) : 0;
angle = endAngle;
if (reset) {
if (animationOpts.animateScale) {
outerRadius = 0;
}
if (animationOpts.animateRotate) {
startAngle = endAngle = datasetStartAngle;
}
}
const properties = {
x: centerX,
y: centerY,
innerRadius: 0,
outerRadius,
startAngle,
endAngle,
options: me.resolveDataElementOptions(i, arc.active ? 'active' : mode)
};
me.updateElement(arc, i, properties, mode);
}
}
countVisibleElements() {
const dataset = this.getDataset();
const meta = this._cachedMeta;
let count = 0;
meta.data.forEach((element, index) => {
if (!isNaN(dataset.data[index]) && this.chart.getDataVisibility(index)) {
count++;
}
});
return count;
}
/**
* @private
*/
_computeAngle(index, mode, defaultAngle) {
return this.chart.getDataVisibility(index)
? toRadians(this.resolveDataElementOptions(index, mode).angle || defaultAngle)
: 0;
}
}
PolarAreaController.id = 'polarArea';
/**
* @type {any}
*/
PolarAreaController.defaults = {
dataElementType: 'arc',
animation: {
animateRotate: true,
animateScale: true
},
animations: {
numbers: {
type: 'number',
properties: ['x', 'y', 'startAngle', 'endAngle', 'innerRadius', 'outerRadius']
},
},
indexAxis: 'r',
startAngle: 0,
};
/**
* @type {any}
*/
PolarAreaController.overrides = {
aspectRatio: 1,
plugins: {
legend: {
labels: {
generateLabels(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
const {labels: {pointStyle}} = chart.legend.options;
return data.labels.map((label, i) => {
const meta = chart.getDatasetMeta(0);
const style = meta.controller.getStyle(i);
return {
text: label,
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
pointStyle: pointStyle,
hidden: !chart.getDataVisibility(i),
// Extra data used for toggling the correct item
index: i
};
});
}
return [];
}
},
onClick(e, legendItem, legend) {
legend.chart.toggleDataVisibility(legendItem.index);
legend.chart.update();
}
},
// Need to override these to give a nice default
tooltip: {
callbacks: {
title() {
return '';
},
label(context) {
return context.chart.data.labels[context.dataIndex] + ': ' + context.formattedValue;
}
}
}
},
scales: {
r: {
type: 'radialLinear',
angleLines: {
display: false
},
beginAtZero: true,
grid: {
circular: true
},
pointLabels: {
display: false
},
startAngle: 0
}
}
};