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/08 06:52:59 UTC

[incubator-echarts] branch label-enhancement updated: feat(label): squeeze the labels then hide if there is no space.

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 a7310d8  feat(label): squeeze the labels then hide if there is no space.
a7310d8 is described below

commit a7310d8458b6a8a02dde9960b5dfe8f90d86a253
Author: pissang <bm...@gmail.com>
AuthorDate: Mon Jun 8 14:52:26 2020 +0800

    feat(label): squeeze the labels then hide if there is no space.
---
 src/label/LabelManager.ts      |  8 +++---
 src/label/labelLayoutHelper.ts | 61 +++++++++++++++++++++++++++++++++++++-----
 2 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/src/label/LabelManager.ts b/src/label/LabelManager.ts
index 5c5d320..5601d2b 100644
--- a/src/label/LabelManager.ts
+++ b/src/label/LabelManager.ts
@@ -285,6 +285,7 @@ class LabelManager {
             layoutOption = layoutOption || {};
             labelItem.computedLayoutOption = layoutOption;
 
+            const degreeToRadian = Math.PI / 180;
             if (hostEl) {
                 hostEl.setTextConfig({
                     // Force to set local false.
@@ -293,7 +294,8 @@ class LabelManager {
                     position: (layoutOption.x != null || layoutOption.y != null)
                         ? null : defaultLabelAttr.attachedPos,
                     // Ignore rotation config on the host el if rotation is changed.
-                    rotation: layoutOption.rotation != null ? layoutOption.rotation : defaultLabelAttr.attachedRot,
+                    rotation: layoutOption.rotate != null
+                        ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.attachedRot,
                     offset: [layoutOption.dx || 0, layoutOption.dy || 0]
                 });
             }
@@ -317,8 +319,8 @@ class LabelManager {
                 label.setStyle('y', defaultLabelAttr.style.y);
             }
 
-            label.rotation = layoutOption.rotation != null
-                ? layoutOption.rotation : defaultLabelAttr.rotation;
+            label.rotation = layoutOption.rotate != null
+                ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation;
 
             for (let k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) {
                 const key = LABEL_OPTION_TO_STYLE_KEYS[k];
diff --git a/src/label/labelLayoutHelper.ts b/src/label/labelLayoutHelper.ts
index fe7693d..3c8a6e3 100644
--- a/src/label/labelLayoutHelper.ts
+++ b/src/label/labelLayoutHelper.ts
@@ -132,14 +132,26 @@ function shiftLayout(
     }
 
     // TODO bleedMargin?
-    const minGap = list[0].rect[xyDim] - minBound;
+    const first = list[0];
     const last = list[len - 1];
-    const maxGap = maxBound - last.rect[xyDim] - last.rect[sizeDim];
+    let minGap = first.rect[xyDim] - minBound;
+    let maxGap = maxBound - last.rect[xyDim] - last.rect[sizeDim];
 
     // If ends exceed two bounds
     handleBoundsGap(minGap, maxGap, 1);
     handleBoundsGap(maxGap, minGap, -1);
 
+    // Handle bailout when there is not enough space.
+    minGap = first.rect[xyDim] - minBound;
+    maxGap = maxBound - last.rect[xyDim] - last.rect[sizeDim];
+
+    if (minGap < 0) {
+        squeezeWhenBailout(-minGap);
+    }
+    if (maxGap < 0) {
+        squeezeWhenBailout(maxGap);
+    }
+
     function handleBoundsGap(gapThisBound: number, gapOtherBound: number, moveDir: 1 | -1) {
         if (gapThisBound < 0) {
             // Move from other gap if can.
@@ -180,13 +192,48 @@ function shiftLayout(
             return;
         }
 
+        if (Math.abs(delta) > totalGaps) {
+            delta = totalGaps * (delta < 0 ? -1 : 1);
+        }
+
         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);
+            const movement = gaps[i] / totalGaps * delta;
+            if (delta > 0) {
+                // Forward
+                shiftList(movement, 0, i + 1);
+            }
+            else {
+                // Backward
+                shiftList(movement, len - i - 1, len);
+            }
+        }
+    }
+
+    /**
+     * Squeeze to allow overlap if there is no more space available.
+     * Let other overlapping strategy like hideOverlap do the job instead of keep exceeding the bounds.
+     */
+    function squeezeWhenBailout(delta: number) {
+        const dir = delta < 0 ? -1 : 1;
+        delta = Math.abs(delta);
+        const moveForEachLabel = Math.ceil(delta / (len - 1));
+
+        for (let i = 0; i < len - 1; i++) {
+            if (dir > 0) {
+                // Forward
+                shiftList(moveForEachLabel, 0, i + 1);
+            }
+            else {
+                // Backward
+                shiftList(-moveForEachLabel, len - i - 1, len);
+            }
+
+            delta -= moveForEachLabel;
+
+            if (delta <= 0) {
+                return;
+            }
         }
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org