Skip to content

Commit

Permalink
Merge pull request #1621 from tradingview/1620-improve-price-scale-la…
Browse files Browse the repository at this point in the history
…bels-alignment

1620: Improve price scale labals alignment
  • Loading branch information
SlicedSilver authored Jun 21, 2024
2 parents f9cbe08 + 68fbe34 commit 71b3395
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 27 deletions.
8 changes: 4 additions & 4 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ module.exports = [
{
name: 'CJS',
path: 'dist/lightweight-charts.production.cjs',
limit: '48.24 KB',
limit: '48.27 KB',
},
{
name: 'ESM',
path: 'dist/lightweight-charts.production.mjs',
limit: '48.16 KB',
limit: '48.18 KB',
},
{
name: 'Standalone-ESM',
path: 'dist/lightweight-charts.standalone.production.mjs',
limit: '49.87 KB',
limit: '49.92 KB',
},
{
name: 'Standalone',
path: 'dist/lightweight-charts.standalone.production.js',
limit: '49.91 KB',
limit: '49.96 KB',
},
];
71 changes: 48 additions & 23 deletions src/gui/price-axis-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,52 @@ function buildPriceAxisViewsGetter(
};
}

function recalculateOverlapping(views: IPriceAxisView[], direction: 1 | -1, scaleHeight: number, rendererOptions: Readonly<PriceAxisViewRendererOptions>): void {
if (!views.length) {
return;
}
let currentGroupStart = 0;

const initLabelHeight = views[0].height(rendererOptions, true);
let spaceBeforeCurrentGroup = direction === 1
? scaleHeight / 2 - (views[0].getFixedCoordinate() - initLabelHeight / 2)
: views[0].getFixedCoordinate() - initLabelHeight / 2 - scaleHeight / 2;
spaceBeforeCurrentGroup = Math.max(0, spaceBeforeCurrentGroup);

for (let i = 1; i < views.length; i++) {
const view = views[i];
const prev = views[i - 1];
const height = prev.height(rendererOptions, false);
const coordinate = view.getFixedCoordinate();
const prevFixedCoordinate = prev.getFixedCoordinate();

const overlap = direction === 1
? coordinate > prevFixedCoordinate - height
: coordinate < prevFixedCoordinate + height;

if (overlap) {
const fixedCoordinate = prevFixedCoordinate - height * direction;
view.setFixedCoordinate(fixedCoordinate);
const edgePoint = fixedCoordinate - direction * height / 2;
const outOfViewport = direction === 1 ? edgePoint < 0 : edgePoint > scaleHeight;
if (outOfViewport && spaceBeforeCurrentGroup > 0) {
// shift the whole group up or down
const desiredGroupShift = direction === 1 ? -1 - edgePoint : edgePoint - scaleHeight;
const possibleShift = Math.min(desiredGroupShift, spaceBeforeCurrentGroup);
for (let k = currentGroupStart; k < views.length; k++) {
views[k].setFixedCoordinate(views[k].getFixedCoordinate() + direction * possibleShift);
}
spaceBeforeCurrentGroup -= possibleShift;
}
} else {
currentGroupStart = i;
spaceBeforeCurrentGroup = direction === 1
? prevFixedCoordinate - height - coordinate
: coordinate - (prevFixedCoordinate + height);
}
}
}

export class PriceAxisWidget implements IDestroyable {
private readonly _pane: PaneWidget;
private readonly _options: Readonly<ChartOptionsInternalBase>;
Expand Down Expand Up @@ -597,29 +643,8 @@ export class PriceAxisWidget implements IDestroyable {
}
}

for (let i = 1; i < top.length; i++) {
const view = top[i];
const prev = top[i - 1];
const height = prev.height(rendererOptions, false);
const coordinate = view.coordinate();
const prevFixedCoordinate = prev.getFixedCoordinate();

if (coordinate > prevFixedCoordinate - height) {
view.setFixedCoordinate(prevFixedCoordinate - height);
}
}

for (let j = 1; j < bottom.length; j++) {
const view = bottom[j];
const prev = bottom[j - 1];
const height = prev.height(rendererOptions, true);
const coordinate = view.coordinate();
const prevFixedCoordinate = prev.getFixedCoordinate();

if (coordinate < prevFixedCoordinate + height) {
view.setFixedCoordinate(prevFixedCoordinate + height);
}
}
recalculateOverlapping(top, 1, this._size.height, rendererOptions);
recalculateOverlapping(bottom, -1, this._size.height, rendererOptions);
}

private _drawBackLabels(target: CanvasRenderingTarget2D): void {
Expand Down
44 changes: 44 additions & 0 deletions tests/e2e/graphics/test-cases/price-scale/improve-alignment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function runTestCase(container) {
const chartOptions = {
height: 500,
width: 600,
rightPriceScale: {
scaleMargins: {
top: 0,
bottom: 0,
},
entireTextOnly: true,
alignLabels: true,
},
};

const chart = (window.chart = LightweightCharts.createChart(
container,
chartOptions
));

const data1 = Array.from({ length: 10 }).map((_, index) => ({ time: index * 10000, value: 100 - index }));
const data2 = Array.from({ length: 10 }).map((_, index) => ({ time: index * 10000, value: 108.3 - index * 2 }));
const data3 = Array.from({ length: 10 }).map((_, index) => ({ time: index * 10000, value: 99 + index }));
const data4 = Array.from({ length: 10 }).map((_, index) => ({ time: index * 10000, value: 92.8 + (index - 1) * 2 }));

const series1 = chart.addLineSeries();
series1.setData(data1);

const series2 = chart.addLineSeries({
color: 'green',
});
series2.setData(data2);

const series3 = chart.addLineSeries({
color: 'purple',
});
series3.setData(data3);

const series4 = chart.addLineSeries({
color: 'orange',
});
series4.setData(data4);

chart.timeScale().fitContent();
}

0 comments on commit 71b3395

Please sign in to comment.