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/03/23 14:52:56 UTC

[incubator-echarts] branch next updated: refact: upgrade to zrender next.

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

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


The following commit(s) were added to refs/heads/next by this push:
     new 7264082  refact: upgrade to zrender next.
7264082 is described below

commit 7264082dfcd6fd27e8bf24bf865bc6144435bf09
Author: pissang <bm...@gmail.com>
AuthorDate: Mon Mar 23 22:52:12 2020 +0800

    refact: upgrade to zrender next.
---
 echarts.all.ts                               |   2 +-
 src/chart/bar/BarView.ts                     |  45 ++-
 src/chart/bar/PictorialBarView.ts            |  23 +-
 src/chart/bar/barItemStyle.ts                |   4 +-
 src/chart/bar/helper.ts                      |  59 ---
 src/chart/boxplot/BoxplotView.ts             |  13 +-
 src/chart/candlestick/CandlestickView.ts     |  14 +-
 src/chart/custom.ts                          |   2 +-
 src/chart/funnel/FunnelSeries.ts             |   3 +-
 src/chart/funnel/FunnelView.ts               |  14 +-
 src/chart/gauge/GaugeView.ts                 |  24 +-
 src/chart/gauge/PointerPath.ts               |   6 +-
 src/chart/graph/GraphSeries.ts               |   9 +-
 src/chart/graph/GraphView.ts                 |  32 +-
 src/chart/heatmap/HeatmapView.ts             |   7 +-
 src/chart/helper/EffectLine.ts               |   1 -
 src/chart/helper/LargeLineDraw.ts            |  18 +-
 src/chart/helper/LargeSymbolDraw.ts          |  26 +-
 src/chart/helper/Line.ts                     |  33 +-
 src/chart/helper/LineDraw.ts                 |   8 +-
 src/chart/helper/LinePath.ts                 |  15 +-
 src/chart/helper/Polyline.ts                 |   6 +-
 src/chart/helper/Symbol.ts                   |   8 +-
 src/chart/helper/SymbolDraw.ts               |   8 +-
 src/chart/line/poly.ts                       |  27 +-
 src/chart/map/MapView.ts                     |  90 ++---
 src/chart/parallel/ParallelView.ts           |   6 +-
 src/chart/pie/PieSeries.ts                   |   4 +-
 src/chart/pie/PieView.ts                     |  25 +-
 src/chart/pie/labelLayout.ts                 |   3 +-
 src/chart/radar/RadarView.ts                 |  16 +-
 src/chart/sankey/SankeyView.ts               |  17 +-
 src/chart/sunburst/SunburstPiece.ts          |   6 +-
 src/chart/sunburst/SunburstSeries.ts         |   3 +-
 src/chart/themeRiver/ThemeRiverView.ts       |   6 +-
 src/chart/tree/TreeView.ts                   |  51 ++-
 src/chart/treemap/TreemapView.ts             |  44 +-
 src/component/axis/AngleAxisView.ts          |  11 +-
 src/component/axis/AxisBuilder.ts            |  43 +-
 src/component/axisPointer/BaseAxisPointer.ts |  12 +-
 src/component/axisPointer/viewHelper.ts      |  29 +-
 src/component/calendar/CalendarView.ts       |  33 +-
 src/component/dataZoom/SliderZoomView.ts     |  25 +-
 src/component/helper/BrushController.ts      |   4 +-
 src/component/helper/MapDraw.ts              |   8 +-
 src/component/helper/RoamController.ts       |   2 +-
 src/component/legend/LegendView.ts           |  27 +-
 src/component/legend/ScrollableLegendView.ts |   6 +-
 src/component/marker/MarkAreaView.ts         |   9 +-
 src/component/timeline/SliderTimelineView.ts |  14 +-
 src/component/title.ts                       |  16 +-
 src/component/toolbox/ToolboxView.ts         |  84 ++--
 src/component/toolbox/featureManager.ts      |   5 +-
 src/component/tooltip/TooltipRichContent.ts  |  34 +-
 src/component/visualMap/ContinuousView.ts    |  95 ++---
 src/component/visualMap/PiecewiseView.ts     |  16 +-
 src/coord/geo/geoSVGLoader.ts                |   2 +-
 src/coord/geo/geoSourceManager.ts            |   2 +-
 src/coord/parallel/AxisModel.ts              |   4 +-
 src/echarts.ts                               |   2 +
 src/loading/default.ts                       |  16 +-
 src/model/mixin/areaStyle.ts                 |   4 +-
 src/model/mixin/itemStyle.ts                 |  13 +-
 src/model/mixin/lineStyle.ts                 |   4 +-
 src/model/mixin/textStyle.ts                 |  25 +-
 src/util/format.ts                           |  41 +-
 src/util/graphic.ts                          | 573 ++++++++-------------------
 src/util/layout.ts                           |   6 +-
 src/util/shape/sausage.ts                    |   8 +-
 src/util/symbol.ts                           |   8 +-
 src/util/types.ts                            |  30 +-
 src/view/Chart.ts                            |   2 +-
 src/view/Component.ts                        |   2 +-
 73 files changed, 829 insertions(+), 1064 deletions(-)

diff --git a/echarts.all.ts b/echarts.all.ts
index f801b1d..b8d3d90 100644
--- a/echarts.all.ts
+++ b/echarts.all.ts
@@ -267,7 +267,7 @@ import './src/component/visualMapPiecewise';
 
 
 // Provide IE 6,7,8 compatibility.
-import 'zrender/src/vml/vml';
+// import 'zrender/src/vml/vml';
 
 // Render via SVG rather than canvas.
 import 'zrender/src/svg/svg';
diff --git a/src/chart/bar/BarView.ts b/src/chart/bar/BarView.ts
index 0342978..04b5999 100644
--- a/src/chart/bar/BarView.ts
+++ b/src/chart/bar/BarView.ts
@@ -19,11 +19,10 @@
 
 import {__DEV__} from '../../config';
 import * as zrUtil from 'zrender/src/core/util';
-import {Rect, Sector, getECData, updateProps, initProps, setHoverStyle} from '../../util/graphic';
-import {setLabel} from './helper';
+import {Rect, Sector, getECData, updateProps, initProps, enableHoverEmphasis, setLabelStyle} from '../../util/graphic';
 import {getBarItemStyle} from './barItemStyle';
 import Path, { PathProps } from 'zrender/src/graphic/Path';
-import Group from 'zrender/src/container/Group';
+import Group from 'zrender/src/graphic/Group';
 import {throttle} from '../../util/throttle';
 import {createClipPath} from '../helper/createClipPathFromCoordSys';
 import Sausage from '../../util/shape/sausage';
@@ -38,6 +37,7 @@ 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';
 
 const BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'borderWidth'] as const;
 const _eventPos = [0, 0];
@@ -54,7 +54,6 @@ type RectLayout = RectShape;
 
 type BarPossiblePath = Sector | Rect | Sausage;
 
