You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2020/06/07 16:27:27 UTC
[incubator-echarts] branch label-enhancement updated: feat(label):
rewrite the label shift algorithm in layout
This is an automated email from the ASF dual-hosted git repository.
shenyi pushed a commit to branch label-enhancement
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
The following commit(s) were added to refs/heads/label-enhancement by this push:
new 1c7a130 feat(label): rewrite the label shift algorithm in layout
1c7a130 is described below
commit 1c7a13053ddd6517c6616d0e0def2e2442c8f3ea
Author: pissang <bm...@gmail.com>
AuthorDate: Mon Jun 8 00:27:08 2020 +0800
feat(label): rewrite the label shift algorithm in layout
---
src/chart/pie/labelLayout.ts | 4 ++
src/label/labelLayoutHelper.ts | 102 +++++++++++++++++++++++++++--------------
2 files changed, 71 insertions(+), 35 deletions(-)
diff --git a/src/chart/pie/labelLayout.ts b/src/chart/pie/labelLayout.ts
index 473cf5f..d2f7361 100644
--- a/src/chart/pie/labelLayout.ts
+++ b/src/chart/pie/labelLayout.ts
@@ -61,6 +61,10 @@ function adjustSingleSide(
viewTop: number,
farthestX: number
) {
+ if (list.length < 2) {
+ return;
+ }
+
list.sort(function (a, b) {
return a.y - b.y;
});
diff --git a/src/label/labelLayoutHelper.ts b/src/label/labelLayoutHelper.ts
index 49e0c96..fe7693d 100644
--- a/src/label/labelLayoutHelper.ts
+++ b/src/label/labelLayoutHelper.ts
@@ -99,7 +99,7 @@ function shiftLayout(
) {
const len = list.length;
- if (!len) {
+ if (len < 2) {
return;
}
@@ -109,52 +109,84 @@ function shiftLayout(
let lastPos = 0;
let delta;
+ const shifts = [];
+ let totalShifts = 0;
for (let i = 0; i < len; i++) {
- delta = list[i].rect[xyDim] - lastPos;
+ const item = list[i];
+ const rect = item.rect;
+ delta = rect[xyDim] - lastPos;
if (delta < 0) {
- shiftForward(i, len, -delta);
+ // shiftForward(i, len, -delta);
+ rect[xyDim] -= delta;
+ item.label[xyDim] -= delta;
}
- lastPos = list[i].rect[xyDim] + list[i].rect[sizeDim];
+ const shift = Math.max(-delta, 0);
+ shifts.push(shift);
+ totalShifts += shift;
+
+ lastPos = rect[xyDim] + rect[sizeDim];
}
- // TODO bleedMargin?
- if (maxBound < lastPos) {
- shiftBackward(len - 1, lastPos - maxBound);
+ if (totalShifts > 0) {
+ // Shift back to make the distribution more equally.
+ shiftList(-totalShifts / len, 0, len);
}
-
- function shiftForward(start: number, end: number, delta: number) {
- for (let j = start; j < end; j++) {
- list[j].label[xyDim] += delta;
-
- const rect = list[j].rect;
- rect[xyDim] += delta;
-
- if (j > start && j + 1 < end && !list[j + 1].rect.intersect(rect)) {
- // Shift the following so it can be more equaly distributed.
- shiftBackward(j, delta / 2);
- return;
+ // TODO bleedMargin?
+ const minGap = list[0].rect[xyDim] - minBound;
+ const last = list[len - 1];
+ const maxGap = maxBound - last.rect[xyDim] - last.rect[sizeDim];
+
+ // If ends exceed two bounds
+ handleBoundsGap(minGap, maxGap, 1);
+ handleBoundsGap(maxGap, minGap, -1);
+
+ function handleBoundsGap(gapThisBound: number, gapOtherBound: number, moveDir: 1 | -1) {
+ if (gapThisBound < 0) {
+ // Move from other gap if can.
+ const moveFromMaxGap = Math.min(gapOtherBound, -gapThisBound);
+ if (moveFromMaxGap > 0) {
+ shiftList(moveFromMaxGap * moveDir, 0, len);
+ const remained = moveFromMaxGap + gapThisBound;
+ if (remained < 0) {
+ squeezeGaps(-remained * moveDir);
+ }
+ }
+ else {
+ squeezeGaps(-gapThisBound * moveDir);
}
}
-
- shiftBackward(end - 1, delta / 2);
}
- function shiftBackward(end: number, delta: number) {
- for (let j = end; j >= 0; j--) {
- const rect = list[j].rect;
- list[j].label[xyDim] -= delta;
- rect[xyDim] -= delta;
+ function shiftList(delta: number, start: number, end: number) {
+ for (let i = start; i < end; i++) {
+ const item = list[i];
+ const rect = item.rect;
+ rect[xyDim] += delta;
+ item.label[xyDim] += delta;
+ }
+ }
- // const textSize = rect[sizeDim];
- const diffToMinBound = rect[xyDim] - minBound;
- if (diffToMinBound < 0) {
- rect[xyDim] -= diffToMinBound;
- list[j].label[xyDim] -= diffToMinBound;
- }
+ // Squeeze gaps if the labels exceed margin.
+ function squeezeGaps(delta: number) {
+ const gaps: number[] = [];
+ let totalGaps = 0;
+ for (let i = 1; i < len; i++) {
+ const prevItemRect = list[i - 1].rect;
+ const gap = Math.max(list[i].rect[xyDim] - prevItemRect[xyDim] - prevItemRect[sizeDim], 0);
+ gaps.push(gap);
+ totalGaps += gap;
+ }
+ if (!totalGaps) {
+ return;
+ }
- if (j > 0 && !rect.intersect(list[j - 1].rect)) {
- break;
- }
+ for (let i = 0; i < len - 1; i++) {
+ // Distribute the shift delta to all gaps.
+ // NOTE:
+ // it may overlap if remained gap is not enough for the total movements.
+ // aka totalGaps / delta is < 1. In this situation the label may move too much and cause overlap again.
+ // This is by design. Let the hideOverlap do the job instead of keep exceeding the bounds.
+ shiftList(gaps[i] / totalGaps * delta, 0, i + 1);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org