[BUG]: forced minimum tick spacing (box/violin/candlestick/ohlc) leaks between figures on the same graph div

未關閉
#7,968 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

評估

難度
3/5
預估耗時
1-2 天
新手友好度
65/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
冷清
技術堆疊
javascript

研究方向

先檢查 Axes.minDtick,以及 issue 中提到的 setConvert、ax.clearCalc 和 doCalcdata 進入點。使用提供的 box 和 scatter 圖形重現 Plotly.newPlot 與 Plotly.react 之間的差異,然後確認強制設定的 tick 間距會在圖形之間重設,且兩條路徑產生相同的 tick。

由索引模型根據 Issue 內容生成。

描述

bug P2 size: 1
Description

Box, violin, candlestick and ohlc traces ask their position axis for a minimum tick spacing, so that each box gets a tick of its own rather than ticks at meaningless in-between positions. That forcing is silently lost whenever the figure is drawn into a graph div that already held a different figure — so Plotly.react, restyle, addTraces and friends can produce different ticks than Plotly.newPlot of the exact same figure.

It goes the other way too: a graph div that once held a box plot keeps the forced spacing after you react to a trace type that never asked for it.

Steps to reproduce
var boxFig = {
    data: [{type: 'box', x: [1, 1, 2, 2, 3, 3], y: [1, 2, 3, 4, 5, 6]}],
    layout: {width: 700, height: 400}
};
var scatterFig = {data: [{y: [1, 2, 3]}], layout: {width: 700, height: 400}};

// x ticks: 1, 2, 3  — correct, one per box
Plotly.newPlot(gd, boxFig);

// x ticks: 0.5, 1, 1.5, 2, 2.5, 3, 3.5  — same figure, half the ticks land between boxes
Plotly.newPlot(gd, scatterFig).then(function() { return Plotly.react(gd, boxFig); });

It is most visible on a date axis. Five daily candles at width: 1000, reached by reacting from a line chart over the same dates:

newPlot:  Jan 1 | Jan 2 | Jan 3 | Jan 4 | Jan 5
react:    12:00 Dec 31, 2023 | 00:00 Jan 1, 2024 | 12:00 | 00:00 Jan 2, 2024 | 12:00 | ...

Every second tick falls in the gap between two candles, and the axis now starts on the day before the data.

Notes

Axes.minDtick keeps its state in ax._minDtick / ax._forceTick0, with three meanings: undefined (nothing forced yet — adopt this trace's spacing), a positive number (a forcing is in effect), and 0 (forcing cancelled — by non-grouped bars, or by scatter/heatmap calc — and sticky, so a later trace can't reinstate it).

The reset back to undefined between passes sits at the bottom of setConvert, but it can't take effect on a real axis: setConvert runs while supplyDefaults builds the new _fullLayout, where those keys don't exist yet, and relinkPrivateKeys then copies the old values back onto it. So whichever figure the graph div held first decides the forcing for every figure after it. newPlot escapes it only because it starts from an empty _fullLayout.

Found by a sweep comparing react against newPlot of the same figure — 7 of 12 divergences traced back here.

Fix proposed in #7950, which moves the reset into ax.clearCalc(), alongside the equivalent relink cleanup doCalcdata already does for shared color axes.

主要語言
JavaScript
星號
18.3k
分支
2k
平均合併
2 天 12 小時
30 天內合併 PR
28

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

plotly/plotly.js 的其他 Issue

查看 plotly/plotly.js 的全部 Issue

相似的 Issue

更多 JavaScript Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。