echarts 切换 tab 后空白或变形是因为非激活 tab 的 .tab-pane 为 display: none,导致 init 时获取宽高为 0;应在 shown.bs.tab 事件中调用 chart.resize() 并确保容器可见。

为什么切换 Tab 后 ECharts 图表空白或变形
ECharts 实例初始化时会读取容器 offsetWidth 和 offsetHeight 计算绘图区域,而 Bootstrap 的 .tab-pane 在非激活状态默认是 display: none —— 此时尺寸为 0,echarts.init() 拿到的宽高就是 0,导致渲染失败或 canvas 留白。不是代码写错,是 DOM 可见性与图表生命周期不匹配。
监听 shown.bs.tab 并调用 resize()
必须等 Tab 面板完全显示(即 shown.bs.tab 事件触发)后再通知图表重算尺寸。注意事件名和 data-toggle 属性要一致:
- 若 HTML 中用的是
data-toggle="tab"(常见于.nav-tabs),监听shown.bs.tab - 若用的是
data-toggle="pill"(常见于.nav-pills),监听shown.bs.pill
示例:
const myChart = echarts.init(document.getElementById('chart1'));
// ... setOption
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
// 确保只对当前激活 tab 下的 chart 生效(避免误 resize 其他图表)
if ($(e.target).attr('href') === '#tab-charts') {
myChart.resize();
}
});
多个图表共存时如何统一管理
手动维护每个 chart 变量容易遗漏,推荐用数组集中注册 + 循环 resize:
- 在全局作用域定义
const charts = [] - 每次
echarts.init()后立即charts.push(myChart) - 在
shown.bs.tab回调里遍历调用resize(),但要注意:仅当对应 tab 面板可见时才 resize,否则可能因容器不可见再次拿不到尺寸
更稳妥的做法是加一层可见性判断:
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
const targetPane = $($(e.target).attr('href'));
charts.forEach(chart => {
if (targetPane.find(chart.getDom()).length) {
chart.resize();
}
});
});
为什么不能在 show.bs.tab 或 click 里 resize
show.bs.tab 触发时面板尚未添加 .active 类,DOM 还没完成重排,offsetWidth 仍为 0;click 更早,此时面板甚至还没开始切换。只有 shown.bs.tab 是唯一能确保面板已渲染、尺寸可读的时机。另外,如果图表容器用了 flex 或 grid 布局且未设明确宽高,resize() 也可能失效——这时得检查 CSS 是否给了父容器最小尺寸(如 min-width: 300px)。











