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/23 05:27:26 UTC

[incubator-echarts] 01/01: Merge branch 'next' into label-enhancement

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 58dc3f701961ef455019720670fe629430b57f6e
Merge: 83df54f 9963aa4
Author: pissang <bm...@gmail.com>
AuthorDate: Tue Jun 23 13:26:39 2020 +0800

    Merge branch 'next' into label-enhancement

 .github/workflows/nodejs.yml                       |   12 +-
 dist/echarts-en.common.js                          |  520 ++++--
 dist/echarts-en.common.min.js                      |    2 +-
 dist/echarts-en.js                                 |  737 ++++++---
 dist/echarts-en.js.map                             |    2 +-
 dist/echarts-en.min.js                             |    2 +-
 dist/echarts-en.simple.js                          |  435 +++--
 dist/echarts-en.simple.min.js                      |    2 +-
 dist/echarts.common.js                             |  494 ++++--
 dist/echarts.common.min.js                         |    2 +-
 dist/echarts.js                                    |  711 +++++---
 dist/echarts.js.map                                |    2 +-
 dist/echarts.min.js                                |    2 +-
 dist/echarts.simple.js                             |  409 +++--
 dist/echarts.simple.min.js                         |    2 +-
 dist/extension/bmap.js                             |  338 +++-
 dist/extension/bmap.js.map                         |    2 +-
 dist/extension/bmap.min.js                         |    2 +-
 extension-src/bmap/BMapView.ts                     |    5 +-
 extension/bmap/BMapView.js                         |    8 +-
 map/js/province/gansu.js                           |    4 +-
 option.ts                                          |  107 ++
 package-lock.json                                  |    8 +-
 package.json                                       |    4 +-
 src/{chart/bar.ts => action/changeAxisOrder.ts}    |   39 +-
 src/chart/bar.ts                                   |    1 +
 src/chart/bar/BarSeries.ts                         |    4 +-
 src/chart/bar/BarView.ts                           |  300 +++-
 src/chart/bar/PictorialBarSeries.ts                |    2 +
 src/chart/custom.ts                                | 1745 ++++++++++++++++----
 src/chart/graph/GraphSeries.ts                     |    2 +-
 src/chart/heatmap/HeatmapView.ts                   |    4 +-
 src/chart/helper/EffectSymbol.ts                   |    3 +-
 src/chart/helper/LineDraw.ts                       |    6 +-
 src/chart/helper/Symbol.ts                         |    4 +-
 src/chart/helper/createClipPathFromCoordSys.ts     |    4 +
 src/chart/helper/labelHelper.ts                    |   15 +-
 src/chart/line/LineView.ts                         |   41 +-
 src/chart/map/MapSeries.ts                         |    8 +-
 src/chart/parallel/ParallelSeries.ts               |    2 +
 src/chart/sankey/sankeyLayout.ts                   |   22 +-
 src/chart/sunburst/SunburstPiece.ts                |    2 +
 src/chart/sunburst/SunburstView.ts                 |    3 +-
 src/chart/tree/TreeSeries.ts                       |    7 +-
 src/chart/treemap/TreemapSeries.ts                 |   21 +-
 src/chart/treemap/TreemapView.ts                   |   29 +-
 src/component/axis/RadiusAxisView.ts               |   11 +-
 src/component/dataZoom/AxisProxy.ts                |  115 +-
 src/component/dataZoom/DataZoomModel.ts            |    4 +-
 src/component/dataZoom/InsideZoomModel.ts          |    2 +-
 src/component/dataZoom/SliderZoomModel.ts          |    2 +-
 src/component/dataZoom/dataZoomProcessor.ts        |    2 +-
 src/component/dataZoom/helper.ts                   |    1 +
 src/component/dataset.ts                           |   49 +-
 src/component/gridSimple.ts                        |    1 +
 src/component/helper/MapDraw.ts                    |   36 +-
 src/component/timeline/SliderTimelineModel.ts      |    2 +-
 src/component/title.ts                             |    6 +-
 src/component/toolbox/ToolboxView.ts               |    2 +-
 src/component/toolbox/feature/MagicType.ts         |    3 +-
 src/component/toolbox/feature/SaveAsImage.ts       |    3 +-
 src/component/tooltip/TooltipView.ts               |    2 +-
 src/component/visualMap/PiecewiseModel.ts          |   16 +-
 src/coord/Axis.ts                                  |    2 +-
 src/coord/CoordinateSystem.ts                      |    3 +
 src/coord/axisCommonTypes.ts                       |   16 +-
 src/coord/axisHelper.ts                            |  167 +-
 src/coord/axisModelCommonMixin.ts                  |   57 +-
 src/coord/calendar/Calendar.ts                     |   17 +-
 src/coord/cartesian/Axis2D.ts                      |   15 +-
 src/coord/cartesian/AxisModel.ts                   |   26 +-
 src/coord/cartesian/Grid.ts                        |   65 +-
 src/coord/cartesian/GridModel.ts                   |    2 +-
 src/coord/cartesian/cartesianAxisHelper.ts         |   35 +
 src/coord/cartesian/defaultAxisExtentFromData.ts   |  262 +++
 src/coord/geo/GeoModel.ts                          |    4 +-
 src/coord/geo/geoJSONLoader.ts                     |    4 +-
 src/coord/geo/geoSourceManager.ts                  |    6 +-
 src/coord/geo/parseGeoJson.ts                      |    4 +-
 src/coord/polar/polarCreator.ts                    |   16 +-
 src/coord/polar/prepareCustom.ts                   |    1 +
 src/coord/radar/Radar.ts                           |    7 +-
 src/coord/scaleRawExtentInfo.ts                    |  321 ++++
 src/data/List.ts                                   |   15 +-
 src/data/Tree.ts                                   |   40 +-
 src/data/helper/dataStackHelper.ts                 |    6 +-
 src/echarts.ts                                     |  119 +-
 src/helper.ts                                      |    2 -
 src/langEN.ts                                      |   26 +
 src/loading/default.ts                             |   97 +-
 src/model/Component.ts                             |    5 +
 src/model/Series.ts                                |    2 +-
 src/model/mixin/dataFormat.ts                      |   24 +-
 src/model/mixin/itemStyle.ts                       |    4 +-
 src/scale/Ordinal.ts                               |   25 +-
 src/scale/Scale.ts                                 |    9 +-
 src/util/clazz.ts                                  |   16 +-
 src/util/format.ts                                 |   18 +-
 src/util/graphic.ts                                |  299 +++-
 src/util/styleCompat.ts                            |  256 +++
 src/util/types.ts                                  |   14 +-
 src/visual/symbol.ts                               |   18 +-
 test/axis-extrema.html                             |   39 +
 test/axis-filter-extent.html                       |  422 +++++
 test/bar-background.html                           |   68 +-
 test/bar-race.html                                 |  455 +++++
 test/calendar-timezone.html                        |  173 ++
 ...-d3.html => circle-packing-with-d3.compat.html} |    0
 test/circle-packing-with-d3.html                   |   50 +-
 test/custom-feature.html                           |  130 +-
 test/custom-text-content.html                      | 1193 +++++++++++++
 test/custom-transition-texture.js                  |    1 +
 test/custom-transition.html                        | 1490 +++++++++++++++++
 test/custom-transition2.html                       |  269 +++
 test/effectScatter2.html                           |  106 ++
 test/heatmap-gap-bug.html                          |  188 +++
 test/hoverStyle.html                               |    3 +-
 test/line-crash.html                               |  131 ++
 test/lines-bus.html                                |   17 +-
 test/loading.html                                  |   55 +-
 test/map-nameProperty.html                         |  252 +++
 test/map.html                                      |   72 +
 test/min-max-function.html                         |  117 +-
 test/pie-animation.html                            |   47 +-
 test/runTest/actions/__meta__.json                 |    4 +
 test/runTest/actions/bar-background.json           |    1 +
 test/runTest/actions/line-crash.json               |    1 +
 test/runTest/actions/pie-animation.json            |    1 +
 test/runTest/actions/treemap-action.json           |    1 +
 test/sankey-depth.html                             |   14 +-
 test/symbol3.html                                  |  105 ++
 test/toolbox-saveImage-background-svg.html         |  208 +++
 132 files changed, 11818 insertions(+), 2153 deletions(-)

diff --cc src/chart/bar/BarView.ts
index b9f86e2,336c256..2b2e7f2
--- a/src/chart/bar/BarView.ts
+++ b/src/chart/bar/BarView.ts
@@@ -26,18 -26,22 +26,28 @@@ import 
      updateProps,
      initProps,
      enableHoverEmphasis,
-     setLabelStyle
+     setLabelStyle,
 -    clearStates,
+     updateLabel,
+     initLabel
  } from '../../util/graphic';
  import Path, { PathProps } from 'zrender/src/graphic/Path';
 -import * as numberUtil from '../../util/number';
  import Group from 'zrender/src/graphic/Group';
  import {throttle} from '../../util/throttle';
  import {createClipPath} from '../helper/createClipPathFromCoordSys';
  import Sausage from '../../util/shape/sausage';
  import ChartView from '../../view/Chart';
- import List from '../../data/List';
+ import List, {DefaultDataVisual} from '../../data/List';
  import GlobalModel from '../../model/Global';
  import ExtensionAPI from '../../ExtensionAPI';
- import { StageHandlerProgressParams, ZRElementEvent, ColorString } from '../../util/types';
 -import { StageHandlerProgressParams, ZRElementEvent, ColorString, OrdinalSortInfo, Payload, OrdinalNumber, OrdinalRawValue, DisplayState, ParsedValue } from '../../util/types';
++import {
++    StageHandlerProgressParams,
++    ZRElementEvent,
++    ColorString,
++    OrdinalSortInfo,
++    Payload,
++    OrdinalNumber,
++    ParsedValue
++} from '../../util/types';
  import BarSeriesModel, { BarSeriesOption, BarDataItemOption } from './BarSeries';
  import type Axis2D from '../../coord/cartesian/Axis2D';
  import type Cartesian2D from '../../coord/cartesian/Cartesian2D';
@@@ -198,7 -272,7 +278,15 @@@ class BarView extends ChartView 
                  }
  
                  const el = elementCreator[coord.type](
-                     dataIndex, layout, isHorizontalOrRadial, animationModel, false, roundCap
 -                    seriesModel, data, dataIndex, layout, isHorizontalOrRadial, animationModel, false, getDuring(), roundCap
++                    seriesModel,
++                    data,
++                    dataIndex,
++                    layout,
++                    isHorizontalOrRadial,
++                    animationModel,
++                    false,
++                    getDuring(),
++                    roundCap
                  );
                  data.setItemGraphicEl(dataIndex, el);
                  group.add(el);
@@@ -238,13 -317,53 +331,67 @@@
                  }
  
                  if (el) {
-                     updateProps(el as Path, {
-                         shape: layout
-                     }, animationModel, newIndex);
 -                    clearStates(el);
 -
+                     if (coord.type === 'cartesian2d'
+                         && baseAxis.type === 'category' && (baseAxis as Axis2D).model.get('sort')
+                     ) {
+                         const rect = layout as RectShape;
 -                        let seriesShape, axisShape;
++                        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: 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 {
                      el = elementCreator[coord.type](
-                         newIndex, layout, isHorizontalOrRadial, animationModel, true, roundCap
 -                        seriesModel, data, newIndex, layout, isHorizontalOrRadial, animationModel, true, getDuring(), roundCap
++                        seriesModel,
++                        data,
++                        newIndex,
++                        layout,
++                        isHorizontalOrRadial,
++                        animationModel,
++                        true,
++                        getDuring(),
++                        roundCap
                      );
                  }
  
@@@ -415,9 -614,17 +642,19 @@@ const elementCreator: 
              const animateTarget = {} as RectShape;
              rectShape[animateProperty] = 0;
              animateTarget[animateProperty] = layout[animateProperty];
+ 
              (isUpdate ? updateProps : initProps)(rect, {
                  shape: animateTarget
-             }, animationModel, dataIndex);
+             }, 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);
++            (isUpdate ? updateLabel : initLabel)(
++                rect, data, newIndex, labelModel, seriesModel, animationModel, defaultTextGetter
++            );
          }
  
          return rect;
@@@ -450,8 -657,9 +687,9 @@@
              sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle;
              animateTarget[animateProperty] = layout[animateProperty];
              (isUpdate ? updateProps : initProps)(sector, {
 -                shape: animateTarget,
 +                shape: animateTarget
-             }, animationModel, dataIndex);
+                 // __value: typeof dataValue === 'string' ? parseInt(dataValue, 10) : dataValue
+             }, animationModel);
          }
  
          return sector;
diff --cc src/chart/custom.ts
index 28de10d,d7fcccc..6fdb2e1
--- a/src/chart/custom.ts
+++ b/src/chart/custom.ts
@@@ -463,35 -1278,39 +1278,39 @@@ function makeRenderItem
       * `visual.color` is applied at `fill`. If user want apply visual.color on `stroke`,
       * it can be implemented as:
       * `api.style({stroke: api.visual('color'), fill: null})`;
+      *
+      * [Compat]: since ec5, RectText has been separated from its hosts el.
+      * so `api.style()` will only return the style from `itemStyle` but not handle `label`
+      * any more. But `series.label` config is never published in doc.
+      * We still compat it in `api.style()`. But not encourage to use it and will still not
+      * to pulish it to doc.
       * @public
-      * @param {Object} [extra]
-      * @param {number} [dataIndexInside=currDataIndexInside]
+      * @param dataIndexInside by default `currDataIndexInside`.
       */
-     function style(extra, dataIndexInside) {
+     function style(extra?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps {
+         if (__DEV__) {
+             warnDeprecated('api.style', 'Please write literal style directly instead.');
+         }
+ 
          dataIndexInside == null && (dataIndexInside = currDataIndexInside);
-         updateCache(dataIndexInside);
  
-         const itemStyle = currItemModel.getModel(ITEM_STYLE_NORMAL_PATH).getItemStyle();
+         const style = data.getItemVisual(dataIndexInside, 'style');
+         const visualColor = style && style.fill;
+         const opacity = style && style.opacity;
  
-         currVisualColor != null && (itemStyle.fill = currVisualColor);
-         const opacity = data.getItemVisual(dataIndexInside, 'opacity');
+         let itemStyle = getItemStyleModel(dataIndexInside, NORMAL).getItemStyle();
+         visualColor != null && (itemStyle.fill = visualColor);
          opacity != null && (itemStyle.opacity = opacity);
  
-         const labelModel = extra
-             ? applyExtraBefore(extra, currLabelNormalModel)
-             : currLabelNormalModel;
- 
-         const textStyle = graphicUtil.createTextStyle(labelModel, null, {
-             inheritColor: currVisualColor,
-             isRectText: true
-         });
- 
-         // TODO
-         zrUtil.extend(itemStyle, textStyle);
- 
-         itemStyle.text = labelModel.getShallow('show')
-             ? zrUtil.retrieve2(
-                 customSeries.getFormattedLabel(dataIndexInside, 'normal'),
 -        const opt = {autoColor: isString(visualColor) ? visualColor : '#000'};
++        const opt = {inheritColor: isString(visualColor) ? visualColor : '#000'};
+         const labelModel = getLabelModel(dataIndexInside, NORMAL);
+         // Now that the feture of "auto adjust text fill/stroke" has been migrated to zrender
+         // since ec5, we should set `isAttached` as `false` here and make compat in
+         // `convertToEC4StyleForCustomSerise`.
+         const textStyle = graphicUtil.createTextStyle(labelModel, null, opt, false, true);
+         textStyle.text = labelModel.getShallow('show')
+             ? retrieve2(
+                 customSeries.getFormattedLabel(dataIndexInside, NORMAL),
                  getDefaultLabel(data, dataIndexInside)
              )
              : null;
diff --cc src/chart/sunburst/SunburstView.ts
index 625543b,6de104f..afdd28d
--- a/src/chart/sunburst/SunburstView.ts
+++ b/src/chart/sunburst/SunburstView.ts
@@@ -25,7 -25,10 +25,8 @@@ import SunburstSeriesModel, { SunburstS
  import GlobalModel from '../../model/Global';
  import ExtensionAPI from '../../ExtensionAPI';
  import { TreeNode } from '../../data/Tree';
 -import {windowOpen} from '../../util/format';
 -
 -
 -const ROOT_TO_NODE_ACTION = 'sunburstRootToNode';
 +import { ROOT_TO_NODE_ACTION } from './sunburstAction';
++import { windowOpen } from '../../util/format';
  
  interface DrawTreeNode extends TreeNode {
      parentNode: DrawTreeNode
diff --cc src/chart/treemap/TreemapView.ts
index db06317,5b5d5d2..cd5af6a
--- a/src/chart/treemap/TreemapView.ts
+++ b/src/chart/treemap/TreemapView.ts
@@@ -935,8 -928,11 +937,10 @@@ function renderNode
          graphic.setLabelStyle(
              rectEl, normalLabelModel, emphasisLabelModel,
              {
 -                defaultText: isShow ? defaultText : null,
 -                autoColor: visualColor,
 +                defaultText: isShow ? text : null,
-                 inheritColor: visualColor
++                inheritColor: visualColor,
+                 labelFetcher: seriesModel,
 -                labelDataIndex: thisNode.dataIndex,
 -                labelProp: upperLabelRect ? 'upperLabel' : 'label'
++                labelDataIndex: thisNode.dataIndex
              }
          );
  
diff --cc src/echarts.ts
index ba7f00e,eeca2de..ed58220
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@@ -1814,7 -1801,10 +1843,10 @@@ class ECharts extends Eventful 
              });
          };
  
 -        updateZ = function (model: ComponentModel, view: ComponentView | ChartView): void {
 +        function updateZ(model: ComponentModel, view: ComponentView | ChartView): void {
+             if (model.preventAutoZ) {
+                 return;
+             }
              const z = model.get('z');
              const zlevel = model.get('zlevel');
              // Set z and zlevel
diff --cc src/model/mixin/dataFormat.ts
index 5d12795,45d205b..eacee23
--- a/src/model/mixin/dataFormat.ts
+++ b/src/model/mixin/dataFormat.ts
@@@ -17,11 -17,12 +17,19 @@@
  * under the License.
  */
  
+ import * as zrUtil from 'zrender/src/core/util';
 -import Element from 'zrender/src/Element';
  import {retrieveRawValue} from '../../data/helper/dataProvider';
  import {formatTpl} from '../../util/format';
- import { DataHost, DisplayState, TooltipRenderMode, CallbackDataParams, ColorString, ZRColor } from '../../util/types';
 -import { DataHost, DisplayState, TooltipRenderMode, CallbackDataParams, ColorString, ZRColor, OptionDataValue, ParsedValue } from '../../util/types';
++import {
++    DataHost,
++    DisplayState,
++    TooltipRenderMode,
++    CallbackDataParams,
++    ColorString,
++    ZRColor,
++    OptionDataValue
++} from '../../util/types';
  import GlobalModel from '../Global';
- import Element from 'zrender/src/Element';
  
  const DIMENSION_LABEL_REG = /\{@(.+?)\}/g;
  
@@@ -42,8 -44,8 +51,7 @@@ class DataFormatMixin 
       */
      getDataParams(
          dataIndex: number,
--        dataType?: string,
-         el?: Element // May be used in override.
 -        el?: Element, // May be used in override.
++        dataType?: string
      ): CallbackDataParams {
  
          const data = this.getData(dataType);
@@@ -95,25 -97,30 +103,31 @@@
          dataIndex: number,
          status?: DisplayState,
          dataType?: string,
 -        dimIndex?: number,
 -        labelProp?: string,
 -        // interpolateValues?: ParsedValue | ParsedValue[]
 +        labelDimIndex?: number,
-         formatter?: string | ((params: object) => string)
++        formatter?: string | ((params: object) => string),
+         extendParams?: Partial<CallbackDataParams>
      ): string {
          status = status || 'normal';
          const data = this.getData(dataType);
 -        const itemModel = data.getItemModel(dataIndex);
  
 -        const params = this.getDataParams(dataIndex, dataType, null);
 +        const params = this.getDataParams(dataIndex, dataType);
+ 
+         if (extendParams) {
+             zrUtil.extend(params, extendParams);
+         }
+ 
 -        if (dimIndex != null && (params.value instanceof Array)) {
 -            params.value = params.value[dimIndex];
 +        if (labelDimIndex != null && (params.value instanceof Array)) {
 +            params.value = params.value[labelDimIndex];
          }
  
 -        // @ts-ignore FIXME:TooltipModel
 -        const formatter = itemModel.get(status === 'normal'
 -            ? [(labelProp || 'label'), 'formatter']
 -            : [status, labelProp || 'label', 'formatter']
 -        );
 +        if (!formatter) {
 +            const itemModel = data.getItemModel(dataIndex);
 +            // @ts-ignore
 +            formatter = itemModel.get(status === 'normal'
 +                ? ['label', 'formatter']
 +                : [status, 'label', 'formatter']
 +            );
 +        }
  
          if (typeof formatter === 'function') {
              params.status = status;
diff --cc src/util/graphic.ts
index bf863ba,fe27f60..182a2b7
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@@ -45,10 -43,10 +45,10 @@@ import IncrementalDisplayable from 'zre
  import * as subPixelOptimizeUtil from 'zrender/src/graphic/helper/subPixelOptimize';
  import { Dictionary } from 'zrender/src/core/types';
  import LRU from 'zrender/src/core/LRU';
 -import Displayable, { DisplayableProps } from 'zrender/src/graphic/Displayable';
 +import Displayable, { DisplayableProps, DisplayableState } from 'zrender/src/graphic/Displayable';
  import { PatternObject } from 'zrender/src/graphic/Pattern';
  import { GradientObject } from 'zrender/src/graphic/Gradient';
- import Element, { ElementEvent, ElementTextConfig } from 'zrender/src/Element';
+ import Element, { ElementEvent, ElementTextConfig, ElementProps } from 'zrender/src/Element';
  import Model from '../model/Model';
  import {
      AnimationOptionMixin,
@@@ -61,7 -59,10 +61,11 @@@
      DataModel,
      ECEventData,
      ZRStyleProps,
-     AnimationOption
++    AnimationOption,
+     TextCommonOption,
+     SeriesOption,
+     ParsedValue,
+     CallbackDataParams
  } from './types';
  import GlobalModel from '../model/Global';
  import { makeInner } from './model';
@@@ -74,8 -75,12 +78,13 @@@ import 
      isArrayLike,
      map,
      defaults,
-     indexOf
++    indexOf,
+     isObject
  } from 'zrender/src/core/util';
+ import * as numberUtil from './number';
+ import SeriesModel from '../model/Series';
+ import {interpolateNumber} from 'zrender/src/animation/Animator';
+ import List from '../data/List';
  
  
  const mathMax = Math.max;
@@@ -122,13 -121,13 +124,11 @@@ type TextCommonParams = 
       */
      disableBox?: boolean
      /**
 -     * Specify a color when color is 'auto',
 -     * for textFill, textStroke, textBackgroundColor, and textBorderColor. If autoColor specified, it is used as default textFill.
 +     * Specify a color when color is 'inherit',
 +     * If inheritColor specified, it is used as default textFill.
       */
 -    autoColor?: ColorString
 -
 -    forceRich?: boolean
 +    inheritColor?: ColorString
  
-     getTextPosition?: (textStyleModel: Model, isEmphasis?: boolean) => string | string[] | number[]
- 
      defaultOutsidePosition?: LabelOption['position']
  
      textStyle?: ZRStyleProps
@@@ -431,61 -452,7 +431,63 @@@ export function clearStates(el: Element
      }
  }
  
 -/**
 +function elementStateProxy(this: Displayable, stateName: string): DisplayableState {
 +    let state = this.states[stateName];
 +    if (stateName === 'emphasis' && this.style) {
 +        const hasEmphasis = indexOf(this.currentStates, stateName) >= 0;
 +        if (!(this instanceof ZRText)) {
 +            const currentFill = this.style.fill;
 +            const currentStroke = this.style.stroke;
 +            if (currentFill || currentStroke) {
 +                let fromState: {fill: ColorString, stroke: ColorString};
 +                if (!hasEmphasis) {
 +                    fromState = {fill: currentFill, stroke: currentStroke};
 +                    for (let i = 0; i < this.animators.length; i++) {
 +                        const animator = this.animators[i];
 +                        if (animator.__fromStateTransition
 +                            // Dont consider the animation to emphasis state.
 +                            && animator.__fromStateTransition.indexOf('emphasis') < 0
 +                            && animator.targetName === 'style'
 +                        ) {
 +                            animator.saveFinalToTarget(fromState, ['fill', 'stroke']);
 +                        }
 +                    }
 +                }
 +
 +                state = state || {};
 +                // Apply default color lift
 +                let emphasisStyle = state.style || {};
 +                let cloned = false;
 +                if (!hasFillOrStroke(emphasisStyle.fill)) {
 +                    cloned = true;
 +                    // Not modify the original value.
 +                    state = extend({}, state);
 +                    emphasisStyle = extend({}, emphasisStyle);
 +                    // Already being applied 'emphasis'. DON'T lift color multiple times.
 +                    emphasisStyle.fill = hasEmphasis ? currentFill : liftColor(fromState.fill);
 +                }
 +                if (!hasFillOrStroke(emphasisStyle.stroke)) {
 +                    if (!cloned) {
 +                        state = extend({}, state);
 +                        emphasisStyle = extend({}, emphasisStyle);
 +                    }
 +                    emphasisStyle.stroke = hasEmphasis ? currentStroke : liftColor(fromState.stroke);
 +                }
 +
 +                state.style = emphasisStyle;
 +            }
 +        }
 +        if (state) {
-             state.z2 = this.z2 + Z2_EMPHASIS_LIFT;
++            const z2EmphasisLift = (this as ECElement).z2EmphasisLift;
++            // TODO Share with textContent?
++            state.z2 = this.z2 + z2EmphasisLift != null ? z2EmphasisLift : Z2_EMPHASIS_LIFT;
 +        }
 +    }
 +
 +    return state;
 +}
 +
 +/**FI
   * Set hover style (namely "emphasis style") of element.
   * @param el Should not be `zrender/graphic/Group`.
   */
@@@ -654,32 -605,54 +656,81 @@@ interface SetLabelStyleOpt<LDI> extend
      defaultText?: string | (
          (labelDataIndex: LDI, opt: SetLabelStyleOpt<LDI>) => string
      ),
-     // Fetch text by `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)`
+     // Fetch text by:
+     // opt.labelFetcher.getFormattedLabel(
+     //     opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp
+     // )
      labelFetcher?: {
 -        getFormattedLabel?: (
 +        getFormattedLabel: (
              // In MapDraw case it can be string (region name)
              labelDataIndex: LDI,
 -            state: DisplayState,
 -            dataType: string,
 -            labelDimIndex: number,
 -            labelProp: string,
 +            status: DisplayState,
 +            dataType?: string,
 +            labelDimIndex?: number,
-             formatter?: string | ((params: object) => string)
++            formatter?: string | ((params: object) => string),
+             extendParams?: Partial<CallbackDataParams>
          ) => string
 +        // getDataParams: (labelDataIndex: LDI, dataType?: string) => object
      },
      labelDataIndex?: LDI,
      labelDimIndex?: number
  }
  
  
 -function getLabelText<LDI>(opt?: SetLabelStyleOpt<LDI>, interpolateValues?: ParsedValue | ParsedValue[]) {
 +type LabelModel = Model<LabelOption & {
 +    formatter?: string | ((params: any) => string)
 +}>;
 +type LabelModelForText = Model<Omit<
 +    // Remove
 +    LabelOption, 'position' | 'rotate'
 +> & {
 +    formatter?: string | ((params: any) => string)
 +}>;
++
++function getLabelText<LDI>(
++    opt?: SetLabelStyleOpt<LDI>,
++    normalModel: LabelModel,
++    emphasisModel: LabelModel,
++    interpolateValues?: ParsedValue | ParsedValue[]
++) {
+     const labelFetcher = opt.labelFetcher;
+     const labelDataIndex = opt.labelDataIndex;
+     const labelDimIndex = opt.labelDimIndex;
 -    const labelProp = opt.labelProp;
+ 
+     let baseText;
+     if (labelFetcher) {
 -        baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex, labelProp, {
 -            value: interpolateValues
 -        });
++        baseText = labelFetcher.getFormattedLabel(
++            labelDataIndex,
++            'normal',
++            null,
++            labelDimIndex,
++            normalModel && normalModel.get('formatter'),
++            {
++                value: interpolateValues
++            }
++        );
+     }
+     if (baseText == null) {
+         baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt) : opt.defaultText;
+     }
+     const emphasisStyleText = retrieve2(
+         labelFetcher
 -            ? labelFetcher.getFormattedLabel(labelDataIndex, 'emphasis', null, labelDimIndex, labelProp)
++            ? labelFetcher.getFormattedLabel(
++                labelDataIndex,
++                'emphasis',
++                null,
++                labelDimIndex,
++                emphasisModel && emphasisModel.get('formatter')
++            )
+             : null,
+         baseText
+     );
+     return {
+         normal: baseText,
+         emphasis: emphasisStyleText
+     };
+ }
+ 
  /**
   * Set normal styles and emphasis styles about text on target element
   * If target is a ZRText. It will create a new style object.
@@@ -708,33 -677,11 +759,8 @@@ function setLabelStyle<LDI>
      const showNormal = normalModel.getShallow('show');
      const showEmphasis = emphasisModel.getShallow('show');
  
 -    // Consider performance, only fetch label when necessary.
 -    // If `normal.show` is `false` and `emphasis.show` is `true` and `emphasis.formatter` is not set,
 -    // label should be displayed, where text is fetched by `normal.formatter` or `opt.defaultText`.
      let richText = isSetOnText ? targetEl as ZRText : null;
      if (showNormal || showEmphasis) {
-         let baseText;
-         if (labelFetcher) {
-             baseText = labelFetcher.getFormattedLabel(
-                 labelDataIndex, 'normal', null, labelDimIndex,
-                 normalModel.get('formatter')
-             );
-         }
-         if (baseText == null) {
-             baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt) : opt.defaultText;
-         }
-         const normalStyleText = baseText;
-         const emphasisStyleText = retrieve2(
-             labelFetcher
-                 ? labelFetcher.getFormattedLabel(
-                     labelDataIndex, 'emphasis', null, labelDimIndex,
-                     emphasisModel.get('formatter')
-                 )
-                 : null,
-             baseText
-         );
- 
          if (!isSetOnText) {
              // Reuse the previous
              richText = targetEl.getTextContent();
@@@ -785,8 -738,9 +811,9 @@@
          // auto slient is those cases.
          richText.silent = !!normalModel.getShallow('silent');
  
-         normalStyle.text = normalStyleText;
-         emphasisState.style.text = emphasisStyleText;
 -        const labelText = getLabelText(opt);
++        const labelText = getLabelText(opt, normalModel, emphasisModel);
+         normalStyle.text = labelText.normal;
+         emphasisState.style.text = labelText.emphasis;
  
          // Keep x and y
          if (richText.style.x != null) {
@@@ -831,9 -784,10 +858,10 @@@ export function createTextStyle
  export function createTextConfig(
      textStyle: TextStyleProps,
      textStyleModel: Model,
-     opt?: Pick<TextCommonParams, 'getTextPosition' | 'defaultOutsidePosition' | 'inheritColor'>,
 -    opt: TextCommonParams,
 -    isEmphasis: boolean
++    opt?: Pick<TextCommonParams, 'defaultOutsidePosition' | 'inheritColor'>,
 +    isNotNormal?: boolean
  ) {
+     opt = opt || {};
      const textConfig: ElementTextConfig = {};
      let labelPosition;
      let labelRotate = textStyleModel.getShallow('rotate');
@@@ -842,16 -796,11 +870,11 @@@
      );
      const labelOffset = textStyleModel.getShallow('offset');
  
-     if (opt.getTextPosition) {
-         labelPosition = opt.getTextPosition(textStyleModel, isNotNormal);
-     }
-     else {
-         labelPosition = textStyleModel.getShallow('position')
-             || (isNotNormal ? null : 'inside');
-         // 'outside' is not a valid zr textPostion value, but used
-         // in bar series, and magic type should be considered.
-         labelPosition === 'outside' && (labelPosition = opt.defaultOutsidePosition || 'top');
-     }
+     labelPosition = textStyleModel.getShallow('position')
 -        || (isEmphasis ? null : 'inside');
++        || (isNotNormal ? null : 'inside');
+     // 'outside' is not a valid zr textPostion value, but used
+     // in bar series, and magric type should be considered.
+     labelPosition === 'outside' && (labelPosition = opt.defaultOutsidePosition || 'top');
  
      if (labelPosition != null) {
          textConfig.position = labelPosition;
@@@ -1144,15 -1116,26 +1186,27 @@@ function animateOrSetProps<Props>
          }
  
          duration > 0
-             ? el.animateTo(props, {
-                 duration,
-                 delay: animationDelay || 0,
-                 easing: animationEasing,
-                 done: cb,
-                 setToFinal: true,
-                 force: !!cb
-             })
-             : (el.stopAnimation(), el.attr(props), cb && cb());
+             ? (
+                 isFrom
+                     ? el.animateFrom(props, {
+                         duration,
+                         delay: animationDelay || 0,
+                         easing: animationEasing,
+                         done: cb,
+                         force: !!cb || !!during,
+                         during: during
+                     })
+                     : el.animateTo(props, {
+                         duration,
+                         delay: animationDelay || 0,
+                         easing: animationEasing,
+                         done: cb,
+                         force: !!cb || !!during,
++                        setToFinal: true,
+                         during: during
+                     })
+             )
+             : (el.stopAnimation(), el.attr(props), cb && (cb as AnimateOrSetPropsOption['cb'])());
      }
      else {
          el.stopAnimation();
@@@ -1202,10 -1186,108 +1257,108 @@@ export function initProps<Props>
      el: Element<Props>,
      props: Props,
      animatableModel?: Model<AnimationOptionMixin>,
-     dataIndex?: number | (() => void),
-     cb?: () => void
+     dataIndex?: AnimateOrSetPropsOption['dataIndex'] | AnimateOrSetPropsOption['cb'] | AnimateOrSetPropsOption,
+     cb?: AnimateOrSetPropsOption['cb'] | AnimateOrSetPropsOption['during'],
+     during?: AnimateOrSetPropsOption['during']
+ ) {
+     animateOrSetProps(false, el, props, animatableModel, dataIndex, cb, during);
+ }
+ 
+ function animateOrSetLabel<Props extends PathProps>(
+     isUpdate: boolean,
+     el: Element<Props>,
+     data: List,
+     dataIndex: number,
+     labelModel: Model<LabelOption>,
+     seriesModel: SeriesModel,
+     animatableModel?: Model<AnimationOptionMixin>,
+     defaultTextGetter?: (value: ParsedValue[] | ParsedValue) => string
+ ) {
+     const element = el as Element<Props> & { __value: ParsedValue[] | ParsedValue };
+     const valueAnimationEnabled = labelModel && labelModel.get('valueAnimation');
+     if (valueAnimationEnabled) {
+         const precisionOption = labelModel.get('precision');
+         let precision: number = precisionOption === 'auto' ? 0 : precisionOption;
+ 
+         let interpolateValues: (number | string)[] | (number | string);
+         const rawValues = seriesModel.getRawValue(dataIndex);
+         let isRawValueNumber = false;
+         if (typeof rawValues === 'number') {
+             isRawValueNumber = true;
+             interpolateValues = rawValues;
+         }
+         else {
+             interpolateValues = [];
+             for (let i = 0; i < (rawValues as []).length; ++i) {
+                 const info = data.getDimensionInfo(i);
+                 if (info.type !== 'ordinal') {
+                     interpolateValues.push((rawValues as [])[i]);
+                 }
+             }
+         }
+ 
+         const during = (percent: number) => {
+             let interpolated;
+             if (isRawValueNumber) {
+                 const value = interpolateNumber(0, interpolateValues as number, percent);
+                 interpolated = numberUtil.round(value, precision);
+             }
+             else {
+                 interpolated = [];
+                 for (let i = 0, j = 0; i < (rawValues as []).length; ++i) {
+                     const info = data.getDimensionInfo(i);
+                     // Don't interpolate ordinal dims
+                     if (info.type === 'ordinal') {
+                         interpolated[i] = (rawValues as [])[i];
+                     }
+                     else {
+                         const value = interpolateNumber(0, (interpolateValues as number[])[i], percent);
+                         interpolated[i] = numberUtil.round(value), precision;
+                         ++j;
+                     }
+                 }
+             }
+             const text = el.getTextContent();
+             if (text) {
+                 const labelText = getLabelText({
+                     labelDataIndex: dataIndex,
+                     labelFetcher: seriesModel,
+                     defaultText: defaultTextGetter
+                         ? defaultTextGetter(interpolated)
+                         : interpolated + ''
 -                }, interpolated);
++                }, labelModel, null, interpolated);
+                 text.style.text = labelText.normal;
+                 text.dirty();
+             }
+         };
+ 
+         const props: ElementProps = {};
+         animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, null, during);
+     }
+ }
+ 
+ export function updateLabel<Props>(
+     el: Element<Props>,
+     data: List,
+     dataIndex: number,
+     labelModel: Model<LabelOption>,
+     seriesModel: SeriesModel,
+     animatableModel?: Model<AnimationOptionMixin>,
+     defaultTextGetter?: (value: ParsedValue[] | ParsedValue) => string
+ ) {
+     animateOrSetLabel(true, el, data, dataIndex, labelModel, seriesModel, animatableModel, defaultTextGetter);
+ }
+ 
+ export function initLabel<Props>(
+     el: Element<Props>,
+     data: List,
+     dataIndex: number,
+     labelModel: Model<LabelOption>,
+     seriesModel: SeriesModel,
+     animatableModel?: Model<AnimationOptionMixin>,
+     defaultTextGetter?: (value: ParsedValue[] | ParsedValue) => string
  ) {
-     animateOrSetProps(false, el, props, animatableModel, dataIndex, cb);
+     animateOrSetLabel(false, el, data, dataIndex, labelModel, seriesModel, animatableModel, defaultTextGetter);
  }
  
  /**
diff --cc src/util/types.ts
index e4f508e,50b7f7c..a739352
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@@ -106,9 -106,7 +106,10 @@@ export interface ECElement extends Elem
      };
      highDownSilentOnTouch?: boolean;
      onStateChange?: (fromState: 'normal' | 'emphasis', toState: 'normal' | 'emphasis') => void;
 +
 +    highlighted?: boolean;
 +    selected?: boolean;
+     z2EmphasisLift?: number;
  }
  
  export interface DataHost {


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