Skip to content

Commit

Permalink
Fixed locking visible range on resize when fixing left edge is enabled
Browse files Browse the repository at this point in the history
Fixes #991

1. We couldn't rely on the state while updating the state without a proper verifying that the state is correct.
  Thus if we change width/barSpacing/rightOffset we have to mark visible
  range as invalidated to make sure that it will be updated on getting current logical/visible range.
2. To fix left edge to could rely on logical range rather than strict range.
  Visible range is a range of edges of a bar, not the middle.
  • Loading branch information
timocov committed Feb 21, 2022
1 parent 0fd0c15 commit 91efc8e
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 19 deletions.
37 changes: 18 additions & 19 deletions src/model/time-scale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,42 +361,41 @@ export class TimeScale {
return this._width;
}

public setWidth(width: number): void {
if (!isFinite(width) || width <= 0) {
public setWidth(newWidth: number): void {
if (!isFinite(newWidth) || newWidth <= 0) {
return;
}

if (this._width === width) {
if (this._width === newWidth) {
return;
}

if (this._options.lockVisibleTimeRangeOnResize && this._width) {
const oldWidth = this._width;
this._width = newWidth;
this._visibleRangeInvalidated = true;

if (this._options.lockVisibleTimeRangeOnResize && oldWidth !== 0) {
// recalculate bar spacing
const newBarSpacing = this._barSpacing * width / this._width;
const newBarSpacing = this._barSpacing * newWidth / oldWidth;
this._barSpacing = newBarSpacing;
}

// if time scale is scrolled to the end of data and we have fixed right edge
// keep left edge instead of right
// we need it to avoid "shaking" if the last bar visibility affects time scale width
if (this._options.fixLeftEdge) {
const visibleRange = this.visibleStrictRange();
if (visibleRange !== null) {
const firstVisibleBar = visibleRange.left();
// firstVisibleBar could be less than 0
// since index is a center of bar
if (firstVisibleBar <= 0) {
const delta = this._width - width;
// reduce _rightOffset means move right
// we could move more than required - this will be fixed by _correctOffset()
this._rightOffset -= Math.round(delta / this._barSpacing) + 1;
}
const visibleRange = this.visibleLogicalRange();

// note that logical left range means not the middle of a bar (it's the left border)
if (visibleRange !== null && visibleRange.left() <= 0) {
const delta = oldWidth - newWidth;
// reduce _rightOffset means move right
// we could move more than required - this will be fixed by _correctOffset()
this._rightOffset -= Math.round(delta / this._barSpacing) + 1;
this._visibleRangeInvalidated = true;
}
}

this._width = width;
this._visibleRangeInvalidated = true;

// updating bar spacing should be first because right offset depends on it
this._correctBarSpacing();
this._correctOffset();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
function generateData() {
const res = [];
const time = new Date(Date.UTC(2018, 0, 1, 0, 0, 0, 0));
for (let i = 0; i < 10; ++i) {
res.push({
time: time.getTime() / 1000,
value: i,
});

time.setUTCDate(time.getUTCDate() + 1);
}

return res;
}

function runTestCase(container) {
const chart = LightweightCharts.createChart(container, {
timeScale: {
fixLeftEdge: true,
fixRightEdge: true,
lockVisibleTimeRangeOnResize: true,
},
});

const series = chart.addLineSeries();

const data = generateData();

series.setData(data);

chart.timeScale().setVisibleLogicalRange({ from: 0.5, to: data.length - 1.5 });

return new Promise(resolve => {
requestAnimationFrame(() => {
chart.applyOptions({ width: 550 });

requestAnimationFrame(() => {
chart.applyOptions({ width: 600 });

requestAnimationFrame(() => {
const visibleRange = chart.timeScale().getVisibleLogicalRange();
console.assert(visibleRange.from === 0.5, `from in logical range should be 0.5, but is ${visibleRange.from}`);
console.assert(visibleRange.to === data.length - 1.5, `to in logical range should be ${data.length - 1.5}, but is ${visibleRange.to}`);
resolve();
});
});
});
});
}
3 changes: 3 additions & 0 deletions website/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ function HeroChart(): JSX.Element {

const { width, height } = container.getBoundingClientRect();
chart.resize(width, height);

// TODO: remove this after releasing the new version (fixed in v4.0.0)
// and use lockVisibleTimeRangeOnResize time scale option instead
chart.timeScale().setVisibleLogicalRange(visibleLogicalRange);
};

Expand Down

0 comments on commit 91efc8e

Please sign in to comment.