plotly / plotly/plotly.js

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

オープン
#7,968 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

bug P2 size: 1
主要言語
JavaScript
スター
18.3k
フォーク
2k
平均マージ
2日 12時間
マージ済み PR(30日)
28

説明

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.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず、issue で言及されている Axes.minDtick と、setConvert、ax.clearCalc、doCalcdata の各エントリーポイントを調べます。提供された box と scatter の figure を使って Plotly.newPlot と Plotly.react の違いを再現し、その後、figure 間で強制された tick の間隔がリセットされ、両方のパスが同じ tick を生成することを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
javascript
領域
data-visualization
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
静か
明瞭さ
明確に書かれている
初心者へのやさしさ
65/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。