《产品经理说“Tool 分组要一条会渐变的彩虹轴,还要能 zoom!”——我 3 步把它拆成 1024 个像素》

#ECharts #数据可视化 #前端干货 #需求拆解 #线性渐变


0. 开场 3 连问

  1. 为什么 Tool 分组要单独一条轴?
    答:一条轴上混排了几十种 Tool,用户想一眼看出"哪一段属于哪把 Tool"。
  2. 为什么非要"渐变色"而不是直接写死颜色?
    答:Tool 顺序、数量、颜色全由后端返回,写死就 GG。
  3. 为什么要在彩虹轴上叠加 dataZoom?
    答:彩虹轴 = 导航条,拖动它≈拖动地图的"缩略图",体验才丝滑。

一句话总结:
把"Tool 名"→"颜色"→"渐变"→"可拖动"全自动化,让用户 0 配置就能彩虹导航。

1. 先改数据结构,让"颜色"和"数据"同频共振

老结构的问题:

js 复制代码
xAxis: ['T1', 'T2', 'T3' ...]        // 只存名字
series: [{name: 'T1', data: [...]}, ...] // 颜色靠索引去 externalColors 里硬匹配

新结构(加 2 个字段即可):

js 复制代码
sitexAxis: ['T1', 'T1', 'T2', 'T3', 'T3', 'T3'] // 每个数据点对应的真实 Tool
colors:   ['#FF6B6B','#FF6B6B','#4ECDC4','#45B7D1','#45B7D1','#45B7D1'] // 一一对应

生成逻辑 3 行代码:

js 复制代码
const colors = [...new Set(sitexAxis)].map(code => {
  const idx = filterSites.findIndex(f => f.value === code);
  return idx >= 0 ? externalColors[idx] : '#ccc';
});

好处

  • 后端顺序随意变,前端不崩。
  • 颜色数组直接丢给 makeAxisColor 做渐变,无需二次查找。

2. 彩虹轴 = 线性渐变 + 分段色标

ECharts 的 axisLine.lineStyle.color 只认相对位置的色标,格式:

js 复制代码
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
  {offset: 0,   color: '#FF6B6B'},
  {offset: 0.3, color: '#FF6B6B'},
  {offset: 0.3, color: '#4ECDC4'},
  {offset: 0.5, color: '#4ECDC4'},
  ...
])

算法一句话:
"相同 Tool 连续段" = 一个色块,头尾各插 2 个色标,offset = 索引 / 总长。

代码 20 行不到:

js 复制代码
function makeAxisColor(data, externalColors) {
  const total = data.length;
  const colorMap = new Map();
  let colorIdx = 0;
  const stops = [];
  let startIdx = 0;

  while (startIdx < total) {
    const value = data[startIdx];
    if (!colorMap.has(value)) {
      colorMap.set(value, externalColors[colorIdx++ % externalColors.length]);
    }
    const color = colorMap.get(value);
    const endIdx = data.findIndex((v, i) => i > startIdx && v !== value);
    const realEnd = endIdx === -1 ? total : endIdx;
    stops.push({ offset: startIdx / total, color });
    stops.push({ offset: realEnd / total, color });
    startIdx = realEnd;
  }
  return new echarts.graphic.LinearGradient(0, 0, 1, 0, stops);
}

自测技巧

console.log(stops) 可以看到每段颜色起止,copy 到 colorgradient.dev 一眼验证对不对。


3. 叠加 dataZoom 的 2 个坑

坑 1:彩虹轴是第三条 xAxisxAxisIndex 必须对应。

js 复制代码
dataZoom: [
  {
    type: 'slider',
    xAxisIndex: [0, 1],   // 主轴 + 占位轴
    ...
  },
  {
    type: 'inside',
    xAxisIndex: [0, 1],
    ...
  }
]

坑 2:彩虹轴本身不要响应拖动,把它当"导航条"而非"控制条"。

解决:

  • 彩虹轴 axisLabel.interval = 0 强制全显,
  • dataZoom 的 xAxisIndex 不包含彩虹轴索引(这里是 2),
  • 这样拖动时彩虹轴不会被裁剪,仅作视觉参考。

4. 最终 10 行伪代码,把 3 步串成 pipeline

js 复制代码
// 1. 生成 sitexAxis & colors
const sitexAxis = [];
const colors = [...new Set(sitexAxis)].map(...);

// 2. 生成渐变
const axisColor = makeAxisColor(sitexAxis, colors);

// 3. 配置第三条轴 + dataZoom
const chartOptions = {
  xAxis: [
    { type: 'category', data: mainX },        // 主轴
    { type: 'category', data: mainX, show: false }, // 占位
    { type: 'category', data: sitexAxis, position: 'bottom', offset: 40,
      axisLine: { lineStyle: { color: axisColor, width: 16 } },
      axisLabel: { interval: 0, color: '#fff', fontWeight: 600,
        formatter: (v, i) => i === 0 || sitexAxis[i] !== sitexAxis[i-1] ? v : '' }
    }
  ],
  dataZoom: [
    { type: 'slider', xAxisIndex: [0, 1], bottom: 23, brushSelect: false },
    { type: 'inside', xAxisIndex: [0, 1] }
  ]
};

5. 上线效果

  • 20 把 Tool,彩虹导航条 1 秒生成。
  • 拖动底部 zoom,彩虹段实时跟随,0 额外配置。
  • 测试小姐姐说"像网易云的歌词渐变条,好酷"。

6. 小结口诀

"数据先对齐,颜色再映射,渐变算断点,zoom 别绑错。"

背下来,下次再遇到"彩虹轴 + 可拖动"需求,直接复制粘贴,提前下班去撸串。

(完)

相关推荐
C_心欲无痕1 天前
css - 使用@media print:打印完美网页
前端·css
青茶3601 天前
【js教程】如何用jq的js方法获取url链接上的参数值?
开发语言·前端·javascript
脩衜者1 天前
极其灵活且敏捷的WPF组态控件ConPipe 2026
前端·物联网·ui·wpf
Mike_jia1 天前
Dockge:轻量开源的 Docker 编排革命,让容器管理回归优雅
前端
GISer_Jing1 天前
前端GEO优化:AI时代的SEO新战场
前端·人工智能
没想好d1 天前
通用管理后台组件库-4-消息组件开发
前端
文艺理科生1 天前
Google A2UI 解读:当 AI 不再只是陪聊,而是开始画界面
前端·vue.js·人工智能
晴栀ay1 天前
React性能优化三剑客:useMemo、memo与useCallback
前端·javascript·react.js
JS_GGbond1 天前
JavaScript继承大冒险:从“原型江湖”到“class殿堂”
前端