做数据可视化这几年Echarts 用得最多也最头疼的其实不是不会配图而是“图能出来但没法看”。尤其是多列折线图和柱状图数据一多标签label就开始互相打架这边刚显示一个数值那边立刻压上去糊成黑乎乎一团柱状图更惨多一个系列就多一排柱子顶部的标签根本排不开。今天这篇就把我实际项目中踩过的坑和最终验证有效的方案完整拆一遍从原理到配置再到直接能抄的代码全部讲透。不管你是刚入门的小白还是已经用 Echarts 做了两三个项目的开发者这篇文章都能帮你少走弯路。核心思路是先搞懂标签为什么会遮挡再根据场景选择对应的解法——它们不是互相替代的关系而是配合使用。适合正在做数据大屏、业务报表、后台分析图表被多系列图表标签搞到头秃的人。1. 标签遮挡的本质坐标系空间永远不够用1.1 一个坐标系要装下所有系列的“名牌”先说清楚遮挡产生的根本原因。Echarts 绘图本质上是把数据映射到一个有限的坐标系里——宽度是容器决定的高度是 grid 决定的都是固定像素。折线图每增加一个 series就多一条折线多条线在接近或交叉的位置标签就会抢占同一片屏幕空间。柱状图更直接每个类目下的柱子数量乘以宽度总和不能超过类目占位宽度柱子越挤标签越没地方放。这就像一张桌子只有十个座位突然来了三十个人不可能每个人都有舒服的位置。Echarts 默认不会帮你想办法它只管把标签画在数据点旁边画完就完事。所以我们能做的无非是四件事让标签变少、让标签错开、让标签能压住背景、或者干脆把标签从“常驻”改成“按需出现”。1.2 三种最常见的“翻车现场”先对号入座看看你遇到的是哪种情况。第一种折线图多系列标签重叠。典型场景两条折线走势接近比如去年的销售额和今年的销售额在 3 月到 6 月之间差距很小。此时两个系列每个数据点的 label 几乎会叠在一起数值只能看清最后一个显示的。第二种柱状图同组柱子标签打架。典型场景每个季度有 4 个产品线的销量柱状图用了 4 个 series柱子并排显示每个柱子顶部都有一个数字标签。数据量少比如只有 4 个季度还勉强能看一旦类目变成 12 个月标签要么互相挤压要么直接超出绘图区被截断。第三种X 轴或标签文字过长导致的连带问题。类目名称太长X 轴刻度标签开始旋转、省略图表整体被压缩结果就是我们给数据点加的数值标签也跟着遭殃——它们会尝试避开轴标签上下挪动最后和相邻系列叠上。这三种情况对应不同的解法但有一点是共通的先明确你最想展示的信息是什么。如果每个点的具体数值都必须可见那就得从布局和交互上下功夫如果核心是趋势和对比完全没必要每个点都放标签。2. 先把 label 的基础配置吃透2.1 折线图标签常用配置项在看解决方案之前必须熟悉 Echarts label 的基本配置。很多朋友一开始只会写label: { show: true }然后就没了这样当然控制不住遮挡。折线图里我常用的 label 完整配置长这样label: { show: true, position: top, distance: 8, rotate: 0, offset: [0, 0], formatter: function (params) { return params.value 万; }, fontSize: 11, fontWeight: normal, color: #333, backgroundColor: rgba(255,255,255,0.85), padding: [4, 6], borderRadius: 2, shadowBlur: 4, shadowColor: rgba(0,0,0,0.2) }这里有几个关键点position控制标签相对于数据点的位置折线图最常用的就是top上方和bottom下方。当两条线靠得很近时可以让一条用 top、一条用 bottom实现最基本的错开。distance是标签与数据点的距离。很多人忽略它其实调整距离能让标签跳出“拥挤区”比如一条线的标签往上放得更远一些另一条靠近一些。formatter不只是用来拼字符串的。你完全可以在回调里做逻辑判断决定某个点要不要显示标签。这是后面方案二的核心也是解决遮挡最灵活的手段。backgroundColor和padding是很多人忽略的“救命配置”。当标签不得不压在折线或柱子上时给标签加一个半透明的背景底板文字依然清晰可读。这个技巧在折线交叉、柱状图柱子过窄时尤其有效。2.2 柱状图标签和折线图标签的差异柱状图标签的数量级和折线图一致但位置选择更讲究。柱状图除了top还有inside、insideTop、insideBottom等选项。多系列柱状图的遮挡通常有两个来源同一根柱子上不同系列标签的位置冲突以及并排柱子的顶部标签横向挤压。柱状图里我建议优先掌握这几个配置// 柱状图内部标签 label: { show: true, position: insideTop, distance: 2, fontSize: 10, color: #fff } // 柱状图顶部标签 label: { show: true, position: top, fontSize: 10, color: #333 }insideTop适合柱子高度足够、数值较短的情况标签在柱子内部不占用外部横向空间但柱子太矮时标签会被截断或溢出。top适合柱子较高的情况标签在柱子外面但多个系列并排时就容易横向拥挤。这里有一个必须注意的点柱状图的标签遮挡和barCategoryGap、barGap有密切关系。barCategoryGap控制不同类目之间的间距barGap控制同一类目下不同系列的间距。柱子之间缝隙越大标签空间越大但图表整体不够紧凑。建议在数据量超过 8 个类目时适当增大barGap比如设为20%到40%给标签留出呼吸空间。3. 方案一用 ECharts 5 的 labelLayout 做自动避让3.1 avoidLabelOverlap 的实际效果其实有限Echarts 旧版本里有个配置叫avoidLabelOverlap默认false官方说明是“是否在显示标签的时候防止标签重叠”。听起来很美好但你实际用会发现在多系列折线图里它的生效范围非常有限——它对单个系列内部的标签互斥有一点作用却管不了不同系列标签之间的遮挡。我把话说明白一点avoidLabelOverlap对于“同一个 series 相邻两个数据点的标签重叠”这类情况有一定缓解但对“series A 的标签压住 series B 的标签”基本无能为力。所以如果网上有人告诉你“你把 avoidLabelOverlap 设为 true 就完事了”那是没做过复杂项目的说法。3.2 真正好用的是 labelLayout.hideOverlapECharts 5 引入了labelLayout配置这才是官方为此场景设计的正解。它允许你对所有 label 做统一的布局调整核心有两个值hideOverlap: true自动检测重叠的标签然后隐藏后出现的那个。moveOverlap: shiftY或shiftX自动检测到重叠后把标签沿 Y 轴或 X 轴方向移动尽量错开。实际用法是在series或全局labelLayout中配置option { // 全局生效 labelLayout: { hideOverlap: true }, series: [ { type: line, data: [120, 200, 150, 80, 170, 110], label: { show: true } } ] };当同一坐标点附近有两个不同系列的标签重叠时hideOverlap会根据绘制顺序保留先画的那个隐藏后画的。这样做的好处是代码量最少几乎零成本解决遮挡坏处也很明显——被隐藏标签的那个数据点数值就看不到了。所以在实际项目中我不会把hideOverlap作为唯一的保底方案而是把它放在所有手动处理之后的最后一道防线。比如十条线全部显示标签我手动把每条线的 position 错开但仍有少量点重叠这时开启hideOverlap兜底不会出现大面积信息丢失。3.3 labelLayout 函数模式的高级用法labelLayout除了传对象还可以传函数接收一个参数包含当前标签的位置、数据索引、系列索引等信息你可以返回新的坐标或配置。举个实际例子labelLayout: function (params) { // 如果这条线的标签会和附近标签重叠就往下移 12 个像素 if (params.seriesIndex % 2 1) { return { dy: 12, align: center }; } }这种写法适合你有规律地错开多个系列标签的场景。比如 6 条折线偶数系列标签在点上方奇数系列标签在点下方再通过labelLayout函数对每个系列设置微调位移标签重叠概率会大幅下降。但记住一点labelLayout本身不识别业务语义它只是机械地避让或隐藏。如果两个标签显示的都是同一个重要指标隐藏其中一个可能误导使用者。所以能用人工规则手动控制时优先手动控制。4. 方案二少放标签只标关键信息4.1 formatter 里做数据点筛选如果你的数据点是 12 个月、24 个月甚至更多真心不建议每个月都显示标签。折线图的核心魅力在于趋势趋势大家看线形就够了数值可以靠 tooltip。所以我做报表项目时有一条铁律超过 10 个数据点的折线图默认不开全量标签改用“选择性标注”。使用formatter回调可以在渲染时决定某个节点是否显示内容。例如只显示最后一个点的数值label: { show: true, formatter: function (params) { var total params.data.length; if (params.dataIndex total - 1) { return {value| params.value }; } return ; } }不过要注意formatter返回空字符串时标签虽然不显示文字但 label 的空占位未必能完全避免参与布局渲染。为了彻底干净也可以在数据处理阶段先把非目标点的值设成null这样该点不渲染同时折线仍然连接。另一个常见做法是只显示最大值和最小值。这个我推荐结合markPoint来做比 formatter 更直观。markPoint是大数据标记可以在折线图的最大最小值位置放红色圆点并显示数值标签markPoint: { data: [ { type: max, name: 最大值 }, { type: min, name: 最小值 } ], label: { show: true, position: top, formatter: function (params) { return params.value; } } }用这个方案全图只显示两个数字其他位置靠鼠标悬浮 tooltip 获取图表瞬间清爽。4.2 筛选规则什么时候值得保留标签我个人总结了一套筛选标签的原则不一定适用于所有项目但大部分场景可以复用数据点少于等于 6 个所有点显示标签信息密度完全可接受。数据点 7 到 12 个只显示最大值、最小值、最后一个值或者按业务规则显示几个关键值比如年度目标值、环比最高的月份。数据点超过 12 个默认全部不显示只显示最后一个点的“当前值”以及数据趋势线本身数值全部交给 tooltip。柱状图也类似但柱状图的人类阅读习惯是“逐根柱子对比”所以数据量少时尽量都显示。如果类目超过 8 个我建议只对最大值或超过阈值的柱子显示标签。4.3 用 markLine 替代一部分标签信息很多时候我们真正想强调的不是每个点的值而是一条基准线——平均值、目标值、同比线。这些完全可以用markLine表达既不会遮挡折线又能传递大量信息。markLine: { silent: true, symbol: none, lineStyle: { type: dashed, color: #999 }, label: { formatter: 平均值{c}, position: insideEndTop }, data: [{ type: average, name: 平均值 }] }如果图中已经有了平均值虚线那么折线节点上的标签优先级就可以降低只留头顶几个关键点即可。标签遮挡问题的第一原则永远是减少标签数量而不是无限优化标签布局——因为屏幕和人眼的注意力都是有限的。5. 方案三通过位置、旋转和样式给标签腾地方5.1 不同系列用不同 position天然错位这是成本最低、见效最快的“物理错开法”。折线图中如果系列数量在 2 到 4 条之间可以让它们相邻错开。比如第一条线的标签放在数据点上方position: top第二条线的标签放在数据点下方position: bottom这样同一 X 坐标下标签就占用了上下两个不同区域重叠概率大幅降低。多条线时我会交替设置 position 和 distance比如series: seriesConfig.map(function (item, index) { return { type: line, data: item.data, label: { show: true, position: index % 2 0 ? top : bottom, distance: index % 2 0 ? 6 : 12 } }; });这里distance也做了差异化进一步拉开距离。但这个方法有个局限当两条线的值本身就很接近时即便一个标签在上一个标签在下也可能因为数据点水平距离太近而产生视觉纠缠。所以在数据趋势相似的多系列场景我更推荐结合方案二只标注关键点。柱状图的 position 错开同样有效。同组多系列柱子一种方案是第一个系列的标签放在柱顶外侧后面的系列放在柱体内侧。比如系列 A 用position: top系列 B 用position: insideTop。这样标签文字不会在柱子顶部横向挤成一排。5.2 旋转标签给 X 轴长文本让路当 X 轴类目是长文本时即使轴标签用了interval: 0全部显示也会挤压绘图区。我的习惯是在类目超过 6 个且文本超过 4 个字时直接开启rotate: 40或rotate: 45。旋转后轴方向的标签横向宽度占用大幅减少相当于给多系列柱状图留出了更多纵向标签空间。axisLabel配置xAxis: { type: category, data: categories, axisLabel: { rotate: 40, interval: 0, fontSize: 10 } }需要注意rotate不是免费的它会让轴标签变高从而稍微压缩 plot 区域。此时可以用grid的bottom属性预留一部分空间比如grid: { bottom: 80 }防止旋转后的文字溢出到图表外部。如果你觉得旋转不好看另一个折中方案是formatter做换行比如axisLabel: { formatter: function (value) { return value.length 3 ? value.slice(0, 3) \n value.slice(3) : value; } }这样就能在不旋转的情况下让长文本分两行显示视觉上更友好。5.3 给标签加底色和描边压住数据也能看清当标签实在无法避开数据线或柱子时给标签一个半透明背景板是最实用的技巧。Echarts 的 label 支持backgroundColor、borderColor、borderWidth、padding、borderRadius等样式。最常用的组合是白色半透明底加浅灰边框label: { show: true, position: top, backgroundColor: rgba(255, 255, 255, 0.8), borderColor: #ddd, borderWidth: 1, borderRadius: 4, padding: [3, 6], fontSize: 10, color: #333 }加了背景板之后即使标签叠在折线上线还是线数值还是数值两者都能看清。这个方法在多折线交叉场景里几乎是必须的。我在做某条财务趋势图时三条线在某个区间反复交叉所有标签都叠在一起最后就是用“每条线不同颜色白底标签”救回来的。但这里有个容易踩的坑不要给所有标签加同一颜色的大背景板否则背景板会互相遮挡反而形成新的“色块打架”。我一般只给需要强调的系列加背景或者背景透明度调低一些同时把 padding 保持在较小值。6. 方案四把标签从“常驻”改成“按需出现”6.1 平时不显示鼠标悬浮才显示标签你的用户真的需要在第一眼就看到每个点的数值吗大多数时候不需要。他们想看某个点时会主动把鼠标移过去。Echarts 的emphasis状态配置可以完美实现“悬停显示标签”。方法很简单label.show设为false然后在emphasis.label里设置show: trueseries: [ { type: line, data: d1, label: { show: false }, emphasis: { label: { show: true, position: top, fontSize: 12, fontWeight: bold, backgroundColor: rgba(255,255,255,0.9), padding: [4, 6], borderRadius: 4 } } } ]这样图表最初渲染时非常干净没有遮挡用户把鼠标移到某个点或某个柱子上时该点的数值才浮现出来。这在数据量大、系列多的场景几乎是必杀技。不过要注意emphasis默认只针对“当前 hover 到的图形元素”生效。多个系列在同一个类目下用户 hover 到折线 A 的点只会显示折线 A 的标签柱子同理。如果希望同时显示所有系列该类目的标签就需要用事件驱动了。6.2 把 tooltip 配置到极致让所有信息都藏在提示框里与其在图上堆标签不如把信息全部放进 tooltip。Echarts 的 tooltip 功能比很多人用得深得多。多系列图表建议使用trigger: axis鼠标在某个类目范围内移动时会自动显示所有系列在该类目的值这比标签逐点展示效率更高。完整的 tooltip 配置tooltip: { trigger: axis, confine: true, backgroundColor: rgba(255,255,255,0.95), borderColor: #ccc, padding: [10, 12], textStyle: { color: #333, fontSize: 12 }, axisPointer: { type: cross, crossStyle: { color: #999 } }, formatter: function (params) { var res div stylefont-weight:bold;margin-bottom:6px; params[0].axisValue /div; params.forEach(function (item) { res div span styledisplay:inline-block;width:10px;height:10px;border-radius:50%;background-color: item.color ;margin-right:6px;/span item.seriesName b item.value /b /div; }); return res; } }几个容易忽略但经常救命的配置confine: true可以防止 tooltip 超出图表容器避免在页面边缘被裁掉。多系列 tooltip 内容通常较多建议设置固定背景色、边框和内边距保证可读性。axisPointer.type cross会画一条十字准线用户能直观知道当前数据点所在位置。另外formatter返回 HTML 字符串时可以用item.color获取当前系列的颜色在提示框里做一个圆点图例。这是很多资深开发者的标配让用户从 tooltip 内容中快速区分系列。6.3 dataZoom 让大数据量缩放后再显示标签还有一个极少有人提到的场景数据点特别多时比如一年 365 天、或者几千条记录直接全量渲染必然遮挡成“毛线团”。此时不要和标签布局较劲正确做法是加入dataZoom让用户放大局部区域后再展示细节。dataZoom分为内置型和滑块型常用组合是dataZoom: [ { type: inside, start: 0, end: 20 }, { type: slider, height: 20, bottom: 10, start: 0, end: 20 } ]start: 0, end: 20表示默认只展示前 20% 的数据其余部分通过拖动缩放查看。这样在同一时刻图表上的可见数据点数量有限标签遮挡问题自然缓解。要注意的是dataZoom默认作用于 x 轴对折线图和柱状图都适用。如果你有 30 个类目的柱状图全部显示标签必然重叠我的建议就是默认展示 10 个类目剩余部分靠用户手动缩放。这比任何标签布局优化都管用——因为视觉上同时只能关注那么多信息。7. 实战复盘三个典型项目我怎么落地7.1 多折线指标卡5 个系列每个系列 12 个数据点这是最常见的 dashboard 场景。5 条折线分别代表近一年的几个核心指标如果全部显示标签图上会有 60 个数字无论怎么布局都会乱。我最终采用的方案是“组合拳”所有系列label.show设为false关闭常驻标签。对每个系列通过markPoint只标注最大值和最后值。tooltip使用trigger: axis并开启dataZoom让用户能放大查看细节区域。legend置于顶部便于用户筛选系列。关键代码结构如下option { color: [#5B8FF9, #5AD8A6, #F6BD16, #E8684A, #6DC8EC], tooltip: { trigger: axis, confine: true }, legend: { top: 0 }, dataZoom: [ { type: inside, start: 0, end: 100 } ], grid: { top: 50, left: 50, right: 30, bottom: 50, containLabel: true }, xAxis: { type: category, data: [1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月] }, yAxis: { type: value }, series: seriesList.map(function (item) { return { type: line, name: item.name, data: item.data, label: { show: false }, emphasis: { label: { show: true, position: top } }, markPoint: { label: { show: true, fontSize: 10 }, data: [ { type: max, name: 最高点 }, { type: min, name: 最低点 } ] } }; }) };这样出来的图视线范围内最多只有 10 个数值标签清晰很多。用户想看具体哪个月鼠标移过去tooltip 里 5 个系列的值全部展示。7.2 多系列柱状图3 个系列12 个类目标签挤成一团有个项目展示某业务在 12 个月里 3 个产品线的收入柱子并排显示每个柱子顶部都有数字标签。最初的版本惨不忍睹小数字显示为大数字的中间标签互相叠压整个图表根本没法解读。我的处理分三步第一步把所有系列标签从position: top改为第一个系列放顶部、后两个系列放柱内seriesConfig products.map(function (product, index) { var labelPos ; if (index 0) { labelPos top; } else if (index 1) { labelPos insideTop; } else { labelPos insideBottom; } return { name: product.name, type: bar, data: product.data, barGap: 15%, label: { show: true, position: labelPos, fontSize: 10 } }; });第二步调整barGap为15%给柱子之间留出缝隙减少标签横向挤压。第三步发现问题仍然存在某些月份第一个系列数据很大柱子很高第二个系列数据很小柱子很矮insideTop标签就直接飞出了柱子顶部和第一个系列的top标签叠在一起。于是加了最后一层保险也是我最常用的兜底方案在label上使用formatter对特别小的值不显示标签只显示在可读范围内的值formatter: function (params) { // 柱子高度太矮时标签放内部会溢出直接不显示 if (params.value 100) { return ; } return params.value; }处理后图表整体可用性大幅提升。三个系列中数值较小的柱子不再产生标签数值较大的几个关键月份标签醒目配合 tooltip 完全够用。7.3 长周期数据300 个交易日折线还要显示标签还有一类场景是数据量级很大但业务方坚持要“看到某些位置的数值”。比如股票走势、监控指标等动辄几百个点。这时候任何全局标签策略都无效因为 300 个标签必然糊成黑线。我的做法是先用sampling做降采样然后用markPoint标记趋势关键点再加dataZoom局部查看。Echarts 折线图自带采样算法比如sampling: lttb可以保留趋势特征的同时大幅减少渲染点数series: [ { type: line, data: datas, sampling: lttb, symbol: none, lineStyle: { width: 1.5 }, markPoint: { data: [ { type: max, name: 最高点 }, { type: min, name: 最低点 } ] } } ]sampling: lttb是 largest-triangle-three-buckets 算法的缩写它能在采样时尽量保持原始波形的整体形状比简单间隔抽样效果好很多。建议在数据点超过 500 时启用。这样处理后即便默认展示全部数据范围图上的标签也只剩最高点和最低点两个。用户想看中间某天的值可以用 tooltip或者通过dataZoom放大到局部后配合label的hideOverlap让密集区的标签自动规避。8. 踩坑记录与排查速查表做多了之后你会发现标签遮挡问题往往不是单一原因导致的而是多个配置相互作用的结果。以下是我在实际开发中遇到过并解决过的高频问题整理成一张速查表方便你对照排查。现象常见原因解决方案两条折线标签同时出现在数据点上方互相叠压多个 series 的 label.position 都设为 top交替使用 top 和 bottom或增加 distance 差异化柱状图三四个系列的顶部标签横向挤成一排所有系列的 label.position 都是 top柱子间距不够使用 insideTop/insideBottom 组合或增大 barGap标签被图表边缘截断看不到完整数字容器过窄或 grid 未设置 containLabelgrid.containLabel 设为 true调整 grid 的 top/bottom/left/right鼠标悬浮时 tooltip 超出页面边界tooltip 未设置 confinetooltip.confine true大数据量折线图标签成黑团数据点过多全量显示标签启用 sampling、dataZoom只在 markPoint 标注关键点标签压住了折线文字看不清标签没有背景板给 label 加 backgroundColor、padding、borderRadius同一个 X 坐标下多个系列标签互相遮挡数据值差异小位置错开后仍然重叠关闭常显标签改用 emphasis 悬停显示或 tooltipX 轴长文本类目导致绘图区被挤压类目名称过长axisLabel 未处理设置 axisLabel.rotate 或 formatter 换行开启 labelLayout.hideOverlap 后有些标签消失了hideOverlap 隐藏了重叠标签确认是否可接受如必须保留改用 position 错开或 formatter 条件显示柱状图 label 设为 insideTop 后文字溢出柱子柱子高度较小label 显示区域不够判断数值阈值小数值不显示标签或改用 position:top多条折线颜色接近标签看不出归属没有在标签上体现系列颜色或名称通过 formatter 给标签加系列名称或给多个系列设置差异化颜色和标签背景这里重点强调两个我反复踩过的坑。第一个是grid.containLabel。很多初学者画图时发现 Y 轴刻度文字被裁掉或者 X 轴类目名称被截断第一反应是调 grid 的 left 和 bottom但调来调去容易误伤其他元素。正确做法是在 grid 里设置containLabel: true让 Echarts 自动计算坐标轴标签占用的空间绘图区自动避让。这个配置在标签遮挡问题上虽然不直接作用但它能保证整个绘图区域不被轴标签挤压间接给数据标签腾出了更多空间。第二个是labelLayout和emphasis的优先级关系。有次我配置了labelLayout.hideOverlap同时又配置了emphasis.label.show: true结果鼠标悬浮某个点该点的标签出现了但其它重叠的标签也消失了导致视觉上信息跳动。排查后发现hideOverlap是对所有状态标签都会生效的。后来我把常显标签和悬浮标签分开处理常显只保留关键点悬浮状态通过 tooltip 或单独强调来交互不再依赖hideOverlap。另外一个经验是处理标签遮挡前先在series级别把label配置精简再用emphasis把交互做足。很多项目要求“所有数值都要能看”但实际上用户交互路径里“想看某个点”和“一眼看到所有点”是两种完全不同的需求。前者用 tooltip、后者用常显标签。两者混在一起配置最容易出问题。最后分享一个我刚入行时没人告诉我的技巧把所有系列的emphasis也配置好包括label和itemStyle。比如折线图的悬浮效果默认只放大 symbol 大小不会自动显示标签。如果你希望在鼠标悬浮时能看到该点的具体数值必须在emphasis.label中显式设置show: true。这个技巧在柱状图里同样适用而且能让你的图表交互体验提升一个档次。我个人在实际项目中的体会是Echarts 的标签遮挡没有银弹方案不要想着一个配置解决所有问题。真正高效的做法是回到业务本质想清楚哪些数据是非要在图上展示的哪些数据是“用户需要时再看”的。然后把展示类信息放在标签里把查询类信息放在 tooltip 里最后再用 labelLayout 和样式兜底。这套思路我用在十几个项目里都很稳定你下次遇到多列折线图或柱状图标签糊成一团的时候不妨也按这个顺序排查一遍先减数量、再错位置、后加样式、最后上交互。