-
 function getClipArea(coord: CoordSysOfBar, data: List) {
     let coordSysClipArea;
     if (isCoordinateSystemType<Cartesian2D>(coord, 'cartesian2d')) {
@@ -454,7 +453,7 @@ function removeRect(
     el: Rect
 ) {
     // Not show text when animating
-    el.style.text = null;
+    el.removeTextContent();
     updateProps(el, {
         shape: {
             width: 0
@@ -470,7 +469,7 @@ function removeSector(
     el: Sector
 ) {
     // Not show text when animating
-    el.style.text = null;
+    el.removeTextContent();
     updateProps(el, {
         shape: {
             r: el.shape.r0
@@ -536,7 +535,7 @@ function updateStyle(
     let hoverStyle = getBarItemStyle(itemModel.getModel(['emphasis', 'itemStyle']));
 
     if (!isPolar) {
-        el.setShape('r', itemStyleModel.get('barBorderRadius') || 0);
+        (el as Rect).setShape('r', itemStyleModel.get('barBorderRadius') || 0);
     }
 
     el.useStyle(zrUtil.defaults(
@@ -549,22 +548,30 @@ function updateStyle(
     ));
 
     let cursorStyle = itemModel.getShallow('cursor');
-    cursorStyle && el.attr('cursor', cursorStyle);
+    cursorStyle && (el as Path).attr('cursor', cursorStyle);
 
     if (!isPolar) {
         let labelPositionOutside = isHorizontal
-            ? ((layout as RectLayout).height > 0 ? 'bottom' : 'top')
-            : ((layout as RectLayout).width > 0 ? 'left' : 'right');
-
-        setLabel(
-            el.style, hoverStyle, itemModel, color,
-            seriesModel, dataIndex, labelPositionOutside
+            ? ((layout as RectLayout).height > 0 ? 'bottom' as const : 'top' as const)
+            : ((layout as RectLayout).width > 0 ? 'left' as const : 'right' as const);
+
+        let labelModel = itemModel.getModel('label');
+        let hoverLabelModel = itemModel.getModel(['emphasis', 'label']);
+        setLabelStyle(
+            el, labelModel, hoverLabelModel,
+            {
+                labelFetcher: seriesModel,
+                labelDataIndex: dataIndex,
+                defaultText: getDefaultLabel(seriesModel.getData(), dataIndex),
+                autoColor: color,
+                defaultOutsidePosition: labelPositionOutside
+            }
         );
     }
     if (isZeroOnPolar(layout as SectorLayout)) {
         hoverStyle.fill = hoverStyle.stroke = 'none';
     }
-    setHoverStyle(el, hoverStyle);
+    enableHoverEmphasis(el, hoverStyle);
 }
 
 // In case width or height are too small.
@@ -585,7 +592,7 @@ class LagePathShape {
 interface LargePathProps extends PathProps {
     shape?: LagePathShape
 }
-class LargePath extends Path {
+class LargePath extends Path<LargePathProps> {
     type = 'largeBar';
 
     shape: LagePathShape;
@@ -596,7 +603,11 @@ class LargePath extends Path {
     __barWidth: number;
 
     constructor(opts?: LargePathProps) {
-        super(opts, null, new LagePathShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new LagePathShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: LagePathShape) {
diff --git a/src/chart/bar/PictorialBarView.ts b/src/chart/bar/PictorialBarView.ts
index a91fcf9..e807ba3 100644
--- a/src/chart/bar/PictorialBarView.ts
+++ b/src/chart/bar/PictorialBarView.ts
@@ -21,7 +21,6 @@ import * as zrUtil from 'zrender/src/core/util';
 import * as graphic from '../../util/graphic';
 import {createSymbol} from '../../util/symbol';
 import {parsePercent, isNumeric} from '../../util/number';
-import {setLabel} from './helper';
 import ChartView from '../../view/Chart';
 import PictorialBarSeriesModel, {PictorialBarDataItemOption} from './PictorialBarSeries';
 import ExtensionAPI from '../../ExtensionAPI';
@@ -33,6 +32,7 @@ import type Cartesian2D from '../../coord/cartesian/Cartesian2D';
 import type Displayable from 'zrender/src/graphic/Displayable';
 import type Axis2D from '../../coord/cartesian/Axis2D';
 import type Element from 'zrender/src/Element';
+import { getDefaultLabel } from '../helper/labelHelper';
 
 
 const BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'borderWidth'] as const;
@@ -835,7 +835,7 @@ function removeBar(
 ) {
     // Not show text when animating
     let labelRect = bar.__pictorialBarRect;
-    labelRect && (labelRect.style.text = null);
+    labelRect && (labelRect.removeTextContent());
 
     let pathes = [];
     eachPath(bar, function (path) {
@@ -921,7 +921,7 @@ function updateCommon(
             },
             normalStyle
         ));
-        graphic.setHoverStyle(path, hoverStyle);
+        graphic.enableHoverEmphasis(path, hoverStyle);
 
         cursorStyle && (path.cursor = cursorStyle);
         path.z2 = symbolMeta.z2;
@@ -931,12 +931,21 @@ function updateCommon(
     let barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)];
     let barRect = bar.__pictorialBarRect;
 
-    setLabel(
-        barRect.style, barRectHoverStyle, itemModel,
-        color, opt.seriesModel, dataIndex, barPositionOutside
+    let labelModel = itemModel.getModel('label');
+    let hoverLabelModel = itemModel.getModel(['emphasis', 'label']);
+
+    graphic.setLabelStyle(
+        barRect, labelModel, hoverLabelModel,
+        {
+            labelFetcher: opt.seriesModel,
+            labelDataIndex: dataIndex,
+            defaultText: getDefaultLabel(opt.seriesModel.getData(), dataIndex),
+            autoColor: color,
+            defaultOutsidePosition: barPositionOutside
+        }
     );
 
-    graphic.setHoverStyle(barRect, barRectHoverStyle);
+    graphic.enableHoverEmphasis(barRect, barRectHoverStyle);
 }
 
 function toIntTimes(times: number) {
diff --git a/src/chart/bar/barItemStyle.ts b/src/chart/bar/barItemStyle.ts
index 6a9f172..644daf4 100644
--- a/src/chart/bar/barItemStyle.ts
+++ b/src/chart/bar/barItemStyle.ts
@@ -18,8 +18,8 @@
 */
 
 import makeStyleMapper from '../../model/mixin/makeStyleMapper';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import Model from '../../model/Model';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 const mapStyle = makeStyleMapper(
     [
@@ -47,7 +47,7 @@ type BarItemStyleKeys = 'fill'
     | 'shadowOffsetX'
     | 'shadowOffsetY'
     | 'shadowColor';
-type ItemStyleProps = Pick<StyleProps, BarItemStyleKeys>;
+type ItemStyleProps = Pick<PathStyleProps, BarItemStyleKeys>;
 
 export function getBarItemStyle(model: Model, excludes?: BarItemStyleKeys[]): ItemStyleProps {
     let style = mapStyle(model, excludes);
diff --git a/src/chart/bar/helper.ts b/src/chart/bar/helper.ts
deleted file mode 100644
index a2fa3b6..0000000
--- a/src/chart/bar/helper.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied.  See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-
-import * as graphic from '../../util/graphic';
-import {getDefaultLabel} from '../helper/labelHelper';
-import { StyleProps } from 'zrender/src/graphic/Style';
-import { LabelOption, ColorString } from '../../util/types';
-import BaseBarSeriesModel from './BaseBarSeries';
-import { BarDataItemOption } from './BarSeries';
-import Model from '../../model/Model';
-
-export function setLabel(
-    normalStyle: StyleProps,
-    hoverStyle: StyleProps,
-    itemModel: Model<BarDataItemOption>,
-    color: ColorString,
-    seriesModel: BaseBarSeriesModel,
-    dataIndex: number,
-    labelPositionOutside: LabelOption['position']
-) {
-    let labelModel = itemModel.getModel('label');
-    let hoverLabelModel = itemModel.getModel(['emphasis', 'label']);
-
-    graphic.setLabelStyle(
-        normalStyle, hoverStyle, labelModel, hoverLabelModel,
-        {
-            labelFetcher: seriesModel,
-            labelDataIndex: dataIndex,
-            defaultText: getDefaultLabel(seriesModel.getData(), dataIndex),
-            isRectText: true,
-            autoColor: color
-        }
-    );
-
-    fixPosition(normalStyle, labelPositionOutside);
-    fixPosition(hoverStyle, labelPositionOutside);
-}
-
-function fixPosition(style: StyleProps, labelPositionOutside: LabelOption['position']) {
-    if (style.textPosition === 'outside') {
-        style.textPosition = labelPositionOutside;
-    }
-}
diff --git a/src/chart/boxplot/BoxplotView.ts b/src/chart/boxplot/BoxplotView.ts
index fa0ad36..9a69fff 100644
--- a/src/chart/boxplot/BoxplotView.ts
+++ b/src/chart/boxplot/BoxplotView.ts
@@ -20,13 +20,12 @@
 import * as zrUtil from 'zrender/src/core/util';
 import ChartView from '../../view/Chart';
 import * as graphic from '../../util/graphic';
-import Path, { PathProps } from 'zrender/src/graphic/Path';
+import Path, { PathProps, PathStyleProps } from 'zrender/src/graphic/Path';
 import BoxplotSeriesModel, { BoxplotDataItemOption } from './BoxplotSeries';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
 import List from '../../data/List';
 import { BoxplotItemLayout } from './boxplotLayout';
-import { StyleProps } from 'zrender/src/graphic/Style';
 
 // Update common properties
 const EMPHASIS_ITEM_STYLE_PATH = ['emphasis', 'itemStyle'] as const;
@@ -113,7 +112,11 @@ class BoxPath extends Path<BoxPathProps> {
     shape: BoxPathShape;
 
     constructor(opts?: BoxPathProps) {
-        super(opts, null, new BoxPathShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new BoxPathShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: BoxPathShape) {
@@ -180,7 +183,7 @@ function updateNormalBoxData(
     let borderColor = data.getItemVisual(dataIndex, 'color');
 
     // Exclude borderColor.
-    let itemStyle = normalItemStyleModel.getItemStyle(['borderColor']) as StyleProps;
+    let itemStyle = normalItemStyleModel.getItemStyle(['borderColor']) as PathStyleProps;
     itemStyle.stroke = borderColor;
     itemStyle.strokeNoScale = true;
     el.useStyle(itemStyle);
@@ -188,7 +191,7 @@ function updateNormalBoxData(
     el.z2 = 100;
 
     let hoverStyle = itemModel.getModel(EMPHASIS_ITEM_STYLE_PATH).getItemStyle();
-    graphic.setHoverStyle(el, hoverStyle);
+    graphic.enableHoverEmphasis(el, hoverStyle);
 }
 
 function transInit(points: number[][], dim: number, itemLayout: BoxplotItemLayout) {
diff --git a/src/chart/candlestick/CandlestickView.ts b/src/chart/candlestick/CandlestickView.ts
index b37919d..29712b1 100644
--- a/src/chart/candlestick/CandlestickView.ts
+++ b/src/chart/candlestick/CandlestickView.ts
@@ -222,7 +222,11 @@ class NormalBoxPath extends Path<NormalBoxPathProps> {
     __simpleBox: boolean;
 
     constructor(opts?: NormalBoxPathProps) {
-        super(opts, null, new NormalBoxPathShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new NormalBoxPathShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: NormalBoxPathShape) {
@@ -290,7 +294,7 @@ function setBoxCommon(el: NormalBoxPath, data: List, dataIndex: number, isSimple
     el.__simpleBox = isSimpleBox;
 
     let hoverStyle = itemModel.getModel(EMPHASIS_ITEM_STYLE_PATH).getItemStyle();
-    graphic.setHoverStyle(el, hoverStyle);
+    graphic.enableHoverEmphasis(el, hoverStyle);
 }
 
 function transInit(points: number[][], itemLayout: CandlestickItemLayout) {
@@ -320,7 +324,11 @@ class LargeBoxPath extends Path {
     __sign: number;
 
     constructor(opts?: LargeBoxPathProps) {
-        super(opts, null, new LargeBoxPathShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new LargeBoxPathShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: LargeBoxPathShape) {
diff --git a/src/chart/custom.ts b/src/chart/custom.ts
index 9369cc7..73897aa 100644
--- a/src/chart/custom.ts
+++ b/src/chart/custom.ts
@@ -352,7 +352,7 @@ function updateEl(el, dataIndex, elOption, animatableModel, data, isInit, isRoot
     let styleEmphasis = elOption.styleEmphasis;
     // hoverStyle should always be set here, because if the hover style
     // may already be changed, where the inner cache should be reset.
-    graphicUtil.setElementHoverStyle(el, styleEmphasis);
+    graphicUtil.enableElementHoverEmphasis(el, styleEmphasis);
     if (isRoot) {
         graphicUtil.setAsHighDownDispatcher(el, styleEmphasis !== false);
     }
diff --git a/src/chart/funnel/FunnelSeries.ts b/src/chart/funnel/FunnelSeries.ts
index 17ea344..1a3ee5c 100644
--- a/src/chart/funnel/FunnelSeries.ts
+++ b/src/chart/funnel/FunnelSeries.ts
@@ -38,7 +38,8 @@ import ComponentModel from '../../model/Component';
 
 
 type FunnelLabelOption = Omit<LabelOption, 'position'> & {
-    position?: LabelOption['position'] | 'outer'
+    position?: LabelOption['position']
+        | 'outer' | 'inner' | 'center' | 'rightTop' | 'rightBottom' | 'leftTop' | 'leftBottom'
 };
 
 export interface FunnelDataItemOption {
diff --git a/src/chart/funnel/FunnelView.ts b/src/chart/funnel/FunnelView.ts
index cc1a24f..7a66a50 100644
--- a/src/chart/funnel/FunnelView.ts
+++ b/src/chart/funnel/FunnelView.ts
@@ -114,11 +114,12 @@ class FunnelPiece extends graphic.Group {
                 itemStyleModel.getItemStyle(['opacity'])
             )
         );
-        polygon.hoverStyle = itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
+        const polygonEmphasisState = polygon.ensureState('emphasis');
+        polygonEmphasisState.style = itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
 
         this._updateLabel(data, idx);
 
-        graphic.setHoverStyle(this);
+        graphic.enableHoverEmphasis(this);
     }
 
     _updateLabel(data: List, idx: number) {
@@ -157,7 +158,7 @@ class FunnelPiece extends graphic.Group {
         let visualColor = data.getItemVisual(idx, 'color');
 
         graphic.setLabelStyle(
-            labelText.style, labelText.hoverStyle = {}, labelModel, labelHoverModel,
+            labelText, labelModel, labelHoverModel,
             {
                 labelFetcher: data.hostModel as FunnelSeriesModel,
                 labelDataIndex: idx,
@@ -166,8 +167,8 @@ class FunnelPiece extends graphic.Group {
                 useInsideStyle: !!labelLayout.inside
             },
             {
-                textAlign: labelLayout.textAlign,
-                textVerticalAlign: labelLayout.verticalAlign
+                align: labelLayout.textAlign,
+                verticalAlign: labelLayout.verticalAlign
             }
         );
 
@@ -183,7 +184,8 @@ class FunnelPiece extends graphic.Group {
         });
         labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());
 
-        labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle();
+        const lineEmphasisState = labelLine.ensureState('emphasis');
+        lineEmphasisState.style = labelLineHoverModel.getModel('lineStyle').getLineStyle();
     }
 }
 
diff --git a/src/chart/gauge/GaugeView.ts b/src/chart/gauge/GaugeView.ts
index 3921f1b..7d1aa11 100644
--- a/src/chart/gauge/GaugeView.ts
+++ b/src/chart/gauge/GaugeView.ts
@@ -256,12 +256,12 @@ class GaugeView extends ChartView {
                 let autoColor = getColor(i / splitNumber);
 
                 group.add(new graphic.Text({
-                    style: graphic.setTextStyle({}, labelModel, {
+                    style: graphic.setTextStyle({}, null, labelModel, {
                         text: label,
                         x: unitX * (r - splitLineLen - distance) + cx,
                         y: unitY * (r - splitLineLen - distance) + cy,
-                        textVerticalAlign: unitY < -0.4 ? 'top' : (unitY > 0.4 ? 'bottom' : 'middle'),
-                        textAlign: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center')
+                        verticalAlign: unitY < -0.4 ? 'top' : (unitY > 0.4 ? 'bottom' : 'middle'),
+                        align: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center')
                     }, {autoColor: autoColor}),
                     silent: true
                 }));
@@ -384,7 +384,7 @@ class GaugeView extends ChartView {
                 ));
             }
 
-            graphic.setHoverStyle(
+            graphic.enableHoverEmphasis(
                 pointer, itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle()
             );
         });
@@ -416,13 +416,13 @@ class GaugeView extends ChartView {
 
             this.group.add(new graphic.Text({
                 silent: true,
-                style: graphic.setTextStyle({}, titleModel, {
+                style: graphic.setTextStyle({}, null, titleModel, {
                     x: x,
                     y: y,
                     // FIXME First data name ?
                     text: data.getName(0),
-                    textAlign: 'center',
-                    textVerticalAlign: 'middle'
+                    align: 'center',
+                    verticalAlign: 'middle'
                 }, {autoColor: autoColor, forceRich: true})
             }));
         }
@@ -452,17 +452,17 @@ class GaugeView extends ChartView {
 
             this.group.add(new graphic.Text({
                 silent: true,
-                style: graphic.setTextStyle({}, detailModel, {
+                style: graphic.setTextStyle({}, null, detailModel, {
                     x: x,
                     y: y,
                     text: formatLabel(
                         // FIXME First data name ?
                         value, detailModel.get('formatter')
                     ),
-                    textWidth: isNaN(width) ? null : width,
-                    textHeight: isNaN(height) ? null : height,
-                    textAlign: 'center',
-                    textVerticalAlign: 'middle'
+                    width: isNaN(width) ? null : width,
+                    height: isNaN(height) ? null : height,
+                    align: 'center',
+                    verticalAlign: 'middle'
                 }, {autoColor: autoColor, forceRich: true})
             }));
         }
diff --git a/src/chart/gauge/PointerPath.ts b/src/chart/gauge/PointerPath.ts
index d35e901..5eac5dc 100644
--- a/src/chart/gauge/PointerPath.ts
+++ b/src/chart/gauge/PointerPath.ts
@@ -38,7 +38,11 @@ export default class PointerPath extends Path<PointerPathProps> {
     shape: PointerShape;
 
     constructor(opts?: PointerPathProps) {
-        super(opts, null, new PointerShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new PointerShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: PointerShape) {
diff --git a/src/chart/graph/GraphSeries.ts b/src/chart/graph/GraphSeries.ts
index fa26fe5..fa713f3 100644
--- a/src/chart/graph/GraphSeries.ts
+++ b/src/chart/graph/GraphSeries.ts
@@ -39,7 +39,8 @@ import {
     SymbolOptionMixin,
     BoxLayoutOptionMixin,
     LabelFormatterCallback,
-    Dictionary
+    Dictionary,
+    LineLabelOption
 } from '../../util/types';
 import SeriesModel from '../../model/Series';
 import Graph from '../../data/Graph';
@@ -102,11 +103,11 @@ export interface GraphEdgeItemOption {
     value?: number
 
     lineStyle?: GraphEdgeLineStyleOption
-    label?: LabelOption
+    label?: LineLabelOption
 
     emphasis?: {
         lineStyle?: GraphEdgeLineStyleOption
-        label?: LabelOption
+        label?: LineLabelOption
     }
 
     /**
@@ -171,7 +172,7 @@ interface GraphSeriesOption extends SeriesOption,
     edgeSymbol: string | string[]
     edgeSymbolSize: number | number[]
 
-    edgeLabel?: LabelOption & {
+    edgeLabel?: LineLabelOption & {
         formatter?: LabelFormatterCallback | string
     }
     label?: LabelOption & {
diff --git a/src/chart/graph/GraphView.ts b/src/chart/graph/GraphView.ts
index e3fa615..269637d 100644
--- a/src/chart/graph/GraphView.ts
+++ b/src/chart/graph/GraphView.ts
@@ -266,26 +266,22 @@ class GraphView extends ChartView {
                 if (isLeft) {
                     rad = rad - Math.PI;
                 }
-                let textPosition = isLeft ? 'left' : 'right';
-                graphic.modifyLabelStyle(
-                    symbolPath,
-                    {
-                        textRotation: -rad,
-                        textPosition: textPosition,
-                        textOrigin: 'center'
-                    },
-                    {
-                        textPosition: textPosition
-                    }
-                );
+                let textPosition = isLeft ? 'left' as const : 'right' as const;
+
+                symbolPath.setTextConfig({
+                    rotation: -rad,
+                    position: textPosition
+                    // textOrigin: 'center'
+                });
+                const emphasisState = symbolPath.ensureState('emphasis');
+                zrUtil.extend(emphasisState.textConfig || (emphasisState.textConfig = {}), {
+                    position: textPosition
+                });
             }
             else {
-                graphic.modifyLabelStyle(
-                    symbolPath,
-                    {
-                        textRotation: labelRotate *= Math.PI / 180
-                    }
-                );
+                symbolPath.setTextConfig({
+                    rotation: labelRotate *= Math.PI / 180
+                });
             }
         });
 
diff --git a/src/chart/heatmap/HeatmapView.ts b/src/chart/heatmap/HeatmapView.ts
index 9d837e5..cd11208 100644
--- a/src/chart/heatmap/HeatmapView.ts
+++ b/src/chart/heatmap/HeatmapView.ts
@@ -260,17 +260,16 @@ class HeatmapView extends ChartView {
             }
 
             graphic.setLabelStyle(
-                style, hoverStl, labelModel, hoverLabelModel,
+                rect, labelModel, hoverLabelModel,
                 {
                     labelFetcher: seriesModel,
                     labelDataIndex: idx,
-                    defaultText: defaultText,
-                    isRectText: true
+                    defaultText: defaultText
                 }
             );
 
             rect.setStyle(style);
-            graphic.setHoverStyle(rect, data.hasItemOption ? hoverStl : zrUtil.extend({}, hoverStl));
+            graphic.enableHoverEmphasis(rect, data.hasItemOption ? hoverStl : zrUtil.extend({}, hoverStl));
 
             rect.incremental = incremental;
             // PENDING
diff --git a/src/chart/helper/EffectLine.ts b/src/chart/helper/EffectLine.ts
index 381d749..81b758c 100644
--- a/src/chart/helper/EffectLine.ts
+++ b/src/chart/helper/EffectLine.ts
@@ -19,7 +19,6 @@
 
 /**
  * Provide effect for line
- * @module echarts/chart/helper/EffectLine
  */
 
 import * as graphic from '../../util/graphic';
diff --git a/src/chart/helper/LargeLineDraw.ts b/src/chart/helper/LargeLineDraw.ts
index c411664..8d5d061 100644
--- a/src/chart/helper/LargeLineDraw.ts
+++ b/src/chart/helper/LargeLineDraw.ts
@@ -25,7 +25,7 @@ import * as lineContain from 'zrender/src/contain/line';
 import * as quadraticContain from 'zrender/src/contain/quadratic';
 import { PathProps } from 'zrender/src/graphic/Path';
 import List from '../../data/List';
-import { StageHandlerProgressParams, LineStyleOption } from '../../util/types';
+import { StageHandlerProgressParams, LineStyleOption, ColorString } from '../../util/types';
 import Model from '../../model/Model';
 
 class LargeLinesPathShape {
@@ -58,10 +58,18 @@ class LargeLinesPath extends graphic.Path {
     __startIndex: number;
 
     constructor(opts?: LargeLinesPathProps) {
-        super(opts, {
+        super(opts);
+    }
+
+    getDefaultStyle() {
+        return {
             stroke: '#000',
-            fill: null
-        }, new LargeLinesPathShape());
+            fill: null as ColorString
+        };
+    }
+
+    getDefaultShape() {
+        return new LargeLinesPathShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: LargeLinesPathShape) {
@@ -257,7 +265,7 @@ class LargeLineDraw {
         if (visualColor) {
             lineEl.setStyle('stroke', visualColor);
         }
-        lineEl.setStyle('fill');
+        lineEl.setStyle('fill', null);
 
         if (!isIncremental) {
             let ecData = graphic.getECData(lineEl);
diff --git a/src/chart/helper/LargeSymbolDraw.ts b/src/chart/helper/LargeSymbolDraw.ts
index 19b49d4..dea6dde 100644
--- a/src/chart/helper/LargeSymbolDraw.ts
+++ b/src/chart/helper/LargeSymbolDraw.ts
@@ -57,26 +57,37 @@ class LargeSymbolPath extends graphic.Path<LargeSymbolPathProps> {
     startIndex: number;
     endIndex: number;
 
+    private _ctx: CanvasRenderingContext2D;
+
     constructor(opts?: LargeSymbolPathProps) {
-        super(opts, null, new LargeSymbolPathShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new LargeSymbolPathShape();
     }
 
     setColor: ECSymbol['setColor'];
 
-    buildPath(path: PathProxy, shape: LargeSymbolPathShape) {
+    buildPath(path: PathProxy | CanvasRenderingContext2D, shape: LargeSymbolPathShape) {
         let points = shape.points;
         let size = shape.size;
 
         let symbolProxy = this.symbolProxy;
         let symbolProxyShape = symbolProxy.shape;
-        let ctx = path.getContext ? path.getContext() : path;
+        let ctx = (path as PathProxy).getContext
+            ? (path as PathProxy).getContext()
+            : path as CanvasRenderingContext2D;
         let canBoost = ctx && size[0] < BOOST_SIZE_THRESHOLD;
 
         // Do draw in afterBrush.
         if (canBoost) {
+            this._ctx = ctx;
             return;
         }
 
+        this._ctx = null;
+
         for (let i = 0; i < points.length;) {
             let x = points[i++];
             let y = points[i++];
@@ -97,17 +108,16 @@ class LargeSymbolPath extends graphic.Path<LargeSymbolPathProps> {
         }
     }
 
-    afterBrush(ctx: CanvasRenderingContext2D) {
+    afterBrush() {
         let shape = this.shape;
         let points = shape.points;
         let size = shape.size;
-        let canBoost = size[0] < BOOST_SIZE_THRESHOLD;
+        let ctx = this._ctx;
 
-        if (!canBoost) {
+        if (!ctx) {
             return;
         }
 
-        this.setTransform(ctx);
         // PENDING If style or other canvas status changed?
         for (let i = 0; i < points.length;) {
             let x = points[i++];
@@ -125,8 +135,6 @@ class LargeSymbolPath extends graphic.Path<LargeSymbolPathProps> {
                 size[0], size[1]
             );
         }
-
-        this.restoreTransform(ctx);
     }
 
     findDataIndex(x: number, y: number) {
diff --git a/src/chart/helper/Line.ts b/src/chart/helper/Line.ts
index 628a67b..6598247 100644
--- a/src/chart/helper/Line.ts
+++ b/src/chart/helper/Line.ts
@@ -24,10 +24,10 @@ import ECLinePath from './LinePath';
 import * as graphic from '../../util/graphic';
 import {round} from '../../util/number';
 import List from '../../data/List';
-import { StyleProps } from 'zrender/src/graphic/Style';
-import { ZRTextAlign, ZRTextVerticalAlign } from '../../util/types';
+import { ZRTextAlign, ZRTextVerticalAlign, LineLabelOption } from '../../util/types';
 import SeriesModel from '../../model/Series';
 import type { LineDrawSeriesScope, LineDrawModelOption } from './LineDraw';
+import { RichTextStyleProps } from 'zrender/src/graphic/RichText';
 
 const SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol'] as const;
 
@@ -38,9 +38,9 @@ export interface LineLabel extends graphic.Text {
 }
 
 interface InnerLineLabel extends LineLabel {
-    __textAlign: StyleProps['textAlign']
-    __verticalAlign: StyleProps['textVerticalAlign']
-    __position: StyleProps['textPosition']
+    __align: RichTextStyleProps['align']
+    __verticalAlign: RichTextStyleProps['verticalAlign']
+    __position: LineLabelOption['position']
     __labelDistance: number[]
 }
 
@@ -214,7 +214,8 @@ class Line extends graphic.Group {
             },
             lineStyle
         ));
-        line.hoverStyle = hoverLineStyle;
+        const lineEmphasisState = line.ensureState('emphasis');
+        lineEmphasisState.style = hoverLineStyle;
 
         // Update symbol
         zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) {
@@ -261,14 +262,14 @@ class Line extends graphic.Group {
         // Always set `textStyle` even if `normalStyle.text` is null, because default
         // values have to be set on `normalStyle`.
         if (normalText != null || emphasisText != null) {
-            graphic.setTextStyle(label.style, labelModel, {
+            graphic.setTextStyle(label.style, null, labelModel, {
                 text: normalText as string
             }, {
                 autoColor: defaultLabelColor
             });
 
-            label.__textAlign = labelStyle.textAlign;
-            label.__verticalAlign = labelStyle.textVerticalAlign;
+            label.__align = labelStyle.align;
+            label.__verticalAlign = labelStyle.verticalAlign;
             // 'start', 'middle', 'end'
             label.__position = labelModel.get('position') || 'middle';
 
@@ -279,9 +280,11 @@ class Line extends graphic.Group {
             label.__labelDistance = distance;
         }
 
+        const emphasisState = label.ensureState('emphasis');
         if (emphasisText != null) {
+            emphasisState.ignore = false;
             // Only these properties supported in this emphasis style here.
-            label.hoverStyle = {
+            emphasisState.style = {
                 text: emphasisText as string,
                 textFill: hoverLabelModel.getTextColor(true),
                 // For merging hover style to normal style, do not use
@@ -293,14 +296,12 @@ class Line extends graphic.Group {
             };
         }
         else {
-            label.hoverStyle = {
-                text: null
-            };
+            emphasisState.ignore = true;
         }
 
         label.ignore = !showLabel && !hoverShowLabel;
 
-        graphic.setHoverStyle(this);
+        graphic.enableHoverEmphasis(this);
     }
 
     highlight() {
@@ -464,8 +465,8 @@ class Line extends graphic.Group {
             label.attr({
                 style: {
                     // Use the user specified text align and baseline first
-                    textVerticalAlign: label.__verticalAlign || textVerticalAlign,
-                    textAlign: label.__textAlign || textAlign
+                    verticalAlign: label.__verticalAlign || textVerticalAlign,
+                    align: label.__align || textAlign
                 },
                 position: textPosition,
                 scale: [invScale, invScale],
diff --git a/src/chart/helper/LineDraw.ts b/src/chart/helper/LineDraw.ts
index 4172eb3..9881435 100644
--- a/src/chart/helper/LineDraw.ts
+++ b/src/chart/helper/LineDraw.ts
@@ -25,11 +25,11 @@ import {
     LineStyleOption,
     LineLabelOption,
     ColorString,
-    AnimationOptionMixin
+    AnimationOptionMixin,
+    ZRStyleProps
 } from '../../util/types';
 import Displayable from 'zrender/src/graphic/Displayable';
 import Model from '../../model/Model';
-import { StyleProps } from 'zrender/src/graphic/Style';
 
 interface LineLike extends graphic.Group {
     updateData(data: List, idx: number, scope?: LineDrawSeriesScope): void
@@ -77,8 +77,8 @@ export interface LineDrawModelOption {
 type ListForLineDraw = List<Model<LineDrawModelOption & AnimationOptionMixin>>;
 
 export interface LineDrawSeriesScope {
-    lineStyle?: StyleProps
-    hoverLineStyle?: StyleProps
+    lineStyle?: ZRStyleProps
+    hoverLineStyle?: ZRStyleProps
 
     labelModel?: Model<LineLabelOption>
     hoverLabelModel?: Model<LineLabelOption>
diff --git a/src/chart/helper/LinePath.ts b/src/chart/helper/LinePath.ts
index 3783f5e..f81e61a 100644
--- a/src/chart/helper/LinePath.ts
+++ b/src/chart/helper/LinePath.ts
@@ -24,6 +24,7 @@
 import * as graphic from '../../util/graphic';
 import * as vec2 from 'zrender/src/core/vector';
 import { PathProps } from 'zrender/src/graphic/Path';
+import { ColorString } from '../../util/types';
 
 const straightLineProto = graphic.Line.prototype;
 const bezierCurveProto = graphic.BezierCurve.prototype;
@@ -58,10 +59,18 @@ class ECLinePath extends graphic.Path<ECLineProps> {
     shape: StraightLineShape | CurveShape;
 
     constructor(opts?: ECLineProps) {
-        super(opts, {
+        super(opts);
+    }
+
+    getDefaultStyle() {
+        return {
             stroke: '#000',
-            fill: null
-        }, new StraightLineShape());// Default to be line
+            fill: null as ColorString
+        };
+    }
+
+    getDefaultShape() {
+        return new StraightLineShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: StraightLineShape | CurveShape) {
diff --git a/src/chart/helper/Polyline.ts b/src/chart/helper/Polyline.ts
index c07ff48..01ae543 100644
--- a/src/chart/helper/Polyline.ts
+++ b/src/chart/helper/Polyline.ts
@@ -78,9 +78,11 @@ class Polyline extends graphic.Group {
             },
             lineStyle
         ));
-        line.hoverStyle = hoverLineStyle;
 
-        graphic.setHoverStyle(this);
+        const lineEmphasisState = line.ensureState('emphasis');
+        lineEmphasisState.style = hoverLineStyle;
+
+        graphic.enableHoverEmphasis(this);
     };
 
     updateLayout(lineData: List, idx: number) {
diff --git a/src/chart/helper/Symbol.ts b/src/chart/helper/Symbol.ts
index 4deb542..10a2d57 100644
--- a/src/chart/helper/Symbol.ts
+++ b/src/chart/helper/Symbol.ts
@@ -285,12 +285,11 @@ class Symbol extends graphic.Group {
         let useNameLabel = seriesScope && seriesScope.useNameLabel;
 
         graphic.setLabelStyle(
-            elStyle, hoverItemStyle, labelModel, hoverLabelModel,
+            symbolPath, labelModel, hoverLabelModel,
             {
                 labelFetcher: seriesModel,
                 labelDataIndex: idx,
                 defaultText: getLabelDefaultText,
-                isRectText: true,
                 autoColor: color
             }
         );
@@ -301,12 +300,11 @@ class Symbol extends graphic.Group {
         }
 
         symbolPath.__symbolOriginalScale = getScale(symbolSize);
-        symbolPath.hoverStyle = hoverItemStyle;
         symbolPath.highDownOnUpdate = (
             hoverAnimation && seriesModel.isAnimationEnabled()
         ) ? highDownOnUpdate : null;
 
-        graphic.setHoverStyle(symbolPath);
+        graphic.enableHoverEmphasis(symbolPath, hoverItemStyle);
     }
 
     fadeOut(cb: () => void, opt?: {
@@ -316,7 +314,7 @@ class Symbol extends graphic.Group {
         // Avoid mistaken hover when fading out
         this.silent = symbolPath.silent = true;
         // Not show text when animating
-        !(opt && opt.keepLabel) && (symbolPath.style.text = null);
+        !(opt && opt.keepLabel) && (symbolPath.removeTextContent());
 
         graphic.updateProps(
             symbolPath,
diff --git a/src/chart/helper/SymbolDraw.ts b/src/chart/helper/SymbolDraw.ts
index c35349a..1ff215d 100644
--- a/src/chart/helper/SymbolDraw.ts
+++ b/src/chart/helper/SymbolDraw.ts
@@ -29,10 +29,10 @@ import {
     SymbolOptionMixin,
     ItemStyleOption,
     ZRColor,
-    AnimationOptionMixin
+    AnimationOptionMixin,
+    ZRStyleProps
 } from '../../util/types';
 import { CoordinateSystemClipArea } from '../../coord/CoordinateSystem';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import Model from '../../model/Model';
 
 interface UpdateOpt {
@@ -94,8 +94,8 @@ export interface SymbolDrawItemModelOption extends SymbolOptionMixin<object> {
 }
 
 export interface SymbolDrawSeriesScope {
-    itemStyle?: StyleProps
-    hoverItemStyle?: StyleProps
+    itemStyle?: ZRStyleProps
+    hoverItemStyle?: ZRStyleProps
     symbolRotate?: number
     symbolOffset?: number[]
     labelModel?: Model<LabelOption>
diff --git a/src/chart/line/poly.ts b/src/chart/line/poly.ts
index 9b82d07..1a6ba3f 100644
--- a/src/chart/line/poly.ts
+++ b/src/chart/line/poly.ts
@@ -21,7 +21,6 @@
 
 import Path, { PathProps } from 'zrender/src/graphic/Path';
 import * as vec2 from 'zrender/src/core/vector';
-import fixClipWithShadow from 'zrender/src/graphic/helper/fixClipWithShadow';
 
 const vec2Min = vec2.min;
 const vec2Max = vec2.max;
@@ -322,13 +321,19 @@ export class ECPolyline extends Path<ECPolylineProps> {
 
     shape: ECPolylineShape;
 
-    brush = fixClipWithShadow(Path.prototype.brush);
-
     constructor(opts?: ECPolylineProps) {
-        super(opts, {
+        super(opts);
+    }
+
+    getDefaultStyle() {
+        return {
             stroke: '#000',
-            fill: null
-        }, new ECPolylineShape());
+            fill: null as string
+        };
+    }
+
+    getDefaultShape() {
+        return new ECPolylineShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: ECPolylineShape) {
@@ -376,12 +381,14 @@ export class ECPolygon extends Path {
 
     shape: ECPolygonShape;
 
-    // @ts-ignore
-    brush = fixClipWithShadow(Path.prototype.brush);
-
     constructor(opts?: ECPolygonProps) {
-        super(opts, null, new ECPolygonShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new ECPolygonShape();
     }
+
     buildPath(ctx: CanvasRenderingContext2D, shape: ECPolygonShape) {
         let points = shape.points;
         let stackedOnPoints = shape.stackedOnPoints;
diff --git a/src/chart/map/MapView.ts b/src/chart/map/MapView.ts
index f6eab85..1326c09 100644
--- a/src/chart/map/MapView.ts
+++ b/src/chart/map/MapView.ts
@@ -198,12 +198,12 @@ class MapView extends ChartView {
                 // Prevent from register listeners duplicatedly when roaming.
                 if (!highDownRecord) {
                     highDownRecord = regionGroup[HIGH_DOWN_PROP] = {} as HighDownRecord;
-                    let onEmphasis = zrUtil.curry(onRegionHighDown, true);
-                    let onNormal = zrUtil.curry(onRegionHighDown, false);
-                    regionGroup.on('mouseover', onEmphasis)
-                        .on('mouseout', onNormal)
-                        .on('emphasis', onEmphasis)
-                        .on('normal', onNormal);
+                    // let onEmphasis = zrUtil.curry(onRegionHighDown, true);
+                    // let onNormal = zrUtil.curry(onRegionHighDown, false);
+                    // regionGroup.on('mouseover', onEmphasis)
+                    //     .on('mouseout', onNormal)
+                    //     .on('emphasis', onEmphasis)
+                    //     .on('normal', onNormal);
                 }
 
                 // Prevent removed regions effect current grapics.
@@ -219,7 +219,7 @@ class MapView extends ChartView {
 
                 // FIXME
                 // Consider set option when emphasis.
-                enterRegionHighDown(highDownRecord, false);
+                // enterRegionHighDown(highDownRecord, false);
             }
 
             group.add(circle);
@@ -227,44 +227,44 @@ class MapView extends ChartView {
     }
 }
 
-function onRegionHighDown(this: RegionGroupExtend, toHighOrDown: boolean): void {
-    let highDownRecord = this[HIGH_DOWN_PROP];
-    if (highDownRecord && highDownRecord.recordVersion === this[RECORD_VERSION_PROP]) {
-        enterRegionHighDown(highDownRecord, toHighOrDown);
-    }
-}
-
-function enterRegionHighDown(highDownRecord: HighDownRecord, toHighOrDown: boolean): void {
-    let circle = highDownRecord.circle;
-    let labelModel = highDownRecord.labelModel;
-    let hoverLabelModel = highDownRecord.hoverLabelModel;
-    let emphasisText = highDownRecord.emphasisText;
-    let normalText = highDownRecord.normalText;
-
-    if (toHighOrDown) {
-        circle.style.extendFrom(
-            graphic.setTextStyle({}, hoverLabelModel, {
-                text: hoverLabelModel.get('show') ? emphasisText : null
-            }, {isRectText: true, useInsideStyle: false}, true)
-        );
-        // Make label upper than others if overlaps.
-        circle[ORIGINAL_Z2] = circle.z2;
-        circle.z2 += graphic.Z2_EMPHASIS_LIFT;
-    }
-    else {
-        graphic.setTextStyle(circle.style, labelModel, {
-            text: labelModel.get('show') ? normalText : null,
-            textPosition: labelModel.getShallow('position') || 'bottom'
-        }, {isRectText: true, useInsideStyle: false});
-        // Trigger normalize style like padding.
-        circle.dirty(false);
-
-        if (circle[ORIGINAL_Z2] != null) {
-            circle.z2 = circle[ORIGINAL_Z2];
-            circle[ORIGINAL_Z2] = null;
-        }
-    }
-}
+// function onRegionHighDown(this: RegionGroupExtend, toHighOrDown: boolean): void {
+//     let highDownRecord = this[HIGH_DOWN_PROP];
+//     if (highDownRecord && highDownRecord.recordVersion === this[RECORD_VERSION_PROP]) {
+//         enterRegionHighDown(highDownRecord, toHighOrDown);
+//     }
+// }
+
+// function enterRegionHighDown(highDownRecord: HighDownRecord, toHighOrDown: boolean): void {
+//     let circle = highDownRecord.circle;
+//     let labelModel = highDownRecord.labelModel;
+//     let hoverLabelModel = highDownRecord.hoverLabelModel;
+//     let emphasisText = highDownRecord.emphasisText;
+//     let normalText = highDownRecord.normalText;
+
+//     if (toHighOrDown) {
+//         circle.style.extendFrom(
+//             graphic.setTextStyle({}, hoverLabelModel, {
+//                 text: hoverLabelModel.get('show') ? emphasisText : null
+//             }, {isRectText: true, useInsideStyle: false}, true)
+//         );
+//         // Make label upper than others if overlaps.
+//         circle[ORIGINAL_Z2] = circle.z2;
+//         circle.z2 += graphic.Z2_EMPHASIS_LIFT;
+//     }
+//     else {
+//         graphic.setTextStyle(circle.style, labelModel, {
+//             text: labelModel.get('show') ? normalText : null,
+//             textPosition: labelModel.getShallow('position') || 'bottom'
+//         }, {isRectText: true, useInsideStyle: false});
+//         // Trigger normalize style like padding.
+//         circle.markRedraw();
+
+//         if (circle[ORIGINAL_Z2] != null) {
+//             circle.z2 = circle[ORIGINAL_Z2];
+//             circle[ORIGINAL_Z2] = null;
+//         }
+//     }
+// }
 
 ChartView.registerClass(MapView);
 
diff --git a/src/chart/parallel/ParallelView.ts b/src/chart/parallel/ParallelView.ts
index 03a8ff9..e995669 100644
--- a/src/chart/parallel/ParallelView.ts
+++ b/src/chart/parallel/ParallelView.ts
@@ -25,14 +25,14 @@ import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
 import { StageHandlerProgressParams, ParsedValue, Payload } from '../../util/types';
 import Parallel from '../../coord/parallel/Parallel';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import { OptionAxisType } from '../../coord/axisCommonTypes';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 const DEFAULT_SMOOTH = 0.3;
 
 interface ParallelDrawSeriesScope {
     smooth: number
-    lineStyle: StyleProps
+    lineStyle: PathStyleProps
 }
 class ParallelView extends ChartView {
     static type = 'parallel';
@@ -149,7 +149,7 @@ function createGridClipShape(coordSys: Parallel, seriesModel: ParallelSeriesMode
         }
     });
 
-    let dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height';
+    let dim = parallelModel.get('layout') === 'horizontal' ? 'width' as const : 'height' as const;
     rectEl.setShape(dim, 0);
     graphic.initProps(rectEl, {
         shape: {
diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts
index c409e7a..8c08c5b 100644
--- a/src/chart/pie/PieSeries.ts
+++ b/src/chart/pie/PieSeries.ts
@@ -41,12 +41,14 @@ import {
 import List from '../../data/List';
 
 
-interface PieLabelOption extends Omit<LabelOption, 'rotate'> {
+interface PieLabelOption extends Omit<LabelOption, 'rotate' | 'position'> {
     rotate?: number
     alignTo?: 'none' | 'labelLine' | 'edge'
     margin?: string | number
     bleedMargin?: number
     distanceToLabelLine?: number
+
+    position?: LabelOption['position'] | 'outer' | 'inner' | 'center'
 }
 
 export interface PieDataItemOption extends
diff --git a/src/chart/pie/PieView.ts b/src/chart/pie/PieView.ts
index 159b937..fc6927b 100644
--- a/src/chart/pie/PieView.ts
+++ b/src/chart/pie/PieView.ts
@@ -102,6 +102,7 @@ class PiePiece extends graphic.Group {
         let sector = new graphic.Sector({
             z2: 2
         });
+
         let polyline = new graphic.Polyline();
         let text = new graphic.Text();
         this.add(sector);
@@ -118,12 +119,11 @@ class PiePiece extends graphic.Group {
 
         let seriesModel = data.hostModel as PieSeriesModel;
         let itemModel = data.getItemModel<PieDataItemOption>(idx);
-        let layout = data.getItemLayout(idx) as graphic.Sector['shape'];
-        let sectorShape = zrUtil.extend({
-            label: null
-        }, layout);
+        let layout = data.getItemLayout(idx);
+        let sectorShape = zrUtil.extend({}, layout);
         // Not animate label
         sectorShape.label = null;
+        sectorShape.viewRect = null;
 
         let animationTypeUpdate = seriesModel.getShallow('animationTypeUpdate');
 
@@ -175,7 +175,8 @@ class PiePiece extends graphic.Group {
                 itemModel.getModel('itemStyle').getItemStyle()
             )
         );
-        sector.hoverStyle = itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
+        const sectorEmphasisState = sector.ensureState('emphasis');
+        sectorEmphasisState.style = itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
 
         let cursorStyle = itemModel.getShallow('cursor');
         cursorStyle && sector.attr('cursor', cursorStyle);
@@ -222,7 +223,7 @@ class PiePiece extends graphic.Group {
             }
             : null;
 
-        graphic.setHoverStyle(this);
+        graphic.enableHoverEmphasis(this);
     }
 
     private _updateLabel(data: List, idx: number, withAnimation: boolean): void {
@@ -284,8 +285,7 @@ class PiePiece extends graphic.Group {
         let visualColor = data.getItemVisual(idx, 'color');
 
         graphic.setLabelStyle(
-            labelText.style,
-            labelText.hoverStyle = {},
+            labelText,
             labelModel,
             labelHoverModel,
             {
@@ -296,8 +296,8 @@ class PiePiece extends graphic.Group {
                 useInsideStyle: !!labelLayout.inside
             },
             {
-                textAlign: labelLayout.textAlign,
-                textVerticalAlign: labelLayout.verticalAlign,
+                align: labelLayout.textAlign,
+                verticalAlign: labelLayout.verticalAlign,
                 opacity: data.getItemVisual(idx, 'opacity')
             }
         );
@@ -315,14 +315,15 @@ class PiePiece extends graphic.Group {
         });
         labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());
 
-        labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle();
+        const lineEmphasisState = labelLine.ensureState('emphasis');
+        lineEmphasisState.style = labelLineHoverModel.getModel('lineStyle').getLineStyle();
 
         let smooth = labelLineModel.get('smooth');
         if (smooth && smooth === true) {
             smooth = 0.4;
         }
         labelLine.setShape({
-            smooth: smooth
+            smooth: smooth as number
         });
     }
 }
diff --git a/src/chart/pie/labelLayout.ts b/src/chart/pie/labelLayout.ts
index 8ded15b..e967900 100644
--- a/src/chart/pie/labelLayout.ts
+++ b/src/chart/pie/labelLayout.ts
@@ -234,7 +234,8 @@ function avoidOverlap(
                 }
             }
             if (targetTextWidth < layout.textRect.width) {
-                layout.text = textContain.truncateText(layout.text, targetTextWidth, layout.font);
+                // TODOTODO
+                // layout.text = textContain.truncateText(layout.text, targetTextWidth, layout.font);
                 if (layout.labelAlignTo === 'edge') {
                     realTextWidth = textContain.getWidth(layout.text, layout.font);
                 }
diff --git a/src/chart/radar/RadarView.ts b/src/chart/radar/RadarView.ts
index 140e0c8..cf02d4b 100644
--- a/src/chart/radar/RadarView.ts
+++ b/src/chart/radar/RadarView.ts
@@ -191,7 +191,8 @@ class RadarView extends ChartView {
                     }
                 )
             );
-            polyline.hoverStyle = itemModel.getModel(['emphasis', 'lineStyle']).getLineStyle();
+            const polylineEmphasisState = polyline.ensureState('emphasis');
+            polylineEmphasisState.style = itemModel.getModel(['emphasis', 'lineStyle']).getLineStyle();
 
             let areaStyleModel = itemModel.getModel('areaStyle');
             let hoverAreaStyleModel = itemModel.getModel(['emphasis', 'areaStyle']);
@@ -210,7 +211,8 @@ class RadarView extends ChartView {
                     }
                 )
             );
-            polygon.hoverStyle = hoverAreaStyleModel.getAreaStyle();
+            const polygonEmphasisState = polygon.ensureState('emphasis');
+            polygonEmphasisState.style = hoverAreaStyleModel.getAreaStyle();
 
             let itemStyle = itemModel.getModel('itemStyle').getItemStyle(['color']);
             let itemHoverStyle = itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
@@ -218,19 +220,19 @@ class RadarView extends ChartView {
             let labelHoverModel = itemModel.getModel(['emphasis', 'label']);
             symbolGroup.eachChild(function (symbolPath: RadarSymbol) {
                 symbolPath.setStyle(itemStyle);
-                symbolPath.hoverStyle = zrUtil.clone(itemHoverStyle);
+                const pathEmphasisState = symbolPath.ensureState('emphasis');
+                pathEmphasisState.style = zrUtil.clone(itemHoverStyle);
                 let defaultText = data.get(data.dimensions[symbolPath.__dimIdx], idx);
                 (defaultText == null || isNaN(defaultText as number)) && (defaultText = '');
 
                 graphic.setLabelStyle(
-                    symbolPath.style, symbolPath.hoverStyle, labelModel, labelHoverModel,
+                    symbolPath, labelModel, labelHoverModel,
                     {
                         labelFetcher: data.hostModel,
                         labelDataIndex: idx,
                         labelDimIndex: symbolPath.__dimIdx,
                         defaultText: defaultText as string,
-                        autoColor: color,
-                        isRectText: true
+                        autoColor: color
                     }
                 );
             });
@@ -238,7 +240,7 @@ class RadarView extends ChartView {
             (itemGroup as ECElement).highDownOnUpdate = function (fromState: DisplayState, toState: DisplayState) {
                 polygon.attr('ignore', toState === 'emphasis' ? hoverPolygonIgnore : polygonIgnore);
             };
-            graphic.setHoverStyle(itemGroup);
+            graphic.enableHoverEmphasis(itemGroup);
         });
 
         this._data = data;
diff --git a/src/chart/sankey/SankeyView.ts b/src/chart/sankey/SankeyView.ts
index 76c85a3..b8c3d6a 100644
--- a/src/chart/sankey/SankeyView.ts
+++ b/src/chart/sankey/SankeyView.ts
@@ -117,11 +117,15 @@ interface SankeyPathProps extends PathProps {
     shape?: Partial<SankeyPathShape>
 }
 
-class SankeyPath extends graphic.Path {
+class SankeyPath extends graphic.Path<SankeyPathProps> {
     shape: SankeyPathShape;
 
     constructor(opts?: SankeyPathProps) {
-        super(opts, null, new SankeyPathShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new SankeyPathShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: SankeyPathShape) {
@@ -266,7 +270,7 @@ class SankeyView extends ChartView {
                     break;
             }
 
-            graphic.setHoverStyle(
+            graphic.enableHoverEmphasis(
                 curve,
                 edgeModel.getModel(['emphasis', 'lineStyle']).getItemStyle()
             );
@@ -298,18 +302,17 @@ class SankeyView extends ChartView {
             let hoverStyle = itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
 
             graphic.setLabelStyle(
-                rect.style, hoverStyle, labelModel, labelHoverModel,
+                rect, labelModel, labelHoverModel,
                 {
                     labelFetcher: seriesModel,
                     labelDataIndex: node.dataIndex,
-                    defaultText: node.id,
-                    isRectText: true
+                    defaultText: node.id
                 }
             );
 
             rect.setStyle('fill', node.getVisual('color'));
 
-            graphic.setHoverStyle(rect, hoverStyle);
+            graphic.enableHoverEmphasis(rect, hoverStyle);
 
             group.add(rect);
 
diff --git a/src/chart/sunburst/SunburstPiece.ts b/src/chart/sunburst/SunburstPiece.ts
index 41c7372..a9d3d4e 100644
--- a/src/chart/sunburst/SunburstPiece.ts
+++ b/src/chart/sunburst/SunburstPiece.ts
@@ -241,7 +241,7 @@ class SunburstPiece extends graphic.Group {
         let label = this.childAt(1) as graphic.Text;
 
         graphic.setLabelStyle(
-            label.style, label.hoverStyle || {}, normalModel, labelHoverModel,
+            label, normalModel, labelHoverModel,
             {
                 defaultText: labelModel.getShallow('show') ? text : null,
                 autoColor: visualColor,
@@ -282,8 +282,8 @@ class SunburstPiece extends graphic.Group {
 
         label.attr('style', {
             text: text,
-            textAlign: textAlign,
-            textVerticalAlign: getLabelAttr('verticalAlign') || 'middle',
+            align: textAlign,
+            verticalAlign: getLabelAttr('verticalAlign') || 'middle',
             opacity: getLabelAttr('opacity')
         });
 
diff --git a/src/chart/sunburst/SunburstSeries.ts b/src/chart/sunburst/SunburstSeries.ts
index 056c244..1fd10c0 100644
--- a/src/chart/sunburst/SunburstSeries.ts
+++ b/src/chart/sunburst/SunburstSeries.ts
@@ -31,10 +31,11 @@ import {
 } from '../../util/types';
 import GlobalModel from '../../model/Global';
 
-interface SunburstLabelOption extends Omit<LabelOption, 'rotate'> {
+interface SunburstLabelOption extends Omit<LabelOption, 'rotate' | 'position'> {
     rotate?: 'radial' | 'tangential' | number
     minAngle?: number
     silent?: boolean
+    position?: LabelOption['position'] | 'outside'
 }
 
 interface SunburstDataParams extends CallbackDataParams {
diff --git a/src/chart/themeRiver/ThemeRiverView.ts b/src/chart/themeRiver/ThemeRiverView.ts
index 663b66d..04ce914 100644
--- a/src/chart/themeRiver/ThemeRiverView.ts
+++ b/src/chart/themeRiver/ThemeRiverView.ts
@@ -147,19 +147,19 @@ class ThemeRiverView extends ChartView {
             let hoverItemStyleModel = seriesModel.getModel(['emphasis', 'itemStyle']);
             let itemStyleModel = seriesModel.getModel('itemStyle');
 
-            graphic.setTextStyle(text.style, labelModel, {
+            graphic.setTextStyle(text.style, null, labelModel, {
                 text: labelModel.get('show')
                     ? seriesModel.getFormattedLabel(indices[j - 1], 'normal')
                         || data.getName(indices[j - 1])
                     : null,
-                textVerticalAlign: 'middle'
+                verticalAlign: 'middle'
             });
 
             polygon.setStyle(extend({
                 fill: color
             }, itemStyleModel.getItemStyle(['color'])));
 
-            graphic.setHoverStyle(polygon, hoverItemStyleModel.getItemStyle());
+            graphic.enableHoverEmphasis(polygon, hoverItemStyleModel.getItemStyle());
         }
 
         this._layersSeries = layersSeries;
diff --git a/src/chart/tree/TreeView.ts b/src/chart/tree/TreeView.ts
index 67c9edb..586bc8f 100644
--- a/src/chart/tree/TreeView.ts
+++ b/src/chart/tree/TreeView.ts
@@ -30,13 +30,12 @@ import { __DEV__ } from '../../config';
 import {parsePercent} from '../../util/number';
 import ChartView from '../../view/Chart';
 import TreeSeriesModel, { TreeSeriesOption, TreeSeriesNodeItemOption } from './TreeSeries';
-import Path, { PathProps } from 'zrender/src/graphic/Path';
+import Path, { PathProps, PathStyleProps } from 'zrender/src/graphic/Path';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
 import Tree, { TreeNode } from '../../data/Tree';
 import List from '../../data/List';
 import Model from '../../model/Model';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import { ColorString } from '../../util/types';
 
 type TreeSymbol = SymbolClz & {
@@ -58,9 +57,9 @@ interface TreeSeriesScope extends Pick<
     fadeIn: boolean
 
     itemModel: Model<TreeSeriesNodeItemOption>
-    itemStyle: StyleProps
-    hoverItemStyle: StyleProps
-    lineStyle: StyleProps
+    itemStyle: PathStyleProps
+    hoverItemStyle: PathStyleProps
+    lineStyle: PathStyleProps
     labelModel: Model<TreeSeriesNodeItemOption['label']>
     hoverLabelModel: Model<TreeSeriesNodeItemOption['label']>
     symbolInnerColor: ColorString
@@ -84,13 +83,21 @@ interface TreeNodeLayout {
     rawY: number
 }
 
-class TreePath extends Path {
+class TreePath extends Path<TreeEdgePathProps> {
     shape: TreeEdgeShape;
     constructor(opts?: TreeEdgePathProps) {
-        super(opts, {
+        super(opts);
+    }
+
+    getDefaultStyle() {
+        return {
             stroke: '#000',
-            fill: null
-        }, new TreeEdgeShape());
+            fill: null as string
+        };
+    }
+
+    getDefaultShape() {
+        return new TreeEdgeShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: TreeEdgeShape) {
@@ -497,16 +504,20 @@ function updateNode(
             }
         }
 
-        let textPosition = isLeft ? 'left' : 'right';
+        let textPosition = isLeft ? 'left' as const : 'right' as const;
         let rotate = seriesScope.labelModel.get('rotate');
         let labelRotateRadian = rotate * (Math.PI / 180);
 
-        symbolPath.setStyle({
-            textPosition: seriesScope.labelModel.get('position') || textPosition,
-            textRotation: rotate == null ? -rad : labelRotateRadian,
-            textOrigin: 'center',
-            textVerticalAlign: 'middle'
-        });
+        const textContent = symbolPath.getTextContent();
+        if (textContent) {
+            symbolPath.setTextConfig({
+                position: seriesScope.labelModel.get('position') || textPosition,
+                rotation: rotate == null ? -rad : labelRotateRadian
+                // textOrigin: 'center',
+            });
+            textContent.setStyle('verticalAlign', 'middle');
+        }
+
     }
 
     drawEdge(
@@ -539,7 +550,7 @@ function drawEdge(
                 });
             }
 
-            graphic.updateProps(edge, {
+            graphic.updateProps(edge as Path, {
                 shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
                 style: {opacity: 1}
             }, seriesModel);
@@ -566,7 +577,7 @@ function drawEdge(
                         style: zrUtil.defaults({opacity: 0, strokeNoScale: true}, seriesScope.lineStyle)
                     });
                 }
-                graphic.updateProps(edge, {
+                graphic.updateProps(edge as Path, {
                     shape: {
                         parentPoint: [targetLayout.x, targetLayout.y],
                         childPoints: childPoints
@@ -627,7 +638,7 @@ function removeNode(
 
     if (edge) {
         if (edgeShape === 'curve') {
-            graphic.updateProps(edge, {
+            graphic.updateProps(edge as Path, {
                 shape: getEdgeShape(seriesScope, sourceLayout, sourceLayout),
                 style: {
                     opacity: 0
@@ -637,7 +648,7 @@ function removeNode(
             });
         }
         else if (edgeShape === 'polyline' && seriesScope.layout === 'orthogonal') {
-            graphic.updateProps(edge, {
+            graphic.updateProps(edge as Path, {
                 shape: {
                     parentPoint: [sourceLayout.x, sourceLayout.y],
                     childPoints: [[sourceLayout.x, sourceLayout.y]]
diff --git a/src/chart/treemap/TreemapView.ts b/src/chart/treemap/TreemapView.ts
index b20170c..49cadd2 100644
--- a/src/chart/treemap/TreemapView.ts
+++ b/src/chart/treemap/TreemapView.ts
@@ -17,7 +17,7 @@
 * under the License.
 */
 
-import {bind, each, indexOf, curry, extend, retrieve, clone} from 'zrender/src/core/util';
+import {bind, each, indexOf, curry, extend, retrieve} from 'zrender/src/core/util';
 import * as graphic from '../../util/graphic';
 import DataDiffer from '../../data/DataDiffer';
 import * as helper from '../helper/treeHelper';
@@ -38,7 +38,7 @@ import { TreemapLayoutNode } from './treemapLayout';
 import Element from 'zrender/src/Element';
 import Displayable from 'zrender/src/graphic/Displayable';
 import { makeInner } from '../../util/model';
-import { PathProps } from 'zrender/src/graphic/Path';
+import { PathStyleProps, PathProps } from 'zrender/src/graphic/Path';
 import { TreeSeriesNodeItemOption } from '../tree/TreeSeries';
 import {
     TreemapRootToNodePayload,
@@ -46,7 +46,6 @@ import {
     TreemapRenderPayload,
     TreemapZoomToNodePayload
 } from './treemapAction';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import { ColorString } from '../../util/types';
 
 const Group = graphic.Group;
@@ -72,9 +71,9 @@ const getItemStyleEmphasis = makeStyleMapper([
     ['shadowOffsetY'],
     ['shadowColor']
 ]);
-const getItemStyleNormal = function (model: Model<TreemapSeriesNodeItemOption['itemStyle']>): StyleProps {
+const getItemStyleNormal = function (model: Model<TreemapSeriesNodeItemOption['itemStyle']>): PathStyleProps {
     // Normal style props should include emphasis style props.
-    let itemStyle = getItemStyleEmphasis(model) as StyleProps;
+    let itemStyle = getItemStyleEmphasis(model) as PathStyleProps;
     // Clear styles set by emphasis.
     itemStyle.stroke = itemStyle.fill = itemStyle.lineWidth = null;
     return itemStyle;
@@ -871,17 +870,17 @@ function renderNode(
                 let upperLabelWidth = thisWidth - 2 * borderWidth;
 
                 prepareText(
-                    normalStyle, emphasisStyle, visualBorderColor, upperLabelWidth, upperHeight,
+                    bg, visualBorderColor, upperLabelWidth, upperHeight,
                     {x: borderWidth, y: 0, width: upperLabelWidth, height: upperHeight}
                 );
             }
             // For old bg.
             else {
-                normalStyle.text = emphasisStyle.text = null;
+                bg.removeTextContent();
             }
 
             bg.setStyle(normalStyle);
-            graphic.setElementHoverStyle(bg, emphasisStyle);
+            graphic.enableElementHoverEmphasis(bg, emphasisStyle);
         }
 
         group.add(bg);
@@ -917,10 +916,10 @@ function renderNode(
             normalStyle.fill = visualColor;
             let emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel);
 
-            prepareText(normalStyle, emphasisStyle, visualColor, contentWidth, contentHeight);
+            prepareText(content, visualColor, contentWidth, contentHeight);
 
             content.setStyle(normalStyle);
-            graphic.setElementHoverStyle(content, emphasisStyle);
+            graphic.enableElementHoverEmphasis(content, emphasisStyle);
         }
 
         group.add(content);
@@ -933,8 +932,7 @@ function renderNode(
     }
 
     function prepareText(
-        normalStyle: StyleProps,
-        emphasisStyle: StyleProps,
+        rectEl: graphic.Rect,
         visualColor: ColorString,
         width: number,
         height: number,
@@ -961,23 +959,23 @@ function renderNode(
         let isShow = normalLabelModel.getShallow('show');
 
         graphic.setLabelStyle(
-            normalStyle, emphasisStyle, normalLabelModel, emphasisLabelModel,
+            rectEl, normalLabelModel, emphasisLabelModel,
             {
                 defaultText: isShow ? text : null,
-                autoColor: visualColor,
-                isRectText: true
+                autoColor: visualColor
             }
         );
 
-        upperLabelRect && (normalStyle.textRect = clone(upperLabelRect));
+        // TODOTODO
+        // upperLabelRect && (normalStyle.textRect = clone(upperLabelRect));
 
-        normalStyle.truncate = (isShow && normalLabelModel.get('ellipsis'))
-            ? {
-                outerWidth: width,
-                outerHeight: height,
-                minChar: 2
-            }
-            : null;
+        // normalStyle.truncate = (isShow && normalLabelModel.get('ellipsis'))
+        //     ? {
+        //         outerWidth: width,
+        //         outerHeight: height,
+        //         minChar: 2
+        //     }
+        //     : null;
     }
 
     function giveGraphic<T extends graphic.Group | graphic.Rect>(
diff --git a/src/component/axis/AngleAxisView.ts b/src/component/axis/AngleAxisView.ts
index 28932b9..3f84809 100644
--- a/src/component/axis/AngleAxisView.ts
+++ b/src/component/axis/AngleAxisView.ts
@@ -27,7 +27,7 @@ import GlobalModel from '../../model/Global';
 import Polar from '../../coord/polar/Polar';
 import ComponentView from '../../view/Component';
 import AngleAxis from '../../coord/polar/AngleAxis';
-import { ZRTextAlign, ZRTextVerticalAlign } from '../../util/types';
+import { ZRTextAlign, ZRTextVerticalAlign, ColorString } from '../../util/types';
 
 const elementList = [
     'axisLine',
@@ -261,13 +261,14 @@ const angelAxisElementsBuilders: Record<typeof elementList[number], AngleAxisEle
                 silent: AxisBuilder.isLabelSilent(angleAxisModel)
             });
             group.add(textEl);
-            graphic.setTextStyle(textEl.style, labelModel, {
+            graphic.setTextStyle(textEl.style, null, labelModel, {
                 x: p[0],
                 y: p[1],
-                textFill: labelModel.getTextColor() || angleAxisModel.get(['axisLine', 'lineStyle', 'color']),
+                fill: labelModel.getTextColor()
+                    || angleAxisModel.get(['axisLine', 'lineStyle', 'color']) as ColorString,
                 text: labelItem.formattedLabel,
-                textAlign: labelTextAlign,
-                textVerticalAlign: labelTextVerticalAlign
+                align: labelTextAlign,
+                verticalAlign: labelTextVerticalAlign
             });
 
             // Pack data for mouse event
diff --git a/src/component/axis/AxisBuilder.ts b/src/component/axis/AxisBuilder.ts
index d600fad..e1f5a86 100644
--- a/src/component/axis/AxisBuilder.ts
+++ b/src/component/axis/AxisBuilder.ts
@@ -18,7 +18,6 @@
 */
 
 import {retrieve, defaults, extend, each, isObject} from 'zrender/src/core/util';
-import * as formatUtil from '../../util/format';
 import * as graphic from '../../util/graphic';
 import Model from '../../model/Model';
 import {isRadianAroundZero, remRadian} from '../../util/number';
@@ -27,10 +26,10 @@ import * as matrixUtil from 'zrender/src/core/matrix';
 import {applyTransform as v2ApplyTransform} from 'zrender/src/core/vector';
 import {shouldShowAllLabels} from '../../coord/axisHelper';
 import { AxisBaseModel } from '../../coord/AxisBaseModel';
-import { ZRTextVerticalAlign, ZRTextAlign, ECElement } from '../../util/types';
+import { ZRTextVerticalAlign, ZRTextAlign, ECElement, ColorString } from '../../util/types';
 import { AxisBaseOption } from '../../coord/axisCommonTypes';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import Element from 'zrender/src/Element';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 
 const PI = Math.PI;
@@ -414,14 +413,6 @@ const builders: Record<'axisLine' | 'axisTickLabel' | 'axisName', AxisElementsBu
         let maxWidth = retrieve(
             opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth
         );
-        // FIXME
-        // truncate rich text? (consider performance)
-        let truncatedText = (ellipsis != null && maxWidth != null)
-            ? formatUtil.truncateText(
-                name, maxWidth, textFont, ellipsis,
-                {minChar: 2, placeholder: truncateOpt.placeholder}
-            )
-            : name;
 
         let tooltipOpt = axisModel.get('tooltip', true);
 
@@ -449,18 +440,20 @@ const builders: Record<'axisLine' | 'axisTickLabel' | 'axisName', AxisElementsBu
             }, tooltipOpt)
             : null;
         textEl.__fullText = name;
-        textEl.__truncatedText = truncatedText;
         // Id for animation
         textEl.anid = 'name';
 
-        graphic.setTextStyle(textEl.style, textStyleModel, {
-            text: truncatedText,
-            textFont: textFont,
-            textFill: textStyleModel.getTextColor()
-                || axisModel.get(['axisLine', 'lineStyle', 'color']),
-            textAlign: textStyleModel.get('align')
+        graphic.setTextStyle(textEl.style, null, textStyleModel, {
+            text: name,
+            font: textFont,
+            overflow: 'truncate',
+            width: maxWidth,
+            ellipsis,
+            fill: textStyleModel.getTextColor()
+                || axisModel.get(['axisLine', 'lineStyle', 'color']) as ColorString,
+            align: textStyleModel.get('align')
                 || labelLayout.textAlign,
-            textVerticalAlign: textStyleModel.get('verticalAlign')
+            verticalAlign: textStyleModel.get('verticalAlign')
                 || labelLayout.textVerticalAlign
         });
 
@@ -615,7 +608,7 @@ function createTicks(
     ticksCoords: TickCoord[],
     tickTransform: matrixUtil.MatrixArray,
     tickEndCoord: number,
-    tickLineStyle: StyleProps,
+    tickLineStyle: PathStyleProps,
     anidPrefix: string
 ) {
     let tickEls = [];
@@ -788,14 +781,14 @@ function buildAxisLabel(
         });
         textEl.anid = 'label_' + tickValue;
 
-        graphic.setTextStyle(textEl.style, itemLabelModel, {
+        graphic.setTextStyle(textEl.style, null, itemLabelModel, {
             text: formattedLabel,
-            textAlign: itemLabelModel.getShallow('align', true)
+            align: itemLabelModel.getShallow('align', true)
                 || labelLayout.textAlign,
-            textVerticalAlign: itemLabelModel.getShallow('verticalAlign', true)
+            verticalAlign: itemLabelModel.getShallow('verticalAlign', true)
                 || itemLabelModel.getShallow('baseline', true)
                 || labelLayout.textVerticalAlign,
-            textFill: typeof textColor === 'function'
+            fill: typeof textColor === 'function'
                 ? textColor(
                     // (1) In category axis with data zoom, tick is not the original
                     // index of axis.data. So tick should not be exposed to user
@@ -811,7 +804,7 @@ function buildAxisLabel(
                         : tickValue,
                     index
                 )
-                : textColor
+                : textColor as string
         });
 
         // Pack data for mouse event
diff --git a/src/component/axisPointer/BaseAxisPointer.ts b/src/component/axisPointer/BaseAxisPointer.ts
index 1e79e4a..761a14c 100644
--- a/src/component/axisPointer/BaseAxisPointer.ts
+++ b/src/component/axisPointer/BaseAxisPointer.ts
@@ -33,10 +33,11 @@ import Element from 'zrender/src/Element';
 import { VerticalAlign, HorizontalAlign, CommonAxisPointerOption } from '../../util/types';
 import { PathProps } from 'zrender/src/graphic/Path';
 import Model from '../../model/Model';
+import { RichTextProps } from 'zrender/src/graphic/RichText';
 
 const inner = makeInner<{
     lastProp?: DisplayableProps
-    labelEl?: graphic.Rect
+    labelEl?: graphic.Text
     pointerEl?: Displayable
 }, Element>();
 const clone = zrUtil.clone;
@@ -85,7 +86,7 @@ export interface AxisPointerElementOptions {
         type: 'Line' | 'Rect' | 'Circle' | 'Sector'
     }
 
-    label: PathProps
+    label: RichTextProps
 }
 /**
  * Base axis pointer class in 2D.
@@ -281,7 +282,7 @@ class BaseAxisPointer implements AxisPointer {
         axisPointerModel: AxisPointerModel
     ) {
         if (elOption.label) {
-            let labelEl = inner(group).labelEl = new graphic.Rect(
+            let labelEl = inner(group).labelEl = new graphic.Text(
                 clone(elOption.label)
             );
 
@@ -320,7 +321,8 @@ class BaseAxisPointer implements AxisPointer {
             updateProps(labelEl, {
                 // Consider text length change in vertical axis, animation should
                 // be used on shape, otherwise the effect will be weird.
-                shape: elOption.label.shape,
+                // TODOTODO
+                // shape: elOption.label.shape,
                 position: elOption.label.position
             });
 
@@ -371,7 +373,7 @@ class BaseAxisPointer implements AxisPointer {
         updateMandatoryProps(handle, axisPointerModel, false);
 
         // update style
-        handle.setStyle(handleModel.getItemStyle(null, [
+        (handle as graphic.Path).setStyle(handleModel.getItemStyle(null, [
             'color', 'borderColor', 'borderWidth', 'opacity',
             'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'
         ]));
diff --git a/src/component/axisPointer/viewHelper.ts b/src/component/axisPointer/viewHelper.ts
index 1b7bb9c..229700e 100644
--- a/src/component/axisPointer/viewHelper.ts
+++ b/src/component/axisPointer/viewHelper.ts
@@ -24,10 +24,9 @@ import * as formatUtil from '../../util/format';
 import * as matrix from 'zrender/src/core/matrix';
 import * as axisHelper from '../../coord/axisHelper';
 import AxisBuilder from '../axis/AxisBuilder';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import Axis from '../../coord/Axis';
 import {
-    ScaleDataValue, CallbackDataParams, ZRTextAlign, ZRTextVerticalAlign, ZRColor, CommonAxisPointerOption
+    ScaleDataValue, CallbackDataParams, ZRTextAlign, ZRTextVerticalAlign, ZRColor, CommonAxisPointerOption, ColorString
 } from '../../util/types';
 import { VectorArray } from 'zrender/src/core/vector';
 import GlobalModel from '../../model/Global';
@@ -38,6 +37,7 @@ import { AxisBaseModel } from '../../coord/AxisBaseModel';
 import ExtensionAPI from '../../ExtensionAPI';
 import CartesianAxisModel from '../../coord/cartesian/AxisModel';
 import Model from '../../model/Model';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 interface LayoutInfo {
     position: VectorArray
@@ -56,7 +56,7 @@ type AxisPointerModel = Model<CommonAxisPointerOption>;
 export function buildElStyle(axisPointerModel: AxisPointerModel) {
     let axisPointerType = axisPointerModel.get('type');
     let styleModel = axisPointerModel.getModel(axisPointerType + 'Style' as 'lineStyle' | 'shadowStyle');
-    let style: StyleProps;
+    let style: PathStyleProps;
     if (axisPointerType === 'line') {
         style = styleModel.getLineStyle();
         style.fill = null;
@@ -118,22 +118,23 @@ export function buildLabelElOption(
     }
 
     elOption.label = {
-        shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')},
+        // shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')},
         position: position.slice(),
         // TODO: rich
         style: {
             text: text,
             textFont: font,
-            textFill: labelModel.getTextColor(),
-            textPosition: 'inside',
-            textPadding: paddings,
-            fill: bgColor,
-            stroke: labelModel.get('borderColor') || 'transparent',
-            lineWidth: labelModel.get('borderWidth') || 0,
-            shadowBlur: labelModel.get('shadowBlur'),
-            shadowColor: labelModel.get('shadowColor'),
-            shadowOffsetX: labelModel.get('shadowOffsetX'),
-            shadowOffsetY: labelModel.get('shadowOffsetY')
+            fill: labelModel.getTextColor(),
+            align: 'center',
+            padding: paddings,
+            backgroundColor: bgColor as ColorString,
+            borderColor: labelModel.get('borderColor') || 'transparent',
+            borderRadius: labelModel.get('borderRadius'),
+            borderWidth: labelModel.get('borderWidth') || 0,
+            boxShadowBlur: labelModel.get('shadowBlur'),
+            boxShadowColor: labelModel.get('shadowColor'),
+            boxShadowOffsetX: labelModel.get('shadowOffsetX'),
+            boxShadowOffsetY: labelModel.get('shadowOffsetY')
         },
         // Lable should be over axisPointer.
         z2: 10
diff --git a/src/component/calendar/CalendarView.ts b/src/component/calendar/CalendarView.ts
index 400ea5d..16fa5fd 100644
--- a/src/component/calendar/CalendarView.ts
+++ b/src/component/calendar/CalendarView.ts
@@ -27,7 +27,8 @@ import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
 import { LayoutOrient, OptionDataValueDate, ZRTextAlign, ZRTextVerticalAlign } from '../../util/types';
 import ComponentView from '../../view/Component';
-import { StyleProps } from 'zrender/src/graphic/Style';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
+import { RichTextStyleProps, RichTextProps } from 'zrender/src/graphic/RichText';
 
 const MONTH_TEXT = {
     EN: [
@@ -203,7 +204,7 @@ class CalendarView extends ComponentView {
     }
 
     // render split line
-    _drawSplitline(points: number[][], lineStyle: StyleProps, group: graphic.Group) {
+    _drawSplitline(points: number[][], lineStyle: PathStyleProps, group: graphic.Group) {
 
         let poyline = new graphic.Polyline({
             z2: 20,
@@ -260,7 +261,7 @@ class CalendarView extends ComponentView {
         orient: LayoutOrient,
         position: 'left' | 'right' | 'top' | 'bottom',
         margin: number
-    ) {
+    ): RichTextProps {
 
         point = point.slice();
         let aligns: [ZRTextAlign, ZRTextVerticalAlign] = ['center', 'bottom'];
@@ -289,8 +290,8 @@ class CalendarView extends ComponentView {
             rotation: rotate,
             position: point,
             style: {
-                textAlign: aligns[0],
-                textVerticalAlign: aligns[1]
+                align: aligns[0],
+                verticalAlign: aligns[1]
             }
         };
     }
@@ -345,7 +346,7 @@ class CalendarView extends ComponentView {
         let content = this._formatterLabel(formatter, params);
 
         let yearText = new graphic.Text({z2: 30});
-        graphic.setTextStyle(yearText.style, yearLabel, {text: content}),
+        graphic.setTextStyle(yearText.style, null, yearLabel, {text: content}),
         yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin));
 
         group.add(yearText);
@@ -357,7 +358,7 @@ class CalendarView extends ComponentView {
         orient: LayoutOrient,
         position: 'start' | 'end',
         margin: number
-    ) {
+    ): RichTextStyleProps {
         let align: ZRTextAlign = 'left';
         let vAlign: ZRTextVerticalAlign = 'top';
         let x = point[0];
@@ -389,8 +390,8 @@ class CalendarView extends ComponentView {
         return {
             x: x,
             y: y,
-            textAlign: align,
-            textVerticalAlign: vAlign
+            align: align,
+            verticalAlign: vAlign
         };
     }
 
@@ -442,7 +443,7 @@ class CalendarView extends ComponentView {
 
             let monthText = new graphic.Text({z2: 30});
             zrUtil.extend(
-                graphic.setTextStyle(monthText.style, monthLabel, {text: content}),
+                graphic.setTextStyle(monthText.style, null, monthLabel, {text: content}),
                 this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)
             );
 
@@ -456,9 +457,9 @@ class CalendarView extends ComponentView {
         position: 'start' | 'end',
         margin: number,
         cellSize: number[]
-    ) {
-        let align = 'center';
-        let vAlign = 'middle';
+    ): RichTextStyleProps {
+        let align: ZRTextAlign = 'center';
+        let vAlign: ZRTextVerticalAlign = 'middle';
         let x = point[0];
         let y = point[1];
         let isStart = position === 'start';
@@ -475,8 +476,8 @@ class CalendarView extends ComponentView {
         return {
             x: x,
             y: y,
-            textAlign: align,
-            textVerticalAlign: vAlign
+            align: align,
+            verticalAlign: vAlign
         };
     }
 
@@ -526,7 +527,7 @@ class CalendarView extends ComponentView {
             let weekText = new graphic.Text({z2: 30});
 
             zrUtil.extend(
-                graphic.setTextStyle(weekText.style, dayLabel, {text: nameMap[day]}),
+                graphic.setTextStyle(weekText.style, null, dayLabel, {text: nameMap[day]}),
                 this._weekTextPositionControl(point, orient, pos, margin, cellSize)
             );
             group.add(weekText);
diff --git a/src/component/dataZoom/SliderZoomView.ts b/src/component/dataZoom/SliderZoomView.ts
index 7439857..ea5ce49 100644
--- a/src/component/dataZoom/SliderZoomView.ts
+++ b/src/component/dataZoom/SliderZoomView.ts
@@ -22,7 +22,7 @@ import * as eventTool from 'zrender/src/core/event';
 import * as graphic from '../../util/graphic';
 import * as throttle from '../../util/throttle';
 import DataZoomView from './DataZoomView';
-import {linearMap, asc} from '../../util/number';
+import {linearMap, asc, parsePercent} from '../../util/number';
 import * as layout from '../../util/layout';
 import sliderMove from '../helper/sliderMove';
 import GlobalModel from '../../model/Global';
@@ -30,7 +30,6 @@ import ExtensionAPI from '../../ExtensionAPI';
 import { LayoutOrient, Payload, ZRTextVerticalAlign, ZRTextAlign, ZRElementEvent, ParsedValue } from '../../util/types';
 import SliderZoomModel from './SliderZoomModel';
 import ComponentView from '../../view/Component';
-import { parsePercent } from 'zrender/src/graphic/helper/text';
 import { RectLike } from 'zrender/src/core/BoundingRect';
 import Axis from '../../coord/Axis';
 import SeriesModel from '../../model/Series';
@@ -436,7 +435,7 @@ class SliderZoomView extends DataZoomView {
 
     _renderHandle() {
         let displaybles = this._displayables;
-        let handles: [Icon, Icon] = displaybles.handles = [null, null];
+        let handles: [graphic.Path, graphic.Path] = displaybles.handles = [null, null];
         let handleLabels: [graphic.Text, graphic.Text] = displaybles.handleLabels = [null, null];
         let barGroup = this._displayables.barGroup;
         let size = this._size;
@@ -451,8 +450,10 @@ class SliderZoomView extends DataZoomView {
             onmouseover: bind(this._showDataInfo, this, true),
             onmouseout: bind(this._showDataInfo, this, false),
             style: {
-                fill: dataZoomModel.get('fillerColor'),
-                textPosition: 'inside'
+                fill: dataZoomModel.get('fillerColor')
+            },
+            textConfig: {
+                position: 'inside'
             }
         }));
 
@@ -486,7 +487,7 @@ class SliderZoomView extends DataZoomView {
                     onmouseout: bind(this._showDataInfo, this, false)
                 },
                 {x: -1, y: 0, width: 2, height: 2}
-            );
+            ) as graphic.Path;
 
             let bRect = path.getBoundingRect();
             this._handleHeight = parsePercent(dataZoomModel.get('handleSize'), this._size[1]);
@@ -509,10 +510,10 @@ class SliderZoomView extends DataZoomView {
                 invisible: true,
                 style: {
                     x: 0, y: 0, text: '',
-                    textVerticalAlign: 'middle',
-                    textAlign: 'center',
-                    textFill: textStyleModel.getTextColor(),
-                    textFont: textStyleModel.getFont()
+                    verticalAlign: 'middle',
+                    align: 'center',
+                    fill: textStyleModel.getTextColor(),
+                    font: textStyleModel.getFont()
                 },
                 z2: 10
             }));
@@ -643,8 +644,8 @@ class SliderZoomView extends DataZoomView {
             handleLabels[handleIndex].setStyle({
                 x: textPoint[0],
                 y: textPoint[1],
-                textVerticalAlign: orient === HORIZONTAL ? 'middle' : direction as ZRTextVerticalAlign,
-                textAlign: orient === HORIZONTAL ? direction as ZRTextAlign : 'center',
+                verticalAlign: orient === HORIZONTAL ? 'middle' : direction as ZRTextVerticalAlign,
+                align: orient === HORIZONTAL ? direction as ZRTextAlign : 'center',
                 text: labelTexts[handleIndex]
             });
         }
diff --git a/src/component/helper/BrushController.ts b/src/component/helper/BrushController.ts
index aa31476..d254434 100644
--- a/src/component/helper/BrushController.ts
+++ b/src/component/helper/BrushController.ts
@@ -25,11 +25,11 @@ import * as graphic from '../../util/graphic';
 import * as interactionMutex from './interactionMutex';
 import DataDiffer from '../../data/DataDiffer';
 import { Dictionary } from '../../util/types';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import { ZRenderType } from 'zrender/src/zrender';
 import { ElementEvent } from 'zrender/src/Element';
 import * as matrix from 'zrender/src/core/matrix';
 import Displayable from 'zrender/src/graphic/Displayable';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 
 /**
@@ -73,7 +73,7 @@ export interface BrushCoverConfig {
 
     brushMode?: BrushMode;
     // `brushStyle`, `transformable` is not mandatory, use DEFAULT_BRUSH_OPT by default.
-    brushStyle?: Pick<StyleProps, BrushStyleKey>;
+    brushStyle?: Pick<PathStyleProps, BrushStyleKey>;
     transformable?: boolean;
     removeOnClick?: boolean;
     z?: number;
diff --git a/src/component/helper/MapDraw.ts b/src/component/helper/MapDraw.ts
index aaf9200..f477190 100644
--- a/src/component/helper/MapDraw.ts
+++ b/src/component/helper/MapDraw.ts
@@ -270,7 +270,7 @@ class MapDraw {
                 });
 
                 graphic.setLabelStyle<typeof query>(
-                    textEl.style, textEl.hoverStyle = {}, labelModel, hoverLabelModel,
+                    textEl, labelModel, hoverLabelModel,
                     {
                         labelFetcher: labelFetcher,
                         labelDataIndex: query,
@@ -278,8 +278,8 @@ class MapDraw {
                         useInsideStyle: false
                     },
                     {
-                        textAlign: 'center',
-                        textVerticalAlign: 'middle'
+                        align: 'center',
+                        verticalAlign: 'middle'
                     }
                 );
 
@@ -308,7 +308,7 @@ class MapDraw {
 
             // @ts-ignore FIXME:TS fix the "compatible with each other"?
             regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode');
-            graphic.setHoverStyle(regionGroup, hoverItemStyle);
+            graphic.enableHoverEmphasis(regionGroup, hoverItemStyle);
 
             regionsGroup.add(regionGroup);
         });
diff --git a/src/component/helper/RoamController.ts b/src/component/helper/RoamController.ts
index bc78d16..c6aeab2 100644
--- a/src/component/helper/RoamController.ts
+++ b/src/component/helper/RoamController.ts
@@ -23,7 +23,7 @@ import * as interactionMutex from './interactionMutex';
 import { ZRenderType } from 'zrender/src/zrender';
 import { ZRElementEvent, RoamOptionMixin } from '../../util/types';
 import { Bind3, isString, bind, defaults, clone } from 'zrender/src/core/util';
-import Group from 'zrender/src/container/Group';
+import Group from 'zrender/src/graphic/Group';
 
 // Can be null/undefined or true/false
 // or 'pan/move' or 'zoom'/'scale'
diff --git a/src/component/legend/LegendView.ts b/src/component/legend/LegendView.ts
index 943362d..1f74a29 100644
--- a/src/component/legend/LegendView.ts
+++ b/src/component/legend/LegendView.ts
@@ -37,6 +37,7 @@ import {
     CommonTooltipOption
 } from '../../util/types';
 import Model from '../../model/Model';
+import Displayable from 'zrender/src/graphic/Displayable';
 
 const curry = zrUtil.curry;
 const each = zrUtil.each;
@@ -294,8 +295,8 @@ class LegendView extends ComponentView {
                 style: {
                     x: 0,
                     y: 0,
-                    textAlign: 'center',
-                    textVerticalAlign: 'middle'
+                    align: 'center',
+                    verticalAlign: 'middle'
                 },
                 onclick() {
                     api.dispatchAction({
@@ -310,13 +311,12 @@ class LegendView extends ComponentView {
             let emphasisLabelModel = legendModel.getModel(['emphasis', 'selectorLabel']);
 
             graphic.setLabelStyle(
-                labelText.style, labelText.hoverStyle = {}, labelModel, emphasisLabelModel,
+                labelText, labelModel, emphasisLabelModel,
                 {
-                    defaultText: selectorItem.title,
-                    isRectText: false
+                    defaultText: selectorItem.title
                 }
             );
-            graphic.setHoverStyle(labelText);
+            graphic.enableHoverEmphasis(labelText);
         });
     }
 
@@ -410,13 +410,13 @@ class LegendView extends ComponentView {
         }
 
         itemGroup.add(new graphic.Text({
-            style: graphic.setTextStyle({}, textStyleModel, {
+            style: graphic.setTextStyle({}, null, textStyleModel, {
                 text: content,
                 x: textX,
                 y: itemHeight / 2,
-                textFill: isSelected ? textStyleModel.getTextColor() : inactiveColor,
-                textAlign: textAlign,
-                textVerticalAlign: 'middle'
+                fill: isSelected ? textStyleModel.getTextColor() : inactiveColor,
+                align: textAlign,
+                verticalAlign: 'middle'
             })
         }));
 
@@ -452,7 +452,7 @@ class LegendView extends ComponentView {
 
         this.getContentGroup().add(itemGroup);
 
-        graphic.setHoverStyle(itemGroup);
+        graphic.enableHoverEmphasis(itemGroup);
 
         // @ts-ignore
         itemGroup.__legendDataIndex = dataIndex;
@@ -546,7 +546,7 @@ function setSymbolStyle(
     let itemStyle;
     if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) {
         itemStyle = legendModelItemStyle.getItemStyle();
-        symbol.style.stroke = borderColor;
+        (symbol as graphic.Path).style.stroke = borderColor;
         if (!isSelected) {
             itemStyle.stroke = inactiveBorderColor;
         }
@@ -554,7 +554,8 @@ function setSymbolStyle(
     else {
         itemStyle = legendModelItemStyle.getItemStyle(['borderWidth', 'borderColor']);
     }
-    return symbol.setStyle(itemStyle);
+    (symbol as Displayable).setStyle(itemStyle);
+    return symbol;
 }
 
 function dispatchSelectAction(
diff --git a/src/component/legend/ScrollableLegendView.ts b/src/component/legend/ScrollableLegendView.ts
index dbbd725..23019fb 100644
--- a/src/component/legend/ScrollableLegendView.ts
+++ b/src/component/legend/ScrollableLegendView.ts
@@ -138,10 +138,10 @@ class ScrollableLegendView extends LegendView {
             style: {
                 // Placeholder to calculate a proper layout.
                 text: 'xx/xx',
-                textFill: pageTextStyleModel.getTextColor(),
+                fill: pageTextStyleModel.getTextColor(),
                 font: pageTextStyleModel.getFont(),
-                textVerticalAlign: 'middle',
-                textAlign: 'center'
+                verticalAlign: 'middle',
+                align: 'center'
             },
             silent: true
         }));
diff --git a/src/component/marker/MarkAreaView.ts b/src/component/marker/MarkAreaView.ts
index 64d8864..bb1334a 100644
--- a/src/component/marker/MarkAreaView.ts
+++ b/src/component/marker/MarkAreaView.ts
@@ -208,7 +208,7 @@ class MarkAreaView extends MarkerView {
                     });
                     // Layout
                     areaData.setItemLayout(idx, points);
-                    let el = areaData.getItemGraphicEl(idx) as graphic.Rect;
+                    let el = areaData.getItemGraphicEl(idx) as graphic.Polygon;
                     el.setShape('points', points);
                 });
             }
@@ -292,20 +292,17 @@ class MarkAreaView extends MarkerView {
                 )
             );
 
-            polygon.hoverStyle = itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
-
             graphic.setLabelStyle(
-                polygon.style, polygon.hoverStyle, labelModel, labelHoverModel,
+                polygon, labelModel, labelHoverModel,
                 {
                     labelFetcher: maModel,
                     labelDataIndex: idx,
                     defaultText: areaData.getName(idx) || '',
-                    isRectText: true,
                     autoColor: color
                 }
             );
 
-            graphic.setHoverStyle(polygon, {});
+            graphic.enableHoverEmphasis(polygon, itemModel.getModel(['emphasis', 'itemStyle']).getItemStyle());
 
             graphic.getECData(polygon).dataModel = maModel;
         });
diff --git a/src/component/timeline/SliderTimelineView.ts b/src/component/timeline/SliderTimelineView.ts
index d9fd4d8..877ff38 100644
--- a/src/component/timeline/SliderTimelineView.ts
+++ b/src/component/timeline/SliderTimelineView.ts
@@ -402,7 +402,7 @@ class SliderTimelineView extends TimelineView {
                 onclick: bind(this._changeTimeline, this, value)
             };
             let el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt);
-            graphic.setHoverStyle(el, hoverStyleModel.getItemStyle());
+            graphic.enableHoverEmphasis(el, hoverStyleModel.getItemStyle());
 
             let ecData = graphic.getECData(el);
             if (itemModel.get('tooltip')) {
@@ -448,15 +448,15 @@ class SliderTimelineView extends TimelineView {
                 onclick: bind(this._changeTimeline, this, dataIndex),
                 silent: false
             });
-            graphic.setTextStyle(textEl.style, normalLabelModel, {
+            graphic.setTextStyle(textEl.style, null, normalLabelModel, {
                 text: labelItem.formattedLabel,
-                textAlign: layoutInfo.labelAlign,
-                textVerticalAlign: layoutInfo.labelBaseline
+                align: layoutInfo.labelAlign,
+                verticalAlign: layoutInfo.labelBaseline
             });
 
             group.add(textEl);
-            graphic.setHoverStyle(
-                textEl, graphic.setTextStyle({}, hoverLabelModel)
+            graphic.enableHoverEmphasis(
+                textEl, graphic.setTextStyle({}, null, hoverLabelModel)
             );
 
         }, this);
@@ -516,7 +516,7 @@ class SliderTimelineView extends TimelineView {
             };
             let btn = makeControlIcon(timelineModel, iconPath, rect, opt);
             group.add(btn);
-            graphic.setHoverStyle(btn, hoverStyle);
+            graphic.enableHoverEmphasis(btn, hoverStyle);
         }
     }
 
diff --git a/src/component/title.ts b/src/component/title.ts
index ee31d56..82eeef4 100644
--- a/src/component/title.ts
+++ b/src/component/title.ts
@@ -150,9 +150,9 @@ class TitleView extends ComponentView {
         );
 
         let textEl = new graphic.Text({
-            style: graphic.setTextStyle({}, textStyleModel, {
+            style: graphic.setTextStyle({}, null, textStyleModel, {
                 text: titleModel.get('text'),
-                textFill: textStyleModel.getTextColor()
+                fill: textStyleModel.getTextColor()
             }, {disableBox: true}),
             z2: 10
         });
@@ -161,11 +161,11 @@ class TitleView extends ComponentView {
 
         let subText = titleModel.get('subtext');
         let subTextEl = new graphic.Text({
-            style: graphic.setTextStyle({}, subtextStyleModel, {
+            style: graphic.setTextStyle({}, null, subtextStyleModel, {
                 text: subText,
-                textFill: subtextStyleModel.getTextColor(),
+                fill: subtextStyleModel.getTextColor(),
                 y: textRect.height + titleModel.get('itemGap'),
-                textVerticalAlign: 'top'
+                verticalAlign: 'top'
             }, {disableBox: true}),
             z2: 10
         });
@@ -213,6 +213,7 @@ class TitleView extends ComponentView {
         if (!textAlign) {
             // Align left if title is on the left. center and right is same
             textAlign = (titleModel.get('left') || titleModel.get('right')) as ZRTextAlign;
+            // @ts-ignore
             if (textAlign === 'middle') {
                 textAlign = 'center';
             }
@@ -226,6 +227,7 @@ class TitleView extends ComponentView {
         }
         if (!textVerticalAlign) {
             textVerticalAlign = (titleModel.get('top') || titleModel.get('bottom')) as ZRTextVerticalAlign;
+            // @ts-ignore
             if (textVerticalAlign === 'center') {
                 textVerticalAlign = 'middle';
             }
@@ -241,8 +243,8 @@ class TitleView extends ComponentView {
 
         group.attr('position', [layoutRect.x, layoutRect.y]);
         let alignStyle = {
-            textAlign: textAlign,
-            textVerticalAlign: textVerticalAlign
+            align: textAlign,
+            verticalAlign: textVerticalAlign
         };
         textEl.setStyle(alignStyle);
         subTextEl.setStyle(alignStyle);
diff --git a/src/component/toolbox/ToolboxView.ts b/src/component/toolbox/ToolboxView.ts
index e7fe023..330c5ed 100644
--- a/src/component/toolbox/ToolboxView.ts
+++ b/src/component/toolbox/ToolboxView.ts
@@ -36,6 +36,8 @@ import {
     UserDefinedToolboxFeature
 } from './featureManager';
 import { getUID } from '../../util/component';
+import { RichText } from 'zrender/src/export';
+import Displayable from 'zrender/src/graphic/Displayable';
 
 type IconPath = ToolboxFeatureModel['iconPaths'][string];
 
@@ -201,18 +203,23 @@ class ToolboxView extends ComponentView {
                         width: itemSize,
                         height: itemSize
                     }
-                );
+                ) as Displayable;  // TODO handling image
                 path.setStyle(iconStyleModel.getItemStyle());
-                path.hoverStyle = iconStyleEmphasisModel.getItemStyle();
+
+                const pathEmphasisState = path.ensureState('emphasis');
+                pathEmphasisState.style = iconStyleEmphasisModel.getItemStyle();
 
                 // Text position calculation
-                path.setStyle({
-                    text: titlesMap[iconName],
-                    textAlign: iconStyleEmphasisModel.get('textAlign'),
-                    textBorderRadius: iconStyleEmphasisModel.get('textBorderRadius'),
-                    textPadding: iconStyleEmphasisModel.get('textPadding'),
-                    textFill: null
+                const textContent = new RichText({
+                    style: {
+                        text: titlesMap[iconName],
+                        align: iconStyleEmphasisModel.get('textAlign'),
+                        borderRadius: iconStyleEmphasisModel.get('textBorderRadius'),
+                        padding: iconStyleEmphasisModel.get('textPadding'),
+                        fill: null
+                    }
                 });
+                path.setTextContent(textContent);
 
                 let tooltipModel = toolboxModel.getModel('tooltip');
                 if (tooltipModel && tooltipModel.get('show')) {
@@ -232,29 +239,29 @@ class ToolboxView extends ComponentView {
                     }, tooltipModel.option);
                 }
 
-                graphic.setHoverStyle(path);
+                graphic.enableHoverEmphasis(path);
 
                 if (toolboxModel.get('showTitle')) {
                     (path as ExtendedPath).__title = titlesMap[iconName];
                     (path as graphic.Path).on('mouseover', function () {
-                            // Should not reuse above hoverStyle, which might be modified.
-                            let hoverStyle = iconStyleEmphasisModel.getItemStyle();
-                            let defaultTextPosition = toolboxModel.get('orient') === 'vertical'
-                                ? (toolboxModel.get('right') == null ? 'right' : 'left')
-                                : (toolboxModel.get('bottom') == null ? 'bottom' : 'top');
-                            (path as graphic.Path).setStyle({
-                                textFill: iconStyleEmphasisModel.get('textFill')
-                                    || hoverStyle.fill || hoverStyle.stroke || '#000',
-                                textBackgroundColor: iconStyleEmphasisModel.get('textBackgroundColor'),
-                                textPosition: iconStyleEmphasisModel.get('textPosition') || defaultTextPosition
-                            });
-                        })
-                        .on('mouseout', function () {
-                            path.setStyle({
-                                textFill: null,
-                                textBackgroundColor: null
-                            });
+                        // Should not reuse above hoverStyle, which might be modified.
+                        let hoverStyle = iconStyleEmphasisModel.getItemStyle();
+                        let defaultTextPosition = toolboxModel.get('orient') === 'vertical'
+                            ? (toolboxModel.get('right') == null ? 'right' as const : 'left' as const)
+                            : (toolboxModel.get('bottom') == null ? 'bottom' as const : 'top' as const);
+                        textContent.setStyle({
+                            fill: (iconStyleEmphasisModel.get('textFill')
+                                || hoverStyle.fill || hoverStyle.stroke || '#000') as string,
+                            backgroundColor: iconStyleEmphasisModel.get('textBackgroundColor')
+                        });
+                        path.setTextConfig({
+                            position: iconStyleEmphasisModel.get('textPosition') || defaultTextPosition
                         });
+                        textContent.ignore = false;
+                    })
+                    .on('mouseout', function () {
+                        textContent.ignore = true;
+                    });
                 }
                 path.trigger(featureModel.get(['iconStatus', iconName]) || 'normal');
 
@@ -274,29 +281,36 @@ class ToolboxView extends ComponentView {
 
         // Adjust icon title positions to avoid them out of screen
         group.eachChild(function (icon: IconPath) {
-            let titleText = (icon as ExtendedPath).__title;
-            let hoverStyle = icon.hoverStyle;
+            const titleText = (icon as ExtendedPath).__title;
+            // const hoverStyle = icon.hoverStyle;
+
+            // TODO simplify code?
+            const emphasisState = icon.states.emphasis;
+            const emphasisTextConfig = emphasisState.textConfig || (emphasisState.textConfig = {});
+            const textContent = icon.getTextContent();
+            const emphasisTextState = textContent && textContent.states.emphasis;
             // May be background element
-            if (hoverStyle && titleText) {
+            if (emphasisTextState && titleText) {
+                const emphasisTextStyle = emphasisTextState.style || (emphasisTextState.style = {});
                 let rect = textContain.getBoundingRect(
-                    titleText, textContain.makeFont(hoverStyle)
+                    titleText, RichText.makeFont(emphasisTextStyle)
                 );
                 let offsetX = icon.position[0] + group.position[0];
                 let offsetY = icon.position[1] + group.position[1] + itemSize;
 
                 let needPutOnTop = false;
                 if (offsetY + rect.height > api.getHeight()) {
-                    hoverStyle.textPosition = 'top';
+                    emphasisTextConfig.position = 'top';
                     needPutOnTop = true;
                 }
                 let topOffset = needPutOnTop ? (-5 - rect.height) : (itemSize + 8);
                 if (offsetX + rect.width / 2 > api.getWidth()) {
-                    hoverStyle.textPosition = ['100%', topOffset];
-                    hoverStyle.textAlign = 'right';
+                    emphasisTextConfig.position = ['100%', topOffset];
+                    emphasisTextStyle.align = 'right';
                 }
                 else if (offsetX - rect.width / 2 < 0) {
-                    hoverStyle.textPosition = [0, topOffset];
-                    hoverStyle.textAlign = 'left';
+                    emphasisTextConfig.position = [0, topOffset];
+                    emphasisTextStyle.align = 'left';
                 }
             }
         });
diff --git a/src/component/toolbox/featureManager.ts b/src/component/toolbox/featureManager.ts
index e4b3ca4..2f6e0c0 100644
--- a/src/component/toolbox/featureManager.ts
+++ b/src/component/toolbox/featureManager.ts
@@ -21,8 +21,9 @@ import Model from '../../model/Model';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../ExtensionAPI';
 import * as graphic from '../../util/graphic';
+import Displayable from 'zrender/src/graphic/Displayable';
 
-type IconPath = ReturnType<typeof graphic.createIcon>;
+// type IconPath = ReturnType<typeof graphic.createIcon>;
 
 type IconStyle = ItemStyleOption & {
     // TODO Move to a individual textStyle option
@@ -57,7 +58,7 @@ export interface ToolboxFeatureModel<Opts extends ToolboxFeatureOption = Toolbox
      * Collection of icon paths.
      * Will be injected during rendering in the view.
      */
-    iconPaths: Dictionary<IconPath>
+    iconPaths: Dictionary<Displayable>
 
     setIconStatus(iconName: string, status: DisplayState): void
 }
diff --git a/src/component/tooltip/TooltipRichContent.ts b/src/component/tooltip/TooltipRichContent.ts
index ba5e5ca..89ffacb 100644
--- a/src/component/tooltip/TooltipRichContent.ts
+++ b/src/component/tooltip/TooltipRichContent.ts
@@ -18,7 +18,7 @@
 */
 
 import * as zrUtil from 'zrender/src/core/util';
-// import Group from 'zrender/src/container/Group';
+// import Group from 'zrender/src/graphic/Group';
 import Text from 'zrender/src/graphic/Text';
 import ExtensionAPI from '../../ExtensionAPI';
 import { ZRenderType } from 'zrender/src/zrender';
@@ -26,8 +26,8 @@ import { TooltipOption } from './TooltipModel';
 import * as graphic from '../../util/graphic';
 import { Dictionary } from 'zrender/src/core/types';
 import { ColorString } from '../../util/types';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import Model from '../../model/Model';
+import RichText, { RichTextStyleProps } from 'zrender/src/graphic/RichText';
 
 class TooltipRichContent {
 
@@ -77,7 +77,7 @@ class TooltipRichContent {
             this._zr.remove(this.el);
         }
 
-        let markers: StyleProps['rich'] = {};
+        let markers: RichTextStyleProps['rich'] = {};
         let text = content;
         let prefix = '{marker';
         let suffix = '|}';
@@ -87,10 +87,10 @@ class TooltipRichContent {
             let name = text.substr(startId + prefix.length, endId - startId - prefix.length);
             if (name.indexOf('sub') > -1) {
                 markers['marker' + name] = {
-                    textWidth: 4,
-                    textHeight: 4,
-                    textBorderRadius: 2,
-                    textBackgroundColor: markerRich[name]
+                    width: 4,
+                    height: 4,
+                    borderRadius: 2,
+                    backgroundColor: markerRich[name]
 
                     // TODO: textOffset is not implemented for rich text
                     // textOffset: [3, 0]
@@ -98,10 +98,10 @@ class TooltipRichContent {
             }
             else {
                 markers['marker' + name] = {
-                    textWidth: 10,
-                    textHeight: 10,
-                    textBorderRadius: 5,
-                    textBackgroundColor: markerRich[name]
+                    width: 10,
+                    height: 10,
+                    borderRadius: 5,
+                    backgroundColor: markerRich[name]
                 };
             }
 
@@ -109,15 +109,15 @@ class TooltipRichContent {
             startId = text.indexOf('{marker');
         }
 
-        this.el = new Text({
+        this.el = new RichText({
             style: {
                 rich: markers,
                 text: content,
-                textLineHeight: 20,
-                textBackgroundColor: tooltipModel.get('backgroundColor'),
-                textBorderRadius: tooltipModel.get('borderRadius'),
-                textFill: tooltipModel.get(['textStyle', 'color']),
-                textPadding: tooltipModel.get('padding')
+                lineHeight: 20,
+                backgroundColor: tooltipModel.get('backgroundColor'),
+                borderRadius: tooltipModel.get('borderRadius'),
+                fill: tooltipModel.get(['textStyle', 'color']),
+                padding: tooltipModel.get('padding')
             },
             z: tooltipModel.get('z')
         });
diff --git a/src/component/visualMap/ContinuousView.ts b/src/component/visualMap/ContinuousView.ts
index 3cbf81b..137a108 100644
--- a/src/component/visualMap/ContinuousView.ts
+++ b/src/component/visualMap/ContinuousView.ts
@@ -178,23 +178,23 @@ class ContinuousView extends VisualMapView {
             style: {
                 x: position[0],
                 y: position[1],
-                textVerticalAlign: orient === 'horizontal' ? 'middle' : align as TextVerticalAlign,
-                textAlign: orient === 'horizontal' ? align as TextAlign : 'center',
+                verticalAlign: orient === 'horizontal' ? 'middle' : align as TextVerticalAlign,
+                align: orient === 'horizontal' ? align as TextAlign : 'center',
                 text: text,
-                textFont: textStyleModel.getFont(),
-                textFill: textStyleModel.getTextColor()
+                font: textStyleModel.getFont(),
+                fill: textStyleModel.getTextColor()
             }
         }));
     }
 
     private _renderBar(targetGroup: graphic.Group) {
-        let visualMapModel = this.visualMapModel;
-        let shapes = this._shapes;
-        let itemSize = visualMapModel.itemSize;
-        let orient = this._orient;
-        let useHandle = this._useHandle;
-        let itemAlign = helper.getItemAlign(visualMapModel, this.api, itemSize);
-        let barGroup = shapes.barGroup = this._createBarGroup(itemAlign);
+        const visualMapModel = this.visualMapModel;
+        const shapes = this._shapes;
+        const itemSize = visualMapModel.itemSize;
+        const orient = this._orient;
+        const useHandle = this._useHandle;
+        const itemAlign = helper.getItemAlign(visualMapModel, this.api, itemSize);
+        const barGroup = shapes.barGroup = this._createBarGroup(itemAlign);
 
         // Bar
         barGroup.add(shapes.outOfRange = createPolygon());
@@ -205,8 +205,8 @@ class ContinuousView extends VisualMapView {
             zrUtil.bind(this._dragHandle, this, 'all', true)
         ));
 
-        let textRect = visualMapModel.textStyleModel.getTextRect('国');
-        let textSize = mathMax(textRect.width, textRect.height);
+        const textRect = visualMapModel.textStyleModel.getTextRect('国');
+        const textSize = mathMax(textRect.width, textRect.height);
 
         // Handle
         if (useHandle) {
@@ -230,9 +230,9 @@ class ContinuousView extends VisualMapView {
         textSize: number,
         orient: Orient
     ) {
-        let onDrift = zrUtil.bind(this._dragHandle, this, handleIndex, false);
-        let onDragEnd = zrUtil.bind(this._dragHandle, this, handleIndex, true);
-        let handleThumb = createPolygon(
+        const onDrift = zrUtil.bind(this._dragHandle, this, handleIndex, false);
+        const onDragEnd = zrUtil.bind(this._dragHandle, this, handleIndex, true);
+        const handleThumb = createPolygon(
             createHandlePoints(handleIndex, textSize),
             getCursor(this._orient),
             onDrift,
@@ -245,8 +245,8 @@ class ContinuousView extends VisualMapView {
         // transform (orient/inverse). So label is built separately but not
         // use zrender/graphic/helper/RectText, and is located based on view
         // group (according to handleLabelPoint) but not barGroup.
-        let textStyleModel = this.visualMapModel.textStyleModel;
-        let handleLabel = new graphic.Text({
+        const textStyleModel = this.visualMapModel.textStyleModel;
+        const handleLabel = new graphic.Text({
             draggable: true,
             drift: onDrift,
             onmousemove(e) {
@@ -256,13 +256,13 @@ class ContinuousView extends VisualMapView {
             ondragend: onDragEnd,
             style: {
                 x: 0, y: 0, text: '',
-                textFont: textStyleModel.getFont(),
-                textFill: textStyleModel.getTextColor()
+                font: textStyleModel.getFont(),
+                fill: textStyleModel.getTextColor()
             }
         });
         this.group.add(handleLabel);
 
-        let handleLabelPoint = [
+        const handleLabelPoint = [
             orient === 'horizontal'
                 ? textSize / 2
                 : textSize * 1.5,
@@ -283,29 +283,29 @@ class ContinuousView extends VisualMapView {
         textSize: number,
         orient: Orient
     ) {
-        let indicator = createPolygon([[0, 0]], 'move');
+        const indicator = createPolygon([[0, 0]], 'move');
         indicator.position[0] = itemSize[0];
         indicator.attr({invisible: true, silent: true});
         barGroup.add(indicator);
 
-        let textStyleModel = this.visualMapModel.textStyleModel;
-        let indicatorLabel = new graphic.Text({
+        const textStyleModel = this.visualMapModel.textStyleModel;
+        const indicatorLabel = new graphic.Text({
             silent: true,
             invisible: true,
             style: {
                 x: 0, y: 0, text: '',
-                textFont: textStyleModel.getFont(),
-                textFill: textStyleModel.getTextColor()
+                font: textStyleModel.getFont(),
+                fill: textStyleModel.getTextColor()
             }
         });
         this.group.add(indicatorLabel);
 
-        let indicatorLabelPoint = [
+        const indicatorLabelPoint = [
             orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT + 3,
             0
         ];
 
-        let shapes = this._shapes;
+        const shapes = this._shapes;
         shapes.indicator = indicator;
         shapes.indicatorLabel = indicatorLabel;
         shapes.indicatorLabelPoint = indicatorLabelPoint;
@@ -395,17 +395,17 @@ class ContinuousView extends VisualMapView {
     }
 
     private _updateView(forSketch?: boolean) {
-        let visualMapModel = this.visualMapModel;
-        let dataExtent = visualMapModel.getExtent();
-        let shapes = this._shapes;
+        const visualMapModel = this.visualMapModel;
+        const dataExtent = visualMapModel.getExtent();
+        const shapes = this._shapes;
 
-        let outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]];
-        let inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds;
+        const outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]];
+        const inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds;
 
-        let visualInRange = this._createBarVisual(
+        const visualInRange = this._createBarVisual(
             this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange'
         );
-        let visualOutOfRange = this._createBarVisual(
+        const visualOutOfRange = this._createBarVisual(
             dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange'
         );
 
@@ -431,17 +431,17 @@ class ContinuousView extends VisualMapView {
         handleEnds: number[],
         forceState: ContinuousModel['stateList'][number]
     ): BarVisual {
-        let opts = {
+        const opts = {
             forceState: forceState,
             convertOpacityToAlpha: true
         };
-        let colorStops = this._makeColorGradient(dataInterval, opts);
+        const colorStops = this._makeColorGradient(dataInterval, opts);
 
-        let symbolSizes = [
+        const symbolSizes = [
             this.getControllerVisual(dataInterval[0], 'symbolSize', opts) as number,
             this.getControllerVisual(dataInterval[1], 'symbolSize', opts) as number
         ];
-        let barPoints = this._createBarPoints(handleEnds, symbolSizes);
+        const barPoints = this._createBarPoints(handleEnds, symbolSizes);
 
         return {
             barColor: new LinearGradient(0, 0, 0, 1, colorStops),
@@ -541,8 +541,8 @@ class ContinuousView extends VisualMapView {
                 x: textPoint[0],
                 y: textPoint[1],
                 text: visualMapModel.formatValueText(this._dataInterval[handleIndex]),
-                textVerticalAlign: 'middle',
-                textAlign: this._applyTransform(
+                verticalAlign: 'middle',
+                align: this._applyTransform(
                     this._orient === 'horizontal'
                         ? (handleIndex === 0 ? 'bottom' : 'top')
                         : 'left',
@@ -577,7 +577,7 @@ class ContinuousView extends VisualMapView {
         ));
 
         let opts = {convertOpacityToAlpha: true};
-        let color = this.getControllerVisual(cursorValue, 'color', opts);
+        let color = this.getControllerVisual(cursorValue, 'color', opts) as ColorString;
         indicator.setStyle('fill', color);
 
         // Update handle label position.
@@ -586,14 +586,15 @@ class ContinuousView extends VisualMapView {
             graphic.getTransform(indicator, this.group)
         );
 
-        let indicatorLabel = shapes.indicatorLabel;
+        const indicatorLabel = shapes.indicatorLabel;
         indicatorLabel.attr('invisible', false);
-        let align = this._applyTransform('left', shapes.barGroup);
-        let orient = this._orient;
+        const align = this._applyTransform('left', shapes.barGroup);
+        const orient = this._orient;
+        const isHorizontal = orient === 'horizontal';
         indicatorLabel.setStyle({
             text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue),
-            textVerticalAlign: orient === 'horizontal' ? align as TextVerticalAlign : 'middle',
-            textAlign: orient === 'horizontal' ? 'center' : align as TextAlign,
+            verticalAlign: isHorizontal ? align as TextVerticalAlign : 'middle',
+            align: isHorizontal ? 'center' : align as TextAlign,
             x: textPoint[0],
             y: textPoint[1]
         });
diff --git a/src/component/visualMap/PiecewiseView.ts b/src/component/visualMap/PiecewiseView.ts
index dd96400..ec35bde 100644
--- a/src/component/visualMap/PiecewiseView.ts
+++ b/src/component/visualMap/PiecewiseView.ts
@@ -79,10 +79,10 @@ class PiecewiseVisualMapView extends VisualMapView {
                         x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap,
                         y: itemSize[1] / 2,
                         text: piece.text,
-                        textVerticalAlign: 'middle',
-                        textAlign: itemAlign as TextAlign,
-                        textFont: textFont,
-                        textFill: textFill,
+                        verticalAlign: 'middle',
+                        align: itemAlign as TextAlign,
+                        font: textFont,
+                        fill: textFill,
                         opacity: visualState === 'outOfRange' ? 0.5 : 1
                     }
                 }));
@@ -161,11 +161,11 @@ class PiecewiseVisualMapView extends VisualMapView {
             style: {
                 x: showLabel ? (itemAlign === 'right' ? itemSize[0] : 0) : itemSize[0] / 2,
                 y: itemSize[1] / 2,
-                textVerticalAlign: 'middle',
-                textAlign: showLabel ? (itemAlign as TextAlign) : 'center',
+                verticalAlign: 'middle',
+                align: showLabel ? (itemAlign as TextAlign) : 'center',
                 text: text,
-                textFont: textStyleModel.getFont(),
-                textFill: textStyleModel.getTextColor()
+                font: textStyleModel.getFont(),
+                fill: textStyleModel.getTextColor()
             }
         }));
 
diff --git a/src/coord/geo/geoSVGLoader.ts b/src/coord/geo/geoSVGLoader.ts
index ca13d40..95951f6 100644
--- a/src/coord/geo/geoSVGLoader.ts
+++ b/src/coord/geo/geoSVGLoader.ts
@@ -18,7 +18,7 @@
 */
 
 import {parseSVG, makeViewBoxTransform} from 'zrender/src/tool/parseSVG';
-import Group from 'zrender/src/container/Group';
+import Group from 'zrender/src/graphic/Group';
 import Rect from 'zrender/src/graphic/shape/Rect';
 import {assert, createHashMap, HashMap} from 'zrender/src/core/util';
 import BoundingRect from 'zrender/src/core/BoundingRect';
diff --git a/src/coord/geo/geoSourceManager.ts b/src/coord/geo/geoSourceManager.ts
index 2b2882b..f34b0de 100644
--- a/src/coord/geo/geoSourceManager.ts
+++ b/src/coord/geo/geoSourceManager.ts
@@ -26,7 +26,7 @@ import BoundingRect from 'zrender/src/core/BoundingRect';
 import { NameMap } from './geoTypes';
 import Region from './Region';
 import { Dictionary } from 'zrender/src/core/types';
-import Group from 'zrender/src/container/Group';
+import Group from 'zrender/src/graphic/Group';
 
 
 interface Loader {
diff --git a/src/coord/parallel/AxisModel.ts b/src/coord/parallel/AxisModel.ts
index 28bd826..4252311 100644
--- a/src/coord/parallel/AxisModel.ts
+++ b/src/coord/parallel/AxisModel.ts
@@ -27,15 +27,15 @@ import {AxisModelCommonMixin} from '../axisModelCommonMixin';
 import ParallelAxis from './ParallelAxis';
 import { ZRColor, ParsedValue } from '../../util/types';
 import { AxisBaseOption } from '../axisCommonTypes';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import Parallel from './Parallel';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 
 // 'normal' means there is no "active intervals" existing.
 export type ParallelActiveState = 'normal' | 'active' | 'inactive';
 export type ParallelAxisInterval = number[];
 type ParallelAreaSelectStyleKey = 'fill' | 'lineWidth' | 'stroke' | 'opacity';
-export type ParallelAreaSelectStyleProps = Pick<StyleProps, ParallelAreaSelectStyleKey> & {
+export type ParallelAreaSelectStyleProps = Pick<PathStyleProps, ParallelAreaSelectStyleKey> & {
     // Selected area width.
     width: number;
 };
diff --git a/src/echarts.ts b/src/echarts.ts
index cf28561..6ccb173 100644
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@ -66,6 +66,8 @@ import {
 import Displayable from 'zrender/src/graphic/Displayable';
 import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
 
+// At least canvas renderer.
+import 'zrender/src/canvas/canvas';
 
 declare let global: any;
 type ModelFinder = modelUtil.ModelFinder;
diff --git a/src/loading/default.ts b/src/loading/default.ts
index cccc66b..80ba022 100644
--- a/src/loading/default.ts
+++ b/src/loading/default.ts
@@ -73,11 +73,17 @@ export default function (
     });
     let labelRect = new graphic.Rect({
         style: {
-            fill: 'none',
-            text: opts.text,
-            textPosition: 'right',
-            textDistance: 10,
-            textFill: opts.textColor
+            fill: 'none'
+        },
+        textContent: new graphic.Text({
+            style: {
+                text: opts.text,
+                fill: opts.textColor
+            }
+        }),
+        textConfig: {
+            position: 'right',
+            distance: 10
         },
         zlevel: opts.zlevel,
         z: 10001
diff --git a/src/model/mixin/areaStyle.ts b/src/model/mixin/areaStyle.ts
index 6cd6277..309593a 100644
--- a/src/model/mixin/areaStyle.ts
+++ b/src/model/mixin/areaStyle.ts
@@ -18,9 +18,9 @@
 */
 
 import makeStyleMapper from './makeStyleMapper';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import Model from '../Model';
 import { AreaStyleOption } from '../../util/types';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 const getAreaStyle = makeStyleMapper([
     ['fill', 'color'],
@@ -31,7 +31,7 @@ const getAreaStyle = makeStyleMapper([
     ['shadowColor']
 ]);
 
-type AreaStyleProps = Pick<StyleProps,
+type AreaStyleProps = Pick<PathStyleProps,
     'fill'
     | 'shadowBlur'
     | 'shadowOffsetX'
diff --git a/src/model/mixin/itemStyle.ts b/src/model/mixin/itemStyle.ts
index e976f09..2fd3157 100644
--- a/src/model/mixin/itemStyle.ts
+++ b/src/model/mixin/itemStyle.ts
@@ -19,8 +19,8 @@
 
 import makeStyleMapper from './makeStyleMapper';
 import Model from '../Model';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import { ItemStyleOption } from '../../util/types';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 const getItemStyle = makeStyleMapper([
     ['fill', 'color'],
@@ -30,10 +30,7 @@ const getItemStyle = makeStyleMapper([
     ['shadowBlur'],
     ['shadowOffsetX'],
     ['shadowOffsetY'],
-    ['shadowColor'],
-    // TODO?
-    ['textPosition'],
-    ['textAlign']
+    ['shadowColor']
 ]);
 
 type ItemStyleKeys = 'fill'
@@ -43,11 +40,9 @@ type ItemStyleKeys = 'fill'
     | 'shadowBlur'
     | 'shadowOffsetX'
     | 'shadowOffsetY'
-    | 'shadowColor'
-    | 'textPosition'
-    | 'textAlign';
+    | 'shadowColor';
 
-type ItemStyleProps = Pick<StyleProps, ItemStyleKeys>;
+type ItemStyleProps = Pick<PathStyleProps, ItemStyleKeys>;
 
 class ItemStyleMixin {
 
diff --git a/src/model/mixin/lineStyle.ts b/src/model/mixin/lineStyle.ts
index f2857ff..fcf7b29 100644
--- a/src/model/mixin/lineStyle.ts
+++ b/src/model/mixin/lineStyle.ts
@@ -19,8 +19,8 @@
 
 import makeStyleMapper from './makeStyleMapper';
 import Model from '../Model';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import { LineStyleOption } from '../../util/types';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
 
 const getLineStyle = makeStyleMapper([
     ['lineWidth', 'width'],
@@ -40,7 +40,7 @@ type LineStyleKeys = 'lineWidth'
     | 'shadowOffsetY'
     | 'shadowColor';
 
-type LineStyleProps = Pick<StyleProps, LineStyleKeys>;
+type LineStyleProps = Pick<PathStyleProps, LineStyleKeys>;
 
 class LineStyleMixin {
 
diff --git a/src/model/mixin/textStyle.ts b/src/model/mixin/textStyle.ts
index bf99fbe..343dbc7 100644
--- a/src/model/mixin/textStyle.ts
+++ b/src/model/mixin/textStyle.ts
@@ -17,10 +17,10 @@
 * under the License.
 */
 
-import * as textContain from 'zrender/src/contain/text';
 import * as graphicUtil from '../../util/graphic';
 import Model from '../Model';
 import { LabelOption, ColorString } from '../../util/types';
+import { RichText } from 'zrender/src/export';
 
 const PATH_COLOR = ['textStyle', 'color'] as const;
 
@@ -29,6 +29,8 @@ type LabelRectRelatedOption = Pick<LabelOption,
     'align' | 'verticalAlign' | 'padding' | 'lineHeight' | 'baseline' | 'rich'
 > & LabelFontOption;
 
+// TODO Performance improvement?
+const tmpRichText = new RichText();
 class TextStyleMixin {
     /**
      * Get color property or get color from option.textStyle.color
@@ -56,16 +58,19 @@ class TextStyleMixin {
     }
 
     getTextRect(this: Model<LabelRectRelatedOption> & TextStyleMixin, text: string): graphicUtil.BoundingRect {
-        return textContain.getBoundingRect(
+        tmpRichText.useStyle({
             text,
-            this.getFont(),
-            this.getShallow('align'),
-            this.getShallow('verticalAlign') || this.getShallow('baseline'),
-            this.getShallow('padding') as number[],
-            this.getShallow('lineHeight'),
-            this.getShallow('rich')
-            // this.getShallow('truncateText')
-        );
+            fontStyle: this.getShallow('fontStyle'),
+            fontWeight: this.getShallow('fontWeight'),
+            fontSize: this.getShallow('fontSize'),
+            fontFamily: this.getShallow('fontFamily'),
+            verticalAlign: this.getShallow('verticalAlign') || this.getShallow('baseline'),
+            padding: this.getShallow('padding') as number[],
+            lineHeight: this.getShallow('lineHeight'),
+            rich: this.getShallow('rich')
+        });
+        tmpRichText.update();
+        return tmpRichText.getBoundingRect();
     }
 };
 
diff --git a/src/util/format.ts b/src/util/format.ts
index 4c69e54..f4e51d4 100644
--- a/src/util/format.ts
+++ b/src/util/format.ts
@@ -18,12 +18,9 @@
 */
 
 import * as zrUtil from 'zrender/src/core/util';
-import * as textContain from 'zrender/src/contain/text';
 import * as numberUtil from './number';
 import {TooltipRenderMode, ColorString} from './types';
 import { Dictionary } from 'zrender/src/core/types';
-import { StyleProps } from 'zrender/src/graphic/Style';
-// import Text from 'zrender/src/graphic/Text';
 
 /**
  * Add a comma each three digit.
@@ -245,40 +242,4 @@ export function formatTime(tpl: string, value: number | string | Date, isUTC?: b
  */
 export function capitalFirst(str: string): string {
     return str ? str.charAt(0).toUpperCase() + str.substr(1) : str;
-}
-
-export let truncateText = textContain.truncateText;
-
-export function getTextBoundingRect(opt: StyleProps): ReturnType<typeof textContain.getBoundingRect> {
-    return textContain.getBoundingRect(
-        opt.text,
-        opt.font,
-        opt.textAlign,
-        opt.textVerticalAlign,
-        opt.textPadding as number[],
-        opt.textLineHeight,
-        opt.rich,
-        opt.truncate
-    );
-}
-
-/**
- * @deprecated
- * the `textLineHeight` was added later.
- * For backward compatiblility, put it as the last parameter.
- * But deprecated this interface. Please use `getTextBoundingRect` instead.
- */
-export function getTextRect(
-    text: StyleProps['text'],
-    font: StyleProps['font'],
-    textAlign: StyleProps['textAlign'],
-    textVerticalAlign: StyleProps['textVerticalAlign'],
-    textPadding: StyleProps['textPadding'],
-    rich: StyleProps['rich'],
-    truncate: StyleProps['truncate'],
-    textLineHeight: number
-): ReturnType<typeof textContain.getBoundingRect> {
-    return textContain.getBoundingRect(
-        text, font, textAlign, textVerticalAlign, textPadding as number[], textLineHeight, rich, truncate
-    );
-}
+}
\ No newline at end of file
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index 3b0beeb..72502ef 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -24,9 +24,9 @@ import * as matrix from 'zrender/src/core/matrix';
 import * as vector from 'zrender/src/core/vector';
 import Path, { PathProps } from 'zrender/src/graphic/Path';
 import Transformable from 'zrender/src/core/Transformable';
-import ZImage, {ZImageStyleProps} from 'zrender/src/graphic/Image';
-import Group from 'zrender/src/container/Group';
-import Text from 'zrender/src/graphic/Text';
+import ZImage, { ImageStyleProps } from 'zrender/src/graphic/Image';
+import Group from 'zrender/src/graphic/Group';
+import RichText, { RichTextStyleProps } from 'zrender/src/graphic/RichText';
 import Circle from 'zrender/src/graphic/shape/Circle';
 import Sector from 'zrender/src/graphic/shape/Sector';
 import Ring from 'zrender/src/graphic/shape/Ring';
@@ -42,10 +42,9 @@ import RadialGradient from 'zrender/src/graphic/RadialGradient';
 import BoundingRect from 'zrender/src/core/BoundingRect';
 import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
 import * as subPixelOptimizeUtil from 'zrender/src/graphic/helper/subPixelOptimize';
-import { Dictionary, ImageLike } from 'zrender/src/core/types';
+import { Dictionary } from 'zrender/src/core/types';
 import LRU from 'zrender/src/core/LRU';
 import Displayable, { DisplayableProps } from 'zrender/src/graphic/Displayable';
-import { StyleProps } from 'zrender/src/graphic/Style';
 import { PatternObject } from 'zrender/src/graphic/Pattern';
 import { GradientObject } from 'zrender/src/graphic/Gradient';
 import Element, { ElementEvent } from 'zrender/src/Element';
@@ -59,7 +58,8 @@ import {
     ZRRectLike,
     ColorString,
     DataModel,
-    ECEventData
+    ECEventData,
+    ZRStyleProps
 } from './types';
 import GlobalModel from '../model/Global';
 import { makeInner } from './model';
@@ -93,11 +93,6 @@ type ExtendShapeReturn = ReturnType<typeof Path.extend>;
 
 
 type ExtendedProps = {
-    __hoverStlDirty?: boolean
-    __hoverStl?: StyleProps
-    __cachedNormalStl?: StyleProps
-    __cachedNormalZ2?: number
-
     __highlighted?: boolean | 'layer' | 'plain'
     __highByOuter: number
 
@@ -109,17 +104,11 @@ type ExtendedProps = {
 type ExtendedElement = Element & ExtendedProps;
 type ExtendedDisplayable = Displayable & ExtendedProps;
 
-type ExtendedStyleProps = StyleProps & {
-    insideRollback?: StyleProps
-    insideRollbackOpt?: TextCommonParams
-};
-
 type TextCommonParams = {
     /**
      * Whether diable drawing box of block (outer most).
      */
     disableBox?: boolean
-    isRectText?: boolean
     /**
      * Specify a color when color is 'auto',
      * for textFill, textStroke, textBackgroundColor, and textBorderColor. If autoColor specified, it is used as default textFill.
@@ -138,7 +127,9 @@ type TextCommonParams = {
 
     getTextPosition?: (textStyleModel: Model, isEmphasis?: boolean) => string | string[] | number[]
 
-    textStyle?: StyleProps
+    defaultOutsidePosition?: LabelOption['position']
+
+    textStyle?: ZRStyleProps
 };
 
 /**
@@ -250,7 +241,7 @@ export function makeImage(
             width: rect.width,
             height: rect.height
         },
-        onload: function (img: ImageLike) {
+        onload(img) {
             if (layout === 'center') {
                 let boundingRect = {
                     width: img.width,
@@ -375,144 +366,18 @@ function liftColor(color: string): string {
     return liftedColor;
 }
 
-function cacheElementStl(el: ExtendedDisplayable) {
-    if (!el.__hoverStlDirty) {
-        return;
-    }
-    el.__hoverStlDirty = false;
-
-    let hoverStyle = el.__hoverStl;
-    if (!hoverStyle) {
-        el.__cachedNormalStl = el.__cachedNormalZ2 = null;
-        return;
-    }
-
-    let normalStyle = el.__cachedNormalStl = {} as StyleProps;
-    el.__cachedNormalZ2 = el.z2;
-    let elStyle = el.style;
+function singleEnterEmphasis(el: Displayable) {
+    el.useState('emphasis');
 
-    const styleKeys = zrUtil.keys(hoverStyle);
-    for (let idx = 0; idx < styleKeys.length; idx++) {
-        const key = styleKeys[idx];
-        if (hoverStyle[key] != null) {
-            (normalStyle as any)[key] = elStyle[key];
-        }
-    }
+    // TODO default lift fill/stroke. z2
+    // TODO hover layer
 
-    // Always cache fill and stroke to normalStyle for lifting color.
-    normalStyle.fill = elStyle.fill;
-    normalStyle.stroke = elStyle.stroke;
+    // applyDefaultTextStyle(targetStyle);
 }
 
-function singleEnterEmphasis(el: ExtendedDisplayable) {
-    let hoverStl = el.__hoverStl;
 
-    if (!hoverStl || el.__highlighted) {
-        return;
-    }
-
-    let zr = el.__zr;
-
-    let useHoverLayer = el.useHoverLayer && zr && zr.painter.type === 'canvas';
-    el.__highlighted = useHoverLayer ? 'layer' : 'plain';
-
-    if (el.isGroup || (!zr && el.useHoverLayer)) {
-        return;
-    }
-
-    let elTarget = el;
-    let targetStyle = el.style;
-
-    if (useHoverLayer) {
-        elTarget = zr.addHover(el);
-        targetStyle = elTarget.style;
-    }
-
-    rollbackDefaultTextStyle(targetStyle);
-
-    if (!useHoverLayer) {
-        cacheElementStl(elTarget);
-    }
-
-    // styles can be:
-    // {
-    //    label: {
-    //        show: false,
-    //        position: 'outside',
-    //        fontSize: 18
-    //    },
-    //    emphasis: {
-    //        label: {
-    //            show: true
-    //        }
-    //    }
-    // },
-    // where properties of `emphasis` may not appear in `normal`. We previously use
-    // module:echarts/util/model#defaultEmphasis to merge `normal` to `emphasis`.
-    // But consider rich text and setOption in merge mode, it is impossible to cover
-    // all properties in merge. So we use merge mode when setting style here.
-    // But we choose the merge strategy that only properties that is not `null/undefined`.
-    // Because when making a textStyle (espacially rich text), it is not easy to distinguish
-    // `hasOwnProperty` and `null/undefined` in code, so we trade them as the same for simplicity.
-    // But this strategy brings a trouble that `null/undefined` can not be used to remove
-    // style any more in `emphasis`. Users can both set properties directly on normal and
-    // emphasis to avoid this issue, or we might support `'none'` for this case if required.
-    targetStyle.extendFrom(hoverStl);
-
-    setDefaultHoverFillStroke(targetStyle, hoverStl, 'fill');
-    setDefaultHoverFillStroke(targetStyle, hoverStl, 'stroke');
-
-    applyDefaultTextStyle(targetStyle);
-
-    if (!useHoverLayer) {
-        el.dirty(false);
-        el.z2 += Z2_EMPHASIS_LIFT;
-    }
-}
-
-function setDefaultHoverFillStroke(
-    targetStyle: StyleProps,
-    hoverStyle: StyleProps,
-    prop: 'fill' | 'stroke'
-) {
-    if (!hasFillOrStroke(hoverStyle[prop]) && hasFillOrStroke(targetStyle[prop])) {
-        targetStyle[prop] = liftColor(targetStyle[prop] as string);
-    }
-}
-
-function singleEnterNormal(el: ExtendedDisplayable) {
-    let highlighted = el.__highlighted;
-
-    if (!highlighted) {
-        return;
-    }
-
-    el.__highlighted = false;
-
-    if (el.isGroup) {
-        return;
-    }
-
-    if (highlighted === 'layer') {
-        el.__zr && el.__zr.removeHover(el);
-    }
-    else {
-        let style = el.style;
-
-        let normalStl = el.__cachedNormalStl;
-        if (normalStl) {
-            rollbackDefaultTextStyle(style);
-            el.setStyle(normalStl);
-            applyDefaultTextStyle(style);
-        }
-        // `__cachedNormalZ2` will not be reset if calling `setElementHoverStyle`
-        // when `el` is on emphasis state. So here by comparing with 1, we try
-        // hard to make the bug case rare.
-        let normalZ2 = el.__cachedNormalZ2;
-        if (normalZ2 != null && el.z2 - normalZ2 === Z2_EMPHASIS_LIFT) {
-            el.z2 = normalZ2;
-        }
-    }
+function singleEnterNormal(el: Displayable) {
+    el.clearStates();
 }
 
 function traverseUpdate<T>(
@@ -537,27 +402,14 @@ function traverseUpdate<T>(
 }
 
 /**
- * Set hover style (namely "emphasis style") of element, based on the current
- * style of the given `el`.
- * This method should be called after all of the normal styles have been adopted
- * to the `el`. See the reason on `setHoverStyle`.
- *
- * @param el Should not be `zrender/container/Group`.
- * @param el.hoverStyle Can be set on el or its descendants,
- *        e.g., `el.hoverStyle = ...; graphic.setHoverStyle(el); `.
- *        Often used when item group has a label element and it's hoverStyle is different.
- * @param hoverStl The specified hover style.
- *        If set as `false`, disable the hover style.
- *        Similarly, The `el.hoverStyle` can alse be set
- *        as `false` to disable the hover style.
- *        Otherwise, use the default hover style if not provided.
+ * Set hover style (namely "emphasis style") of element.
+ * @param el Should not be `zrender/graphic/Group`.
  */
-export function setElementHoverStyle(el: Displayable, hoverStl: StyleProps) {
-    const extendedEl = el as ExtendedDisplayable;
-    // For performance consideration, it might be better to make the "hover style" only the
-    // difference properties from the "normal style", but not a entire copy of all styles.
-    hoverStl = extendedEl.__hoverStl = hoverStl !== false && (extendedEl.hoverStyle || hoverStl || {});
-    extendedEl.__hoverStlDirty = true;
+export function enableElementHoverEmphasis(el: Displayable, hoverStl?: ZRStyleProps) {
+    if (hoverStl) {
+        const emphasisState = el.ensureState('emphasis');
+        emphasisState.style = hoverStl;
+    }
 
     // FIXME
     // It is not completely right to save "normal"/"emphasis" flag on elements.
@@ -565,19 +417,9 @@ export function setElementHoverStyle(el: Displayable, hoverStl: StyleProps) {
     // (1) A highlighted elements are moved out of the view port and re-enter
     // again by dataZoom.
     // (2) call `setOption` and replace elements totally when they are highlighted.
-    if (extendedEl.__highlighted) {
-        // Consider the case:
-        // The styles of a highlighted `el` is being updated. The new "emphasis style"
-        // should be adapted to the `el`. Notice here new "normal styles" should have
-        // been set outside and the cached "normal style" is out of date.
-        extendedEl.__cachedNormalStl = null;
-        // Do not clear `__cachedNormalZ2` here, because setting `z2` is not a constraint
-        // of this method. In most cases, `z2` is not set and hover style should be able
-        // to rollback. Of course, that would bring bug, but only in a rare case, see
-        // `doSingleLeaveHover` for details.
-        singleEnterNormal(extendedEl);
-
-        singleEnterEmphasis(extendedEl);
+    if ((el as ExtendedDisplayable).__highlighted) {
+        singleEnterNormal(el);
+        singleEnterEmphasis(el);
     }
 }
 
@@ -610,39 +452,23 @@ function shouldSilent(el: ExtendedDisplayable, e: ElementEvent) {
 }
 
 /**
- * Set hover style (namely "emphasis style") of element,
- * based on the current style of the given `el`.
- *
- * (1)
- * **CONSTRAINTS** for this method:
- * <A> This method MUST be called after all of the normal styles having been adopted
- * to the `el`.
- * <B> The input `hoverStyle` (that is, "emphasis style") MUST be the subset of the
- * "normal style" having been set to the el.
- * <C> `color` MUST be one of the "normal styles" (because color might be lifted as
- * a default hover style).
+ * Enable the function that mouseover will trigger the emphasis state.
  *
- * The reason: this method treat the current style of the `el` as the "normal style"
- * and cache them when enter/update the "emphasis style". Consider the case: the `el`
- * is in "emphasis" state and `setOption`/`dispatchAction` trigger the style updating
- * logic, where the el should shift from the original emphasis style to the new
- * "emphasis style" and should be able to "downplay" back to the new "normal style".
+ * It will set hoverStyle to 'emphasis' state of each children displayables.
+ * If hoverStyle is not given, it will just ignore it and use the preset 'emphasis' state.
  *
- * Indeed, it is error-prone to make a interface has so many constraints, but I have
- * not found a better solution yet to fit the backward compatibility, performance and
- * the current programming style.
- *
- * (2)
+ * NOTICE
+ * (1)
  * Call the method for a "root" element once. Do not call it for each descendants.
  * If the descendants elemenets of a group has itself hover style different from the
  * root group, we can simply mount the style on `el.hoverStyle` for them, but should
  * not call this method for them.
  *
- * (3) These input parameters can be set directly on `el`:
+ * (2) These input parameters can be set directly on `el`:
  */
-export function setHoverStyle(el: Element, hoverStyle?: StyleProps) {
+export function enableHoverEmphasis(el: Element, hoverStyle?: ZRStyleProps) {
     setAsHighDownDispatcher(el, true);
-    traverseUpdate(el as ExtendedElement, setElementHoverStyle, hoverStyle);
+    traverseUpdate(el as ExtendedElement, enableElementHoverEmphasis, hoverStyle);
 }
 
 /**
@@ -744,24 +570,25 @@ interface SetLabelStyleOpt<LDI> extends TextCommonParams {
  * See more info in `setTextStyleCommon`.
  */
 export function setLabelStyle<LDI>(
-    normalStyle: StyleProps,
-    emphasisStyle: StyleProps,
+    hostEl: Element,
     normalModel: Model,
     emphasisModel: Model,
     opt?: SetLabelStyleOpt<LDI>,
-    normalSpecified?: StyleProps,
-    emphasisSpecified?: StyleProps
+    normalSpecified?: RichTextStyleProps,
+    emphasisSpecified?: RichTextStyleProps
+    // TODO specified position?
 ) {
     opt = opt || EMPTY_OBJ;
-    let labelFetcher = opt.labelFetcher;
-    let labelDataIndex = opt.labelDataIndex;
-    let labelDimIndex = opt.labelDimIndex;
+    const isSetOnRichText = hostEl instanceof RichText;
+    const labelFetcher = opt.labelFetcher;
+    const labelDataIndex = opt.labelDataIndex;
+    const labelDimIndex = opt.labelDimIndex;
 
     // This scenario, `label.normal.show = true; label.emphasis.show = false`,
     // is not supported util someone requests.
 
-    let showNormal = normalModel.getShallow('show');
-    let showEmphasis = emphasisModel.getShallow('show');
+    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,
@@ -785,44 +612,67 @@ export function setLabelStyle<LDI>(
         )
         : null;
 
+    let richText = isSetOnRichText ? hostEl as RichText : null;
     // Optimize: If style.text is null, text will not be drawn.
     if (normalStyleText != null || emphasisStyleText != null) {
+        if (!isSetOnRichText) {
+            // Reuse the previous
+            richText = hostEl.getTextContent();
+            if (!richText) {
+                richText = new RichText();
+                hostEl.setTextContent(richText);
+            }
+            richText.ignore = !normalStyleText;
+        }
+        const emphasisStyle: RichTextStyleProps = {};
+
+        const emphasisState = richText.ensureState('emphasis');
+        emphasisState.style = emphasisStyle;
+        emphasisState.ignore = !emphasisStyleText;
+
+        let textConfig: Element['textConfig'];
+        let emphasisTextLayout: Element['textConfig'];
+        if (!isSetOnRichText) {
+            textConfig = {};
+            emphasisTextLayout = emphasisState.textConfig = {};
+        }
         // Always set `textStyle` even if `normalStyle.text` is null, because default
         // values have to be set on `normalStyle`.
         // If we set default values on `emphasisStyle`, consider case:
         // Firstly, `setOption(... label: {normal: {text: null}, emphasis: {show: true}} ...);`
         // Secondly, `setOption(... label: {noraml: {show: true, text: 'abc', color: 'red'} ...);`
         // Then the 'red' will not work on emphasis.
-        setTextStyle(normalStyle, normalModel, normalSpecified, opt);
-        setTextStyle(emphasisStyle, emphasisModel, emphasisSpecified, opt, true);
-    }
+        setTextStyle(
+            richText.style,
+            textConfig,
+            normalModel,
+            normalSpecified,
+            opt
+        );
+        setTextStyle(
+            emphasisStyle,
+            emphasisTextLayout,
+            emphasisModel,
+            emphasisSpecified,
+            opt,
+            true
+        );
 
-    normalStyle.text = normalStyleText;
-    emphasisStyle.text = emphasisStyleText;
-}
+        if (!isSetOnRichText) {
+            hostEl.setTextConfig(textConfig);
+        }
 
-/**
- * Modify label style manually.
- * Only works after `setLabelStyle` and `setElementHoverStyle` called.
- */
-export function modifyLabelStyle(
-    el: Displayable,
-    normalStyleProps?: StyleProps,
-    emphasisStyleProps?: StyleProps
-) {
-    const extendedEl = el as ExtendedDisplayable;
-    let elStyle = extendedEl.style as StyleProps;
-    if (normalStyleProps) {
-        rollbackDefaultTextStyle(elStyle);
-        extendedEl.setStyle(normalStyleProps);
-        applyDefaultTextStyle(elStyle);
+        richText.style.text = normalStyleText;
+        richText.states.emphasis.style.text = emphasisStyleText;
+
+        richText.dirty();
     }
-    elStyle = extendedEl.__hoverStl;
-    if (emphasisStyleProps && elStyle) {
-        rollbackDefaultTextStyle(elStyle);
-        zrUtil.extend(elStyle, emphasisStyleProps);
-        applyDefaultTextStyle(elStyle);
+    else if (richText) {
+        // Not display rich text.
+        richText.ignore = true;
     }
+
+    hostEl.dirty();
 }
 
 /**
@@ -830,46 +680,20 @@ export function modifyLabelStyle(
  * See more info in `setTextStyleCommon`.
  */
 export function setTextStyle(
-    textStyle: StyleProps,
+    textStyle: RichTextStyleProps,
+    textConfig: Element['textConfig'],  // If textContent is attached on RichText.
     textStyleModel: Model,
-    specifiedTextStyle?: StyleProps,    // Can be overrided by settings in model.
+    specifiedTextStyle?: RichTextStyleProps,    // Can be overrided by settings in model.
     opt?: TextCommonParams,
     isEmphasis?: boolean
 ) {
-    setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis);
+    setTextStyleCommon(textStyle, textConfig, textStyleModel, opt, isEmphasis);
     specifiedTextStyle && zrUtil.extend(textStyle, specifiedTextStyle);
     // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);
 
     return textStyle;
 }
 
-/**
- * Set text option in the style.
- * See more info in `setTextStyleCommon`.
- * @deprecated
- * @param {Object} textStyle
- * @param {module:echarts/model/Model} labelModel
- * @param {string|boolean} defaultColor Default text color.
- *        If set as false, it will be processed as a emphasis style.
- */
-export function setText(
-    textStyle: StyleProps,
-    labelModel: Model,
-    defaultColor: string | false
-) {
-    let opt: TextCommonParams = {isRectText: true};
-    let isEmphasis;
-
-    if (defaultColor === false) {
-        isEmphasis = true;
-    }
-    else {
-        // Support setting color as 'auto' to get visual color.
-        opt.autoColor = defaultColor;
-    }
-    setTextStyleCommon(textStyle, labelModel, opt, isEmphasis);
-    // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);
-}
 
 /**
  * The uniform entry of set text style, that is, retrieve style definitions
@@ -880,8 +704,7 @@ export function setText(
  * default value can be adopted, merge would make the logic too complicated
  * to manage.)
  *
- * The `textStyle` object can either be a plain object or an instance of
- * `zrender/src/graphic/Style`, and either be the style of normal or emphasis.
+ * The `textStyle` object can either be the style of normal or emphasis.
  * After this mothod called, the `textStyle` object can then be used in
  * `el.setStyle(textStyle)` or `el.hoverStyle = textStyle`.
  *
@@ -889,7 +712,8 @@ export function setText(
  * See `applyDefaultTextStyle` `rollbackDefaultTextStyle` for more details.
  */
 function setTextStyleCommon(
-    textStyle: StyleProps,
+    textStyle: RichTextStyleProps,
+    textConfig: Element['textConfig'],  // If textContent is attached on RichText.
     textStyleModel: Model,
     opt?: TextCommonParams,
     isEmphasis?: boolean
@@ -897,29 +721,6 @@ function setTextStyleCommon(
     // Consider there will be abnormal when merge hover style to normal style if given default value.
     opt = opt || EMPTY_OBJ;
 
-    if (opt.isRectText) {
-        let textPosition;
-        if (opt.getTextPosition) {
-            textPosition = opt.getTextPosition(textStyleModel, isEmphasis);
-        }
-        else {
-            textPosition = textStyleModel.getShallow('position')
-                || (isEmphasis ? null : 'inside');
-            // 'outside' is not a valid zr textPostion value, but used
-            // in bar series, and magric type should be considered.
-            textPosition === 'outside' && (textPosition = 'top');
-        }
-
-        textStyle.textPosition = textPosition;
-        textStyle.textOffset = textStyleModel.getShallow('offset');
-        let labelRotate = textStyleModel.getShallow('rotate');
-        labelRotate != null && (labelRotate *= Math.PI / 180);
-        textStyle.textRotation = labelRotate;
-        textStyle.textDistance = zrUtil.retrieve2(
-            textStyleModel.getShallow('distance'), isEmphasis ? null : 5
-        );
-    }
-
     let ecModel = textStyleModel.ecModel;
     let globalTextStyle = ecModel && ecModel.option.textStyle;
 
@@ -938,7 +739,7 @@ function setTextStyleCommon(
     //     }
     // }
     let richItemNames = getRichItemNames(textStyleModel);
-    let richResult: Dictionary<StyleProps>;
+    let richResult: RichTextStyleProps['rich'];
     if (richItemNames) {
         richResult = {};
         for (let name in richItemNames) {
@@ -955,14 +756,43 @@ function setTextStyleCommon(
         }
     }
     textStyle.rich = richResult;
+    textStyle.overflow = textStyleModel.get('overflow');
 
     setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isEmphasis, true);
 
+    if (textConfig) {
+        let textPosition;
+        if (opt.getTextPosition) {
+            textPosition = opt.getTextPosition(textStyleModel, isEmphasis);
+        }
+        else {
+            textPosition = textStyleModel.getShallow('position')
+                || (isEmphasis ? null : 'inside');
+            // 'outside' is not a valid zr textPostion value, but used
+            // in bar series, and magric type should be considered.
+            textPosition === 'outside' && (textPosition = opt.defaultOutsidePosition || 'top');
+        }
+
+        textConfig.position = textPosition;
+        textConfig.offset = textStyleModel.getShallow('offset');
+        let labelRotate = textStyleModel.getShallow('rotate');
+        labelRotate != null && (labelRotate *= Math.PI / 180);
+        textConfig.rotation = labelRotate;
+        textConfig.distance = zrUtil.retrieve2(
+            textStyleModel.getShallow('distance'), isEmphasis ? null : 5
+        );
+
+        // fill and auto is determined by the color of path fill if it's not specified by developers.
+        textConfig.insideFill = textStyle.fill ? 'auto' : null;
+        // TODO: stroke set to autoColor. if label is inside?
+        textConfig.insideStroke = textStyle.stroke ? 'auto' : (opt.autoColor || null);
+    }
+
+
+    // TODO
     if (opt.forceRich && !opt.textStyle) {
         opt.textStyle = {};
     }
-
-    return textStyle;
 }
 
 // Consider case:
@@ -999,7 +829,7 @@ function getRichItemNames(textStyleModel: Model<LabelOption>) {
 }
 
 function setTokenTextStyle(
-    textStyle: StyleProps,
+    textStyle: RichTextStyleProps['rich'][string],
     textStyleModel: Model<LabelOption>,
     globalTextStyle: LabelOption,
     opt?: TextCommonParams,
@@ -1009,24 +839,19 @@ function setTokenTextStyle(
     // In merge mode, default value should not be given.
     globalTextStyle = !isEmphasis && globalTextStyle || EMPTY_OBJ;
 
-    textStyle.textFill = getAutoColor(textStyleModel.getShallow('color'), opt)
+    textStyle.fill = getAutoColor(textStyleModel.getShallow('color'), opt)
         || globalTextStyle.color;
-    textStyle.textStroke = getAutoColor(textStyleModel.getShallow('textBorderColor'), opt)
+    textStyle.stroke = getAutoColor(textStyleModel.getShallow('textBorderColor'), opt)
         || globalTextStyle.textBorderColor;
-    textStyle.textStrokeWidth = zrUtil.retrieve2(
+    textStyle.lineWidth = zrUtil.retrieve2(
         textStyleModel.getShallow('textBorderWidth'),
         globalTextStyle.textBorderWidth
     );
 
     if (!isEmphasis) {
-        if (isBlock) {
-            (textStyle as ExtendedStyleProps).insideRollbackOpt = opt;
-            applyDefaultTextStyle(textStyle);
-        }
-
         // Set default finally.
-        if (textStyle.textFill == null) {
-            textStyle.textFill = opt.autoColor;
+        if (textStyle.fill == null) {
+            textStyle.fill = opt.autoColor;
         }
     }
 
@@ -1038,26 +863,26 @@ function setTokenTextStyle(
     textStyle.fontSize = textStyleModel.getShallow('fontSize') || globalTextStyle.fontSize;
     textStyle.fontFamily = textStyleModel.getShallow('fontFamily') || globalTextStyle.fontFamily;
 
-    textStyle.textAlign = textStyleModel.getShallow('align');
-    textStyle.textVerticalAlign = textStyleModel.getShallow('verticalAlign')
+    textStyle.align = textStyleModel.getShallow('align');
+    textStyle.verticalAlign = textStyleModel.getShallow('verticalAlign')
         || textStyleModel.getShallow('baseline');
 
-    textStyle.textLineHeight = textStyleModel.getShallow('lineHeight');
-    textStyle.textWidth = textStyleModel.getShallow('width');
-    textStyle.textHeight = textStyleModel.getShallow('height');
+    textStyle.lineHeight = textStyleModel.getShallow('lineHeight');
+    textStyle.width = textStyleModel.getShallow('width');
+    textStyle.height = textStyleModel.getShallow('height');
     textStyle.textTag = textStyleModel.getShallow('tag');
 
     if (!isBlock || !opt.disableBox) {
-        textStyle.textBackgroundColor = getAutoColor(textStyleModel.getShallow('backgroundColor') as string, opt);
-        textStyle.textPadding = textStyleModel.getShallow('padding');
-        textStyle.textBorderColor = getAutoColor(textStyleModel.getShallow('borderColor'), opt);
-        textStyle.textBorderWidth = textStyleModel.getShallow('borderWidth');
-        textStyle.textBorderRadius = textStyleModel.getShallow('borderRadius');
-
-        textStyle.textBoxShadowColor = textStyleModel.getShallow('shadowColor');
-        textStyle.textBoxShadowBlur = textStyleModel.getShallow('shadowBlur');
-        textStyle.textBoxShadowOffsetX = textStyleModel.getShallow('shadowOffsetX');
-        textStyle.textBoxShadowOffsetY = textStyleModel.getShallow('shadowOffsetY');
+        textStyle.backgroundColor = getAutoColor(textStyleModel.getShallow('backgroundColor') as string, opt);
+        textStyle.padding = textStyleModel.getShallow('padding');
+        textStyle.borderColor = getAutoColor(textStyleModel.getShallow('borderColor'), opt);
+        textStyle.borderWidth = textStyleModel.getShallow('borderWidth');
+        textStyle.borderRadius = textStyleModel.getShallow('borderRadius');
+
+        textStyle.boxShadowColor = textStyleModel.getShallow('shadowColor');
+        textStyle.boxShadowBlur = textStyleModel.getShallow('shadowBlur');
+        textStyle.boxShadowOffsetX = textStyleModel.getShallow('shadowOffsetX');
+        textStyle.boxShadowOffsetY = textStyleModel.getShallow('shadowOffsetY');
     }
 
     textStyle.textShadowColor = textStyleModel.getShallow('textShadowColor')
@@ -1076,90 +901,6 @@ function getAutoColor(color: ColorString, opt?: {
     return color !== 'auto' ? color : (opt && opt.autoColor) ? opt.autoColor : null;
 }
 
-/**
- * Give some default value to the input `textStyle` object, based on the current settings
- * in this `textStyle` object.
- *
- * The Scenario:
- * when text position is `inside` and `textFill` is not specified, we show
- * text border by default for better view. But it should be considered that text position
- * might be changed when hovering or being emphasis, where the `insideRollback` is used to
- * restore the style.
- *
- * Usage (& NOTICE):
- * When a style object (eithor plain object or instance of `zrender/src/graphic/Style`) is
- * about to be modified on its text related properties, `rollbackDefaultTextStyle` should
- * be called before the modification and `applyDefaultTextStyle` should be called after that.
- * (For the case that all of the text related properties is reset, like `setTextStyleCommon`
- * does, `rollbackDefaultTextStyle` is not needed to be called).
- */
-function applyDefaultTextStyle(textStyle: StyleProps) {
-    let textPosition = textStyle.textPosition;
-    let opt = (textStyle as ExtendedStyleProps).insideRollbackOpt;
-    let insideRollback;
-
-    if (opt && textStyle.textFill == null) {
-        let autoColor = opt.autoColor;
-        let isRectText = opt.isRectText;
-        let useInsideStyle = opt.useInsideStyle;
-
-        let useInsideStyleCache = useInsideStyle !== false
-            && (useInsideStyle === true
-                || (isRectText
-                    && textPosition
-                    // textPosition can be [10, 30]
-                    && typeof textPosition === 'string'
-                    && textPosition.indexOf('inside') >= 0
-                )
-            );
-        let useAutoColorCache = !useInsideStyleCache && autoColor != null;
-
-        // All of the props declared in `CACHED_LABEL_STYLE_PROPERTIES` are to be cached.
-        if (useInsideStyleCache || useAutoColorCache) {
-            insideRollback = {
-                textFill: textStyle.textFill,
-                textStroke: textStyle.textStroke,
-                textStrokeWidth: textStyle.textStrokeWidth
-            };
-        }
-        if (useInsideStyleCache) {
-            textStyle.textFill = '#fff';
-            // Consider text with #fff overflow its container.
-            if (textStyle.textStroke == null) {
-                textStyle.textStroke = autoColor;
-                textStyle.textStrokeWidth == null && (textStyle.textStrokeWidth = 2);
-            }
-        }
-        if (useAutoColorCache) {
-            textStyle.textFill = autoColor;
-        }
-    }
-
-    // Always set `insideRollback`, so that the previous one can be cleared.
-    (textStyle as ExtendedStyleProps).insideRollback = insideRollback;
-}
-
-/**
- * Consider the case: in a scatter,
- * label: {
- *     normal: {position: 'inside'},
- *     emphasis: {position: 'top'}
- * }
- * In the normal state, the `textFill` will be set as '#fff' for pretty view (see
- * `applyDefaultTextStyle`), but when switching to emphasis state, the `textFill`
- * should be retured to 'autoColor', but not keep '#fff'.
- */
-function rollbackDefaultTextStyle(style: StyleProps) {
-    let insideRollback = (style as ExtendedStyleProps).insideRollback;
-    if (insideRollback) {
-        // Reset all of the props in `CACHED_LABEL_STYLE_PROPERTIES`.
-        style.textFill = insideRollback.textFill;
-        style.textStroke = insideRollback.textStroke;
-        style.textStrokeWidth = insideRollback.textStrokeWidth;
-        (style as ExtendedStyleProps).insideRollback = null;
-    }
-}
-
 export function getFont(opt: LabelOption, ecModel: GlobalModel) {
     let gTextStyleModel = ecModel && ecModel.getModel('textStyle');
     return zrUtil.trim([
@@ -1435,13 +1176,13 @@ export function createIcon(
     rect?: ZRRectLike
 ): SVGPath | ZImage {
     const innerOpts: DisplayableProps = zrUtil.extend({rectHover: true}, opt);
-    const style: StyleProps = innerOpts.style = {strokeNoScale: true};
+    const style: ZRStyleProps = innerOpts.style = {strokeNoScale: true};
     rect = rect || {x: -1, y: -1, width: 2, height: 2};
 
     if (iconStr) {
         return iconStr.indexOf('image://') === 0
             ? (
-                (style as ZImageStyleProps).image = iconStr.slice(8),
+                (style as ImageStyleProps).image = iconStr.slice(8),
                 zrUtil.defaults(style, rect),
                 new ZImage(innerOpts)
             )
@@ -1556,7 +1297,7 @@ registerShape('arc', Arc);
 export {
     Group,
     ZImage as Image,
-    Text,
+    RichText as Text,
     Circle,
     Sector,
     Ring,
diff --git a/src/util/layout.ts b/src/util/layout.ts
index dd566c4..d02a412 100644
--- a/src/util/layout.ts
+++ b/src/util/layout.ts
@@ -127,7 +127,7 @@ function boxLayout(
 /**
  * VBox or HBox layouting
  * @param {string} orient
- * @param {module:zrender/container/Group} group
+ * @param {module:zrender/graphic/Group} group
  * @param {number} gap
  * @param {number} [width=Infinity]
  * @param {number} [height=Infinity]
@@ -136,7 +136,7 @@ export let box = boxLayout;
 
 /**
  * VBox layouting
- * @param {module:zrender/container/Group} group
+ * @param {module:zrender/graphic/Group} group
  * @param {number} gap
  * @param {number} [width=Infinity]
  * @param {number} [height=Infinity]
@@ -145,7 +145,7 @@ export let vbox = zrUtil.curry(boxLayout, 'vertical');
 
 /**
  * HBox layouting
- * @param {module:zrender/container/Group} group
+ * @param {module:zrender/graphic/Group} group
  * @param {number} gap
  * @param {number} [width=Infinity]
  * @param {number} [height=Infinity]
diff --git a/src/util/shape/sausage.ts b/src/util/shape/sausage.ts
index fd4c780..1879c80 100644
--- a/src/util/shape/sausage.ts
+++ b/src/util/shape/sausage.ts
@@ -38,12 +38,16 @@ interface SausagePathProps extends PathProps {
     shape?: SausageShape
 }
 
-class SausagePath extends Path {
+class SausagePath extends Path<SausagePathProps> {
 
     type = 'sausage';
 
     constructor(opts?: SausagePathProps) {
-        super(opts, null, new SausageShape());
+        super(opts);
+    }
+
+    getDefaultShape() {
+        return new SausageShape();
     }
 
     buildPath(ctx: CanvasRenderingContext2D, shape: SausageShape) {
diff --git a/src/util/symbol.ts b/src/util/symbol.ts
index c30ea21..9d2d96b 100644
--- a/src/util/symbol.ts
+++ b/src/util/symbol.ts
@@ -280,10 +280,10 @@ const SymbolClz = graphic.Path.extend({
         height: 0
     },
 
-    calculateTextPosition: function (out, style, rect) {
-        let res = calculateTextPosition(out, style, rect);
+    calculateTextPosition(out, config, rect) {
+        let res = calculateTextPosition(out, config, rect);
         let shape = this.shape;
-        if (shape && shape.symbolType === 'pin' && style.textPosition === 'inside') {
+        if (shape && shape.symbolType === 'pin' && config.position === 'inside') {
             res.y = rect.y + rect.height * 0.4;
         }
         return res;
@@ -323,7 +323,7 @@ function symbolPathSetColor(this: ECSymbol, color: ZRColor, innerColor?: string)
             symbolStyle.fill && (symbolStyle.fill = color);
             symbolStyle.stroke && (symbolStyle.stroke = color);
         }
-        this.dirty(false);
+        this.markRedraw();
     }
 }
 
diff --git a/src/util/types.ts b/src/util/types.ts
index 0f9df29..ae0922d 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -25,8 +25,8 @@
  * be put in this file.
  */
 
-import Group from 'zrender/src/container/Group';
-import Element, {ElementEvent} from 'zrender/src/Element';
+import Group from 'zrender/src/graphic/Group';
+import Element, {ElementEvent, ElementTextConfig} from 'zrender/src/Element';
 import DataFormatMixin from '../model/mixin/dataFormat';
 import GlobalModel from '../model/Global';
 import ExtensionAPI from '../ExtensionAPI';
@@ -38,11 +38,14 @@ import { Dictionary, ImageLike, TextAlign, TextVerticalAlign } from 'zrender/src
 import { PatternObject } from 'zrender/src/graphic/Pattern';
 import Source from '../data/Source';
 import { TooltipMarker } from './format';
-import { easingType } from 'zrender/src/animation/easing';
+import { AnimationEasing } from 'zrender/src/animation/easing';
 import { LinearGradientObject } from 'zrender/src/graphic/LinearGradient';
 import { RadialGradientObject } from 'zrender/src/graphic/RadialGradient';
 import { RectLike } from 'zrender/src/core/BoundingRect';
-import ZRText from 'zrender/src/graphic/Text';
+import { TextStyleProps } from 'zrender/src/graphic/Text';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
+import { ImageStyleProps } from 'zrender/src/graphic/Image';
+import RichText, { RichTextStyleProps } from 'zrender/src/graphic/RichText';
 
 
 
@@ -66,7 +69,7 @@ export type ZRLineType = 'solid' | 'dotted' | 'dashed';
 export type ZRFontStyle = 'normal' | 'italic' | 'oblique';
 export type ZRFontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | number;
 
-export type ZREasing = easingType;
+export type ZREasing = AnimationEasing;
 
 export type ZRTextAlign = TextAlign;
 export type ZRTextVerticalAlign = TextVerticalAlign;
@@ -75,6 +78,8 @@ export type ZRElementEvent = ElementEvent;
 
 export type ZRRectLike = RectLike;
 
+export type ZRStyleProps = PathStyleProps | ImageStyleProps | TextStyleProps | RichTextStyleProps;
+
 // ComponentFullType can be:
 //     'xxx.yyy': means ComponentMainType.ComponentSubType.
 //     'xxx': means ComponentMainType.
@@ -562,7 +567,7 @@ export interface AnimationOptionMixin {
     /**
      * Easing of initialize animation
      */
-    animationEasing?: easingType
+    animationEasing?: AnimationEasing
     /**
      * Delay of initialize animation
      * Can be a callback to specify duration of each element
@@ -577,7 +582,7 @@ export interface AnimationOptionMixin {
     /**
      * Easing of data update animation.
      */
-    animationEasingUpdate?: easingType
+    animationEasingUpdate?: AnimationEasing
     /**
      * Delay of data update animation.
      * Can be a callback to specify duration of each element
@@ -748,11 +753,13 @@ export interface LabelOption extends TextCommonOption {
     show?: boolean
     // TODO: TYPE More specified 'inside', 'insideTop'....
     // x, y can be both percent string or number px.
-    position?: string | (number | string)[]
+    position?: ElementTextConfig['position']
     distance?: number
     rotate?: number
     offset?: number[]
 
+    overflow?: RichTextStyleProps['overflow']
+
     // TODO: TYPE not all label support formatter
     // formatter?: string | ((params: CallbackDataParams) => string)
 
@@ -762,14 +769,17 @@ export interface LabelOption extends TextCommonOption {
 /**
  * Option for labels on line, like markLine, lines
  */
-export interface LineLabelOption extends Omit<LabelOption, 'distance'> {
+export interface LineLabelOption extends Omit<LabelOption, 'distance' | 'position'> {
     position?: 'start'
         | 'middle'
         | 'end'
+        | 'insideStart'
         | 'insideStartTop'
         | 'insideStartBottom'
+        | 'insideMiddle'
         | 'insideMiddleTop'
         | 'insideMiddleBottom'
+        | 'insideEnd'
         | 'insideEndTop'
         | 'insideEndBottom'
         | 'insideMiddleBottom'
@@ -819,7 +829,7 @@ interface PositionCallback {
          * Will be HTMLDivElement when renderMode is html
          * Otherwise it's graphic.Text
          */
-        el: HTMLDivElement | ZRText | null,
+        el: HTMLDivElement | RichText | null,
         /**
          * Rect of hover elements. Will be null if not hovered
          */
diff --git a/src/view/Chart.ts b/src/view/Chart.ts
index 4728d99..f201b3c 100644
--- a/src/view/Chart.ts
+++ b/src/view/Chart.ts
@@ -18,7 +18,7 @@
 */
 
 import {each} from 'zrender/src/core/util';
-import Group from 'zrender/src/container/Group';
+import Group from 'zrender/src/graphic/Group';
 import * as componentUtil from '../util/component';
 import * as clazzUtil from '../util/clazz';
 import * as modelUtil from '../util/model';
diff --git a/src/view/Component.ts b/src/view/Component.ts
index 2f3f5c9..5fbdebd 100644
--- a/src/view/Component.ts
+++ b/src/view/Component.ts
@@ -17,7 +17,7 @@
 * under the License.
 */
 
-import Group from 'zrender/src/container/Group';
+import Group from 'zrender/src/graphic/Group';
 import * as componentUtil from '../util/component';
 import * as clazzUtil from '../util/clazz';
 import ComponentModel from '../model/Component';


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