最近、プロジェクトでEChartsを使用してグラフを作成し始めましたが、React + AntdでEChartを使用する際に多くの落とし穴に遭遇しました。ソリューションを記録することで、すべての人に役立つことを願っています。初めて使用するため、コードを最適化する余地がたくさんあります。皆さんが私を助けてくれることを願っています。ありがとう〜
最終効果
1.折れ線グラフ上の点をクリックして、2つの円グラフデータのリンクを実現します
。2。ECharts円グラフデータが0であるか、円グラフが空になると消えるという問題に対処します。
ReactでEChartsを使用する方法
1.レンダーにdivを追加します
<div id='echartLine' style={
{
width: '100%', height: 300, margin: '24px 0' }} />
<div id='pieTotal' style={
{
width: '100%', height: 300, margin: '24px 0' }} />
<div id='pieReject' style={
{
width: '100%', height: 300, margin: '24px 0' }} />
2.EChartsチャートを初期化します
// 饼图初始option
const initPieOption = {
// tooltip: {
// show: false,
// },
dataset: {
dimensions: ['desc', 'type', 'value'],
source: [{
desc: '', type: '', value: 1 }], // 当无数据时,给饼图个初始数据
},
grid: {
left: '3%',
right: '3%',
bottom: '0%',
containLabel: true,
},
series: [
{
type: 'pie',
radius: ['75%', '45%'],
stillShowZeroSum: false,
itemStyle: {
color: '#e7e7e7',
},
label: {
normal: {
show: true,
position: 'center',
formatter: function () {
var result = ''
result = '暂无数据'
return result
},
textStyle: {
fontSize: 16,
color: '#e2e2e2',
},
},
},
},
],
}
// 初始化图表
initChart = () => {
// const { trendList } = this.state
// 折线图
var lineChart = echarts.init(document.getElementById('echartLine'))
// 建议将ECharts图表实例进行储存,而不是每次数据变化都进行实例初始化
this.setState({
lineChart })
lineChart.setOption({
title: {
text: '趋势',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
},
legend: {
formatter: function (name) {
switch (name) {
case 'total':
return '总量 ' + name
case 'passCount':
return '通过量 ' + name
case 'rejectCount':
return '拒绝量 ' + name
}
},
},
dataset: {
// 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。
// 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。
dimensions: ['date', 'total', 'passCount', 'rejectCount'],
source: [],
},
xAxis: {
type: 'category' },
yAxis: {
type: 'value',
},
grid: {
left: '3%',
right: '6%',
bottom: '0%',
containLabel: true,
},
series: [
{
type: 'line' },
{
type: 'line' },
{
type: 'line' },
],
})
// 饼图总量
var pieChartTotal = echarts.init(document.getElementById('pieTotal'))
this.setState({
pieChartTotal })
// 饼图拒绝量
var pieChartReject = echarts.init(document.getElementById('pieReject'))
this.setState({
pieChartReject })
// 使图表自适应div大小,防止图表溢出
window.addEventListener('resize', function () {
lineChart.resize()
pieChartTotal.resize()
pieChartReject.resize()
})
}
3.データが変更されたら、グラフを再レンダリングします
// 获取趋势图
fetchBaseTrend = async () => {
const res = await api.getBaseTrend()
this.setState({
trendList: res,
}, () => {
// 获取到数据后再去调用渲染图表函数
this.generateChart()
})
}
generateChart = () => {
const {
trendList, lineChart, pieChartTotal, pieChartReject } = this.state
lineChart.setOption({
dataset: {
// 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。
// 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。
dimensions: ['date', 'total', 'passCount', 'rejectCount'],
source: trendList,
},
})
// 由于我对饼图无数据做了处理,所以每次setOption之前都要先执行clear(),防止之前setOption内的灰色背景属性仍生效
pieChartTotal.clear()
pieChartReject.clear()
// 默认用数据加载第一条渲染饼图,可能存在无数据情况,因此需要判断
pieChartTotal.setOption(trendList[0] && !!trendList[0].totalRatio.length ? this.PieOption('total') : initPieOption)
pieChartReject.setOption(trendList[0] && !!trendList[0].rejectRatio.length ? this.PieOption('reject') : initPieOption)
}
4.折れ線グラフをクリックして円グラフをレンダリングする方法
コードのこの部分を最適化する余地はたくさんありますが、私は長い間それを変更していて、より良い方法を見つけられませんでした。皆さんがコメントを手伝ってくれることを願っています。ありがとう〜
generateChart = () => {
lineChart.on('click', function (event) {
pieChartTotal.clear()
pieChartTotal.setOption(event.data && !!event.data.totalRatio.length ? {
dataset: {
// 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。
// 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。
dimensions: ['desc', 'type', 'value'],
source: event.data && event.data.totalRatio,
},
legend: {
orient: 'vertical',
left: 70,
},
tooltip: {
trigger: 'item',
formatter: function (params) {
var result = ''
result = params.name + ' : ' + params.data.value + ' ( ' + params.percent + '% )'
return result
},
},
series: [
{
type: 'pie',
radius: ['75%', '50%'],
label: {
normal: {
show: true,
position: 'center',
color: '#4c4a4a',
formatter: function (data) {
var result = ''
result = event.name + '\n' + '总量' + ' ' + event.data.total
return result
},
textStyle: {
fontSize: 16,
color: '#00c0ef',
},
},
},
},
],
} : initPieOption)
pieChartReject.clear()
pieChartReject.setOption(event.data.rejectRatio && !!event.data.rejectRatio.length ? {
dataset: {
// 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。
// 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。
dimensions: ['desc', 'type', 'value'],
source: event.data && event.data.rejectRatio,
},
legend: {
orient: 'vertical',
right: 70,
},
series: [
{
type: 'pie',
radius: ['75%', '45%'],
label: {
normal: {
show: true,
position: 'center',
color: '#4c4a4a',
formatter: function (data) {
var result = ''
result = event.name + '\n' + '拒绝量' + ' ' + event.data.rejectCount
return result
},
textStyle: {
fontSize: 16,
color: '#00c0ef',
},
},
},
},
],
} : initPieOption)
})
}
4.TrendListデータ構造
[{
"date": "2020-03-23",
"total": 52,
"passCount": 51,
"rejectCount": 1,
"totalRatio": [{
"type": "text",
"desc": "文本",
"value": 27
}, {
"type": "picture",
"desc": "图片",
"value": 25
}],
"rejectRatio": [{
"type": "picture",
"desc": "图片",
"value": 1
}]
}, {
"date": "2020-03-24",
"total": 25,
"passCount": 18,
"rejectCount": 7,
"totalRatio": [{
"type": "picture",
"desc": "图片",
"value": 15
}, {
"type": "text",
"desc": "文本",
"value": 10
}],
"rejectRatio": [{
"type": "picture",
"desc": "图片",
"value": 7
}]
}]
ECharts FAQ
問題:エラー:コンポーネントseries.pieが存在しません。最初にロードしてください。
理由:パイコンポーネントが導入されていません。
解決策:
import 'echarts/lib/chart/pie'
問題:ECharts3はnoDataLoadingOptionを削除します。データがない場合、コンテナーにデータが表示されません。切り替え後、グラフを表示できません。
解決策:
- データに値があるかどうかを判断し、値がない場合は処理します
- setOptionでインスタンスのオプションをクリアします
- EChartsインスタンスを抽出し、毎回作成しないでください
- 特定のコードは上記のコードブロックで見ることができます。よくわからない場合は、個人的に私に尋ねることができます
// 默认用数据加载第一条渲染饼图,可能存在无数据情况,因此需要判断
pieChartTotal.setOption(trendList[0] && !!trendList[0].totalRatio.length ? this.PieOption('total') : initPieOption)
問題:ラベルフォーマッター形式のコンテンツ、折り返す必要があります。
理由:ラベルはキャンバスに基づいており、htmlをサポートしておらず、折り返しのみをサポートしています\ n解決
:
formatter: function (data) {
var result = ''
result = event.name + '\n' + '总量' + ' ' + event.data.total
return result
},
問題:チャートがdivをオーバーフローし、適応的に解決できない
:
window.addEventListener('resize', function () {
lineChart.resize()
})
問題:クリックイベントが複数回バインドされ、コールバックが複数回トリガーされる原因になります
。
myChart.off('click')// 防止累计触发
myChart.on('click', function (event) {
const url = reportTypesMap[item.key]['url']
if (!url) return false
const href = window.location.href.split('#')[0]
window.open(`${
href}#${
url}?time=${
event.name}`)
})