You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将线性渐变实现的连续图例转为离散阶梯式图例?

将连续渐变图例转为离散阶梯图例

我目前用线性渐变实现了连续图例,现在想把它改成具有恒定阶梯值的离散图例。以下是当前代码、目标效果示意图:

当前代码

const legendColor = [{
    offset: 0.0,
    color: "#ff0000"
  },
  {
    offset: 0.2,
    color: "#ffff00"
  },
  {
    offset: 0.4,
    color: "#00ff00"
  },
  {
    offset: 0.6,
    color: "#00ffff"
  },
  {
    offset: 0.8,
    color: "#0000ff"
  },
  {
    offset: 1.0,
    color: "#ff00ff"
  }
];

const svg = d3.select("svg");
const colorScale2 = d3.scaleLinear().domain([0, 1]).range([0, 400]);
const id = "linear-gradient-0";
const linearGradient2 = svg.append("defs")
  .append("linearGradient")
  .attr("id", "linear-gradient-1")
  .attr("x1", "100%")
  .attr("x2", "0%")
  .attr("y1", "0%")
  .attr("y2", "0%");

// append the color
linearGradient2
  .selectAll("stop")
  .data(legendColor)
  .enter()
  .append("stop")
  .attr("offset", function(data) {
    return colorScale2(data.offset) / 4 + "%";
    //return data.offset + "%";
  })
  .attr("stop-color", function(data) {
    return data.color;
  });

// draw the rectangle and fill with gradient
svg.append("rect")
  .attr("x", 10)
  .attr("y", 88)
  .attr("width", 400)
  .attr("height", 20)
  .style("fill", "url(#linear-gradient-1)");

目标效果

目标离散图例效果

解决方案

实现离散阶梯图例,最直观的方式是直接为每个颜色绘制独立矩形块,无需使用线性渐变,代码修改如下:

const legendColor = [{
    offset: 0.0,
    color: "#ff0000"
  },
  {
    offset: 0.2,
    color: "#ffff00"
  },
  {
    offset: 0.4,
    color: "#00ff00"
  },
  {
    offset: 0.6,
    color: "#00ffff"
  },
  {
    offset: 0.8,
    color: "#0000ff"
  },
  {
    offset: 1.0,
    color: "#ff00ff"
  }
];

const svg = d3.select("svg");
const totalWidth = 400;
const startX = 10;
const startY = 88;
const blockHeight = 20;
const blockWidth = totalWidth / legendColor.length;

// 绘制每个颜色块
let currentX = startX;
legendColor.forEach(colorItem => {
  svg.append("rect")
    .attr("x", currentX)
    .attr("y", startY)
    .attr("width", blockWidth)
    .attr("height", blockHeight)
    .style("fill", colorItem.color);
  
  currentX += blockWidth;
});

// 添加色块分隔线,还原目标图效果
currentX = startX;
for (let i = 1; i < legendColor.length; i++) {
  currentX += blockWidth;
  svg.append("line")
    .attr("x1", currentX)
    .attr("y1", startY)
    .attr("x2", currentX)
    .attr("y2", startY + blockHeight)
    .style("stroke", "#000")
    .style("stroke-width", 1);
}

方案说明

  • 移除原线性渐变相关代码,直接遍历颜色数组绘制独立矩形,每个色块宽度均分总宽度
  • 添加黑色竖线作为色块分隔,匹配目标图的阶梯视觉效果
  • 如果需要按offset间隔比例分配色块宽度,可将blockWidth的计算逻辑改为基于相邻offset的差值

如果一定要通过线性渐变模拟阶梯效果,可通过重复设置渐变断点实现:

const legendColor = [{
    offset: 0.0,
    color: "#ff0000"
  },
  {
    offset: 0.2,
    color: "#ffff00"
  },
  {
    offset: 0.4,
    color: "#00ff00"
  },
  {
    offset: 0.6,
    color: "#00ffff"
  },
  {
    offset: 0.8,
    color: "#0000ff"
  },
  {
    offset: 1.0,
    color: "#ff00ff"
  }
];

const svg = d3.select("svg");
const totalWidth = 400;
const gradientId = "linear-gradient-1";

// 生成阶梯渐变断点:每个颜色的起始和结束位置
const stopPoints = [];
legendColor.forEach((item, idx) => {
  stopPoints.push({offset: item.offset, color: item.color});
  if (idx < legendColor.length - 1) {
    stopPoints.push({offset: legendColor[idx+1].offset, color: item.color});
  }
});

// 创建渐变
const linearGradient = svg.append("defs")
  .append("linearGradient")
  .attr("id", gradientId)
  .attr("x1", "0%")
  .attr("x2", "100%")
  .attr("y1", "0%")
  .attr("y2", "0%");

linearGradient
  .selectAll("stop")
  .data(stopPoints)
  .enter()
  .append("stop")
  .attr("offset", d => `${d.offset * 100}%`)
  .attr("stop-color", d => d.color);

// 绘制渐变矩形
svg.append("rect")
  .attr("x", 10)
  .attr("y", 88)
  .attr("width", totalWidth)
  .attr("height", 20)
  .style("fill", `url(#${gradientId})`);

// 添加分隔线
let currentX = 10;
for (let i = 1; i < legendColor.length; i++) {
  currentX += (legendColor[i].offset - legendColor[i-1].offset) * totalWidth;
  svg.append("line")
    .attr("x1", currentX)
    .attr("y1", 88)
    .attr("x2", currentX)
    .attr("y2", 88 + 20)
    .style("stroke", "#000")
    .style("stroke-width", 1);
}

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 21:21:12