当前位置: 首页 > 工具软件 > BizCharts > 使用案例 >

bizcharts图表封装之百分比堆叠面积图(可设置Slider)

郭博涉
2023-12-01

一、百分比堆叠面积图(可设置Slider)

需求:

        统计出x年下,人民年收入(收入:1万以下、1万-10万、10万-20万、20万以上)所占比例

要求:

       使用堆叠面积图;保留小数点后两位小数

遇到问题:

       后端接口返回x年各收入所占比例,四舍五入导致这些数据加起来后有时候会大于100% ,有时候会小于100%,而这又是合理的。小于100% 时,图表正常(异常的不太明显),但是若大于100%时,纵坐标会多出一个刻度,对应的grid也会多出一条。

      演示时,领导说,虽然数据上是合理的,但是看着太突兀了,想个办法让纵坐标看起来最大为100%。技术上可实现,设置maxLimit就行,此处不详说。

解决问题:

         使用百分比堆积柱状图,此时,后端不需要返回具体比例(百分比),只需要返回数量,至于占比、保留小数,统统交给组件,这样可以保证一组数据的百分比和是100%(最起码看起来是===》图表纵坐标最大值100%)
 

import React from "react";
import {Axis, Chart, Geom, Legend, Tooltip} from "bizcharts";
// @ts-ignore
import Slider from 'bizcharts-plugin-slider';
// @ts-ignore
import DataSet from '@antv/data-set';
import {dealSliderChange, filterSliderData} from "@/pages/charts/utils/chartsCommon";

interface IStackedPercentageAreaProps {
  data: any[]; // 数据源
  xAxis: string; // x轴坐标
  yAxis: string; // y轴坐标
  legendName: string; // 图例对应的变量(数据中表示种类的字段)
  color?: string[];
  height?: number;
  maxLen?: number;
}

/**
 * 百分比堆叠面积图(可设置滚动条)
 * @param props
 * @constructor
 */
const StackedPercentageArea: React.FC<IStackedPercentageAreaProps> = (props) => {
  const {height = 400, xAxis, yAxis, data, maxLen, color, legendName} = props;
  let flag: boolean = false;
  let ds = new DataSet();
  let rows=[];
  let dv = ds
    .createView()
    .source(data)
    .transform({
      type: "percent",
      field: yAxis,
      dimension:legendName ,
      groupBy: [xAxis],
      as: "percent"
    });
  // 获取数据中横坐标的个数,作为是否出现滚动条的依据;
  if (maxLen) {
    const xAxisData = [...new Set(data.map((item) => item[xAxis]))];
    // 设置一个flag,用来判断是否出现滚动条(以及是否需要处理数据)
    flag = xAxisData.length > maxLen;
    if (flag) {
      const startLength = 0;
      const endLength = maxLen - 1;
      /*
          此处处理区别于单条折线图
            初始化时,应取xAxisData中的第1个(index为0)作为start,取所能展示的最后一个(index为max-1)作为end
       */
      ds = new DataSet({
        state: {
          start: xAxisData[startLength],
          end: xAxisData[endLength],
        },
      });
      rows=dv.rows||[];
      dv = ds.createView()
        .source(data).transform({
          type: "percent",
          field: yAxis,
          // 统计销量
          dimension:legendName ,
          // 每年的占比
          groupBy: [xAxis],
          // 以不同产品类别为分组
          as: "percent"
        }).transform({
          type: 'filter',
          // eslint-disable-next-line consistent-return
          callback: (obj: any) => filterSliderData(flag, ds, data, obj, xAxis),
        });
    }
  }
  const cols = {
    percent: {
      min: 0,
      formatter(val:number) {
        // 保留两位小数
        return `${(val * 100).toFixed(2)  }%`;
      }
    }
  };
  cols[xAxis]={
    range: [0, 1]
  }
  return (
    <>
      <Chart height={height} data={dv} forceFit scale={cols}>
        <Axis name={xAxis} />
        <Axis name="percent" />
        <Legend />
        <Tooltip
        />
        <Geom type="areaStack"
              position={`${xAxis}*percent`}
              color={color ? [`${legendName}`, color] : legendName}
        />
        <Geom
          type="lineStack"
          position={`${xAxis}*percent`}
          size={2}
          color={color ? [`${legendName}`, color] : legendName}
        />
      </Chart>
      {
        flag && <Slider
            onChange={(obj: any) => dealSliderChange(obj, ds)}
            height={20}
            width="auto"
            xAxis={xAxis}
            yAxis="percent"
            data={rows}
            start={ds.state.start}
            end={ds.state.end}
            padding={[50]}
            textStyle={{
              fontSize: '0',
            }}
            backgroundChart={{
              type: 'heatmap',
            }}
        />
      }
    </>
  );
};

export default StackedPercentageArea;

二、使用

import React,{memo}  from 'react';
import StackedPercentageArea from "@/pages/charts/compnent/StackedPercentageArea";

import {maxLen} from "@/pages/charts/utils/chartsCommon";

const StackedPercentageAreaMemo=memo(StackedPercentageArea);

const stackedData= [
  {
    country: "Europe",
    year: "1750",
    value: 163
  },
  {
    country: "Europe",
    year: "1800",
    value: 203
  },
  {
    country: "Europe",
    year: "1850",
    value: 276
  },
  {
    country: "Europe",
    year: "1900",
    value: 408
  },
  {
    country: "Europe",
    year: "1950",
    value: 547
  },
  {
    country: "Europe",
    year: "1999",
    value: 729
  },
  {
    country: "Europe",
    year: "2050",
    value: 628
  },
  {
    country: "Europe",
    year: "2100",
    value: 828
  },
  {
    country: "Asia",
    year: "1750",
    value: 502
  },
  {
    country: "Asia",
    year: "1800",
    value: 635
  },
  {
    country: "Asia",
    year: "1850",
    value: 809
  },
  {
    country: "Asia",
    year: "1900",
    value: 947
  },
  {
    country: "Asia",
    year: "1950",
    value: 1402
  },
  {
    country: "Asia",
    year: "1999",
    value: 3634
  },
  {
    country: "Asia",
    year: "2050",
    value: 5268
  },
  {
    country: "Asia",
    year: "2100",
    value: 7268
  },
  {
    country: "Asia",
    year: "2200",
    value: 7568
  },
  {
    country: "Europe",
    year: "2200",
    value: 7568
  }
];
const ChartsIndex:React.FC<{}>=()=>{

  return(
    <div style={{background:'white'}}>
      <h1>bizCharts图表封装</h1>
      <h2>面积图-多-百分比堆叠面积图</h2>
      <StackedPercentageAreaMemo data={stackedData} xAxis="year" yAxis="value" legendName="country" maxLen={maxLen}/>
    </div>
  );
}
export default ChartsIndex;

三、涉及到的公共方法

    https://mp.csdn.net/console/editor/html/106548389

 类似资料: