tradingview / lightweight-charts

Performant financial charts built with HTML5 canvas
https://www.tradingview.com/lightweight-charts/
Apache License 2.0
9.1k stars 1.57k forks source link

Unable to move chart into right end with only visible whitespace items #1605

Open MarvinMiles opened 3 months ago

MarvinMiles commented 3 months ago

Lightweight Charts™ Version: 4.1.4

Steps to reproduce:

  1. Create a chart instance
  2. Add series with only whitespace data, which contains time values per each second (for simplicity). From 9:00 to 11:00 unix time.
  3. Add series with actual data. From 9:45 to 10:15 unix time (thus placing it in the middle of whitespace timeline)
  4. Try to reach left and right end of timeline.

Actual behavior: Chart supports infinity moving to left side while whitespace series data is present (as expected). But moving chart forward into right side cause locking move when last bar of main series data riches starting point of timescale.

Expected behavior: Charts able to move left and right side freely while whitespace is present at timescale.

Screenshots:

https://github.com/tradingview/lightweight-charts/assets/1912057/83d37d49-f020-49d9-a132-93046dcbb635

JSFiddle link: https://jsfiddle.net/njw3bed9/1/

SlicedSilver commented 3 months ago

Thank you for the JSFiddle example which clearly shows the issue. I'm adding the 'needs investigation' label because we will need to discuss internally whether a change to this behaviour should be the default and expected behaviour going forward, or whether we should put the new behaviour behind an option.

I can see a benefit to both approaches. Additionally, the fact that the behaviour is different for the past (left) direction compared to the future direction is unexpected.

drgarlic commented 2 months ago

One solution to this is to have all of the area that you want scrollable as whitespace data and the very last data a line data with a NaN value.

Like so:

const whitespaceStartDate = "1970-01-01";
const whitespaceEndDate = "2100-01-01";
const whitespaceDateDataset: ((WhitespaceData | SingleValueData) & Numbered)[] =
  new Array(
    getNumberOfDaysBetweenTwoDates(
      new Date(whitespaceStartDate),
      new Date(whitespaceEndDate),
    ),
  );
// Hack to be able to scroll freely
// Setting them all to NaN is much slower
for (let i = 0; i < whitespaceDateDataset.length; i++) {
  const date = new Date(whitespaceStartDate);
  date.setUTCDate(date.getUTCDay() + i);

  const number = date.valueOf() / ONE_DAY_IN_MS;
  const time = dateToString(date);

  if (i === whitespaceDateDataset.length - 1) {
    whitespaceDateDataset[i] = {
      number,
      time,
      value: NaN,
    };
  } else {
    whitespaceDateDataset[i] = {
      number,
      time,
    };
  }
}