/** @format */ // import 'echarts/lib/chart/line'; // import 'echarts/lib/chart/pie'; // import 'echarts/lib/chart/gauge'; import 'echarts/lib/chart/bar'; import 'echarts/lib/component/tooltip'; // import 'echarts/lib/component/toolbox'; import 'echarts/lib/component/title'; import 'echarts/lib/component/legend'; import 'echarts/lib/component/grid'; import echarts from 'echarts/lib/echarts'; import _ from 'lodash'; import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { globalTheme, ThemeData } from '../../../utils/theme'; interface BasicBarCrosswiseChartProps { /** * 容器大小 */ size?: { width: number; height: number }; /** * 配置项 */ option?: Record; /** * 数据源,统一为数组格式 */ data?: Record; /** * 主题色配置 */ theme?: ThemeData; } const BasicBarCrosswiseChart = (props: BasicBarCrosswiseChartProps) => { const { size = { height: 500 }, option = {}, data, data: { yData = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'], xData = [[18203, 23489, 29034, 104970, 131744, 630230]], } = {}, theme = { /** * 文本颜色 */ textColor: 'red', /** * 组件主色 */ primaryColor: '#50E1', secondColor: '#FDAFFF', thirdColor: '#DDD', colorList: ['#50E1', '#FDA568', '#DDD'], }, } = props; const wrapperRef = useRef(null); const [echartsInc, setEchartsInc] = useState | null>( null, ); const themeList = theme ? theme : globalTheme; function formatSeries(data: Record, index: number, op = {}) { // series 模板 const series = (option && option.series && option.series[index]) || {}; const baseSeries = { name: series.name || `系列${index + 1}`, type: series.type || `bar`, data: data, itemStyle: series.itemStyle, smooth: false, barCategoryGap: series.barCategoryGap || null, label: series.label, stack: series.stack ? series.stack : '', }; const latestSeries = _.mergeWith(baseSeries, op); latestSeries.data = data; return latestSeries; } const optionBase = { color: [...themeList.colorList], tooltip: { show: true, trigger: 'axis', triggerOn: 'mousemove', axisPointer: { // 坐标轴指示器,坐标轴触发有效 type: 'shadow', // 默认为直线,可选为:'line' | 'shadow' }, hideDelay: 100, textStyle: { fontFamily: 'Microsoft Yahei', fontWeight: 'normal', fontSize: 14, color: themeList.textColor, }, }, legend: { show: true, padding: 2, itemGap: 5, itemWidth: 6, icon: 'rect', itemHeight: 6, left: 'right', orient: 'horizontal', textStyle: { fontFamily: 'Microsoft Yahei', fontWeight: 'normal', fontSize: 12, color: '#999', }, }, grid: { left: 30, right: 40, bottom: 30, top: 30, containLabel: true, }, xAxis: { type: 'value', show: true, name: '', axisTick: { alignWithLabel: true, show: false, }, nameTextStyle: {}, axisLabel: { show: true, color: themeList.textColor, fontWeight: 'normal', fontFamily: 'Microsoft YaHei', fontSize: 12, rotate: 0, interval: 0, }, axisLine: { show: false, lineStyle: { color: '#333' }, }, splitLine: { show: false, lineStyle: { color: '#999', type: 'dashed' }, }, }, yAxis: { type: 'category', min: 0, max: 'dataMax', axisTick: { show: false, }, data: yData, axisLabel: { show: true, color: '#999', fontWeight: 'normal', fontFamily: 'Microsoft YaHei', fontSize: 12, interval: 'auto', formatter: '{value}', }, axisLine: { show: false, lineStyle: { color: '#333' }, }, splitLine: { show: false, lineStyle: { color: '#aaa', type: 'dashed' }, }, }, series: [], animation: true, animationEasing: 'cubicOut', animationEasingUpdate: 'cubicOut', animationDuration: 500, animationDurationUpdate: 300, }; useLayoutEffect(() => { if (wrapperRef && wrapperRef.current) { const myChart = echarts.init(wrapperRef.current, null, { devicePixelRatio: 2, }); setEchartsInc(myChart); const latestOption = _.mergeWith(optionBase, option); latestOption.series = xData.map( (item: Record[], index: number) => formatSeries(item, index, option.series && option.series[index]), ); myChart.setOption(latestOption); } }, []); useEffect(() => { if (!echartsInc) { return; } const latestOption = _.mergeWith(optionBase, option); latestOption.series = xData.map( (item: Record[], index: number) => formatSeries(item, index, option.series && option.series[index]), ); echartsInc.setOption(latestOption, { notMerge: true }); }, [theme.primaryColor, option, data]); useEffect(() => { if (!echartsInc) { return; } echartsInc.resize(); }, [size]); return
; }; export default BasicBarCrosswiseChart;