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/05/28 05:43:26 UTC

[incubator-echarts] branch label-enhancement updated (6fa462f -> fba40c7)

This is an automated email from the ASF dual-hosted git repository.

shenyi pushed a change to branch label-enhancement
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git.


    from 6fa462f  fix: compat barBorderXXX in backgroundStyle. rename barBorderRadius to borderRadius
     new 34e4cb0  feat: label and labelLine animation
     new 906e363  fix: compat barBorderXXX in backgroundStyle
     new 678b42d  fix: fix class error in ES6 built file
     new fba40c7  fix: fix not existed emphasis state caused error.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/chart/pie/PieView.ts           |  31 +++-------
 src/chart/pie/labelLayout.ts       |   5 ++
 src/echarts.ts                     |  15 +++--
 src/label/LabelManager.ts          | 118 ++++++++++++++++++++++++++++++-------
 src/label/labelGuideHelper.ts      |   2 +-
 src/preprocessor/backwardCompat.ts |   2 +
 src/util/clazz.ts                  |  26 +++++---
 src/util/graphic.ts                |   4 +-
 8 files changed, 142 insertions(+), 61 deletions(-)


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


[incubator-echarts] 01/04: feat: label and labelLine animation

Posted by sh...@apache.org.
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

commit 34e4cb0f6a282b493abef79426cc09083780e8f7
Author: pissang <bm...@gmail.com>
AuthorDate: Thu May 28 13:39:34 2020 +0800

    feat: label and labelLine animation
---
 src/chart/pie/PieView.ts      |  31 ++++-------
 src/chart/pie/labelLayout.ts  |   5 ++
 src/echarts.ts                |  15 +++---
 src/label/LabelManager.ts     | 118 ++++++++++++++++++++++++++++++++++--------
 src/label/labelGuideHelper.ts |   2 +-
 5 files changed, 120 insertions(+), 51 deletions(-)

