Skip to content

Commit e3da845

Browse files
committed
🐛 fix: fix text position parsing
1 parent b79f169 commit e3da845

File tree

5 files changed

+44
-29
lines changed

5 files changed

+44
-29
lines changed

src/model/Layer/Text.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,13 @@ class Text extends BaseLayer {
128128
switch (whiteSpace) {
129129
case 'normal':
130130
case 'nowrap':
131-
return text
132-
.trim()
133-
.replace(/\n/g, ' ') // replace newline characters with space
134-
.replace(/\s+/g, ' '); // collapse whitespace
131+
return (
132+
text
133+
// replace newline characters with space
134+
.replace(/\n/g, ' ')
135+
// collapse whitespace
136+
.replace(/\s+/g, ' ')
137+
);
135138
case 'pre-line':
136139
return text
137140
.replace(/(^[^\S\n]+)|([^\S\n]+$)/g, '') // trim but leave \n

src/parser/pseudoText.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Text from '../model/Layer/Text';
2-
import { getTextContext } from '../utils/text';
2+
import { getTextLinesAndRange } from '../utils/text';
33

44
/**
55
* 解析伪类
@@ -43,12 +43,12 @@ export const parsePseudoToText = (
4343

4444
document.body.append(pseudoNode); // 插入到 dom 中 用于获取文本宽度
4545

46-
const { textBCR } = getTextContext(pseudoNode);
46+
const { rangeBCR } = getTextLinesAndRange(pseudoNode);
4747

4848
let x = nodeBCR.left;
4949
switch (pseudoElt) {
5050
case 'after':
51-
x = nodeBCR.right - parseFloat(marginRight) - textBCR.width;
51+
x = nodeBCR.right - parseFloat(marginRight) - rangeBCR.width;
5252
break;
5353
case 'placeholder':
5454
x = nodeBCR.left + parseFloat(paddingLeft);
@@ -64,9 +64,9 @@ export const parsePseudoToText = (
6464
const nodeDisplay = getComputedStyle(node).display;
6565
// 处理垂直居中的样式
6666
if (nodeDisplay !== 'inline') {
67-
y += (nodeBCR.height - textBCR.height) / 2;
67+
y += (nodeBCR.height - rangeBCR.height) / 2;
6868
} else {
69-
y += (nodeBCR.height - textBCR.height) / 2;
69+
y += (nodeBCR.height - rangeBCR.height) / 2;
7070
}
7171
}
7272

@@ -107,12 +107,12 @@ export const parsePseudoToText = (
107107
} else {
108108
textStyle = Text.getTextStyleFromNode(node);
109109
}
110-
textStyle.lineHeight = textBCR.height;
110+
textStyle.lineHeight = rangeBCR.height;
111111

112112
return new Text({
113113
x,
114114
y,
115-
width: textBCR.width,
115+
width: rangeBCR.width,
116116
height: nodeBCR.height,
117117
text: pseudoText,
118118
style: textStyle,

src/parser/text.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Text from '../model/Layer/Text';
22

33
import {
4-
getTextContext,
4+
getTextLinesAndRange,
55
getTextAbsBCR,
66
getLineTextWithWidth,
77
} from '../utils/text';
@@ -29,24 +29,35 @@ export const parseToText = (node: Element): Text | Text[] | undefined => {
2929
// 上述 4 个要素综合影响文本的 x y 坐标
3030
// 有待重构
3131

32-
const { lines, textBCR } = getTextContext(childNode);
33-
const { x, y, width: bcrWidth, height } = getTextAbsBCR(node, childNode);
32+
// 大部分时候可以直接使用 rangeBCR 作为文本的 BCR
33+
const { lines, rangeBCR } = getTextLinesAndRange(childNode);
34+
35+
const {
36+
// x,
37+
y,
38+
width: bcrWidth,
39+
height,
40+
} = getTextAbsBCR(node, childNode);
3441
let textWidth = bcrWidth;
3542

3643
const { display, whiteSpace, overflow, textOverflow, width } = styles;
3744

38-
if (display === 'inline') {
39-
textStyle.lineHeight = textBCR.height / lines;
45+
if ('inline'.includes(display)) {
46+
textStyle.lineHeight = rangeBCR.height / lines;
4047
}
41-
// **** 处理文本 ****** //
48+
// **** 处理文本带省略的情况 ****** //
4249

4350
let textValue = Text.fixWhiteSpace(childNode.nodeValue || '', whiteSpace);
4451
const originText = textValue;
4552
// 针对隐藏或者带省略号的
4653
if (overflow === 'hidden') {
47-
textWidth = parseFloat(width); // 修改其宽度
48-
54+
// 修改宽度
55+
textWidth = parseFloat(width);
56+
// 并对比修改后的文本内容
4957
textValue = getLineTextWithWidth(childNode, textWidth);
58+
59+
// 如果是 ellipsis 类型且存在省略号
60+
// 按省略号添加
5061
if (
5162
textOverflow === 'ellipsis' &&
5263
originText.length !== textValue.length
@@ -57,7 +68,8 @@ export const parseToText = (node: Element): Text | Text[] | undefined => {
5768
}
5869

5970
return new Text({
60-
x: ['inline-block'].includes(display) ? x : textBCR.x,
71+
// x: ['inline-block'].includes(display) ? x : rangeBCR.x,
72+
x: rangeBCR.x,
6173
// y: textBCR.y,
6274
y,
6375
width: textWidth,

src/utils/text.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
* 获取文本定界框与行数
33
* @param textNode
44
*/
5-
export const getTextContext = (textNode: Node) => {
5+
export const getTextLinesAndRange = (textNode: Node) => {
66
// 创建Range 对象
77
const rangeHelper = document.createRange();
88
rangeHelper.selectNodeContents(textNode); // 选中文本节点
99

1010
const textRanges = Array.from(rangeHelper.getClientRects());
1111

1212
const lines = textRanges.length;
13-
const textBCR = rangeHelper.getBoundingClientRect();
13+
const rangeBCR = rangeHelper.getBoundingClientRect();
1414

1515
rangeHelper.detach();
1616
return {
17-
textBCR,
17+
rangeBCR,
1818
lines,
1919
textRanges,
2020
};
@@ -35,7 +35,7 @@ export const getTextAbsBCR = (parentNode: Element, textNode: Node) => {
3535
let { x } = nodeBCR;
3636
let { y } = nodeBCR;
3737

38-
const { lines, textBCR } = getTextContext(textNode);
38+
const { lines, rangeBCR } = getTextLinesAndRange(textNode);
3939

4040
const {
4141
lineHeight,
@@ -48,9 +48,9 @@ export const getTextAbsBCR = (parentNode: Element, textNode: Node) => {
4848
borderTopWidth,
4949
} = styles;
5050

51-
const textWidth = textBCR.width;
51+
const textWidth = rangeBCR.width;
5252
const lineHeightInt = parseInt(lineHeight, 10);
53-
const textBCRHeight = textBCR.height;
53+
const textBCRHeight = rangeBCR.height;
5454

5555
let fixY = 0;
5656

@@ -113,9 +113,9 @@ export const getLineTextWithWidth = (textNode: ChildNode, width: number) => {
113113
const charNode = textNode.cloneNode(true);
114114
charNode.textContent = textContent;
115115
document.body.appendChild(charNode);
116-
const { textBCR } = getTextContext(charNode);
116+
const { rangeBCR } = getTextLinesAndRange(charNode);
117117
document.body.removeChild(charNode);
118-
if (textBCR.width < width) {
118+
if (rangeBCR.width < width) {
119119
textContent += text[i];
120120
}
121121
}

tests/__tests__/model/Layer/Text.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('fixWhiteSpace', () => {
1010
1111
1212
your father `;
13-
const output = "Luke, I'm your father";
13+
const output = " Luke, I'm your father ";
1414

1515
expect(fixWhiteSpace(input, 'normal')).toEqual(output);
1616
expect(fixWhiteSpace(input, 'nowrap')).toEqual(output);

0 commit comments

Comments
 (0)