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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ellipses displaying even when the text does not exceed the limit #2

Merged
merged 4 commits into from
Apr 21, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ const text = {
| top | number \| () => number | - | (必填)相对父元素y轴的偏移 |
| width | number | - | 文本宽度 |
| content | string | - | 文本内容 |
| color | string | - | 字体颜色 |
| fontSize | number | 14 | 字体大小 |
| fontWeight | string | 'normal' | 字体的粗细程度,一些字体只提供 normal 和 bold 两种值 |
| fontFamily | string | 'sans-serif' | 字体名称 |
Expand Down
58 changes: 37 additions & 21 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { isNonEmptyArray } from '@inottn/fp-utils';
import { loadFontFace, toTempFilePath } from './adapter';
import {
binarySearch,
calculateLeftOffset,
mergePosition,
normalizeConfig,
} from './utils';
import { calculateLeftOffset, mergePosition, normalizeConfig } from './utils';
import type {
AugmentedRequired,
Canvas,
Expand Down Expand Up @@ -224,28 +219,49 @@ export class MiniPoster {
getAllLines(data: TextConfig) {
const { context } = this;
const { width, content, lineClamp = Infinity } = data;
const lines = [];
let index = 0;

while (index < content.length && lines.length < lineClamp) {
const prevIndex = index;
if (width == void 0) {
return [content];
}
Copy link
Owner

Choose a reason for hiding this comment

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

这段逻辑应该不会触发。


if (width <= 0) {
return content.split('');
}

index =
binarySearch(
content,
(end) =>
context.measureText(content.slice(index, end + 1)).width > width!,
) + 1;
const lines = [];
let index = 0;
const { length } = content;

while (index < length && lines.length < lineClamp) {
let left = index;
let right = length;
let mid = right;
while (left < mid) {
const measureWidth = context.measureText(
content.slice(index, mid),
).width;
if (measureWidth > width) {
right = mid;
mid = left + ((mid - left) >> 1);
} else if (measureWidth < width) {
left = mid;
Copy link
Owner

Choose a reason for hiding this comment

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

可以考虑修改 binarySearch 函数的实现,因为 getAllLines 方法不关注 binarySearch 具体的实现逻辑,对应的逻辑拆分会让代码看上去会更清晰一点。

Copy link
Contributor Author

@forzgc forzgc Apr 22, 2024

Choose a reason for hiding this comment

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

没使用 binarySearch 是考虑到两点

一是如果文本只够一行的话,binarySearch 会测量多次才能得到结果,考虑到海报中单行文本比较多的情况,所以希望能先进行一次全部文本的测量

二是 binarySearch 每次调用的时候传入的content都是完整的,而已经push进lines的那部分文本其实不需要在参与进来,除了会导致测量次数增加之外,还会有测量空字符串的情况

原因是 content.slice(index, end + 1) 中 end + 1可能小于 index

binarySearch(
          content,
          (end) =>
            context.measureText(content.slice(index, end + 1)).width > width!,
        ) + 1;

因为这两个原因,改动后的代码我不确定是否通用,所以直接写在了getAllLines中

mid = mid + ((right - mid) >> 1);
} else {
break;
}
}

if (index === prevIndex) {
index = prevIndex + 1;
if (index === mid) {
mid = index + 1;
}

if (lineClamp === lines.length + 1) {
lines.push(content.slice(prevIndex, index - 1) + '...');
if (lineClamp === lines.length + 1 && mid < length) {
lines.push(content.slice(index, mid - 1) + '...');
} else {
lines.push(content.slice(prevIndex, index));
lines.push(content.slice(index, mid));
}

index = mid;
}

return lines;
Expand Down
Loading