react-chartjs-2+chart.js画饼状图

 可以隐藏其中某部分(点击对应图例,然后该图例就被一条折线覆盖了,饼图对应部分也被隐藏,当然百分比也随之改变)

也可以隐藏多个部分

下面看看代码部分:

(背景:项目采用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来表示

下面贴上参考网址:

https://github.com/jerairrest/react-chartjs-2

https://www.chartjs.org/docs/latest/charts/doughnut.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值