Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce calls to getStringSize when calculating visible ticks (#2589) #3953

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cartesian/getEquidistantTicks.ts
Expand Up @@ -35,7 +35,7 @@ export function getEquidistantTicks(

const tickCoord = entry.coordinate;
// We will always show the first tick.
const isShow = index === 0 || isVisible(sign, tickCoord, size, start, end);
const isShow = index === 0 || isVisible(sign, tickCoord, () => size, start, end);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the tick size not already computed in line 34?
If I understand correctly, this should be

    // Check if the element collides with the next element
    const getSize = () => getTickSize(entry, index);

    const tickCoord = entry.coordinate;
    // We will always show the first tick.
    const isShow = index === 0 || isVisible(sign, tickCoord, getSize, start, end);

Now we would not call getTickSize directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing so triggers the following lint error:

image

But I think I managed to find a workaround. Pushing a new commit 馃槃


if (!isShow) {
// Start all over with a larger stepsize
Expand Down
33 changes: 24 additions & 9 deletions src/cartesian/getTicks.ts
Expand Up @@ -24,9 +24,17 @@ function getTicksEnd(

for (let i = len - 1; i >= 0; i--) {
let entry = result[i];
const size = getTickSize(entry, i);
let size: number | undefined;
const getSize = () => {
if (size === undefined) {
size = getTickSize(entry, i);
}

return size;
};
nikolasrieble marked this conversation as resolved.
Show resolved Hide resolved

if (i === len - 1) {
const gap = sign * (entry.coordinate + (sign * size) / 2 - end);
const gap = sign * (entry.coordinate + (sign * getSize()) / 2 - end);
result[i] = entry = {
...entry,
tickCoord: gap > 0 ? entry.coordinate - gap * sign : entry.coordinate,
Expand All @@ -35,10 +43,10 @@ function getTicksEnd(
result[i] = entry = { ...entry, tickCoord: entry.coordinate };
}

const isShow = isVisible(sign, entry.tickCoord, size, start, end);
const isShow = isVisible(sign, entry.tickCoord, getSize, start, end);

if (isShow) {
end = entry.tickCoord - sign * (size / 2 + minTickGap);
end = entry.tickCoord - sign * (getSize() / 2 + minTickGap);
result[i] = { ...entry, isShow: true };
}
}
Expand Down Expand Up @@ -69,7 +77,7 @@ function getTicksStart(
tickCoord: tailGap > 0 ? tail.coordinate - tailGap * sign : tail.coordinate,
};

const isTailShow = isVisible(sign, tail.tickCoord, tailSize, start, end);
const isTailShow = isVisible(sign, tail.tickCoord, () => tailSize, start, end);
nikolasrieble marked this conversation as resolved.
Show resolved Hide resolved

if (isTailShow) {
end = tail.tickCoord - sign * (tailSize / 2 + minTickGap);
Expand All @@ -80,10 +88,17 @@ function getTicksStart(
const count = preserveEnd ? len - 1 : len;
for (let i = 0; i < count; i++) {
let entry = result[i];
const size = getTickSize(entry, i);
let size: number | undefined;
const getSize = () => {
if (size === undefined) {
size = getTickSize(entry, i);
}

return size;
};

if (i === 0) {
const gap = sign * (entry.coordinate - (sign * size) / 2 - start);
const gap = sign * (entry.coordinate - (sign * getSize()) / 2 - start);
result[i] = entry = {
...entry,
tickCoord: gap < 0 ? entry.coordinate - gap * sign : entry.coordinate,
Expand All @@ -92,10 +107,10 @@ function getTicksStart(
result[i] = entry = { ...entry, tickCoord: entry.coordinate };
}

const isShow = isVisible(sign, entry.tickCoord, size, start, end);
const isShow = isVisible(sign, entry.tickCoord, getSize, start, end);

if (isShow) {
start = entry.tickCoord + sign * (size / 2 + minTickGap);
start = entry.tickCoord + sign * (getSize() / 2 + minTickGap);
result[i] = { ...entry, isShow: true };
}
}
Expand Down
16 changes: 15 additions & 1 deletion src/util/TickUtils.ts
Expand Up @@ -23,7 +23,21 @@ export function getTickBoundaries(viewBox: CartesianViewBox, sign: number, sizeK
};
}

export function isVisible(sign: number, tickPosition: number, size: number, start: number, end: number): boolean {
export function isVisible(
sign: number,
tickPosition: number,
getSize: () => number,
start: number,
end: number,
): boolean {
/* Since getSize() is expensive (it reads the ticks' size from the DOM), we do this check first to avoid calculating
* the tick's size. */
if (sign * tickPosition < sign * start || sign * tickPosition > sign * end) {
return false;
}
nikolasrieble marked this conversation as resolved.
Show resolved Hide resolved

const size = getSize();

return sign * (tickPosition - (sign * size) / 2 - start) >= 0 && sign * (tickPosition + (sign * size) / 2 - end) <= 0;
}

Expand Down
28 changes: 28 additions & 0 deletions test/util/TickUtils.spec.ts
@@ -0,0 +1,28 @@
import { isVisible } from '../../src/util/TickUtils';

describe('isVisible', () => {
test.each([
{ sign: 1, position: 50, size: 10, start: 0, end: 100 },
{ sign: 1, position: 50, size: 50, start: 0, end: 100 },
{ sign: 1, position: 50, size: 100, start: 0, end: 100 },
{ sign: 0, position: 50, size: 10, start: 0, end: 100 },
{ sign: 0, position: 50, size: 50, start: 0, end: 100 },
{ sign: 0, position: 50, size: 100, start: 0, end: 100 },
])('is returns true if tick is inside limits: (%o)', ({ sign, position, size, start, end }) => {
expect(isVisible(sign, position, () => size, start, end)).toBeTruthy();
});

test.each([
{ sign: -1, position: 50, size: 10, start: 0, end: 100 },
{ sign: -1, position: 50, size: 50, start: 0, end: 100 },
{ sign: -1, position: 50, size: 100, start: 0, end: 100 },
{ sign: 1, position: 50, size: 101, start: 0, end: 100 },
{ sign: 1, position: 10, size: 10_000, start: 50, end: 100 },
{ sign: 1, position: 110, size: 10_000, start: 50, end: 100 },
{ sign: -1, position: 50, size: 101, start: 0, end: 100 },
{ sign: -1, position: 10, size: 10_000, start: 50, end: 100 },
{ sign: -1, position: 110, size: 10_000, start: 50, end: 100 },
])('is returns false if tick is outside limits: (%o)', ({ sign, position, size, start, end }) => {
expect(isVisible(sign, position, () => size, start, end)).toBeFalsy();
});
});