diff --git a/src/chart/pie/PieView.ts b/src/chart/pie/PieView.ts
index 0f2865a..8187c6a 100644
--- a/src/chart/pie/PieView.ts
+++ b/src/chart/pie/PieView.ts
@@ -136,9 +136,7 @@ class PiePiece extends graphic.Sector {
         const cursorStyle = itemModel.getShallow('cursor');
         cursorStyle && sector.attr('cursor', cursorStyle);
 
-        // Label and text animation should be applied only for transition type animation when update
-        const withAnimation = !firstCreate && animationTypeUpdate === 'transition';
-        this._updateLabel(data, idx, withAnimation);
+        this._updateLabel(data, idx);
 
         const emphasisState = sector.ensureState('emphasis');
         emphasisState.shape = {
@@ -165,12 +163,11 @@ class PiePiece extends graphic.Sector {
         (sector as ECElement).selected = seriesModel.isSelected(data.getName(idx));
     }
 
-    private _updateLabel(data: List, idx: number, withAnimation: boolean): void {
+    private _updateLabel(data: List, idx: number): void {
         const sector = this;
         const labelLine = sector.getTextGuideLine();
         const labelText = sector.getTextContent();
 
-        const seriesModel = data.hostModel;
         const itemModel = data.getItemModel<PieDataItemOption>(idx);
         const layout = data.getItemLayout(idx);
         const labelLayout = layout.label;
@@ -225,25 +222,15 @@ class PiePiece extends graphic.Sector {
             outsideFill: visualColor
         });
 
-        const targetTextPos = {
+        labelLine.attr({
+            shape: targetLineShape
+        });
+        // Make sure update style on labelText after setLabelStyle.
+        // Because setLabelStyle will replace a new style on it.
+        labelText.attr({
             x: labelLayout.x,
             y: labelLayout.y
-        };
-        if (withAnimation) {
-            graphic.updateProps(labelLine, {
-                shape: targetLineShape
-            }, seriesModel, idx);
-
-            graphic.updateProps(labelText, targetTextPos, seriesModel, idx);
-        }
-        else {
-            labelLine.attr({
-                shape: targetLineShape
-            });
-            // Make sure update style on labelText after setLabelStyle.
-            // Because setLabelStyle will replace a new style on it.
-            labelText.attr(targetTextPos);
-        }
+        });
 
         labelText.attr({
             rotation: labelLayout.rotation,
diff --git a/src/chart/pie/labelLayout.ts b/src/chart/pie/labelLayout.ts
index 04542b5..d1da84d 100644
--- a/src/chart/pie/labelLayout.ts
+++ b/src/chart/pie/labelLayout.ts
@@ -323,6 +323,11 @@ export default function (
         const text = seriesModel.getFormattedLabel(idx, 'normal')
                 || data.getName(idx);
         const textRect = textContain.getBoundingRect(text, font, textAlign, 'top');
+        // Text has a default 1px stroke. Exclude this.
+        textRect.x -= 1;
+        textRect.y -= 1;
+        textRect.width += 2.1;
+        textRect.height += 2.1;
 
         const isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
         if (labelPosition === 'center') {
diff --git a/src/echarts.ts b/src/echarts.ts
index 6723c9d..3a68ce7 100644
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@ -1097,6 +1097,7 @@ class ECharts extends Eventful {
         const labelManager = this._labelManager;
         labelManager.updateLayoutConfig(this._api);
         labelManager.layout();
+        labelManager.animateLabels();
     }
 
     appendData(params: {
@@ -1722,16 +1723,20 @@ class ECharts extends Eventful {
                 // Add labels.
                 labelManager.addLabelsOfSeries(chartView);
 
-                // NOTE: Update states after label is added.
-                // Because in LabelManager#addLabel. It will cache the properties(transform, textConfig) of label.
-                // We need to cache the normal state. Not other states.
-                updateStates(seriesModel, chartView);
             });
 
             scheduler.unfinished = unfinished || scheduler.unfinished;
 
             labelManager.updateLayoutConfig(api);
             labelManager.layout();
+            labelManager.animateLabels();
+
+            ecModel.eachSeries(function (seriesModel) {
+                const chartView = ecIns._chartsMap[seriesModel.__viewId];
+                // NOTE: Update states after label is updated.
+                // label should be in normal status when layouting.
+                updateStates(seriesModel, chartView);
+            });
 
             // If use hover layer
             // TODO
@@ -1877,8 +1882,6 @@ class ECharts extends Eventful {
                         states.push('emphasis');
                     }
                     el.useStates(states);
-                    // el.toggleState('select', (el as ECElement).selected);
-                    // el.toggleState('emphasis', (el as ECElement).highlighted);
                 }
             });
         };
diff --git a/src/label/LabelManager.ts b/src/label/LabelManager.ts
index 8d203e4..3cbdef5 100644
--- a/src/label/LabelManager.ts
+++ b/src/label/LabelManager.ts
@@ -25,7 +25,9 @@ import {
     Point,
     BoundingRect,
     getECData,
-    Polyline
+    Polyline,
+    updateProps,
+    initProps
 } from '../util/graphic';
 import { MatrixArray } from 'zrender/src/core/matrix';
 import ExtensionAPI from '../ExtensionAPI';
@@ -38,10 +40,13 @@ import {
 } from '../util/types';
 import { parsePercent } from '../util/number';
 import ChartView from '../view/Chart';
-import { ElementTextConfig, ElementTextGuideLineConfig } from 'zrender/src/Element';
+import { ElementTextConfig } from 'zrender/src/Element';
 import { RectLike } from 'zrender/src/core/BoundingRect';
 import Transformable from 'zrender/src/core/Transformable';
 import { updateLabelGuideLine } from './labelGuideHelper';
+import SeriesModel from '../model/Series';
+import { makeInner } from '../util/model';
+import { retrieve2, guid, each } from 'zrender/src/core/util';
 
 interface DisplayedLabelItem {
     label: ZRText
@@ -56,7 +61,7 @@ interface LabelLayoutDesc {
     label: ZRText
     labelGuide: Polyline
 
-    seriesIndex: number
+    seriesModel: SeriesModel
     dataIndex: number
 
     layoutOption: LabelLayoutOptionCallback | LabelLayoutOption
@@ -100,7 +105,7 @@ function prepareLayoutCallbackParams(labelItem: LabelLayoutDesc): LabelLayoutOpt
     const label = labelItem.label;
     return {
         dataIndex: labelItem.dataIndex,
-        seriesIndex: labelItem.seriesIndex,
+        seriesIndex: labelItem.seriesModel.seriesIndex,
         text: labelItem.label.style.text,
         rect: labelItem.hostRect,
         labelRect: labelAttr.rect,
@@ -115,26 +120,38 @@ const LABEL_OPTION_TO_STYLE_KEYS = ['align', 'verticalAlign', 'width', 'height']
 
 const dummyTransformable = new Transformable();
 
+const labelAnimationStore = makeInner<{
+    oldLayout: {
+        x: number,
+        y: number,
+        rotation: number
+    }
+}, ZRText>();
+
+const labelLineAnimationStore = makeInner<{
+    oldLayout: {
+        points: number[][]
+    }
+}, Polyline>();
+
 class LabelManager {
 
     private _labelList: LabelLayoutDesc[] = [];
+    private _chartViewList: ChartView[] = [];
 
     constructor() {}
 
     clearLabels() {
         this._labelList = [];
+        this._chartViewList = [];
     }
 
     /**
      * Add label to manager
-     * @param dataIndex
-     * @param seriesIndex
-     * @param label
-     * @param layoutOption
      */
     addLabel(
         dataIndex: number,
-        seriesIndex: number,
+        seriesModel: SeriesModel,
         label: ZRText,
         layoutOption: LabelLayoutDesc['layoutOption']
     ) {
@@ -171,7 +188,7 @@ class LabelManager {
             label,
             labelGuide: labelGuide,
 
-            seriesIndex,
+            seriesModel,
             dataIndex,
 
             layoutOption,
@@ -215,6 +232,8 @@ class LabelManager {
     }
 
     addLabelsOfSeries(chartView: ChartView) {
+        this._chartViewList.push(chartView);
+
         const seriesModel = chartView.__model;
         const layoutOption = seriesModel.get('labelLayout');
         chartView.group.traverse((child) => {
@@ -226,7 +245,7 @@ class LabelManager {
             const textEl = child.getTextContent();
             const dataIndex = getECData(child).dataIndex;
             if (textEl && dataIndex != null) {
-                this.addLabel(dataIndex, seriesModel.seriesIndex, textEl, layoutOption);
+                this.addLabel(dataIndex, seriesModel, textEl, layoutOption);
             }
         });
     }
@@ -251,6 +270,7 @@ class LabelManager {
             }
 
             layoutOption = layoutOption || {};
+
             if (hostEl) {
                 hostEl.setTextConfig({
                     // Force to set local false.
@@ -288,10 +308,7 @@ class LabelManager {
 
             for (let k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) {
                 const key = LABEL_OPTION_TO_STYLE_KEYS[k];
-                label.setStyle(
-                    key,
-                    layoutOption[key] != null ? layoutOption[key] : defaultLabelAttr.style[key]
-                );
+                label.setStyle(key, layoutOption[key] != null ? layoutOption[key] : defaultLabelAttr.style[key]);
             }
 
             labelItem.overlap = layoutOption.overlap;
@@ -325,9 +342,6 @@ class LabelManager {
 
             const globalRect = localRect.clone();
             globalRect.applyTransform(transform);
-            // Text has a default 1px stroke. Exclude this.
-            globalRect.width -= 3;
-            globalRect.height -= 3;
 
             let obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null;
             let overlapped = false;
@@ -362,14 +376,10 @@ class LabelManager {
             const labelGuide = labelItem.labelGuide;
             // TODO Callback to determine if this overlap should be handled?
             if (overlapped) {
-                // label.setStyle({ opacity: 0.1 });
-                // label.z = 0;
                 label.hide();
                 labelGuide && labelGuide.hide();
             }
             else {
-                // TODO Restore z
-                // label.setStyle({ opacity: 1 });
                 label.attr('ignore', labelItem.defaultAttr.ignore);
                 labelGuide && labelGuide.attr('ignore', labelItem.defaultAttr.labelGuideIgnore);
 
@@ -391,6 +401,70 @@ class LabelManager {
             );
         }
     }
+
+    animateLabels() {
+        each(this._chartViewList, function (chartView) {
+            const seriesModel = chartView.__model;
+            if (!seriesModel.isAnimationEnabled()) {
+                return;
+            }
+
+            chartView.group.traverse((child) => {
+                if (child.ignore) {
+                    return true;    // Stop traverse descendants.
+                }
+
+                // Only support label being hosted on graphic elements.
+                const textEl = child.getTextContent();
+                const guideLine = child.getTextGuideLine();
+
+                if (textEl && !textEl.ignore && !textEl.invisible) {
+                    const layoutStore = labelAnimationStore(textEl);
+                    const oldLayout = layoutStore.oldLayout;
+                    const newProps = {
+                        x: textEl.x,
+                        y: textEl.y,
+                        rotation: textEl.rotation
+                    };
+                    if (!oldLayout) {
+                        textEl.attr(newProps);
+                        const oldOpacity = retrieve2(textEl.style.opacity, 1);
+                        // Fade in animation
+                        textEl.style.opacity = 0;
+                        initProps(textEl, {
+                            style: { opacity: oldOpacity }
+                        }, seriesModel);
+                    }
+                    else {
+                        textEl.attr(oldLayout);
+                        updateProps(textEl, newProps, seriesModel);
+                    }
+                    layoutStore.oldLayout = newProps;
+                }
+
+                if (guideLine && !guideLine.ignore && !guideLine.invisible) {
+                    const layoutStore = labelLineAnimationStore(guideLine);
+                    const oldLayout = layoutStore.oldLayout;
+                    const newLayout = { points: guideLine.shape.points };
+                    if (!oldLayout) {
+                        guideLine.setShape(newLayout);
+                        guideLine.style.strokePercent = 0;
+                        initProps(guideLine, {
+                            style: { strokePercent: 1 }
+                        }, seriesModel);
+                    }
+                    else {
+                        guideLine.attr({ shape: oldLayout });
+                        updateProps(guideLine, {
+                            shape: newLayout
+                        }, seriesModel);
+                    }
+
+                    layoutStore.oldLayout = newLayout;
+                }
+            });
+        });
+    }
 }
 
 
diff --git a/src/label/labelGuideHelper.ts b/src/label/labelGuideHelper.ts
index b20511a..da4848b 100644
--- a/src/label/labelGuideHelper.ts
+++ b/src/label/labelGuideHelper.ts
@@ -346,7 +346,7 @@ export function updateLabelGuideLine(
     for (let i = 0; i < searchSpace.length; i++) {
         const candidate = searchSpace[i];
         getCandidateAnchor(candidate, 0, labelRect, pt0, dir);
-        Point.scaleAndAdd(pt1, pt0, dir, labelGuideConfig.len);
+        Point.scaleAndAdd(pt1, pt0, dir, labelGuideConfig.len == null ? 15 : labelGuideConfig.len);
 
         const dist = anchorPoint ? anchorPoint.distance(pt1)
             : (target instanceof Path


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


[incubator-echarts] 03/04: fix: fix class error in ES6 built file

Posted by sh...@apache.org.
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

commit 678b42d5797c3b975cdacef834e0aa6fffed078d
Author: pissang <bm...@gmail.com>
AuthorDate: Thu May 28 13:41:56 2020 +0800

    fix: fix class error in ES6 built file
---
 src/util/clazz.ts | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/src/util/clazz.ts b/src/util/clazz.ts
index ddf3549..7507bdf 100644
--- a/src/util/clazz.ts
+++ b/src/util/clazz.ts
@@ -99,17 +99,25 @@ export function enableClassExtend(rootClz: ExtendableConstructor, mandatoryMetho
         // constructor.
         // If this constructor/$constructor is declared, it is responsible for
         // calling the super constructor.
-        const ExtendedClass = (class {
-            constructor() {
-                if (!proto.$constructor) {
-                    superClass.apply(this, arguments);
+        function ExtendedClass(this: any, ...args: any[]) {
+            if (!proto.$constructor) {
+                try {
+                    // Will throw error if superClass is a es6 native class.
+                    superClass.apply(this, args);
                 }
-                else {
-                    proto.$constructor.apply(this, arguments);
+                catch (e) {
+                    const ins = zrUtil.createObject(
+                        // @ts-ignore
+                        ExtendedClass.prototype, new superClass(...args)
+                    );
+                    return ins;
                 }
             }
-            static [IS_EXTENDED_CLASS] = true;
-        }) as ExtendableConstructor;
+            else {
+                proto.$constructor.apply(this, arguments);
+            }
+        };
+        ExtendedClass[IS_EXTENDED_CLASS] = true;
 
         zrUtil.extend(ExtendedClass.prototype, proto);
 
@@ -119,7 +127,7 @@ export function enableClassExtend(rootClz: ExtendableConstructor, mandatoryMetho
         zrUtil.inherits(ExtendedClass, this);
         ExtendedClass.superClass = superClass;
 
-        return ExtendedClass as ExtendableConstructor;
+        return ExtendedClass as unknown as ExtendableConstructor;
     };
 }
 


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


[incubator-echarts] 02/04: fix: compat barBorderXXX in backgroundStyle

Posted by sh...@apache.org.
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

commit 906e36324fa8677bfebfca574050d171b5496db3
Author: pissang <bm...@gmail.com>
AuthorDate: Thu May 28 13:40:24 2020 +0800

    fix: compat barBorderXXX in backgroundStyle
---
 src/preprocessor/backwardCompat.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/preprocessor/backwardCompat.ts b/src/preprocessor/backwardCompat.ts
index c303624..13c22a0 100644
--- a/src/preprocessor/backwardCompat.ts
+++ b/src/preprocessor/backwardCompat.ts
@@ -25,6 +25,7 @@ import {normalizeToArray} from '../util/model';
 import { Dictionary } from 'zrender/src/core/types';
 import { ECUnitOption, SeriesOption } from '../util/types';
 import { __DEV__ } from '../config';
+import type { BarSeriesOption } from '../chart/bar/BarSeries';
 
 function get(opt: Dictionary<any>, path: string): any {
     const pathArr = path.split(',');
@@ -129,6 +130,7 @@ export default function (option: ECUnitOption, isTheme?: boolean) {
         }
         else if (seriesType === 'bar') {
             compatBarItemStyle(seriesOpt);
+            compatBarItemStyle((seriesOpt as BarSeriesOption).backgroundStyle);
             // @ts-ignore
             compatBarItemStyle(seriesOpt.emphasis);
             const data = seriesOpt.data;


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


[incubator-echarts] 04/04: fix: fix not existed emphasis state caused error.

Posted by sh...@apache.org.
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

commit fba40c7a5ef29381ccb6daabdd7ce1510b04698d
Author: pissang <bm...@gmail.com>
AuthorDate: Thu May 28 13:43:05 2020 +0800

    fix: fix not existed emphasis state caused error.
---
 src/util/graphic.ts | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index 72bf70e..36d7fd3 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -462,7 +462,9 @@ function elementStateProxy(this: Displayable, stateName: string): DisplayableSta
                 state.style = emphasisStyle;
             }
         }
-        state.z2 = this.z2 + Z2_EMPHASIS_LIFT;
+        if (state) {
+            state.z2 = this.z2 + Z2_EMPHASIS_LIFT;
+        }
     }
 
     return state;


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