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

求助:开发横轴以长度替代天数的类似日程图表(已试Syncfusion等库)

解决方案:自定义分段水平条形图(横轴替换为“长度”)

方案1:使用Chart.js实现

Chart.js支持堆叠水平条形图配置,完全可以适配你的需求,以下是可直接复用的核心代码:

数据结构定义

// 按项目分组,每个阶段对应长度值
const chartData = {
  labels: ["项目A", "项目B", "项目C"],
  datasets: [
    {
      label: "阶段1",
      data: [120, 90, 150],
      backgroundColor: "#FF6384",
      borderColor: "#FF6384",
      borderWidth: 1
    },
    {
      label: "阶段2",
      data: [80, 110, 70],
      backgroundColor: "#36A2EB",
      borderColor: "#36A2EB",
      borderWidth: 1
    },
    {
      label: "阶段3",
      data: [50, 60, 80],
      backgroundColor: "#FFCE56",
      borderColor: "#FFCE56",
      borderWidth: 1
    }
  ]
};

图表配置(替换横轴为“长度”)

const config = {
  type: 'bar',
  data: chartData,
  options: {
    indexAxis: 'y', // 切换为水平条形图
    scales: {
      x: {
        title: {
          display: true,
          text: '长度', // 替换原横轴的“天数”
          font: { size: 16, weight: 'bold' }
        },
        stacked: true, // 开启堆叠模式
        ticks: { precision: 0 } // 显示整数刻度
      },
      y: { stacked: true }
    },
    plugins: {
      legend: { position: 'top' },
      tooltip: { mode: 'index', intersect: false }
    }
  }
};

// 初始化图表(需提前在页面添加<canvas id="myChart"></canvas>)
new Chart(document.getElementById('myChart'), config);

方案2:原生Canvas手动绘制(高度自定义)

如果现有库的配置无法满足细节需求,原生Canvas可以实现100%自定义控制:

核心绘制代码

const canvas = document.getElementById('customChart');
const ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 400;

// 自定义数据
const projectData = [
  { name: "项目A", stages: [120, 80, 50], colors: ["#FF6384", "#36A2EB", "#FFCE56"] },
  { name: "项目B", stages: [90, 110, 60], colors: ["#FF6384", "#36A2EB", "#FFCE56"] },
  { name: "项目C", stages: [150, 70, 80], colors: ["#FF6384", "#36A2EB", "#FFCE56"] }
];

const barHeight = 40;
const padding = 60;
// 计算最大总长度,用于刻度缩放
const maxTotalLength = projectData.reduce((max, item) => {
  return Math.max(max, item.stages.reduce((sum, len) => sum + len, 0));
}, 0);
const scaleRatio = (canvas.width - padding * 2) / maxTotalLength;

// 绘制横轴标签
ctx.font = '16px Arial';
ctx.fillText('长度', canvas.width / 2, canvas.height - 20);

// 绘制每个项目的分段条形
projectData.forEach((item, idx) => {
  let currentX = padding;
  const yPos = padding + idx * (barHeight + 20);
  
  // 绘制项目名称
  ctx.fillText(item.name, 10, yPos + barHeight / 2 + 5);
  
  // 绘制各阶段分段及长度标注
  item.stages.forEach((length, stageIdx) => {
    ctx.fillStyle = item.colors[stageIdx];
    ctx.fillRect(currentX, yPos, length * scaleRatio, barHeight);
    
    // 标注阶段长度
    ctx.fillStyle = '#000';
    ctx.fillText(length.toString(), currentX + 10, yPos + barHeight / 2 + 5);
    
    currentX += length * scaleRatio;
  });
});

// 绘制横轴刻度
for (let i = 0; i <= maxTotalLength; i += 50) {
  const tickX = padding + i * scaleRatio;
  ctx.beginPath();
  ctx.moveTo(tickX, canvas.height - padding);
  ctx.lineTo(tickX, canvas.height - padding + 5);
  ctx.stroke();
  ctx.fillText(i.toString(), tickX - 10, canvas.height - padding + 20);
}

注意事项

  • 你之前尝试的Syncfusion、Dhtmlx其实也支持这类需求,可能是未找到正确的堆叠条形图配置项,建议查阅官方文档中stacked bar chart+axis label customization的章节
  • 原生Canvas方案适合需要特殊标注、自定义样式的场景,灵活性最高

内容的提问来源于stack exchange,提问作者Muhammad Hamza Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:13:22