Skip to content

Commit 9a0b4ef

Browse files
DmitiryPotychkinanandtiwaryaaron-steinfeld
authored
Fix cartesian axis boundary (#502)
* fix: ENG-7505 - timestamps boundary and truncate * fix: (cartesian axis boundary) - linting * fix: (cartesian axis boundary) - code style * fix(cartesian-axis): refactoring * fix(cartesian-axis): refactoring Co-authored-by: Dmitriy Potychkin <dmitriy.traceable.ai> Co-authored-by: Anand Tiwary <[email protected]> Co-authored-by: Aaron Steinfeld <[email protected]>
1 parent 2f2db19 commit 9a0b4ef

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

projects/observability/src/shared/components/cartesian/d3/axis/cartesian-axis.ts

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ export class CartesianAxis<TData = {}> {
4848
.attr('transform', this.getAxisTransform())
4949
.node()!;
5050

51-
this.maybeTruncateAxisTicks(axisSvgSelection);
5251
this.addGridLinesIfNeeded();
5352

5453
return this;
@@ -79,17 +78,87 @@ export class CartesianAxis<TData = {}> {
7978
if (!this.configuration.tickLabels) {
8079
selection.selectAll('.tick text').remove();
8180
}
81+
82+
if (this.configuration.location === AxisLocation.Bottom) {
83+
const maxTextTickTextLength = this.getMaxTickTextLength(selection);
84+
const isLabelRotated = this.rotateAxisTicks(selection, maxTextTickTextLength);
85+
this.removeOverflowedTicks(selection, maxTextTickTextLength, isLabelRotated);
86+
} else {
87+
this.maybeTruncateAxisTicks(selection);
88+
}
89+
}
90+
91+
private getMaxTickTextLength(axisSvgSelection: Selection<SVGGElement, unknown, null, undefined>): number {
92+
const ticksSelection = axisSvgSelection.selectAll('text');
93+
94+
const allElementLength: number[] = [];
95+
96+
ticksSelection.each((_, index, nodes) =>
97+
allElementLength.push(this.svgUtilService.getElementTextLength(nodes[index] as SVGTextElement))
98+
);
99+
100+
return Math.max(...allElementLength);
82101
}
83102

84103
private maybeTruncateAxisTicks(axisSvgSelection: Selection<SVGGElement, unknown, null, undefined>): void {
85104
const ticksSelection = axisSvgSelection.selectAll('text');
86105
const tickBandwidth = Math.abs(this.scale.getRangeEnd() - this.scale.getRangeStart()) / ticksSelection.size();
87106

88-
ticksSelection.each((_datum, index, nodes) =>
107+
ticksSelection.each((_, index, nodes) =>
89108
this.svgUtilService.truncateText(nodes[index] as SVGTextElement, tickBandwidth)
90109
);
91110
}
92111

112+
private getTickTransformValue(tick: Selection<BaseType, unknown, null, undefined>, axis: 'x' | 'y'): number {
113+
const tickTranslateAxis = axis === 'x' ? 0 : 1;
114+
115+
const tickTranslateValues = tick.attr('transform').replace(/.*\(|\).*/g, '');
116+
const tickTranslateValue = tickTranslateValues.split(',')[tickTranslateAxis] ?? '0';
117+
118+
return parseInt(tickTranslateValue);
119+
}
120+
121+
private removeOverflowedTicks(
122+
axisSvgSelection: Selection<SVGGElement, unknown, null, undefined>,
123+
maxTextTickTextLength: number,
124+
isLabelRotated: boolean
125+
): void {
126+
axisSvgSelection.selectAll('.tick').each((_, i, n) => {
127+
const currentTick = select(n[i]);
128+
129+
const currentTickPosition = this.getTickTransformValue(currentTick, 'x');
130+
const isTickOutOfLeftEdge = currentTickPosition < maxTextTickTextLength / 2;
131+
const isTickOutOfRightEdge =
132+
this.scale.initData.bounds.endX - (currentTickPosition + (isLabelRotated ? 0 : maxTextTickTextLength / 2)) < 0;
133+
134+
if (isTickOutOfLeftEdge || isTickOutOfRightEdge) {
135+
currentTick.remove();
136+
}
137+
});
138+
}
139+
140+
private rotateAxisTicks(
141+
axisSvgSelection: Selection<SVGGElement, unknown, null, undefined>,
142+
maxTextLength: number
143+
): boolean {
144+
const ticksSelection = axisSvgSelection.selectAll('text');
145+
146+
const tickBandwidth = (this.scale.getRangeEnd() - this.scale.getRangeStart()) / ticksSelection.size();
147+
148+
const isLabelRotate = maxTextLength > tickBandwidth;
149+
150+
if (isLabelRotate) {
151+
axisSvgSelection
152+
.selectAll('.tick text')
153+
.style('text-anchor', 'end')
154+
.style('font-size', '100%')
155+
.attr('y', '3')
156+
.attr('transform', `rotate(-35)`);
157+
}
158+
159+
return isLabelRotate;
160+
}
161+
93162
private getAxisTransform(): string {
94163
switch (this.configuration.location) {
95164
case AxisLocation.Left:

projects/observability/src/shared/components/utils/svg/svg-util.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ export class SvgUtilService {
8080
throw Error('No parent SVG tag found for provided element');
8181
}
8282

83+
public getElementTextLength(element: SVGTextElement): number {
84+
return this.domElementMeasurerService.getComputedTextLength(element);
85+
}
86+
8387
public truncateText(element: SVGTextElement, width: number): void {
8488
let textLength = this.domElementMeasurerService.getComputedTextLength(element);
8589

0 commit comments

Comments
 (0)