Skip to content

Commit 2631ecb

Browse files
committed
fix(image): optimize text rendering
1 parent 9685c63 commit 2631ecb

File tree

18 files changed

+499
-204
lines changed

18 files changed

+499
-204
lines changed

packages/image/src/annotations/Annotation.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { BasicImageAnnotation, ToolName } from '../interface';
22
import { Group } from '../shapes/Group';
3-
import { type Shape } from '../shapes';
4-
import { monitor } from '../singletons';
3+
import { eventEmitter, monitor } from '../singletons';
54
import { DEFAULT_LABEL_COLOR } from '../constant';
5+
import type { DomPortal } from '../core/DomPortal';
6+
import { EInternalEvent } from '../enums/internalEvent.enum';
67

78
// TODO: 去除本类的any
89
export interface AnnotationParams<Data extends BasicImageAnnotation, Style> {
@@ -23,16 +24,18 @@ export interface AnnotationParams<Data extends BasicImageAnnotation, Style> {
2324
onPick?: (e: MouseEvent, annotation: any) => void;
2425
}
2526

26-
export class Annotation<Data extends BasicImageAnnotation, IShape extends Shape<Style>, Style> {
27+
export class Annotation<Data extends BasicImageAnnotation, Style> {
2728
public id: string;
2829

30+
public doms: DomPortal[] = [];
31+
2932
public data: Data;
3033

3134
public name: ToolName;
3235

3336
public style: Style;
3437

35-
public group: Group<IShape, Style>;
38+
public group: Group;
3639

3740
public hoveredStyle?: Style | ((style: Style) => Style);
3841

@@ -63,8 +66,20 @@ export class Annotation<Data extends BasicImageAnnotation, IShape extends Shape<
6366

6467
// 建立order和id的映射关系
6568
monitor?.setOrderIndexedAnnotationIds(data.order, id);
69+
70+
this.group.on(EInternalEvent.MouseOver, this.__handleMouseOver);
71+
this.group.on(EInternalEvent.MouseOut, this.__handleMouseOut);
72+
eventEmitter.on(EInternalEvent.NoTarget, this.__handleMouseOut);
6673
}
6774

75+
private __handleMouseOver = () => {
76+
this.doms.forEach((dom) => dom.toTop());
77+
};
78+
79+
private __handleMouseOut = () => {
80+
this.doms.forEach((dom) => dom.resetZIndex());
81+
};
82+
6883
public get bbox() {
6984
return this.group.bbox;
7085
}
@@ -84,7 +99,36 @@ export class Annotation<Data extends BasicImageAnnotation, IShape extends Shape<
8499
}
85100

86101
public destroy() {
102+
this.doms.forEach((dom) => dom.destroy());
87103
this.data = null as any;
88104
this.group.destroy();
105+
this.group.off(EInternalEvent.MouseOver, this.__handleMouseOver);
106+
this.group.off(EInternalEvent.MouseOut, this.__handleMouseOut);
107+
eventEmitter.off(EInternalEvent.NoTarget, this.__handleMouseOut);
108+
}
109+
110+
protected generateLabelDom(text: string, style?: string, extra?: string) {
111+
return `
112+
<div style="color: #fff; font-size: 12px; font-weight: bold; background-color: ${
113+
this.labelColor
114+
}; padding: 2px 4px; ${style ?? ''};">
115+
${this.showOrder ? this.data.order + ' ' : ''}${text}
116+
${extra ?? ''}
117+
</div>
118+
`;
119+
}
120+
121+
protected generateAttributeDom(text: string, style?: string, extra?: string) {
122+
return `
123+
<div style="color: #fff; font-size: 12px; font-weight: bold; background-color: ${
124+
this.labelColor
125+
}; padding: 2px 4px; ${style ?? ''};">
126+
${text
127+
.split('\n')
128+
.map((line) => `<div>${line}</div>`)
129+
.join('')}
130+
${extra ?? ''}
131+
</div>
132+
`;
89133
}
90134
}

packages/image/src/annotations/Cuboid.annotation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ export interface CuboidData extends BasicImageAnnotation {
4242
back: CuboidVertex;
4343
}
4444

45-
export type CuboidGroup = Group<Polygon | ShapeText, CuboidStyle>;
45+
export type CuboidGroup = Group;
4646

