正常来说,导致Echarts 图表不渲染的原因有以下几个:
(1)图表的data数据源不正确(无论是legend.data还是series.data的值,比如series数组里有一些值是null)
(2)图表的legend数组长度与series数组长度不一致
(3)图表的配置项不正确,如下配置是正确的:
const chartOption = {
tooltip: {
trigger: 'item',
confine: true,
formatter: '{b} : {c} ({d}%)',
backgroundColor: 'rgba(0, 0, 0, .7)',
textStyle: {
fontSize: 12,
},
},
legend: {
left: '30%',
top: 'center',
orient: 'vertical',
data: legend,
itemGap: 8,
itemWidth: 4, // 设置宽度
itemHeight: 4, // 设置高度
textStyle: {
fontSize: 12,
color: OAColor.lightText
},
},
series: {
name: '拜访统计',
type: 'pie',
radius: ['18%', '45%'],
center: ['17%', '37%'],
avoidLabelOverlap: false,
data: seriesData,
label: {
normal: {
show: false,
position: 'center'
},
},
labelLine: {
normal: {
show: false
}
},
}
};
(4)没有给图表一个高度和宽度(例如:flex: 1, width: '100%')
(5)图表库版本bug
下面举一个博主真实遇到且坑了我2天半的例子:
首页饼图:
错误❌代码:
// 渲染图表
_renderChart = () => {
let { chartData, total } = this.state;
const seriesData = chartData.map((item, index) => {
if (index < 5) {
if (!item.name) item.name = '其他'
return {
name: item.name,
value: item.count,
} // 问题就出在这里,使用map函数,并且if限制在5条记录以内,多余的统计归为‘其他’
// 由于数组chartData的长度length是大于5的,因此超出5以外的都会返回null,
// 这就直接导致了数据异常,图表无法渲染出来
}
});
let legend = chartData.map(item => item.name);
let otherTotal = 0;
chartData.forEach((item, index) => {
if (index >= 5)
otherTotal += item.count;
});
if (chartData.length > 5) {
seriesData.push({ name: '其他', value: otherTotal })
};
const chartOption = {
tooltip: {
trigger: 'item',
confine: true,
formatter: '{b} : {c} ({d}%)',
backgroundColor: 'rgba(0, 0, 0, .7)',
textStyle: {
fontSize: 12,
},
},
legend: {
left: '30%',
top: 'center',
orient: 'vertical',
data: legend,
itemGap: 8,
itemWidth: 4, // 设置宽度
itemHeight: 4, // 设置高度
textStyle: {
fontSize: 12,
color: OAColor.lightText
},
},
series: {
name: '拜访统计',
type: 'pie',
radius: ['18%', '45%'],
center: ['17%', '37%'],
avoidLabelOverlap: false,
data: seriesData,
label: {
normal: {
show: false,
position: 'center'
},
},
labelLine: {
normal: {
show: false
}
},
}
};
return <View style={styles.pieContainer}>
<Charts cellType='pie' chartOption={chartOption} chartHeight={150} />
<View style={{ flexDirection: 'row', position: 'absolute', right: '13%' }}>
<View style={{ flexDirection: 'column', paddingRight: 20 }}>
{
chartData ? chartData.map((item, index) => {
if (index < 5)
return <Text key={index} style={styles.vcount}>{item.count}</Text>
else if (index == 5)
return <Text key={index} style={styles.vcount}>{otherTotal}</Text>
}) : null
}
</View>
<View style={{ flexDirection: 'column' }}>
{
chartData ? chartData.map((item, index) => {
if (index < 5)
return <Text key={index} style={styles.vcount}>{this._computeRate(item.count, total)}</Text>
else if (index == 5)
return <Text key={index} style={styles.vcount}>{this._computeRate(otherTotal, total)}</Text>
}) : null
}
</View>
</View>
</View>
};
正确✅代码:
// 渲染图表
_renderChart = () => {
let { chartData, total } = this.state;
const arr = [];
chartData.forEach((item, index) => {
if (index < 5) {
if (!item.name) item.name = '其他'
arr.push({
name: item.name,
value: item.count,
})
}
});
const seriesData = arr;
let legend = chartData.map(item => item.name);
let otherTotal = 0;
chartData.forEach((item, index) => {
if (index >= 5)
otherTotal += item.count;
});
if (chartData.length > 5) {
seriesData.push({ name: '其他', value: otherTotal })
};
const chartOption = {
tooltip: {
trigger: 'item',
confine: true,
formatter: '{b} : {c} ({d}%)',
backgroundColor: 'rgba(0, 0, 0, .7)',
textStyle: {
fontSize: 12,
},
},
legend: {
left: '30%',
top: 'center',
orient: 'vertical',
data: legend,
itemGap: 8,
itemWidth: 4, // 设置宽度
itemHeight: 4, // 设置高度
textStyle: {
fontSize: 12,
color: OAColor.lightText
},
},
series: {
name: '拜访统计',
type: 'pie',
radius: ['18%', '45%'],
center: ['17%', '37%'],
avoidLabelOverlap: false,
data: seriesData,
label: {
normal: {
show: false,
position: 'center'
},
},
labelLine: {
normal: {
show: false
}
},
}
};
return <View style={styles.pieContainer}>
<Charts cellType='pie' chartOption={chartOption} chartHeight={150} />
<View style={{ flexDirection: 'row', position: 'absolute', right: '13%' }}>
<View style={{ flexDirection: 'column', paddingRight: 20 }}>
{
chartData ? chartData.map((item, index) => {
if (index < 5)
return <Text key={index} style={styles.vcount}>{item.count}</Text>
else if (index == 5)
return <Text key={index} style={styles.vcount}>{otherTotal}</Text>
}) : null
}
</View>
<View style={{ flexDirection: 'column' }}>
{
chartData ? chartData.map((item, index) => {
if (index < 5)
return <Text key={index} style={styles.vcount}>{this._computeRate(item.count, total)}</Text>
else if (index == 5)
return <Text key={index} style={styles.vcount}>{this._computeRate(otherTotal, total)}</Text>
}) : null
}
</View>
</View>
</View>
};