Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "feat: optimiza label overlap\n\n",
"type": "none",
"packageName": "@visactor/vrender-components"
}
],
"packageName": "@visactor/vrender-components",
"email": "lixuef1313@163.com"
}
22 changes: 19 additions & 3 deletions packages/vrender-components/src/axis/overlap/auto-rotate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,28 @@ export function autoRotate(items: IText[], rotateConfig: RotateConfig) {

let i = 0;
let n = 0;
if (labelRotateAngle && labelRotateAngle.length > 0) {
n = labelRotateAngle.length;

let testAngle = labelRotateAngle;
if (items.length > 2) {
// 大量数据下性能优化
// 标签过多时无论如何旋转都无法展示全部标签,通过逻辑减少尝试次数
if (orient === 'bottom' || orient === 'top') {
if (Math.abs(items[1].attribute.x - items[0].attribute.x) < items[0].attribute.fontSize / 2) {
testAngle = [labelRotateAngle[labelRotateAngle.length - 1]];
}
} else {
if (Math.abs(items[1].attribute.y - items[0].attribute.y) < items[0].attribute.fontSize / 2) {
testAngle = [labelRotateAngle[labelRotateAngle.length - 1]];
}
}
}

if (testAngle && testAngle.length > 0) {
n = testAngle.length;
}

while (i < n) {
const angle = labelRotateAngle[i++];
const angle = testAngle[i++];
items.forEach(item => {
// item.angle = angle;
item.attribute.angle = degreeToRadian(angle);
Expand Down
2 changes: 1 addition & 1 deletion packages/vrender-components/src/label/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ export class LabelBase<T extends BaseLabelAttrs> extends AnimateComponent<T> {

const filteredLabels: (IText | IRichText)[] = [];
const overlapLabels: (IText | IRichText)[] = labels;
if (!isBoolean(overlap) && isFunction(overlap.filterBeforeOverlap)) {
if (!isBoolean(overlap) && isFunction(overlap?.filterBeforeOverlap)) {
const getRelatedGraphic = this.getRelatedGraphic.bind(this);
labels.forEach(label => {
if (overlap.filterBeforeOverlap(label, getRelatedGraphic, this)) {
Expand Down
44 changes: 34 additions & 10 deletions packages/vrender-components/src/label/overlap/place.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ export function canPlaceInside(textBound: IBoundsLike, shapeBound: IAABBBounds)
return shapeBound.encloses(textBound);
}

/**
* 通过预先获取一次文本的 AABB 边界,按候选坐标计算平移后的边界进行碰撞判定,避免反复更新文本属性。
*/
export function placeToCandidates(
$: BitmapTool,
bitmap: Bitmap,
Expand All @@ -88,19 +91,40 @@ export function placeToCandidates(
changePosition = false
): PointLocationCfg | false {
const validCandidates = candidates.filter(candidate => isValid(candidate));

const curX = (text.attribute.x as number) ?? 0;
const curY = (text.attribute.y as number) ?? 0;
const base = text.AABBBounds;
const candidateBounds = {
x1: base.x1,
x2: base.x2,
y1: base.y1,
y2: base.y2
};

let lastCandidate: PointLocationCfg | undefined;
for (let i = 0; i < validCandidates.length; i++) {
let measureText;
if (changePosition) {
measureText = text;
} else {
measureText = text.clone();
const c = validCandidates[i];
lastCandidate = c;
const nx = (c.x as number) ?? curX;
const ny = (c.y as number) ?? curY;
const dx = nx - curX;
const dy = ny - curY;

candidateBounds.x1 = base.x1 + dx;
candidateBounds.x2 = base.x2 + dx;
candidateBounds.y1 = base.y1 + dy;
candidateBounds.y2 = base.y2 + dy;

if (canPlace($, bitmap, candidateBounds, clampForce, pad)) {
bitmap.setRange(boundToRange($, candidateBounds, true));
// 成功时外部会设置位置,不需要在这里设置
return c;
}
measureText.setAttributes(validCandidates[i]);
}

if (canPlace($, bitmap, measureText.AABBBounds, clampForce, pad)) {
bitmap.setRange(boundToRange($, measureText.AABBBounds, true));
return validCandidates[i];
}
if (changePosition && lastCandidate) {
text.setAttributes(lastCandidate);
}
return false;
}
Expand Down
Loading