针对 ECharts 中 Legend 渲染为下拉框的需求,核心实现思路是:隐藏原生 Legend + 外部实现 Select 组件 + 双向绑定数据。ECharts 原生不支持直接渲染复杂 DOM 组件,但可通过以下方案实现:
实现步骤
隐藏原生 Legend
option = {
legend: {
show: false // 关闭默认图例
}
}
手动创建 Select 组件
<select id="legendSelector" multiple>
<option value="系列1">系列1</option>
<option value="系列2">系列2</option>
</select>
双向数据绑定
// 初始化时同步选项
const seriesNames = chart.getOption().series.map(s => s.name);
renderSelect(seriesNames);
// Select 变化时更新图表
document.getElementById('legendSelector').addEventListener('change', (e) => {
const selected = Array.from(e.target.selectedOptions).map(o => o.value);
chart.dispatchAction({
type: 'legendToggleSelect',
name: selected // 控制系列的显示/隐藏
});
});
// 图表 legend 变化时同步 Select
chart.on('legendselectchanged', (params) => {
syncSelectState(params.selected);
});
补充说明
为何不用 legend.formatter
?
- 虽然支持 HTML 片段,但无法实现交互逻辑
- 下拉框的打开/关闭、多选等行为难以通过纯文本模拟
动态更新注意事项
扩展方案(Vue/React 场景)
// React 示例
function ChartWithSelector() {
const [selected, setSelected] = useState(['系列1']);
useEffect(() => {
chart.dispatchAction({
type: 'legendToggleSelect',
name: selected
});
}, [selected]);
return (
<div>
<select
multiple
value={selected}
onChange={e => setSelected(Array.from(e.target.selectedOptions, o => o.value))}
>
{seriesNames.map(name => (
<option key={name} value={name}>{name}</option>
))}
</select>
<ReactECharts option={options} />
</div>
);
}
关键 API 参考
方法/事件 | 作用 |
---|
legendToggleSelect | 控制系列显隐的 action |
legendselectchanged | 图例选择变化时的回调事件 |
getOption() | 获取当前配置项中的系列名称 |
建议结合第三方 UI 库(如 Ant Design Select)实现更复杂的交互样式。
还是用自定义Select吧;隐藏原始的legend;
虽然Legend支持formatter,返回一个字符串,像这种Select下拉的交互在formatter中实现起来太麻烦了,而且默认Legend和图表原本就有交互(显示/隐藏),不适合图表数据需要更新的情况;
自定义Select完全由自己控制,只需要关注与图表的交互,不管是显示隐藏还是更新数据都比较容易控制;