可以隐藏其中某部分(点击对应图例,然后该图例就被一条折线覆盖了,饼图对应部分也被隐藏,当然百分比也随之改变)
也可以隐藏多个部分
下面看看代码部分:
(背景:项目采用react+typescript)
首先你需要下载react-chartjs-2 和chartjs
npm install --save react-chartjs-2 chart.js
(使用时只要传入对应的alarms数组即可:下面是API)
export interface IAlarmDetail {
/** Description of the event */
description: string;
/** Total number of cases */
total: number;
/** Number of radio, the unit is 1.0 = 100% */
ratio: number;
}
这个是对应的Piechart组件
import * as React from "react";
import {IAlarmDetail} from "./providers/IAlarmDetail";
import {Pie} from "react-chartjs-2";
import {ChartType, TooltipItem} from "chart.js";
export interface IPieChartProps {
/** List of alarm's information */
alarms: IAlarmDetail[];
}
export class PieChart extends React.Component<IPieChartProps> {
constructor(props: IPieChartProps) {
super(props);
this.drawPieChartOfBlockingAlarms = this.drawPieChartOfBlockingAlarms.bind(this);
}
public render() {
return this.props.alarms.length === 0 ? null : this.drawPieChartOfBlockingAlarms();
}
/** each part of pie chart have unique color, total 30 color supported. */
private getColorArr(): string[] {
return [
"#ccccff",
"#aaaaaa",
"#ff8888",
"#ffbb66",
"#ddff77",
"#aaffee",
"#9999ff",
"#888888",
"#ff7744",
"#ff8800",
"#99dd00",
"#00ff99",
"#9955ff",
"#666666",
"#ff5511",
"#ee7700",
"#88aa00",
"#00dd77",
"#f0bbff",
"#dddddd",
"#ffc8b4",
"#ffddaa",
"#eeffbb",
"#00dddd",
"#e38eff",
"#444444",
"#e63f00",
"#cc6600",
"#eeee00",
"#00aa88",
];
}
/** add label of percentage
* @param alarms `IAlarmDetail[]` displaying data list
*/
private addLabel(tooltipItem: TooltipItem<ChartType>, alarms: IAlarmDetail[]) {
const currentIndex = tooltipItem.dataIndex;
/** display locale format, more detail you can see
*[intl -MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) */
return new Intl.NumberFormat(undefined, {style: "percent", maximumFractionDigits: 2}).format(
alarms[currentIndex].ratio
);
}
/**
* configure the options of pie chart
* more detail you can see [Configuration of chart.js](https://www.chartjs.org/docs/latest/configuration/)
* @param alarms `IAlarmDetail[]` displaying data list
*/
private getOptions(alarms: IAlarmDetail[]) {
return {
plugins: {
/** configuration for legend, more detail you can see
* [legend of chart](https://www.chartjs.org/docs/latest/configuration/legend.html)*/
legend: {
display: true,
position: "top",
labels: {
boxWidth: 20,
},
},
/**more detail you can see
* [tooltip-callbacks](https://www.chartjs.org/docs/latest/configuration/tooltip.html#tooltip-callbacks) */
tooltip: {
callbacks: {
afterLabel: (tooltipItem: TooltipItem<ChartType>) => this.addLabel(tooltipItem, alarms),
},
},
},
};
}
/**
* * draw pie chart of blocking alarms by [react-chartjs-2](https://github.com/jerairrest/react-chartjs-2)
* * the configuration you can see [chartjs](https://www.chartjs.org/docs/latest/)
*/
private drawPieChartOfBlockingAlarms() {
const {alarms} = this.props;
const colorArr = this.getColorArr();
const dataArr: string[] = [];
const labels: string[] = [];
const backgroundColorArr: string[] = [];
alarms.forEach((e: IAlarmDetail, index) => {
// use local string
dataArr.push(e.total.toLocaleString());
labels.push(e.description);
backgroundColorArr.push(colorArr[index]);
});
const options = this.getOptions(alarms);
/**
* more detail you can see
* [Dataset Properties](https://www.chartjs.org/docs/latest/charts/doughnut.html#pie)
*/
const dataObj = {
datasets: [
{
data: dataArr,
backgroundColor: backgroundColorArr,
hoverOffset: 6,
},
],
// These labels appear in the legend and in the tooltips when hovering different arcs
labels,
};
return <Pie type="pie" data={dataObj} options={options} />;
}
}
目前支持30种颜色,并且饼图的宽高会随着数据数量的增加而增加。
那么我们看下如何调用
//render 中
// custom defined calculation method, which can be modified if needed
const num = 70 * Math.ceil(alarms.length / 5);
const height = 300 + num;
//这个是当你子项百分比之和不够100%才调用这个getNewAlarmsList,如果够的话,直接把你的 //alarms传进去
const newAlarms = this.getNewAlarmsList(alarms);
<div style={{height, width: height}}>
<PieChart alarms={newAlarms} />
</div>
//下面这个方法是当alarm的item百分比之和不足100%的时候,添加一个others项, 如果你的数据中item百//分比加起来100%,就不需要这个方法了
/**
* when sum of ratio of each item not equal 100%, use 'others' item represent remain number
* if sum of ratio equal 100%, do nothing
* @param alarms : `IAlarmDetail[]` initial alarms array
* @returns new alarms array
*/
private getNewAlarmsList(alarms: IAlarmDetail[]) {
if (alarms.length === 0) return [];
const newAlarms = [...alarms];
// get sum
let sum = 0;
sum = alarms.reduce((prev, next) => prev + next.total, 0);
const _totalSum = Number(sum.toFixed());
// calculate the sum.
const calculatedSum = Number((alarms[0].total / alarms[0].ratio).toFixed());
// if sum not equal calculated sum, add `others` group item
if (calculatedSum !== _totalSum) {
// other number equal calculated sum minus sum
const othersNum = calculatedSum - _totalSum;
const others: IAlarmDetail = {
description: "others",
ratio: othersNum / calculatedSum,
total: othersNum,
};
newAlarms.push(others);
}
return newAlarms;
}
这样就可以了,当然, alarms的值是根据你自己项目的内容来的
下面是我的案例数据
public getAlarms() {
const descriptions = [
"Downstream Jam",
"Indexor stop",
"Black image",
"Emergency stop",
"Temperature",
"Reject control error",
];
const totals = [176, 298, 305, 84, 66, 50];
const percentages = [0.176, 0.298, 0.305, 0.084, 0.066, 0.05];
return descriptions.map<IAlarmDetail>((alarm, index) => ({
description: alarm,
total: totals[index],
ratio: percentages[index],
}));
}
这里注意一下,百分比加起来是不等于1的,剩下的用others来表示
下面贴上参考网址: