Skip to content

Commit 42f61b1

Browse files
象数lzxue
authored andcommitted
feat(tooltip): add text label support for crosshairs
- Add textX and textY options to display labels on crosshairs lines - Support customizable text position and offset configuration - Add textFill style for crosshairs labels in dark theme - Update hideRuleX and hideRuleY to clean up text elements Closes #7275
1 parent e944148 commit 42f61b1

3 files changed

Lines changed: 86 additions & 1 deletion

File tree

src/interaction/tooltip.ts

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Circle, DisplayObject, IElement, Line } from '@antv/g';
1+
import { Circle, DisplayObject, IElement, Line, Text } from '@antv/g';
22
import { sort, group, mean, bisector, minIndex } from '@antv/vendor/d3-array';
33
import { deepMix, lowerFirst, set, throttle, last, isNumber } from '@antv/util';
44
import { Tooltip as TooltipComponent } from '@antv/component';
@@ -347,13 +347,22 @@ function updateRuleX(
347347
polar,
348348
insetLeft,
349349
insetTop,
350+
textXposition = 'start' as const,
351+
textXoffsetX = 5,
352+
textXoffsetY = 0,
353+
textX = undefined,
354+
textY = undefined,
355+
textFill = undefined,
350356
...rest
351357
},
352358
) {
353359
const defaults = {
354360
lineWidth: 1,
355361
stroke: '#1b1e23',
356362
strokeOpacity: 0.5,
363+
textX,
364+
textY,
365+
textFill,
357366
...rest,
358367
};
359368

@@ -429,6 +438,31 @@ function updateRuleX(
429438
ruleX.style.y1 = y1;
430439
ruleX.style.y2 = y2;
431440
root.ruleX = ruleX;
441+
442+
// Render text if crosshairsLabelX or textX is provided
443+
const labelX = defaults.textX;
444+
if (labelX) {
445+
const createTextX = () => {
446+
const text = new Text({
447+
style: {
448+
text: labelX,
449+
fontSize: 12,
450+
fill: defaults.textFill || defaults.stroke,
451+
textAlign: textXposition,
452+
textBaseline: 'middle',
453+
},
454+
});
455+
root.appendChild(text);
456+
return text;
457+
};
458+
459+
const textX = root.textX || createTextX();
460+
// Position at end of the crosshair line (right side)
461+
textX.style.x = x2 + textXoffsetX;
462+
textX.style.y = (y1 + y2) / 2 + textXoffsetY;
463+
textX.style.text = labelX;
464+
root.textX = textX;
465+
}
432466
}
433467
}
434468

@@ -446,13 +480,20 @@ function updateRuleY(
446480
polar,
447481
insetLeft,
448482
insetTop,
483+
textYposition = 'end' as const,
484+
textYoffsetX = 5,
485+
textYoffsetY = 5,
486+
textY = undefined,
487+
textFill = undefined,
449488
...rest
450489
},
451490
) {
452491
const defaults = {
453492
lineWidth: 1,
454493
stroke: '#1b1e23',
455494
strokeOpacity: 0.5,
495+
textY,
496+
textFill,
456497
...rest,
457498
};
458499

@@ -498,6 +539,31 @@ function updateRuleY(
498539
ruleY.style.y1 = y1;
499540
ruleY.style.y2 = y2;
500541
root.ruleY = ruleY;
542+
543+
// Render text if textY is provided
544+
const labelY = defaults.textY;
545+
if (labelY) {
546+
const createTextY = () => {
547+
const text = new Text({
548+
style: {
549+
text: labelY,
550+
fontSize: 12,
551+
fill: defaults.textFill || defaults.stroke,
552+
textAlign: textYposition,
553+
textBaseline: 'bottom',
554+
},
555+
});
556+
root.appendChild(text);
557+
return text;
558+
};
559+
560+
const textYObj = root.textY || createTextY();
561+
// Position at end of the crosshair line (top)
562+
textYObj.style.x = (x1 + x2) / 2 + textYoffsetX;
563+
textYObj.style.y = y2 + textYoffsetY;
564+
textYObj.style.text = labelY;
565+
root.textY = textYObj;
566+
}
501567
}
502568
}
503569

@@ -506,13 +572,21 @@ function hideRuleY(root) {
506572
root.ruleY.remove();
507573
root.ruleY = undefined;
508574
}
575+
if (root.textY) {
576+
root.textY.remove();
577+
root.textY = undefined;
578+
}
509579
}
510580

511581
function hideRuleX(root) {
512582
if (root.ruleX) {
513583
root.ruleX.remove();
514584
root.ruleX = undefined;
515585
}
586+
if (root.textX) {
587+
root.textX.remove();
588+
root.textX = undefined;
589+
}
516590
}
517591

518592
function updateMarker(root, { data, style, theme }) {

src/spec/interaction.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,16 @@ export type TooltipInteraction = {
219219
event, // @todo
220220
options: { title: 'string'; items: TooltipItemValue[] },
221221
) => HTMLElement | string;
222+
// Crosshairs text label options
223+
crosshairsTextFill?: string;
224+
textX?: string;
225+
textY?: string;
226+
textXposition?: 'start' | 'center' | 'end';
227+
textYposition?: 'start' | 'center' | 'end';
228+
textXoffsetX?: number;
229+
textXoffsetY?: number;
230+
textYoffsetX?: number;
231+
textYoffsetY?: number;
222232
} & Record<`crosshairs${any}`, any> &
223233
Record<`marker${any}`, any>;
224234

src/theme/dark.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export const Dark: TC<DarkOptions> = (options) => {
6666
crosshairsStroke: '#fff',
6767
crosshairsLineWidth: 1,
6868
crosshairsStrokeOpacity: 0.25,
69+
crosshairsTextFill: '#fff',
6970
css: {
7071
[g2Selector('tooltip')]: {
7172
background: '#1f1f1f',

0 commit comments

Comments
 (0)