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

ovilia pushed a commit to branch feat-bar-race
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git

commit 03fee21840cffae72e214fd2188523857fd85ade
Author: Ovilia <zwl.s...@gmail.com>
AuthorDate: Wed Jul 29 19:08:14 2020 +0800

    fix(bar-race): fix label animation #12484
---
 src/action/changeAxisOrder.ts                    |   5 +
 src/chart/bar/BarView.ts                         | 322 +++++++++++++----------
 src/component/axis/AxisBuilder.ts                |   5 +-
 src/coord/Axis.ts                                |  10 +-
 src/coord/cartesian/defaultAxisExtentFromData.ts |   8 +-
 src/scale/Ordinal.ts                             |  33 ++-
 src/scale/Scale.ts                               |   7 +
 src/util/graphic.ts                              |  53 ++--
 8 files changed, 277 insertions(+), 166 deletions(-)

diff --git a/src/action/changeAxisOrder.ts b/src/action/changeAxisOrder.ts
index c270dae..dd74b7e 100644
--- a/src/action/changeAxisOrder.ts
+++ b/src/action/changeAxisOrder.ts
@@ -41,6 +41,11 @@ echarts.registerAction({
     ecModel.eachComponent(
         { mainType: componentType, query: payload },
         function (componentModel) {
+            // console.log('in action')
+            if (payload.sortInfo) {
+                // console.log(payload.sortInfo);
+                componentModel.axis.setCategorySortInfo(payload.sortInfo);
+            }
         }
     );
 });
diff --git a/src/chart/bar/BarView.ts b/src/chart/bar/BarView.ts
index a1d4d0d..90855b1 100644
--- a/src/chart/bar/BarView.ts
+++ b/src/chart/bar/BarView.ts
@@ -17,6 +17,10 @@
 * under the License.
 */
 
+import Path, {PathProps} from 'zrender/src/graphic/Path';
+import Group from 'zrender/src/graphic/Group';
+import {extend, map, defaults, each} from 'zrender/src/core/util';
+import type {RectLike} from 'zrender/src/core/BoundingRect';
 import {
     Rect,
     Sector,
@@ -29,8 +33,6 @@ import {
 import { getECData } from "../../util/ecData";
 import { enableHoverEmphasis, setStatesStylesFromModel } from 
'../../util/states';
 import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';
-import Path, { PathProps } from 'zrender/src/graphic/Path';
-import Group from 'zrender/src/graphic/Group';
 import {throttle} from '../../util/throttle';
 import {createClipPath} from '../helper/createClipPathFromCoordSys';
 import Sausage from '../../util/shape/sausage';
@@ -45,20 +47,23 @@ import {
     OrdinalSortInfo,
     Payload,
     OrdinalNumber,
-    ParsedValue
+    ParsedValue,
+    ECElement
 } from '../../util/types';
-import BarSeriesModel, { BarSeriesOption, BarDataItemOption } from 
'./BarSeries';
+import BarSeriesModel, {BarSeriesOption, BarDataItemOption} from './BarSeries';
 import type Axis2D from '../../coord/cartesian/Axis2D';
 import type Cartesian2D from '../../coord/cartesian/Cartesian2D';
-import type { RectLike } from 'zrender/src/core/BoundingRect';
 import type Model from '../../model/Model';
 import { isCoordinateSystemType } from '../../coord/CoordinateSystem';
 import { getDefaultLabel } from '../helper/labelHelper';
 import OrdinalScale from '../../scale/Ordinal';
 import AngleAxis from '../../coord/polar/AngleAxis';
 import RadiusAxis from '../../coord/polar/RadiusAxis';
-import { extend, map, defaults, each } from 'zrender/src/core/util';
 import SeriesModel from '../../model/Series';
+import {AngleAxisModel, RadiusAxisModel} from '../../coord/polar/AxisModel';
+import CartesianAxisModel from '../../coord/cartesian/AxisModel';
+import {LayoutRect} from '../../util/layout';
+import Animator from 'zrender/src/animation/Animator';
 
 const BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'borderWidth'] as const;
 const BAR_BORDER_RADIUS_QUERY = ['itemStyle', 'borderRadius'] as const;
@@ -108,12 +113,19 @@ class BarView extends ChartView {
 
     private _isLargeDraw: boolean;
 
+    private _isFirstFrame: boolean; // First frame after series added
+
     private _backgroundGroup: Group;
 
     private _backgroundEls: (Rect | Sector)[];
 
     private _model: BarSeriesModel;
 
+    constructor () {
+        super();
+        this._isFirstFrame = true;
+    }
+
     render(seriesModel: BarSeriesModel, ecModel: GlobalModel, api: 
ExtensionAPI, payload: Payload) {
         this._model = seriesModel;
 
@@ -132,6 +144,8 @@ class BarView extends ChartView {
         else if (__DEV__) {
             console.warn('Only cartesian2d and polar supported for bar.');
         }
+
+        this._isFirstFrame = false;
     }
 
     incrementalPrepareRender(seriesModel: BarSeriesModel): void {
@@ -168,25 +182,27 @@ class BarView extends ChartView {
 
         const coord = seriesModel.coordinateSystem;
         const baseAxis = coord.getBaseAxis();
-        let valueAxis: Axis2D | RadiusAxis | AngleAxis;
         let isHorizontalOrRadial: boolean;
 
+        let lastAnimator: Animator<any> = null;
+
         if (coord.type === 'cartesian2d') {
             isHorizontalOrRadial = (baseAxis as Axis2D).isHorizontal();
-            valueAxis = coord.getOtherAxis(baseAxis as Axis2D);
         }
         else if (coord.type === 'polar') {
             isHorizontalOrRadial = baseAxis.dim === 'angle';
-            valueAxis = coord.getOtherAxis(baseAxis as (AngleAxis | 
RadiusAxis));
         }
 
         const animationModel = seriesModel.isAnimationEnabled() ? seriesModel 
: null;
-        const axisAnimationModel = baseAxis.model;
 
         const axis2DModel = (baseAxis as Axis2D).model;
         const axisSort = coord.type === 'cartesian2d' && 
axis2DModel.get('sort')
             && axis2DModel.get('sortSeriesIndex') === seriesModel.seriesIndex;
         const realtimeSort = axisSort && axis2DModel.get('realtimeSort');
+        if (realtimeSort && this._isFirstFrame) {
+            this._initSort(data, isHorizontalOrRadial, baseAxis as Axis2D, 
api);
+            return;
+        }
 
         const needsClip = seriesModel.get('clip', true);
         const coordSysClipArea = getClipArea(coord, data);
@@ -195,8 +211,6 @@ class BarView extends ChartView {
         // We don't use clipPath in normal mode because we needs a perfect 
animation
         // And don't want the label are clipped.
 
-        const labelModel = seriesModel.getModel('label');
-
         const roundCap = seriesModel.get('roundCap', true);
 
         const drawBackground = seriesModel.get('showBackground', true);
@@ -206,49 +220,19 @@ class BarView extends ChartView {
         const bgEls: BarView['_backgroundEls'] = [];
         const oldBgEls = this._backgroundEls;
 
-        let hasDuringForOneData = false;
-        let getDuring: () => (() => void) = () => {
-            return null;
-        };
-        if (coord.type === 'cartesian2d') {
-            const oldOrder = (baseAxis.scale as 
OrdinalScale).getCategorySortInfo();
+        const realtimeDuring = () => {
             const orderMap = (idx: number) => {
-                return data.get(valueAxis.dim, idx) as number;
-            };
-
-            if (realtimeSort) {
-                // Sort in animation during
-                const isOrderChanged = this._isDataOrderChanged(data, 
orderMap, oldOrder);
-                if (isOrderChanged) {
-                    getDuring = () => {
-                        if (!hasDuringForOneData) {
-                            hasDuringForOneData = true;
-                            return () => {
-                                const orderMap = (idx: number) => {
-                                    const el = (data.getItemGraphicEl(idx) as 
Rect);
-                                    if (el) {
-                                        const shape = el.shape;
-                                        return isHorizontalOrRadial ? shape.y 
+ shape.height : shape.x + shape.width;
-                                    }
-                                    else {
-                                        return 0;
-                                    }
-                                };
-                                that._updateSort(data, orderMap, baseAxis as 
Axis2D, api);
-                            };
-                        }
-                        else {
-                            return () => null;
-                        }
-                    };
+                const el = (data.getItemGraphicEl(idx) as Rect);
+                if (el) {
+                    const shape = el.shape;
+                    return isHorizontalOrRadial ? shape.y + shape.height : 
shape.x + shape.width;
                 }
-            }
-            else if (axisSort) {
-                // Sort now in the first frame
-                this._updateSort(data, orderMap, baseAxis as Axis2D, api);
-            }
-        }
-
+                else {
+                    return 0;
+                }
+            };
+            that._updateSort(data, orderMap, baseAxis as Axis2D, api);
+        };
 
         data.diff(oldData)
             .add(function (dataIndex) {
@@ -288,17 +272,38 @@ class BarView extends ChartView {
                     layout,
                     isHorizontalOrRadial,
                     animationModel,
+                    baseAxis.model,
                     false,
-                    getDuring(),
                     roundCap
                 );
-                data.setItemGraphicEl(dataIndex, el);
-                group.add(el);
 
                 updateStyle(
                     el, data, dataIndex, itemModel, layout,
                     seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                 );
+
+                if (realtimeSort) {
+                    (el as ECElement).disableLabelAnimation = true;
+
+                    const animator = updateRealtimeAnimation(
+                        seriesModel,
+                        axis2DModel,
+                        animationModel,
+                        el as Rect,
+                        layout as LayoutRect,
+                        data,
+                        dataIndex,
+                        isHorizontalOrRadial,
+                        false
+                    );
+                    animator && (lastAnimator = animator);
+                }
+                else if (coord.type === 'cartesian2d') {
+                    initProps(el, {shape: layout} as any, seriesModel, 
dataIndex);
+                }
+
+                data.setItemGraphicEl(dataIndex, el);
+                group.add(el);
             })
             .update(function (newIndex, oldIndex) {
                 const itemModel = data.getItemModel(newIndex);
@@ -316,13 +321,14 @@ class BarView extends ChartView {
                     const bgLayout = getLayout[coord.type](data, newIndex);
                     const shape = createBackgroundShape(isHorizontalOrRadial, 
bgLayout, coord);
                     updateProps(
-                        bgEl as Path, { shape: shape }, animationModel, 
newIndex
+                        bgEl as Path, {shape: shape as RectShape}, 
animationModel, newIndex
                     );
                 }
 
                 let el = oldData.getItemGraphicEl(oldIndex) as BarPossiblePath;
                 if (!data.hasValue(newIndex)) {
                     group.remove(el);
+                    el = null;
                     return;
                 }
 
@@ -334,58 +340,7 @@ class BarView extends ChartView {
                     }
                 }
 
-                if (el) {
-                    if (coord.type === 'cartesian2d'
-                        && baseAxis.type === 'category' && (baseAxis as 
Axis2D).model.get('sort')
-                    ) {
-                        const rect = layout as RectShape;
-                        let seriesShape;
-                        let axisShape;
-                        if (baseAxis.dim === 'x') {
-                            axisShape = {
-                                x: rect.x,
-                                width: rect.width
-                            };
-                            seriesShape = {
-                                y: rect.y,
-                                height: rect.height
-                            };
-                        }
-                        else {
-                            axisShape = {
-                                y: rect.y,
-                                height: rect.height
-                            };
-                            seriesShape = {
-                                x: rect.x,
-                                width: rect.width
-                            };
-                        }
-
-                        if (!isReorder) {
-                            updateProps(
-                                el as Path,
-                                { shape: seriesShape },
-                                animationModel,
-                                newIndex,
-                                null,
-                                getDuring()
-                            );
-                        }
-                        updateProps(el as Path, { shape: axisShape }, 
axisAnimationModel, newIndex, null);
-                    }
-                    else {
-                        updateProps(el as Path, {
-                            shape: layout
-                        }, animationModel, newIndex, null);
-                    }
-
-                    const defaultTextGetter = (values: ParsedValue | 
ParsedValue[]) => {
-                        return getDefaultLabel(seriesModel.getData(), 
newIndex, values);
-                    };
-                    updateLabel(el, data, newIndex, labelModel, seriesModel, 
animationModel, defaultTextGetter);
-                }
-                else {
+                if (!el) {
                     el = elementCreator[coord.type](
                         seriesModel,
                         data,
@@ -393,20 +348,40 @@ class BarView extends ChartView {
                         layout,
                         isHorizontalOrRadial,
                         animationModel,
-                        true,
-                        getDuring(),
+                        baseAxis.model,
+                        !!el,
                         roundCap
                     );
                 }
 
-                data.setItemGraphicEl(newIndex, el);
-                // Add back
-                group.add(el);
-
                 updateStyle(
                     el, data, newIndex, itemModel, layout,
                     seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                 );
+
+                if (realtimeSort) {
+                    (el as ECElement).disableLabelAnimation = true;
+
+                    const animator = updateRealtimeAnimation(
+                        seriesModel,
+                        axis2DModel,
+                        animationModel,
+                        el as Rect,
+                        layout as LayoutRect,
+                        data,
+                        newIndex,
+                        isHorizontalOrRadial,
+                        false
+                    );
+                    animator && (lastAnimator = animator);
+                }
+                else if (coord.type === 'cartesian2d') {
+                    updateProps(el, {shape: layout}, seriesModel, newIndex, 
null);
+                }
+
+                data.setItemGraphicEl(newIndex, el);
+                // Add back
+                group.add(el);
             })
             .remove(function (dataIndex) {
                 const el = oldData.getItemGraphicEl(dataIndex) as Path;
@@ -424,6 +399,10 @@ class BarView extends ChartView {
         this._backgroundEls = bgEls;
 
         this._data = data;
+
+        if (lastAnimator) {
+            lastAnimator.during(realtimeDuring);
+        }
     }
 
     private _renderLarge(seriesModel: BarSeriesModel, ecModel: GlobalModel, 
api: ExtensionAPI): void {
@@ -515,19 +494,34 @@ class BarView extends ChartView {
         const oldOrder = (baseAxis.scale as 
OrdinalScale).getCategorySortInfo();
         const isOrderChanged = this._isDataOrderChanged(data, orderMap, 
oldOrder);
         if (isOrderChanged) {
-            // re-sort and update in axis
-            const sortInfo = this._dataSort(data, orderMap);
-            baseAxis.setCategorySortInfo(sortInfo);
-
             const action = {
                 type: 'changeAxisOrder',
                 componentType: baseAxis.dim + 'Axis',
-                axisId: baseAxis.index
+                axisId: baseAxis.index,
+                sortInfo: this._dataSort(data, orderMap)
             } as Payload;
             api.dispatchAction(action);
         }
     }
 
+    _initSort(
+        data: List<BarSeriesModel, DefaultDataVisual>,
+        isHorizontal: boolean,
+        baseAxis: Axis2D,
+        api: ExtensionAPI
+    ) {
+        const action = {
+            type: 'changeAxisOrder',
+            componentType: baseAxis.dim + 'Axis',
+            axisId: baseAxis.index,
+            sortInfo: this._dataSort(
+                data,
+                idx => parseInt(data.get(isHorizontal ? 'y' : 'x', idx) as 
string, 10)
+            )
+        } as Payload;
+        api.dispatchAction(action);
+    }
+
     remove() {
         this._clear(this._model);
     }
@@ -547,6 +541,7 @@ class BarView extends ChartView {
             group.removeAll();
         }
         this._data = null;
+        this._isFirstFrame = true;
     }
 
     private _removeBackground(): void {
@@ -608,7 +603,9 @@ interface ElementCreator {
     (
         seriesModel: BarSeriesModel, data: List, newIndex: number,
         layout: RectLayout | SectorLayout, isHorizontalOrRadial: boolean,
-        animationModel: BarSeriesModel, isUpdate: boolean, during: () => void,
+        animationModel: BarSeriesModel,
+        axisModel: CartesianAxisModel | AngleAxisModel | RadiusAxisModel,
+        isUpdate: boolean,
         roundCap?: boolean
     ): BarPossiblePath
 }
@@ -619,7 +616,7 @@ const elementCreator: {
 
     cartesian2d(
         seriesModel, data, newIndex, layout: RectLayout, isHorizontal,
-        animationModel, isUpdate, during
+        animationModel, axisModel, isUpdate, roundCap
     ) {
         const rect = new Rect({
             shape: extend({}, layout),
@@ -628,34 +625,17 @@ const elementCreator: {
 
         rect.name = 'item';
 
-        // Animation
         if (animationModel) {
             const rectShape = rect.shape;
             const animateProperty = isHorizontal ? 'height' : 'width' as 
'width' | 'height';
-            const animateTarget = {} as RectShape;
             rectShape[animateProperty] = 0;
-            animateTarget[animateProperty] = layout[animateProperty];
-
-            (isUpdate ? updateProps : initProps)(rect, {
-                shape: animateTarget
-            }, animationModel, newIndex, null, during);
-
-            const defaultTextGetter = (values: ParsedValue | ParsedValue[]) => 
{
-                return getDefaultLabel(seriesModel.getData(), newIndex, 
values);
-            };
-
-            const labelModel = seriesModel.getModel('label');
-            (isUpdate ? updateLabel : initLabel)(
-                rect, data, newIndex, labelModel, seriesModel, animationModel, 
defaultTextGetter
-            );
         }
-
         return rect;
     },
 
     polar(
         seriesModel, data, newIndex, layout: SectorLayout, isRadial: boolean,
-        animationModel, isUpdate, during, roundCap
+        animationModel, axisModel, isUpdate, roundCap
     ) {
         // Keep the same logic with bar in catesion: use end value to control
         // direction. Notice that if clockwise is true (by default), the sector
@@ -689,6 +669,68 @@ const elementCreator: {
     }
 };
 
+function updateRealtimeAnimation(
+    seriesModel: BarSeriesModel,
+    axisModel: CartesianAxisModel,
+    animationModel: BarSeriesModel,
+    el: Rect,
+    layout: LayoutRect,
+    data: List,
+    newIndex: number,
+    isHorizontal: boolean,
+    isUpdate: boolean
+) {
+    // Animation
+    if (animationModel || axisModel) {
+        let seriesTarget;
+        let axisTarget;
+        if (isHorizontal) {
+            axisTarget = {
+                x: layout.x,
+                width: layout.width
+            };
+            seriesTarget = {
+                y: layout.y,
+                height: layout.height
+            };
+        }
+        else {
+            axisTarget = {
+                y: layout.y,
+                height: layout.height
+            };
+            seriesTarget = {
+                x: layout.x,
+                width: layout.width
+            };
+        }
+
+        (isUpdate ? updateProps : initProps)(el, {
+            shape: seriesTarget
+        }, seriesModel, newIndex, null);
+
+        const lastAnimator = el.animators.length
+            ? el.animators[el.animators.length - 1]
+            : null;
+
+        (isUpdate ? updateProps : initProps)(el, {
+            shape: axisTarget
+        }, axisModel, newIndex);
+
+        const defaultTextGetter = (values: ParsedValue | ParsedValue[]) => {
+            return getDefaultLabel(seriesModel.getData(), newIndex, values);
+        };
+
+        const labelModel = seriesModel.getModel('label');
+        (isUpdate ? updateLabel : initLabel)(
+            el, data, newIndex, labelModel, seriesModel, animationModel, 
defaultTextGetter
+        );
+
+        // TODO:
+        return lastAnimator;
+    }
+}
+
 interface GetLayout {
     (data: List, dataIndex: number, itemModel?: Model<BarDataItemOption>): 
RectLayout | SectorLayout
 }
diff --git a/src/component/axis/AxisBuilder.ts 
b/src/component/axis/AxisBuilder.ts
index 3430c31..733c3fb 100644
--- a/src/component/axis/AxisBuilder.ts
+++ b/src/component/axis/AxisBuilder.ts
@@ -32,6 +32,7 @@ import { ZRTextVerticalAlign, ZRTextAlign, ECElement, 
ColorString } from '../../
 import { AxisBaseOption } from '../../coord/axisCommonTypes';
 import Element from 'zrender/src/Element';
 import { PathStyleProps } from 'zrender/src/graphic/Path';
+import OrdinalScale from '../../scale/Ordinal';
 
 
 const PI = Math.PI;
@@ -751,7 +752,9 @@ function buildAxisLabel(
     const triggerEvent = axisModel.get('triggerEvent');
 
     each(labels, function (labelItem, index) {
-        const tickValue = labelItem.tickValue;
+        const tickValue = axis.scale.type === 'ordinal'
+            ? (axis.scale as OrdinalScale).getRawIndex(labelItem.tickValue)
+            : labelItem.tickValue;
         const formattedLabel = labelItem.formattedLabel;
         const rawLabel = labelItem.rawLabel;
 
diff --git a/src/coord/Axis.ts b/src/coord/Axis.ts
index 0cfb43e..f314526 100644
--- a/src/coord/Axis.ts
+++ b/src/coord/Axis.ts
@@ -177,10 +177,12 @@ class Axis {
 
         const ticksCoords = map(ticks, function (tickVal) {
             return {
-                coord: this.dataToCoord(tickVal),
-                tickValue: this.scale instanceof OrdinalScale
-                    ? this.scale.getCategoryIndex(tickVal)
-                    : tickVal
+                coord: this.dataToCoord(
+                    this.scale.type === 'ordinal'
+                        ? (this.scale as OrdinalScale).getRawIndex(tickVal)
+                        : tickVal
+                ),
+                tickValue: tickVal
             };
         }, this);
 
diff --git a/src/coord/cartesian/defaultAxisExtentFromData.ts 
b/src/coord/cartesian/defaultAxisExtentFromData.ts
index 2b0e58e..b82391b 100644
--- a/src/coord/cartesian/defaultAxisExtentFromData.ts
+++ b/src/coord/cartesian/defaultAxisExtentFromData.ts
@@ -136,7 +136,7 @@ function calculateFilteredExtent(
         // For duplication removal.
         const condDimMap: Dictionary<boolean> = {};
         const tarDimMap: Dictionary<boolean> = {};
-        let condAxisExtent: number[];
+        let condAxis: Axis;
         let tarAxisRecord: AxisRecord;
 
         function addCondition(axis: Axis, axisRecord: AxisRecord) {
@@ -150,7 +150,7 @@ function calculateFilteredExtent(
                 each(getDataDimensionsOnAxis(data, axis.dim), function 
(dataDim) {
                     if (!hasOwn(condDimMap, dataDim)) {
                         condDimMap[dataDim] = true;
-                        condAxisExtent = [rawExtentResult.min, 
rawExtentResult.max];
+                        condAxis = axis;
                     }
                 });
             }
@@ -196,7 +196,7 @@ function calculateFilteredExtent(
         if (singleCondDim && singleTarDim) {
             for (let dataIdx = 0; dataIdx < dataLen; dataIdx++) {
                 const condVal = data.get(singleCondDim, dataIdx) as number;
-                if (condVal >= condAxisExtent[0] && condVal <= 
condAxisExtent[1]) {
+                if (condAxis.scale.isInExtentRange(condVal)) {
                     unionExtent(tarDimExtents[0], data.get(singleTarDim, 
dataIdx) as number);
                 }
             }
@@ -205,7 +205,7 @@ function calculateFilteredExtent(
             for (let dataIdx = 0; dataIdx < dataLen; dataIdx++) {
                 for (let j = 0; j < condDimsLen; j++) {
                     const condVal = data.get(condDims[j], dataIdx) as number;
-                    if (condVal >= condAxisExtent[0] && condVal <= 
condAxisExtent[1]) {
+                    if (condAxis.scale.isInExtentRange(condVal)) {
                         for (let k = 0; k < tarDimsLen; k++) {
                             unionExtent(tarDimExtents[k], data.get(tarDims[k], 
dataIdx) as number);
                         }
diff --git a/src/scale/Ordinal.ts b/src/scale/Ordinal.ts
index a0374f4..0a566d0 100644
--- a/src/scale/Ordinal.ts
+++ b/src/scale/Ordinal.ts
@@ -92,7 +92,7 @@ class OrdinalScale extends Scale {
 
         while (rank <= extent[1]) {
             ticks.push({
-                value: rank
+                value: this.getCategoryIndex(rank)
             });
             rank++;
         }
@@ -113,6 +113,11 @@ class OrdinalScale extends Scale {
         return this._categorySortInfo;
     }
 
+    /**
+     * Get display order after sort
+     *
+     * @param {OrdinalNumber} n index of raw data
+     */
     getCategoryIndex(n: OrdinalNumber): OrdinalNumber {
         if (this._categorySortInfo.length) {
             return this._categorySortInfo[n].beforeSortIndex;
@@ -123,11 +128,26 @@ class OrdinalScale extends Scale {
     }
 
     /**
+     * Get raw data index
+     *
+     * @param {OrdinalNumber} displayIndex index of display
+     */
+    getRawIndex(displayIndex: OrdinalNumber): OrdinalNumber {
+        if (this._categorySortInfo.length) {
+            return this._categorySortInfo[displayIndex].ordinalNumber;
+        }
+        else {
+            return displayIndex;
+        }
+    }
+
+    /**
      * Get item on rank n
      */
     getLabel(tick: ScaleTick): string {
         if (!this.isBlank()) {
-            const cateogry = this._ordinalMeta.categories[tick.value];
+            const rawIndex = this.getRawIndex(tick.value);
+            const cateogry = this._ordinalMeta.categories[rawIndex];
             // Note that if no data, ordinalMeta.categories is an empty array.
             // Return empty if it's not exist.
             return cateogry == null ? '' : cateogry + '';
@@ -142,6 +162,15 @@ class OrdinalScale extends Scale {
         this.unionExtent(data.getApproximateExtent(dim));
     }
 
+    /**
+     * @override
+     * If value is in extent range
+     */
+    isInExtentRange(value: number): boolean {
+        value = this.getCategoryIndex(value);
+        return this._extent[0] <= value && this._extent[1] >= value;
+    }
+
     getOrdinalMeta(): OrdinalMeta {
         return this._ordinalMeta;
     }
diff --git a/src/scale/Scale.ts b/src/scale/Scale.ts
index 0bfd5fc..2b90b6c 100644
--- a/src/scale/Scale.ts
+++ b/src/scale/Scale.ts
@@ -110,6 +110,13 @@ abstract class Scale {
     }
 
     /**
+     * If value is in extent range
+     */
+    isInExtentRange(value: number): boolean {
+        return this._extent[0] <= value && this._extent[1] >= value;
+    }
+
+    /**
      * When axis extent depends on data and no data exists,
      * axis ticks should not be drawn, which is named 'blank'.
      */
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index b351969..bf93f6a 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -70,6 +70,7 @@ import List from '../data/List';
 import { getLabelText } from '../label/labelStyle';
 import { AnimationEasing } from 'zrender/src/animation/easing';
 import { getECData } from './ecData';
+import {makeInner} from './model';
 
 
 const mathMax = Math.max;
@@ -80,6 +81,10 @@ const _customShapeMap: Dictionary<{ new(): Path }> = {};
 type ExtendShapeOpt = Parameters<typeof Path.extend>[0];
 type ExtendShapeReturn = ReturnType<typeof Path.extend>;
 
+const innerLabel = makeInner<{
+    startValue: number | (string | number)[],
+    nextValue: number | (string | number)[]
+}, ZRText>();
 
 /**
  * Extend shape with parameters
@@ -544,7 +549,9 @@ function animateOrSetLabel<Props extends PathProps>(
     const valueAnimationEnabled = labelModel && 
labelModel.get('valueAnimation');
     if (valueAnimationEnabled) {
         const precisionOption = labelModel.get('precision');
-        const precision: number = precisionOption === 'auto' ? 0 : 
precisionOption;
+        const precision: number = !precisionOption || precisionOption === 
'auto'
+            ? 0
+            : precisionOption;
 
         let interpolateValues: (number | string)[] | (number | string);
         const rawValues = seriesModel.getRawValue(dataIndex);
@@ -563,10 +570,23 @@ function animateOrSetLabel<Props extends PathProps>(
             }
         }
 
+        const text = el.getTextContent();
+        const host = text && innerLabel(text);
+        host && (host.startValue = host.nextValue);
+
         const during = (percent: number) => {
+            const text = el.getTextContent();
+            if (!text || !host) {
+                return;
+            }
+
             let interpolated;
             if (isRawValueNumber) {
-                const value = interpolateNumber(0, interpolateValues as 
number, percent);
+                const value = interpolateNumber(
+                    host.startValue as number || 0,
+                    interpolateValues as number,
+                    percent
+                );
                 interpolated = numberUtil.round(value, precision);
             }
             else {
@@ -578,23 +598,26 @@ function animateOrSetLabel<Props extends PathProps>(
                         interpolated[i] = (rawValues as [])[i];
                     }
                     else {
-                        const value = interpolateNumber(0, (interpolateValues 
as number[])[i], percent);
+                        const value = interpolateNumber(
+                            (host.startValue as number[])[i] || 0,
+                            (interpolateValues as number[])[i],
+                            percent
+                        );
                         interpolated[i] = numberUtil.round(value), precision;
                     }
                 }
             }
-            const text = el.getTextContent();
-            if (text) {
-                const labelText = getLabelText({
-                    labelDataIndex: dataIndex,
-                    labelFetcher: seriesModel,
-                    defaultText: defaultTextGetter
-                        ? defaultTextGetter(interpolated)
-                        : interpolated + ''
-                }, {normal: labelModel}, interpolated);
-                text.style.text = labelText.normal;
-                text.dirty();
-            }
+            host.nextValue = interpolated;
+
+            const labelText = getLabelText({
+                labelDataIndex: dataIndex,
+                labelFetcher: seriesModel,
+                defaultText: defaultTextGetter
+                    ? defaultTextGetter(interpolated)
+                    : interpolated + ''
+            }, {normal: labelModel}, interpolated);
+            text.style.text = labelText.normal;
+            text.dirty();
         };
 
         const props: ElementProps = {};


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

Reply via email to