《产品经理说“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 别绑错。"

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

(完)

相关推荐
蜡台2 小时前
H5使用Chrome 权限问题
前端·javascript·chrome
掘金一周2 小时前
你们觉得房贷多少,没有压力 | 沸点周刊 4.30
前端·人工智能·后端
大貔貅喝啤酒2 小时前
接口测试_Postman(详细版)
javascript·测试工具·node.js·自动化·postman
小小码农Come on2 小时前
QML访问子项内容
前端·javascript·html
桜吹雪3 小时前
Langchain.js官方文档:构建具备按需加载技能的 SQL 助手
javascript·人工智能·node.js
han_3 小时前
一篇看懂国内外主流大模型:GPT、Claude、Gemini、DeepSeek、通义千问有什么区别?
前端·人工智能·llm
一行代码一行诗++3 小时前
注释是什么和注释该怎么写(C语言)
java·前端·javascript
涂兵兵_青石疏影3 小时前
beginPath-vs-save详解
前端
陈振wx:zchen20083 小时前
前端-面试题-JavaScript
javascript·前端面试题
泽_浪里白条3 小时前
我在 Superset 6.x 做自定义图表 + Embedded SDK 集成的实战复盘(附踩坑清单)
前端·数据可视化