47-
export class AnnotationCuboid extends Annotation<CuboidData, Polygon | ShapeText, CuboidStyle> {
47+
export class AnnotationCuboid extends Annotation<CuboidData, CuboidStyle> {
4848
private _realFront: Polygon | null = null;
4949

5050
public labelColor: string = LabelBase.DEFAULT_COLOR;

packages/image/src/annotations/Point.annotation.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import { EInternalEvent } from '../enums';
1616

1717
export type PointData = BasicImageAnnotation & AxisPoint;
1818

19-
export type PointGroup = Group<Point | ShapeText, PointStyle>;
19+
export type PointGroup = Group;
2020

21-
export class AnnotationPoint extends Annotation<PointData, Point | ShapeText, PointStyle> {
21+
export class AnnotationPoint extends Annotation<PointData, PointStyle> {
2222
public labelColor: string = LabelBase.DEFAULT_COLOR;
2323

2424
public strokeColor: string = LabelBase.DEFAULT_COLOR;
@@ -62,22 +62,22 @@ export class AnnotationPoint extends Annotation<PointData, Point | ShapeText, Po
6262
}),
6363
);
6464

65-
const attributesText = AnnotationPoint.labelStatic.getLabelTextWithAttributes(data.label, data.attributes);
66-
67-
group.add(
68-
new ShapeText({
69-
id: uid(),
70-
coordinate: {
71-
x: data.x,
72-
y: data.y,
73-
},
74-
text: `${this.showOrder ? data.order + ' ' : ''}${attributesText}`,
75-
style: {
76-
opacity: visible ? 1 : 0,
77-
fill: labelColor,
78-
},
79-
}),
80-
);
65+
// const attributesText = AnnotationPoint.labelStatic.getLabelTextWithAttributes(data.label, data.attributes);
66+
67+
// group.add(
68+
// new ShapeText({
69+
// id: uid(),
70+
// coordinate: {
71+
// x: data.x,
72+
// y: data.y,
73+
// },
74+
// text: `${this.showOrder ? data.order + ' ' : ''}${attributesText}`,
75+
// style: {
76+
// opacity: visible ? 1 : 0,
77+
// fill: labelColor,
78+
// },
79+
// }),
80+
// );
8181
}
8282

8383
private _handleMouseOver = () => {

packages/image/src/annotations/Rect.annotation.ts

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type { Group } from '../shapes';
1212
import { LabelBase } from './Label.base';
1313
import { EInternalEvent } from '../enums';
1414
import { eventEmitter } from '../singletons';
15+
import { DomPortal } from '../core/DomPortal';
1516

1617
export interface RectData extends BasicImageAnnotation {
1718
x: number;
@@ -20,9 +21,9 @@ export interface RectData extends BasicImageAnnotation {
2021
height: number;
2122
}
2223

23-
export type RectGroup = Group<Rect | ShapeText, RectStyle>;
24+
export type RectGroup = Group;
2425

25-
export class AnnotationRect extends Annotation<RectData, Rect | ShapeText, RectStyle> {
26+
export class AnnotationRect extends Annotation<RectData, RectStyle> {
2627
public labelColor: string = LabelBase.DEFAULT_COLOR;
2728

2829
public strokeColor: string = LabelBase.DEFAULT_COLOR;
@@ -46,7 +47,7 @@ export class AnnotationRect extends Annotation<RectData, Rect | ShapeText, RectS
4647
static labelStatic: LabelBase;
4748

4849
private _setupShapes() {
49-
const { data, group, style, labelColor, strokeColor } = this;
50+
const { data, group, style, strokeColor } = this;
5051

5152
const { visible = true } = data;
5253
const commonStyle = {
@@ -67,22 +68,36 @@ export class AnnotationRect extends Annotation<RectData, Rect | ShapeText, RectS
6768
}),
6869
);
6970

70-
const attributesText = AnnotationRect.labelStatic.getLabelTextWithAttributes(data.label, data.attributes);
71-
72-
group.add(
73-
new ShapeText({
74-
id: uid(),
75-
coordinate: {
76-
x: data.x,
77-
y: data.y + data.height,
78-
},
79-
text: `${this.showOrder ? data.order + ' ' : ''}${attributesText}`,
80-
style: {
81-
opacity: visible ? 1 : 0,
82-
fill: labelColor,
83-
},
71+
const labelText = AnnotationRect.labelStatic.getLabelText(data.label);
72+
const attributesText = AnnotationRect.labelStatic.getAttributeTexts(data.label, data.attributes);
73+
74+
this.doms.push(
75+
new DomPortal({
76+
content: this.generateLabelDom(labelText),
77+
getPosition: (shape) => ({
78+
x: shape.dynamicCoordinate[0].x,
79+
y: shape.dynamicCoordinate[0].y - 28,
80+
}),
81+
order: data.order,
82+
preventPointerEvents: true,
83+
bindShape: group.shapes[0] as Rect,
8484
}),
8585
);
86+
87+
if (attributesText) {
88+
this.doms.push(
89+
new DomPortal({
90+
content: this.generateAttributeDom(attributesText),
91+
getPosition: (shape) => ({
92+
x: shape.dynamicCoordinate[0].x,
93+
y: shape.dynamicCoordinate[0].y + (shape as Rect).dynamicHeight + 5,
94+
}),
95+
order: data.order,
96+
preventPointerEvents: true,
97+
bindShape: group.shapes[0] as Rect,
98+
}),
99+
);
100+
}
86101
}
87102

88103
private _handleMouseOver = () => {

0 commit comments

Comments
 (0)