react函数式 父子组件传值+echarts百分比进度条
实现效果展示
这多个相同的图表是通过循环调用子组件传递不同的数据进行显示,图中显示一样的数据是接口返回的
父组件调用子组件传递数据
import React, { useEffect, useState } from 'react';
import Proportion from '../../components/echart/Proportion';
export default function Integrated() {
const [gross, setGross] = useState([]);
// 请求
useEffect(() => {
getSynthesize().then((res) => {
console.log(res);
// 小图表
setGross(icons(res.data));
})
}, []);
// 这部分将接口数据处理成数组,返回给gross数组,方便循环(可能觉得push更好,但是我觉得都得循环判断索性直接用switch语句了)
const icons = (info) => {
for (const key in info) {
switch (key) {
case 'h_one':
gross[0] = { id: '11', num: info[key].ok, sum: info[key].all, name: '视频监控' }
break;
case 'h_two':
gross[1] = { id: '22', num: info[key].ok, sum: info[key].all, name: '消防报警' }
break;
case 'h_three':
gross[2] = { id: '33', num: info[key].ok, sum: info[key].all, name: '门禁管理' }
break;
case 'h_four':
gross[3] = { id: '44', num: info[key].ok, sum: info[key].all, name: '入侵报警' }
break;
case 'h_five':
gross[4] = { id: '55', num: info[key].ok, sum: info[key].all, name: '动力环境' }
break;
case 'h_six':
gross[5] = { id: '66', num: info[key].ok, sum: info[key].all, name: '信息发布' }
break;
case 'h_seven':
gross[6] = { id: '77', num: info[key].ok, sum: info[key].all, name: '可视报警' }
break;
case 'h_eight':
gross[7] = { id: '88', num: info[key].ok, sum: info[key].all, name: '车辆查询' }
break;
default:
break;
}
}
return gross
}
//在这边进行一个循环输出并输出不同颜色
return (
<div className={styles.ratio}>
{
gross.map((item, Index) => (
<div key={item.id}>
<p>{item.name}</p>
{/* 子组件 */}
<Proportion gross={item} color={Index % 2 == 0 ? ['#16CEB9', '#022E44'] : ['#CFE8FC', '#2D71B8']} id={item.id} ></Proportion>
</div>
))
}
</div>
)
}
子组件接收父组件传递的值
import React, { useEffect, useState } from 'react';
import * as echarts from 'echarts';
export default function Proportion({ gross, color, id = '_' }) {
const [nan, setNan] = useState(false);
let myChart, option
useEffect(() => {
//由于在其它页面也进行调用所以要判断是否有传递id
let log = isNaN(Number(id));
setNan(log);
myChart = echarts.init(document.getElementById(`proportion${id}`));
option = {
title: [
{
text: gross.num + '/' + gross.sum,
x: 'center',
top: '48%',
textStyle: {
color: '#FFFFFF',
fontSize: 12,
fontWeight: '100',
},
},
{
text: Math.round((Number(gross.num) / Number(gross.sum)) * 100) + '%',
x: 'center',
top: '30%',
textStyle: {
fontSize: '15',
color: color[0],
fontFamily: 'DINAlternate-Bold, DINAlternate',
foontWeight: '600',
},
},
],
polar: {
radius: ['65%', '75%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
series: [
{
name: '',
type: 'bar',
roundCap: true,
barWidth: 20,
showBackground: true,
backgroundStyle: {
color: 'rgba(66, 66, 66, 0.3)',
},
data: [Math.round((Number(gross.num) / Number(gross.sum)) * 100)],
coordinateSystem: 'polar',
// emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: color[0],
},
{
offset: 1,
color: color[1],
},
]),
},
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['80%'],
center: ['50%', '50%'],
emphasis: { itemStyle: { scale: false, } },
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#0CD3DB',
},
data: [100],
},
],
};
if (nan) {
option.title = [];
option.title = [{
text: Math.round((Number(gross.num) / Number(gross.sum)) * 100) + '%',
x: 'center',
y: 'center',
textStyle: {
fontSize: '22',
color: color[0],
fontFamily: 'DINAlternate-Bold, DINAlternate',
foontWeight: '600',
},
}]
}
myChart.setOption(option);
return () => {
myChart.dispose();
}
}, [gross])
return (
<>
<div style={{ height: nan ? '100px' : "80px", width: nan ? '170px' : "80px" }} id={`proportion${id}`} ></div>
</>
)
}