需求:点击图例,则选中该项,将其他项置灰;再次点击,恢复选中所有选项

做法:监听下legendselectchanged事件,用一个变量来保存上次点击的图例的名字,

  • 如果点击的图例名称和保存的一致,说明是再次点击,应该恢复所有选项,把所有图例都置为 true;
  • 如果点击的图例名称和保存的不一致,说明点击了另外的图例,这是需要更新变量,并且把这次点击的图例的selected设置为true,其他的设置为false。

坑点:如果在legendselectchanged里调用 echarts 的 dispatchActions,会陷入循环调用,如果还是想调用 dispatchActions方法,可参考这篇文章。我就直接调用setOption了。

监听 legendselectchanged 事件代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
onLegendSelectChanged = (e: {
name: string;
selected: { [k: string]: boolean };
}) => {
let selected = Object.assign({}, e.selected);
// 用一个变量来保存上次点击的图例的名字
// 如果新点击的图例名称和保存的一致,说明是再次点击,应该恢复所有选项,
// 就是把所有图例都置为true
if (this.clickedLegendName === e.name) {
this.clickedLegendName = '';
Object.keys(selected).forEach(key => {
selected[key] = true;
});
} else {
// 如果和保存的名称不一致,说明点击了另外的图例
// 更新clickedLegendName
// 把这次点击的图例的selected设置为true,其他的设置为false
this.clickedLegendName = e.name;
Object.keys(selected).forEach(key => {
if (key === e.name) {
selected[key] = true;
} else {
selected[key] = false;
}
});
}
// 重新调用 getEchartsOption
const option = this.getEchartsOption(selected);
// 重新调用 setOption
this.echartRef.setOption(option);
};




组件完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import React, { PureComponent } from 'react';
import _ from 'lodash';
import styled from 'styled-components';
import ReactEcharts from 'echarts-for-react';
import moment from 'moment';

const Root = styled.div``;

type ILineChartProps = {
className?: string;
style?: React.CSSProperties;
rawData: {
data: IRawChartDataItem[];
series: {
name: string;
data: number[];
type: 'line';
areaStyle: {};
}[];
};
loading: boolean;
};
type ILineChartState = {};

class LineChart extends PureComponent<ILineChartProps, ILineChartState> {
echartRef: any = null;
clickedLegendName: string;

getEchartsOption = (selected: { [k: string]: boolean } = {}) => {
const {
rawData: { data, series },
} = this.props;

const option = {
grid: {
top: 24,
bottom: 8,
left: 24,
right: 36,
containLabel: true,
},
legend: { data: series.map(item => item.name), selected },
tooltip: {
trigger: 'axis',
formatter(params: any) {
let text = '';
if (_.isArray(params)) {
text = `${moment(Number(params[0].axisValue)).format(
'YYYY-MM-DD HH:mm:ss',
)}<br/>`;
_.forEach(params, obj => {
let value = obj.value;
text = `${text}${obj.marker}${obj.seriesName}: ${value}<br/>`;
});
} else {
text = `${moment(Number(params.axisValue)).format(
'YYYY-MM-DD HH:mm:ss',
)}<br/>`;
text = `${text}${params}${params.seriesName}: ${params.value}`;
}
return text;
},
},
xAxis: {
data: data.map(o => o.timestamp),
axisLabel: {
formatter(value: string) {
return moment(Number(value)).format('HH:mm');
},
},
},
yAxis: {
type: 'value',
},
series: series,
};
return option;
};

onLegendSelectChanged = (e: {
name: string;
selected: { [k: string]: boolean };
}) => {
let selected = Object.assign({}, e.selected);
if (this.clickedLegendName === e.name) {
this.clickedLegendName = '';
Object.keys(selected).forEach(key => {
selected[key] = true;
});
} else {
this.clickedLegendName = e.name;
Object.keys(selected).forEach(key => {
if (key === e.name) {
selected[key] = true;
} else {
selected[key] = false;
}
});
}
const option = this.getEchartsOption(selected);
this.echartRef.setOption(option);
};

render() {
const { className, style, loading } = this.props;

return (
<Root
className={className}
style={style}
>
<ReactEcharts
ref={(ref:any) => (this.echartRef = ref && ref.getEchartsInstance())}
option={this.getEchartsOption()}
showLoading={loading}
onEvents={{
legendselectchanged: this.onLegendSelectChanged,
}}
/>
</Root>
);
}
}