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

如何固定plotly.express.timeline甘特图的条形宽度/厚度

Plotly甘特图固定条形竖直厚度的实现方案

Plotly本身没有直接提供固定条形像素厚度的配置项,但可以通过动态计算图表总高度的方式实现需求,以下是两种可落地的实现方案:

方案1:Python端预计算图表高度

你之前担心的高度计算非线性问题,本质是没有固定布局边距、图例占位等参数,将这些参数固定后,高度和y轴分类数为完全线性关系,精度足够使用。
实现代码如下:

import datetime as dt
import plotly.express as px

data = [
    {'Task': '1-2', 'Start': '2021-09-26', 'Finish': '2021-09-27', 'Resource': 'R1'},
    {'Task': '2-1', 'Start': '2021-09-23', 'Finish': '2021-09-24', 'Resource': 'R2'},
    {'Task': '2-2', 'Start': '2021-09-26', 'Finish': '2021-09-27', 'Resource': 'R2'},
    {'Task': '3-1', 'Start': '2021-09-30', 'Finish': '2021-10-01', 'Resource': 'R3'},
    {'Task': '3-2', 'Start': '2021-11-26', 'Finish': '2021-11-27', 'Resource': 'R3'},
]

# 固定配置参数,可根据需求调整
BAR_HEIGHT_PX = 30  # 期望的条形固定厚度,单位像素
Y_AXIS_GAP_RATIO = 0.2  # y轴相邻分类的间距占比
TOP_MARGIN = 60  # 顶部边距
BOTTOM_MARGIN = 60  # 底部边距
LEGEND_HEIGHT = 40  # 图例占位高度,图例放在左右侧时可设为0

# 统计y轴去重分类数量
y_category_count = len({d['Resource'] for d in data})
# 计算总图表高度
total_height = int(y_category_count * BAR_HEIGHT_PX / (1 - Y_AXIS_GAP_RATIO) + TOP_MARGIN + BOTTOM_MARGIN + LEGEND_HEIGHT)

fig = px.timeline(
    data,
    x_start="Start",
    x_end="Finish",
    y="Resource",
)

# 更新布局配置
fig.update_layout(
    height=total_height,
    yaxis=dict(
        categorygap=Y_AXIS_GAP_RATIO
    ),
    margin=dict(t=TOP_MARGIN, b=BOTTOM_MARGIN)
)

# 序列化返回即可
return plotly.io.to_json(fig)

方案2:前端动态调整适配

如果不想在Python端处理逻辑,也可以在前端渲染前动态计算高度,修改布局参数后再渲染,实现代码如下:

<script src="https://cdn.plot.ly/plotly-2.0.0.min.js"></script>
<script type="text/javascript">
// 固定配置参数,可根据需求调整
const BAR_HEIGHT_PX = 30;
const Y_AXIS_GAP_RATIO = 0.2;
const TOP_MARGIN = 60;
const BOTTOM_MARGIN = 60;
const LEGEND_HEIGHT = 40;

let graph = {{ gantt_json|safe }};
// 统计y轴去重分类数量
const yCategoryCount = new Set(graph.data[0].y).size;
// 计算总图表高度
const totalHeight = Math.ceil(yCategoryCount * BAR_HEIGHT_PX / (1 - Y_AXIS_GAP_RATIO) + TOP_MARGIN + BOTTOM_MARGIN + LEGEND_HEIGHT);

// 写入布局配置
graph.layout.height = totalHeight;
graph.layout.yaxis = graph.layout.yaxis || {};
graph.layout.yaxis.categorygap = Y_AXIS_GAP_RATIO;
graph.layout.margin = graph.layout.margin || {};
graph.layout.margin.t = TOP_MARGIN;
graph.layout.margin.b = BOTTOM_MARGIN;

Plotly.newPlot('gantt_graph', graph, {});
</script>

注意事项

  • 如果存在同一y轴分类下多条形并行的场景,只需将分类数乘以单分类下最大并行条形数,即可适配计算逻辑
  • 两种方案都可以保证页面缩放时,条形厚度保持固定,不会随窗口尺寸变化

内容的提问来源于stack exchange,提问作者Jérôme

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 19:39:03