import { CSSProperties } from 'react'; import * as echarts from 'echarts'; import { PieSeriesOption } from 'echarts'; import { useRef, useEffect } from 'react'; import { isEmpty, sumBy, head, merge, gt, gte, lte, ceil } from 'lodash'; import { CHARTS_COLORS, LOADING_COLOR } from './type'; import { useSize } from 'ahooks'; // 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型 type ECOption = echarts.ComposeOption; export interface PieProps { color?: Array; series: Array; loading?: boolean; smooth?: boolean; style?: CSSProperties; options?: ECOption; onDownCallBack?: any; loadingType?: any; } function getOptions(width: number) { if (gt(width, 1920)) { return { legend: { textStyle: { width: 140, fontSize: 14, overflow: 'truncate', }, }, radius: ['60%', '80%'], center: ['40%', '50%'], title: { left: '40%', }, }; } else if (gte(width, 1680)) { return { legend: { textStyle: { width: 120, fontSize: 12, overflow: 'truncate', }, }, radius: ['60%', '80%'], center: ['35%', '50%'], title: { left: '35%', }, }; } else if (gte(width, 1440)) { return { legend: { textStyle: { width: 100, fontSize: 10, overflow: 'truncate', }, }, radius: ['50%', '70%'], center: ['35%', '50%'], title: { left: '35%', }, }; } else if (lte(width, 1440)) { return { legend: { textStyle: { width: 80, fontSize: 8, overflow: 'truncate', }, }, radius: ['40%', '60%'], center: ['30%', '50%'], title: { left: '30%', }, }; } else { return { legend: { textStyle: { width: 100, fontSize: 10, overflow: 'truncate', }, }, radius: ['50%', '70%'], center: ['35%', '50%'], title: { left: '35%', }, }; } } export function ChartsPie(props: PieProps) { const { color = CHARTS_COLORS, series, loading, style, options, onDownCallBack, loadingType = { color: LOADING_COLOR }, } = props; const contentEle = useRef(); const chartRef = useRef(); const size = useSize(document.querySelector('body')); // @ts-ignore const sizeOptions = getOptions(size?.width); // @ts-ignore const legendShow = options?.legend?.show; const defaultOptions: ECOption = merge( { color: color, tooltip: { trigger: 'item', formatter: '{b}
数量: {c}
占比: {d}%', }, label: { formatter(params: { [key: string]: any }): any { return `${params?.name}: ${params?.percent ?? 0}%`; }, }, legend: { show: false, itemWidth: 10, itemHeight: 10, }, title: { text: ceil(sumBy(head(series)?.data, 'value'), 2) || 0, top: '47%', textAlign: 'center', left: '50%', textStyle: { color: '#333', fontSize: 22, fontWeight: '400', }, }, }, options, legendShow ? sizeOptions : {}, ); const responsive = useSize(contentEle.current); useEffect(() => { chartRef.current?.resize(); }, [JSON.stringify(responsive)]); useEffect(() => { if (!chartRef.current) { chartRef.current = echarts.init(contentEle.current); } if (loading) { chartRef.current.showLoading(Object.assign({ text: '' }, loadingType)); return; } else { chartRef.current.hideLoading(); } if (!isEmpty(series)) { chartRef.current.setOption({ ...defaultOptions, series: series.map((item) => ({ radius: sizeOptions.radius, center: legendShow ? sizeOptions.center : ['50%', '50%'], ...item, type: 'pie', })), }); if (onDownCallBack) { chartRef.current.on('click', function (params: any) { onDownCallBack(chartRef.current, params, options); }); } } }, [series, loading]); return (
); }