You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2020/03/18 11:29:38 UTC

[incubator-echarts-website] branch asf-site updated: release 4.7.0

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

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


The following commit(s) were added to refs/heads/asf-site by this push:
     new ba8b696  release 4.7.0
ba8b696 is described below

commit ba8b6961538de38a4bdf469af33a0cac904205e1
Author: 100pah <su...@gmail.com>
AuthorDate: Wed Mar 18 18:48:20 2020 +0800

    release 4.7.0
---
 components/analytics.html                          |    2 +
 components/builder.html                            |   10 +-
 components/download.html                           |   10 +-
 en/404.html                                        |    4 +-
 en/api.html                                        |   10 +-
 en/builder.html                                    |   10 +-
 en/builder/echarts.html                            |    2 +-
 en/builder/src/echarts/chart/bar/BarSeries.js      |   15 +-
 en/builder/src/echarts/chart/bar/BarView.js        |  147 +-
 .../echarts/chart/candlestick/candlestickVisual.js |    2 +-
 .../src/echarts/chart/funnel/FunnelSeries.js       |    3 +-
 en/builder/src/echarts/chart/graph/GraphSeries.js  |    3 +-
 en/builder/src/echarts/chart/graph/GraphView.js    |    6 +-
 en/builder/src/echarts/chart/helper/EffectLine.js  |   24 +-
 en/builder/src/echarts/chart/helper/Line.js        |  127 +-
 .../echarts/chart/helper/createRenderPlanner.js    |    9 +-
 en/builder/src/echarts/chart/pie/PieView.js        |    2 +-
 en/builder/src/echarts/chart/radar/RadarSeries.js  |   20 +
 .../src/echarts/chart/sankey/SankeySeries.js       |   14 +-
 en/builder/src/echarts/chart/sankey/SankeyView.js  |   65 +-
 .../src/echarts/chart/sankey/sankeyLayout.js       |    7 +-
 en/builder/src/echarts/chart/tree/TreeSeries.js    |    3 +
 en/builder/src/echarts/chart/tree/TreeView.js      |  169 ++-
 .../src/echarts/chart/treemap/TreemapView.js       |   84 +-
 .../src/echarts/component/axis/AxisBuilder.js      |    2 +-
 .../echarts/component/axis/CartesianAxisView.js    |   87 +-
 .../src/echarts/component/axis/SingleAxisView.js   |   23 +-
 .../src/echarts/component/axis/axisSplitHelper.js  |  106 ++
 .../src/echarts/component/brush/BrushView.js       |    9 +-
 .../src/echarts/component/brush/visualEncoding.js  |    9 +-
 en/builder/src/echarts/component/helper/MapDraw.js |   14 +-
 .../component/legend/ScrollableLegendView.js       |   36 +-
 .../src/echarts/component/marker/MarkLineModel.js  |    3 +-
 .../src/echarts/component/marker/markerHelper.js   |   11 +-
 .../echarts/component/tooltip/TooltipContent.js    |   82 +-
 .../src/echarts/component/tooltip/TooltipView.js   |   13 +-
 en/builder/src/echarts/coord/View.js               |    9 +
 en/builder/src/echarts/coord/radar/Radar.js        |    8 +-
 en/builder/src/echarts/echarts.js                  |    4 +-
 en/builder/src/echarts/layout/barGrid.js           |   27 +-
 en/builder/src/echarts/layout/barPolar.js          |    5 -
 en/builder/src/echarts/scale/Interval.js           |    4 +-
 en/builder/src/echarts/stream/Scheduler.js         |   10 +-
 en/builder/src/echarts/util/graphic.js             |    4 +-
 en/builder/src/zrender/animation/Animation.js      |   10 +-
 en/builder/src/zrender/animation/Animator.js       |   10 +-
 .../builder/src/zrender/animation/track.js         |  624 +++------
 en/builder/src/zrender/core/dom.js                 |  130 ++
 en/builder/src/zrender/core/event.js               |   60 +-
 en/builder/src/zrender/core/fourPointsTransform.js |    2 +
 en/builder/src/zrender/dom/HandlerProxy.js         |    7 +-
 .../src/zrender/graphic/helper/subPixelOptimize.js |   45 +-
 en/builder/src/zrender/mixin/Animatable.js         |    2 +-
 en/builder/src/zrender/mixin/Draggable.js          |    8 +-
 en/builder/src/zrender/zrender.js                  |    2 +-
 en/changelog.html                                  |  101 +-
 en/cheat-sheet.html                                |    4 +-
 en/coding-standard.html                            |    4 +-
 en/committers.html                                 |    6 +-
 en/css/doc-bundle.css                              |    3 +
 en/css/doc-bundle.css.map                          |    2 +-
 en/dependencies.html                               |    4 +-
 en/dist/echarts-en.common.js                       |  984 +++++++++----
 en/dist/echarts-en.common.min.js                   |    2 +-
 en/dist/echarts-en.js                              | 1477 ++++++++++++++------
 en/dist/echarts-en.js.map                          |    2 +-
 en/dist/echarts-en.min.js                          |    2 +-
 en/dist/echarts-en.simple.js                       |  721 +++++++---
 en/dist/echarts-en.simple.min.js                   |    2 +-
 en/dist/echarts.common.js                          |  984 +++++++++----
 en/dist/echarts.common.min.js                      |    2 +-
 en/dist/echarts.js                                 | 1477 ++++++++++++++------
 en/dist/echarts.js.map                             |    2 +-
 en/dist/echarts.min.js                             |    2 +-
 en/dist/echarts.simple.js                          |  721 +++++++---
 en/dist/echarts.simple.min.js                      |    2 +-
 en/documents/api-parts/api.echartsInstance.json    |    2 +-
 en/documents/api.json                              |    2 +-
 en/documents/option-parts/option-outline.json      |    2 +-
 ...tion.series-tree.json => option.edgeShape.json} |   18 +-
 en/documents/option-parts/option.geo.json          |  161 +--
 en/documents/option-parts/option.json              |    1 +
 en/documents/option-parts/option.legend.json       |   55 +
 en/documents/option-parts/option.series-bar.json   |   87 +-
 .../option-parts/option.series-boxplot.json        |   64 +-
 .../option-parts/option.series-candlestick.json    |   66 +-
 .../option-parts/option.series-effectScatter.json  |   64 +-
 .../option-parts/option.series-funnel.json         |   44 +-
 en/documents/option-parts/option.series-gauge.json |   44 +-
 en/documents/option-parts/option.series-graph.json |   64 +-
 .../option-parts/option.series-heatmap.json        |   46 +-
 en/documents/option-parts/option.series-line.json  |   68 +-
 en/documents/option-parts/option.series-lines.json |   46 +-
 en/documents/option-parts/option.series-map.json   |  220 +--
 .../option-parts/option.series-parallel.json       |    2 +-
 .../option-parts/option.series-pictorialBar.json   |   64 +-
 en/documents/option-parts/option.series-pie.json   |   44 +-
 en/documents/option-parts/option.series-radar.json |    4 +-
 .../option-parts/option.series-sankey.json         |    3 +-
 .../option-parts/option.series-scatter.json        |   66 +-
 en/documents/option-parts/option.series-tree.json  |  478 +------
 en/documents/option-parts/option.title.json        |    8 +-
 en/documents/option-parts/option.toolbox.json      |    1 +
 en/documents/option-parts/option.tooltip.json      |    1 +
 en/documents/option.json                           |    2 +-
 en/documents/tutorial-parts/tutorial.json          |    2 +-
 en/documents/tutorial.json                         |    2 +-
 en/download-extension.html                         |    6 +-
 en/download-map.html                               |    4 +-
 en/download-theme.html                             |    4 +-
 en/download.html                                   |    6 +-
 en/faq.html                                        |    4 +-
 en/feature.html                                    |    4 +-
 en/index.html                                      |    6 +-
 en/js/doc-bundle.js                                |    2 +-
 en/js/download.js                                  |    2 +-
 en/maillist.html                                   |    4 +-
 en/option-gl.html                                  |   10 +-
 en/option.html                                     |   10 +-
 en/option3.html                                    |    4 +-
 en/tutorial.html                                   |   10 +-
 examples/data/area-pieces.js                       |   59 +
 examples/data/meta/area-pieces.md                  |    6 +
 examples/data/pie-doughnut.js                      |   20 +-
 examples/data/thumb-dark/area-pieces.jpg           |  Bin 0 -> 16282 bytes
 examples/data/thumb-dark/calendar-charts.jpg       |  Bin 19376 -> 19444 bytes
 .../data/thumb-dark/calendar-effectscatter.jpg     |  Bin 45016 -> 44998 bytes
 examples/data/thumb-dark/confidence-band.jpg       |  Bin 13105 -> 13166 bytes
 examples/data/thumb-dark/custom-hexbin.jpg         |  Bin 54253 -> 54215 bytes
 examples/data/thumb-dark/custom-profile.jpg        |  Bin 19717 -> 19320 bytes
 examples/data/thumb-dark/dynamic-data.jpg          |  Bin 24284 -> 23972 bytes
 examples/data/thumb-dark/effectScatter-bmap.jpg    |  Bin 14757 -> 14754 bytes
 examples/data/thumb-dark/effectScatter-map.jpg     |  Bin 18276 -> 18262 bytes
 examples/data/thumb-dark/geo-lines.jpg             |  Bin 13754 -> 13754 bytes
 examples/data/thumb-dark/geo-map-scatter.jpg       |  Bin 23543 -> 23543 bytes
 examples/data/thumb-dark/graph-force.jpg           |  Bin 24172 -> 24193 bytes
 examples/data/thumb-dark/graph-life-expectancy.jpg |  Bin 25305 -> 25279 bytes
 examples/data/thumb-dark/graph-webkit-dep.jpg      |  Bin 46107 -> 45004 bytes
 examples/data/thumb-dark/graph.jpg                 |  Bin 28114 -> 28118 bytes
 examples/data/thumb-dark/heatmap-bmap.jpg          |  Bin 27103 -> 27105 bytes
 examples/data/thumb-dark/heatmap-map.jpg           |  Bin 13997 -> 13987 bytes
 examples/data/thumb-dark/line-graphic.jpg          |  Bin 25325 -> 24281 bytes
 examples/data/thumb-dark/lines-bmap-bus.jpg        |  Bin 24055 -> 24053 bytes
 examples/data/thumb-dark/lines-bmap.jpg            |  Bin 10131 -> 10154 bytes
 examples/data/thumb-dark/map-bin.jpg               |  Bin 29967 -> 29984 bytes
 examples/data/thumb-dark/map-china-dataRange.jpg   |  Bin 27996 -> 27963 bytes
 examples/data/thumb-dark/map-china.jpg             |  Bin 23928 -> 23904 bytes
 examples/data/thumb-dark/map-labels.jpg            |  Bin 32746 -> 32703 bytes
 examples/data/thumb-dark/map-locate.jpg            |  Bin 23849 -> 23824 bytes
 examples/data/thumb-dark/map-polygon.jpg           |  Bin 31242 -> 31250 bytes
 examples/data/thumb-dark/mix-timeline-finance.jpg  |  Bin 35329 -> 35302 bytes
 examples/data/thumb-dark/pictorialBar-dotted.jpg   |  Bin 24979 -> 25065 bytes
 examples/data/thumb-dark/scatter-effect.jpg        |  Bin 22863 -> 22842 bytes
 .../scatter-life-expectancy-timeline.jpg           |  Bin 17866 -> 17873 bytes
 examples/data/thumb-dark/scatter-map-brush.jpg     |  Bin 33119 -> 33156 bytes
 examples/data/thumb-dark/scatter-map.jpg           |  Bin 18472 -> 18446 bytes
 examples/data/thumb-dark/scatter-nebula.jpg        |  Bin 35325 -> 35302 bytes
 .../data/thumb-dark/scatter-nutrients-matrix.jpg   |  Bin 28147 -> 28131 bytes
 examples/data/thumb-dark/scatter-nutrients.jpg     |  Bin 10806 -> 10807 bytes
 examples/data/thumb-dark/scatter-weibo.jpg         |  Bin 33773 -> 33794 bytes
 examples/data/thumb-dark/tree-polyline.jpg         |  Bin 34648 -> 29121 bytes
 examples/data/thumb-dark/treemap-obama.jpg         |  Bin 31202 -> 29855 bytes
 examples/data/thumb-light/area-pieces.jpg          |  Bin 0 -> 16661 bytes
 examples/data/thumb-light/calendar-charts.jpg      |  Bin 21153 -> 21208 bytes
 .../data/thumb-light/calendar-effectscatter.jpg    |  Bin 45001 -> 44984 bytes
 examples/data/thumb-light/confidence-band.jpg      |  Bin 12761 -> 12759 bytes
 examples/data/thumb-light/custom-hexbin.jpg        |  Bin 54253 -> 54215 bytes
 examples/data/thumb-light/custom-profile.jpg       |  Bin 17118 -> 16622 bytes
 examples/data/thumb-light/dynamic-data.jpg         |  Bin 22414 -> 22147 bytes
 examples/data/thumb-light/dynamic-data2.jpg        |  Bin 12519 -> 12440 bytes
 examples/data/thumb-light/effectScatter-bmap.jpg   |  Bin 30114 -> 30088 bytes
 examples/data/thumb-light/effectScatter-map.jpg    |  Bin 18284 -> 18308 bytes
 examples/data/thumb-light/geo-lines.jpg            |  Bin 13343 -> 13345 bytes
 examples/data/thumb-light/geo-map-scatter.jpg      |  Bin 19776 -> 19779 bytes
 examples/data/thumb-light/graph-force.jpg          |  Bin 22215 -> 22238 bytes
 .../data/thumb-light/graph-life-expectancy.jpg     |  Bin 16401 -> 16409 bytes
 examples/data/thumb-light/graph-webkit-dep.jpg     |  Bin 37852 -> 37838 bytes
 examples/data/thumb-light/graph.jpg                |  Bin 24529 -> 24502 bytes
 examples/data/thumb-light/heatmap-bmap.jpg         |  Bin 50726 -> 50499 bytes
 examples/data/thumb-light/heatmap-map.jpg          |  Bin 13997 -> 13987 bytes
 examples/data/thumb-light/line-graphic.jpg         |  Bin 24073 -> 22806 bytes
 examples/data/thumb-light/lines-bmap-bus.jpg       |  Bin 52845 -> 52867 bytes
 examples/data/thumb-light/lines-bmap.jpg           |  Bin 39357 -> 39366 bytes
 examples/data/thumb-light/map-bin.jpg              |  Bin 43081 -> 43084 bytes
 examples/data/thumb-light/map-china-dataRange.jpg  |  Bin 29152 -> 29153 bytes
 examples/data/thumb-light/map-china.jpg            |  Bin 23455 -> 23456 bytes
 examples/data/thumb-light/map-labels.jpg           |  Bin 31528 -> 31484 bytes
 examples/data/thumb-light/map-locate.jpg           |  Bin 23258 -> 23235 bytes
 examples/data/thumb-light/map-polygon.jpg          |  Bin 31583 -> 31598 bytes
 examples/data/thumb-light/mix-timeline-finance.jpg |  Bin 31905 -> 31906 bytes
 examples/data/thumb-light/pictorialBar-dotted.jpg  |  Bin 23741 -> 23827 bytes
 examples/data/thumb-light/scatter-effect.jpg       |  Bin 16865 -> 16875 bytes
 .../scatter-life-expectancy-timeline.jpg           |  Bin 17444 -> 17454 bytes
 examples/data/thumb-light/scatter-map-brush.jpg    |  Bin 32916 -> 32954 bytes
 examples/data/thumb-light/scatter-map.jpg          |  Bin 18457 -> 18430 bytes
 .../data/thumb-light/scatter-nutrients-matrix.jpg  |  Bin 27131 -> 27137 bytes
 examples/data/thumb-light/scatter-nutrients.jpg    |  Bin 10822 -> 10824 bytes
 examples/data/thumb-light/scatter-weibo.jpg        |  Bin 33773 -> 33794 bytes
 examples/data/thumb-light/tree-polyline.jpg        |  Bin 29218 -> 26505 bytes
 examples/data/thumb-light/treemap-obama.jpg        |  Bin 32324 -> 32227 bytes
 examples/data/thumb/area-pieces.jpg                |  Bin 0 -> 17211 bytes
 examples/data/thumb/calendar-charts.jpg            |  Bin 21225 -> 21240 bytes
 examples/data/thumb/calendar-effectscatter.jpg     |  Bin 45034 -> 44983 bytes
 examples/data/thumb/confidence-band.jpg            |  Bin 12761 -> 12761 bytes
 examples/data/thumb/custom-hexbin.jpg              |  Bin 54253 -> 54215 bytes
 examples/data/thumb/custom-profile.jpg             |  Bin 16916 -> 17136 bytes
 examples/data/thumb/dynamic-data.jpg               |  Bin 22941 -> 22683 bytes
 examples/data/thumb/effectScatter-bmap.jpg         |  Bin 30070 -> 30086 bytes
 examples/data/thumb/effectScatter-map.jpg          |  Bin 18289 -> 18329 bytes
 examples/data/thumb/geo-lines.jpg                  |  Bin 13335 -> 13355 bytes
 examples/data/thumb/geo-map-scatter.jpg            |  Bin 19776 -> 19779 bytes
 examples/data/thumb/graph-force.jpg                |  Bin 22757 -> 22631 bytes
 examples/data/thumb/graph-life-expectancy.jpg      |  Bin 16429 -> 16425 bytes
 examples/data/thumb/graph-webkit-dep.jpg           |  Bin 39378 -> 41112 bytes
 examples/data/thumb/graph.jpg                      |  Bin 26535 -> 26528 bytes
 examples/data/thumb/heatmap-bmap.jpg               |  Bin 50726 -> 50499 bytes
 examples/data/thumb/heatmap-map.jpg                |  Bin 13997 -> 13987 bytes
 examples/data/thumb/line-graphic.jpg               |  Bin 24122 -> 22806 bytes
 examples/data/thumb/lines-bmap-bus.jpg             |  Bin 50623 -> 52867 bytes
 examples/data/thumb/lines-bmap.jpg                 |  Bin 39357 -> 39366 bytes
 examples/data/thumb/map-bin.jpg                    |  Bin 43081 -> 43084 bytes
 examples/data/thumb/map-china-dataRange.jpg        |  Bin 29178 -> 29172 bytes
 examples/data/thumb/map-china.jpg                  |  Bin 23455 -> 23456 bytes
 examples/data/thumb/map-labels.jpg                 |  Bin 31528 -> 31484 bytes
 examples/data/thumb/map-locate.jpg                 |  Bin 23258 -> 23235 bytes
 examples/data/thumb/map-polygon.jpg                |  Bin 31454 -> 31467 bytes
 examples/data/thumb/mix-timeline-finance.jpg       |  Bin 31733 -> 31671 bytes
 examples/data/thumb/pictorialBar-dotted.jpg        |  Bin 24180 -> 24257 bytes
 examples/data/thumb/scatter-effect.jpg             |  Bin 21259 -> 21245 bytes
 .../thumb/scatter-life-expectancy-timeline.jpg     |  Bin 17452 -> 17463 bytes
 examples/data/thumb/scatter-map-brush.jpg          |  Bin 32916 -> 32954 bytes
 examples/data/thumb/scatter-map.jpg                |  Bin 18434 -> 18402 bytes
 examples/data/thumb/scatter-nebula.jpg             |  Bin 33219 -> 33232 bytes
 examples/data/thumb/scatter-nutrients-matrix.jpg   |  Bin 27147 -> 27149 bytes
 examples/data/thumb/scatter-nutrients.jpg          |  Bin 10822 -> 10820 bytes
 examples/data/thumb/scatter-weibo.jpg              |  Bin 33773 -> 33737 bytes
 examples/data/thumb/tree-polyline.jpg              |  Bin 29218 -> 26505 bytes
 examples/data/thumb/treemap-obama.jpg              |  Bin 32700 -> 32605 bytes
 examples/en/editor.html                            |    6 +-
 examples/en/index.html                             |    6 +-
 examples/en/view.html                              |    6 +-
 examples/javascripts/chart-list-data.js            |    2 +-
 examples/vendors/echarts/echarts.js                | 1477 ++++++++++++++------
 examples/vendors/echarts/echarts.min.js            |    2 +-
 examples/vendors/echarts/map/js/china.js           |    2 +-
 .../vendors/echarts/map/js/province/chongqing.js   |    2 +-
 .../vendors/echarts/map/js/province/tianjin.js     |   29 +-
 examples/vendors/echarts/map/json/china.json       |    2 +-
 .../echarts/map/json/province/chongqing.json       |    2 +-
 examples/zh/editor.html                            |    6 +-
 examples/zh/index.html                             |    6 +-
 examples/zh/view.html                              |    6 +-
 layouts/basic.html                                 |    4 +-
 layouts/doc-old.html                               |   10 +-
 layouts/doc.html                                   |   10 +-
 zh/404.html                                        |    4 +-
 zh/api.html                                        |   10 +-
 zh/builder.html                                    |   10 +-
 zh/builder/echarts.html                            |    2 +-
 zh/builder/src/echarts/chart/bar/BarSeries.js      |   15 +-
 zh/builder/src/echarts/chart/bar/BarView.js        |  147 +-
 .../echarts/chart/candlestick/candlestickVisual.js |    2 +-
 .../src/echarts/chart/funnel/FunnelSeries.js       |    3 +-
 zh/builder/src/echarts/chart/graph/GraphSeries.js  |    3 +-
 zh/builder/src/echarts/chart/graph/GraphView.js    |    6 +-
 zh/builder/src/echarts/chart/helper/EffectLine.js  |   24 +-
 zh/builder/src/echarts/chart/helper/Line.js        |  127 +-
 .../echarts/chart/helper/createRenderPlanner.js    |    9 +-
 zh/builder/src/echarts/chart/pie/PieView.js        |    2 +-
 zh/builder/src/echarts/chart/radar/RadarSeries.js  |   20 +
 .../src/echarts/chart/sankey/SankeySeries.js       |   14 +-
 zh/builder/src/echarts/chart/sankey/SankeyView.js  |   65 +-
 .../src/echarts/chart/sankey/sankeyLayout.js       |    7 +-
 zh/builder/src/echarts/chart/tree/TreeSeries.js    |    3 +
 zh/builder/src/echarts/chart/tree/TreeView.js      |  169 ++-
 .../src/echarts/chart/treemap/TreemapView.js       |   84 +-
 .../src/echarts/component/axis/AxisBuilder.js      |    2 +-
 .../echarts/component/axis/CartesianAxisView.js    |   87 +-
 .../src/echarts/component/axis/SingleAxisView.js   |   23 +-
 .../src/echarts/component/axis/axisSplitHelper.js  |  106 ++
 .../src/echarts/component/brush/BrushView.js       |    9 +-
 .../src/echarts/component/brush/visualEncoding.js  |    9 +-
 zh/builder/src/echarts/component/helper/MapDraw.js |   14 +-
 .../component/legend/ScrollableLegendView.js       |   36 +-
 .../src/echarts/component/marker/MarkLineModel.js  |    3 +-
 .../src/echarts/component/marker/markerHelper.js   |   11 +-
 .../echarts/component/tooltip/TooltipContent.js    |   82 +-
 .../src/echarts/component/tooltip/TooltipView.js   |   13 +-
 zh/builder/src/echarts/coord/View.js               |    9 +
 zh/builder/src/echarts/coord/radar/Radar.js        |    8 +-
 zh/builder/src/echarts/echarts.js                  |    4 +-
 zh/builder/src/echarts/layout/barGrid.js           |   27 +-
 zh/builder/src/echarts/layout/barPolar.js          |    5 -
 zh/builder/src/echarts/scale/Interval.js           |    4 +-
 zh/builder/src/echarts/stream/Scheduler.js         |   10 +-
 zh/builder/src/echarts/util/graphic.js             |    4 +-
 zh/builder/src/zrender/animation/Animation.js      |   10 +-
 zh/builder/src/zrender/animation/Animator.js       |   10 +-
 .../zrender/animation/{Animator.js => track.js}    |  624 +++------
 zh/builder/src/zrender/core/dom.js                 |  130 ++
 zh/builder/src/zrender/core/event.js               |   60 +-
 zh/builder/src/zrender/core/fourPointsTransform.js |    2 +
 zh/builder/src/zrender/dom/HandlerProxy.js         |    7 +-
 .../src/zrender/graphic/helper/subPixelOptimize.js |   45 +-
 zh/builder/src/zrender/mixin/Animatable.js         |    2 +-
 zh/builder/src/zrender/mixin/Draggable.js          |    8 +-
 zh/builder/src/zrender/zrender.js                  |    2 +-
 zh/builder3.html                                   |    4 +-
 zh/changelog.html                                  |   38 +-
 zh/cheat-sheet.html                                |    4 +-
 zh/coding-standard.html                            |    4 +-
 zh/committers.html                                 |    6 +-
 zh/css/doc-bundle.css                              |    3 +
 zh/css/doc-bundle.css.map                          |    2 +-
 zh/demo.html                                       |    4 +-
 zh/dependencies.html                               |    4 +-
 zh/dist/echarts-en.common.js                       |  984 +++++++++----
 zh/dist/echarts-en.common.min.js                   |    2 +-
 zh/dist/echarts-en.js                              | 1477 ++++++++++++++------
 zh/dist/echarts-en.js.map                          |    2 +-
 zh/dist/echarts-en.min.js                          |    2 +-
 zh/dist/echarts-en.simple.js                       |  721 +++++++---
 zh/dist/echarts-en.simple.min.js                   |    2 +-
 zh/dist/echarts.common.js                          |  984 +++++++++----
 zh/dist/echarts.common.min.js                      |    2 +-
 zh/dist/echarts.js                                 | 1477 ++++++++++++++------
 zh/dist/echarts.js.map                             |    2 +-
 zh/dist/echarts.min.js                             |    2 +-
 zh/dist/echarts.simple.js                          |  721 +++++++---
 zh/dist/echarts.simple.min.js                      |    2 +-
 zh/documents/api-parts/api.echartsInstance.json    |    2 +-
 zh/documents/api.json                              |    2 +-
 zh/documents/option-parts/option-outline.json      |    2 +-
 .../option-parts/option.dataZoom-inside.json       |    2 +-
 .../option-parts/option.dataZoom-slider.json       |    2 +-
 zh/documents/option-parts/option.geo.json          |    8 +-
 zh/documents/option-parts/option.grid.json         |    4 +-
 zh/documents/option-parts/option.json              |    6 +-
 zh/documents/option-parts/option.legend.json       |   57 +-
 zh/documents/option-parts/option.polar.json        |    4 +-
 zh/documents/option-parts/option.series-bar.json   |   70 +-
 .../option-parts/option.series-boxplot.json        |   54 +-
 .../option-parts/option.series-candlestick.json    |   54 +-
 .../option-parts/option.series-custom.json         |    4 +-
 .../option-parts/option.series-effectScatter.json  |   56 +-
 .../option-parts/option.series-funnel.json         |   36 +-
 zh/documents/option-parts/option.series-gauge.json |   36 +-
 zh/documents/option-parts/option.series-graph.json |   56 +-
 .../option-parts/option.series-heatmap.json        |   32 +-
 zh/documents/option-parts/option.series-line.json  |   56 +-
 zh/documents/option-parts/option.series-lines.json |   36 +-
 zh/documents/option-parts/option.series-map.json   |   56 +-
 .../option-parts/option.series-parallel.json       |    4 +-
 .../option-parts/option.series-pictorialBar.json   |   64 +-
 zh/documents/option-parts/option.series-pie.json   |   36 +-
 zh/documents/option-parts/option.series-radar.json |    4 +-
 .../option-parts/option.series-sankey.json         |    7 +-
 .../option-parts/option.series-scatter.json        |   56 +-
 .../option-parts/option.series-sunburst.json       |    4 +-
 .../option-parts/option.series-themeRiver.json     |    4 +-
 zh/documents/option-parts/option.series-tree.json  |    6 +-
 .../option-parts/option.series-treemap.json        |  104 +-
 zh/documents/option-parts/option.singleAxis.json   |    4 +-
 zh/documents/option-parts/option.title.json        |    8 +-
 zh/documents/option-parts/option.toolbox.json      |    1 +
 zh/documents/option-parts/option.tooltip.json      |    5 +-
 zh/documents/option.json                           |    2 +-
 zh/documents/tutorial-parts/tutorial.json          |    4 +-
 zh/documents/tutorial.json                         |    2 +-
 zh/download-extension.html                         |    6 +-
 zh/download-map.html                               |    4 +-
 zh/download-theme.html                             |    4 +-
 zh/download.html                                   |   10 +-
 zh/download3.html                                  |    6 +-
 zh/examples.html                                   |    4 +-
 zh/faq.html                                        |    4 +-
 zh/feature.html                                    |    4 +-
 zh/index.html                                      |    6 +-
 zh/js/doc-bundle.js                                |    2 +-
 zh/js/download.js                                  |    2 +-
 zh/maillist.html                                   |    4 +-
 zh/option-gl.html                                  |   10 +-
 zh/option.html                                     |   10 +-
 zh/option3.html                                    |   10 +-
 zh/spreadsheet.html                                |   10 +-
 zh/tutorial.html                                   |   10 +-
 386 files changed, 14366 insertions(+), 7319 deletions(-)

diff --git a/components/analytics.html b/components/analytics.html
index 067b966..eff131c 100644
--- a/components/analytics.html
+++ b/components/analytics.html
@@ -1,7 +1,9 @@
 <!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/components/builder.html b/components/builder.html
index 84e3d9c..e0bc43b 100644
--- a/components/builder.html
+++ b/components/builder.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -7,7 +7,7 @@
     document.head.insertBefore(el, document.getElementById('font-hack'));
 }
 </script><title>ECharts 在线构建</title><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[if lte IE 8]><body class="lower-ie"><div id="lowie-main"><img src="./images/forie.png" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts 是一个正在由 Apache 孵化器赞助的 Apache 开源基金会孵化的项目。</p><p>我们正在处理将本站跳转到 <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a> 的迁移工作。您可以现在就前往我们的 Apache 官网。</p></div><a href="https://echarts.apache.org" target="_blank" onclick="logApache()" class="btn"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close-btn">x</ [...]
+<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts 是一个正在由 Apache 孵化器赞助的 Apache 开源基金会孵化的项目。</p><p>我们正在处理将本站跳转到 <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a> 的迁移工作。您可以现在就前往我们的 Apache 官网。</p></div><a href="https://echarts.apache.org" target="_blank" onclick="logApache()" class="btn"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close-btn">x</ [...]
     $('#charts input, #components input, #coords input').each(function () {
         $(this).attr('checked', $(this).parent().hasClass('checked'));
     });
@@ -52,20 +52,22 @@ $("#build").click(function () {
     }
 
     parameters += '&version=3'
-        + '&versionCode=4.6.0';
+        + '&versionCode=4.7.0';
 
     var email = $('#email').val();
     var log = parameters;
     if (email) {
         log += '&email=' + email;
     }
-    _hmt.push(['_trackEvent', 'builder', 'build', '4.6.0', log]);
+    _hmt.push(['_trackEvent', 'builder', 'build', '4.7.0', log]);
 
     window.open('builder/echarts.html?' + parameters);
 });</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/components/download.html b/components/download.html
index 96d1c21..53b6303 100644
--- a/components/download.html
+++ b/components/download.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -7,7 +7,7 @@
     document.head.insertBefore(el, document.getElementById('font-hack'));
 }
 </script><title>下载 - Apache ECharts (incubating)</title><script src="vendors/sweetalert.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[if lte IE 8]><body class="lower-ie"><div id="lowie-main"><img src="./images/forie.png" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts 是一个正在由 Apache 孵化器赞助的 Apache 开源基金会孵化的项目。</p><p>我们正在处理将本站跳转到 <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a> 的迁移工作。您可以现在就前往我们的 Apache 官网。</p></div><a href="https://echarts.apache.org" target="_blank" onclick="logApache()" class="btn"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close-btn">x</ [...]
+<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts 是一个正在由 Apache 孵化器赞助的 Apache 开源基金会孵化的项目。</p><p>我们正在处理将本站跳转到 <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a> 的迁移工作。您可以现在就前往我们的 Apache 官网。</p></div><a href="https://echarts.apache.org" target="_blank" onclick="logApache()" class="btn"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close-btn">x</ [...]
 
 //- $('.download-echarts').click(function (e) {
 //-     var el = document.createElement('div');
@@ -23,14 +23,16 @@
 //-         title: 'Notice',
 //-         content: el
 //-     });
-//-     _hmt.push(['_trackEvent', 'download', 'download', '4.6.0']);
+//-     _hmt.push(['_trackEvent', 'download', 'download', '4.7.0']);
 //- });
 //- $('.download-theme').click(function () {
-//-     _hmt.push(['_trackEvent', 'download', 'download-theme', '4.6.0']);
+//-     _hmt.push(['_trackEvent', 'download', 'download-theme', '4.7.0']);
 //- });</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/404.html b/en/404.html
index 73fc256..14bb944 100644
--- a/en/404.html
+++ b/en/404.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -10,7 +10,9 @@
 <!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts 是一个正在由 Apache 孵化器赞助的 Apache 开源基金会孵化的项目。</p><p>我们正在处理将本站跳转到 <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a> 的迁移工作。您可以现在就前往我们的 Apache 官网。</p></div><a href="https://echarts.apache.org" target="_blank" onclick="logApache()" class="btn"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close-btn">x</ [...]
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/api.html b/en/api.html
index e4bf8fc..37f9390 100644
--- a/en/api.html
+++ b/en/api.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -9,17 +9,19 @@
 </script><title>ECharts Documentation</title><style>html, body {
     /* position: sticky should not have overflow parents.*/
     overflow-x: hidden;
-}</style><link rel="stylesheet" href="css/doc-bundle.css?_v_=1578303605813"><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[if lte IE 8]><body class="lower-ie"><div id="lowie-main"><img src="./images/forie.png" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
+}</style><link rel="stylesheet" href="css/doc-bundle.css?_v_=1584528451173"><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[if lte IE 8]><body class="lower-ie"><div id="lowie-main"><img src="./images/forie.png" alt="ie tip"></div></body><![endif]-->
+<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
     baseUrl: 'documents/api-parts',
     docType: 'api',
     locale: 'en'
 };</script><script type="text/javascript">document.getElementById('nav-doc').className = 'active';
-window.globalArgsExtra.version = '1578303605813';
+window.globalArgsExtra.version = '1584528451173';
 echartsDoc.init('#ec-doc-main', window.globalArgsExtra);</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/builder.html b/en/builder.html
index 9a43d11..7717dcd 100644
--- a/en/builder.html
+++ b/en/builder.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -7,7 +7,7 @@
     document.head.insertBefore(el, document.getElementById('font-hack'));
 }
 </script><title>ECharts Online Builder</title><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[if lte IE 8]><body class="lower-ie"><div id="lowie-main"><img src="./images/forie.png" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
+<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
     $('#charts input, #components input, #coords input').each(function () {
         $(this).attr('checked', $(this).parent().hasClass('checked'));
     });
@@ -52,20 +52,22 @@ $("#build").click(function () {
     }
 
     parameters += '&version=4'
-        + '&versionCode=4.6.0';
+        + '&versionCode=4.7.0';
 
     var email = $('#email').val();
     var log = parameters;
     if (email) {
         log += '&email=' + email;
     }
-    _hmt.push(['_trackEvent', 'builder', 'build', '4.6.0', log]);
+    _hmt.push(['_trackEvent', 'builder', 'build', '4.7.0', log]);
 
     window.open('builder/echarts.html?' + parameters);
 });</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/builder/echarts.html b/en/builder/echarts.html
index afb2379..38efe3b 100644
--- a/en/builder/echarts.html
+++ b/en/builder/echarts.html
@@ -56,7 +56,7 @@
                 'esprima': 'lib/esprima',
                 'estraverse': 'lib/estraverse'
             },
-            urlArgs: 'v=1578303605813'
+            urlArgs: 'v=1584528451173'
         });
 
         require(['build']);
diff --git a/en/builder/src/echarts/chart/bar/BarSeries.js b/en/builder/src/echarts/chart/bar/BarSeries.js
index df6f6aa..12ece04 100644
--- a/en/builder/src/echarts/chart/bar/BarSeries.js
+++ b/en/builder/src/echarts/chart/bar/BarSeries.js
@@ -50,6 +50,19 @@ export default BaseBarSeries.extend({
     clip: true,
     // If use caps on two sides of bars
     // Only available on tangential polar bar
-    roundCap: false
+    roundCap: false,
+    showBackground: false,
+    backgroundStyle: {
+      color: 'rgba(180, 180, 180, 0.2)',
+      borderColor: null,
+      borderWidth: 0,
+      borderType: 'solid',
+      borderRadius: 0,
+      shadowBlur: 0,
+      shadowColor: null,
+      shadowOffsetX: 0,
+      shadowOffsetY: 0,
+      opacity: 1
+    }
   }
 });
\ No newline at end of file
diff --git a/en/builder/src/echarts/chart/bar/BarView.js b/en/builder/src/echarts/chart/bar/BarView.js
index 96d8167..7631f62 100644
--- a/en/builder/src/echarts/chart/bar/BarView.js
+++ b/en/builder/src/echarts/chart/bar/BarView.js
@@ -24,6 +24,7 @@ import { setLabel } from './helper';
 import Model from '../../model/Model';
 import barItemStyle from './barItemStyle';
 import Path from 'zrender/src/graphic/Path';
+import Group from 'zrender/src/container/Group';
 import { throttle } from '../../util/throttle';
 import { createClipPath } from '../helper/createClipPathFromCoordSys';
 import Sausage from '../../util/shape/sausage';
@@ -110,14 +111,25 @@ export default echarts.extendChartView({
     // And don't want the label are clipped.
 
     var roundCap = seriesModel.get('roundCap', true);
+    var drawBackground = seriesModel.get('showBackground', true);
+    var backgroundModel = seriesModel.getModel('backgroundStyle');
+    var bgEls = [];
+    var oldBgEls = this._backgroundEls || [];
     data.diff(oldData).add(function (dataIndex) {
+      var itemModel = data.getItemModel(dataIndex);
+      var layout = getLayout[coord.type](data, dataIndex, itemModel);
+
+      if (drawBackground) {
+        var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, layout);
+        bgEl.useStyle(backgroundModel.getBarItemStyle());
+        bgEls[dataIndex] = bgEl;
+      } // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
+
+
       if (!data.hasValue(dataIndex)) {
         return;
       }
 
-      var itemModel = data.getItemModel(dataIndex);
-      var layout = getLayout[coord.type](data, dataIndex, itemModel);
-
       if (needsClip) {
         // Clip will modify the layout params.
         // And return a boolean to determine if the shape are fully clipped.
@@ -134,6 +146,19 @@ export default echarts.extendChartView({
       group.add(el);
       updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar');
     }).update(function (newIndex, oldIndex) {
+      var itemModel = data.getItemModel(newIndex);
+      var layout = getLayout[coord.type](data, newIndex, itemModel);
+
+      if (drawBackground) {
+        var bgEl = oldBgEls[oldIndex];
+        bgEl.useStyle(backgroundModel.getBarItemStyle());
+        bgEls[newIndex] = bgEl;
+        var shape = createBackgroundShape(isHorizontalOrRadial, layout, coord);
+        graphic.updateProps(bgEl, {
+          shape: shape
+        }, animationModel, newIndex);
+      }
+
       var el = oldData.getItemGraphicEl(oldIndex);
 
       if (!data.hasValue(newIndex)) {
@@ -141,9 +166,6 @@ export default echarts.extendChartView({
         return;
       }
 
-      var itemModel = data.getItemModel(newIndex);
-      var layout = getLayout[coord.type](data, newIndex, itemModel);
-
       if (needsClip) {
         var isClipped = clip[coord.type](coordSysClipArea, layout);
 
@@ -174,6 +196,15 @@ export default echarts.extendChartView({
         el && removeSector(dataIndex, animationModel, el);
       }
     }).execute();
+    var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group());
+    bgGroup.removeAll();
+
+    for (var i = 0; i < bgEls.length; ++i) {
+      bgGroup.add(bgEls[i]);
+    }
+
+    group.add(bgGroup);
+    this._backgroundEls = bgEls;
     this._data = data;
   },
   _renderLarge: function (seriesModel, ecModel, api) {
@@ -190,6 +221,8 @@ export default echarts.extendChartView({
     }
   },
   _incrementalRenderLarge: function (params, seriesModel) {
+    this._removeBackground();
+
     createLarge(seriesModel, this.group, true);
   },
   dispose: zrUtil.noop,
@@ -201,6 +234,9 @@ export default echarts.extendChartView({
     var data = this._data;
 
     if (ecModel && ecModel.get('animation') && data && !this._isLargeDraw) {
+      this._removeBackground();
+
+      this._backgroundEls = [];
       data.eachItemGraphicEl(function (el) {
         if (el.type === 'sector') {
           removeSector(el.dataIndex, ecModel, el);
@@ -213,6 +249,10 @@ export default echarts.extendChartView({
     }
 
     this._data = null;
+  },
+  _removeBackground: function () {
+    this.group.remove(this._backgroundGroup);
+    this._backgroundGroup = null;
   }
 });
 var mathMax = Math.max;
@@ -261,8 +301,10 @@ var clip = {
 var elementCreator = {
   cartesian2d: function (dataIndex, layout, isHorizontal, animationModel, isUpdate) {
     var rect = new graphic.Rect({
-      shape: zrUtil.extend({}, layout)
-    }); // Animation
+      shape: zrUtil.extend({}, layout),
+      z2: 1
+    });
+    rect.name = 'item'; // Animation
 
     if (animationModel) {
       var rectShape = rect.shape;
@@ -287,8 +329,10 @@ var elementCreator = {
     var sector = new ShapeClass({
       shape: zrUtil.defaults({
         clockwise: clockwise
-      }, layout)
-    }); // Animation
+      }, layout),
+      z2: 1
+    });
+    sector.name = 'item'; // Animation
 
     if (animationModel) {
       var sectorShape = sector.shape;
@@ -393,8 +437,11 @@ function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHori
 
 
 function getLineWidth(itemModel, rawLayout) {
-  var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
-  return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height));
+  var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0; // width or height may be NaN for empty data
+
+  var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width);
+  var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height);
+  return Math.min(lineWidth, width, height);
 }
 
 var LargePath = Path.extend({
@@ -423,6 +470,31 @@ function createLarge(seriesModel, group, incremental) {
   var startPoint = [];
   var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
   startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart');
+  var largeDataIndices = data.getLayout('largeDataIndices');
+  var barWidth = data.getLayout('barWidth');
+  var backgroundModel = seriesModel.getModel('backgroundStyle');
+  var drawBackground = seriesModel.get('showBackground', true);
+
+  if (drawBackground) {
+    var points = data.getLayout('largeBackgroundPoints');
+    var backgroundStartPoint = [];
+    backgroundStartPoint[1 - baseDimIdx] = data.getLayout('backgroundStart');
+    var bgEl = new LargePath({
+      shape: {
+        points: points
+      },
+      incremental: !!incremental,
+      __startPoint: backgroundStartPoint,
+      __baseDimIdx: baseDimIdx,
+      __largeDataIndices: largeDataIndices,
+      __barWidth: barWidth,
+      silent: true,
+      z2: 0
+    });
+    setLargeBackgroundStyle(bgEl, backgroundModel, data);
+    group.add(bgEl);
+  }
+
   var el = new LargePath({
     shape: {
       points: data.getLayout('largePoints')
@@ -430,8 +502,8 @@ function createLarge(seriesModel, group, incremental) {
     incremental: !!incremental,
     __startPoint: startPoint,
     __baseDimIdx: baseDimIdx,
-    __largeDataIndices: data.getLayout('largeDataIndices'),
-    __barWidth: data.getLayout('barWidth')
+    __largeDataIndices: largeDataIndices,
+    __barWidth: barWidth
   });
   group.add(el);
   setLargeStyle(el, seriesModel, data); // Enable tooltip and user mouse/touch event handlers.
@@ -485,4 +557,51 @@ function setLargeStyle(el, seriesModel, data) {
   el.style.fill = null;
   el.style.stroke = borderColor;
   el.style.lineWidth = data.getLayout('barWidth');
+}
+
+function setLargeBackgroundStyle(el, backgroundModel, data) {
+  var borderColor = backgroundModel.get('borderColor') || backgroundModel.get('color');
+  var itemStyle = backgroundModel.getItemStyle(['color', 'borderColor']);
+  el.useStyle(itemStyle);
+  el.style.fill = null;
+  el.style.stroke = borderColor;
+  el.style.lineWidth = data.getLayout('barWidth');
+}
+
+function createBackgroundShape(isHorizontalOrRadial, layout, coord) {
+  var coordLayout;
+  var isPolar = coord.type === 'polar';
+
+  if (isPolar) {
+    coordLayout = coord.getArea();
+  } else {
+    coordLayout = coord.grid.getRect();
+  }
+
+  if (isPolar) {
+    return {
+      cx: coordLayout.cx,
+      cy: coordLayout.cy,
+      r0: isHorizontalOrRadial ? coordLayout.r0 : layout.r0,
+      r: isHorizontalOrRadial ? coordLayout.r : layout.r,
+      startAngle: isHorizontalOrRadial ? layout.startAngle : 0,
+      endAngle: isHorizontalOrRadial ? layout.endAngle : Math.PI * 2
+    };
+  } else {
+    return {
+      x: isHorizontalOrRadial ? layout.x : coordLayout.x,
+      y: isHorizontalOrRadial ? coordLayout.y : layout.y,
+      width: isHorizontalOrRadial ? layout.width : coordLayout.width,
+      height: isHorizontalOrRadial ? coordLayout.height : layout.height
+    };
+  }
+}
+
+function createBackgroundEl(coord, isHorizontalOrRadial, layout) {
+  var ElementClz = coord.type === 'polar' ? graphic.Sector : graphic.Rect;
+  return new ElementClz({
+    shape: createBackgroundShape(isHorizontalOrRadial, layout, coord),
+    silent: true,
+    z2: 0
+  });
 }
\ No newline at end of file
diff --git a/en/builder/src/echarts/chart/candlestick/candlestickVisual.js b/en/builder/src/echarts/chart/candlestick/candlestickVisual.js
index aa77aef..05673a1 100644
--- a/en/builder/src/echarts/chart/candlestick/candlestickVisual.js
+++ b/en/builder/src/echarts/chart/candlestick/candlestickVisual.js
@@ -28,7 +28,6 @@ export default {
   performRawSeries: true,
   reset: function (seriesModel, ecModel) {
     var data = seriesModel.getData();
-    var isLargeRender = seriesModel.pipelineContext.large;
     data.setVisual({
       legendSymbol: 'roundRect',
       colorP: getColor(1, seriesModel),
@@ -41,6 +40,7 @@ export default {
       return;
     }
 
+    var isLargeRender = seriesModel.pipelineContext.large;
     return !isLargeRender && {
       progress: progress
     };
diff --git a/en/builder/src/echarts/chart/funnel/FunnelSeries.js b/en/builder/src/echarts/chart/funnel/FunnelSeries.js
index eebf96b..f728aa1 100644
--- a/en/builder/src/echarts/chart/funnel/FunnelSeries.js
+++ b/en/builder/src/echarts/chart/funnel/FunnelSeries.js
@@ -22,14 +22,13 @@ import createListSimply from '../helper/createListSimply';
 import { defaultEmphasis } from '../../util/model';
 import { makeSeriesEncodeForNameBased } from '../../data/helper/sourceHelper';
 import LegendVisualProvider from '../../visual/LegendVisualProvider';
-import { bind } from 'zrender/src/core/util';
 var FunnelSeries = echarts.extendSeriesModel({
   type: 'series.funnel',
   init: function (option) {
     FunnelSeries.superApply(this, 'init', arguments); // Enable legend selection for each data item
     // Use a function instead of direct access because data reference may changed
 
-    this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); // Extend labelLine emphasis
+    this.legendVisualProvider = new LegendVisualProvider(zrUtil.bind(this.getData, this), zrUtil.bind(this.getRawData, this)); // Extend labelLine emphasis
 
     this._defaultLabelLine(option);
   },
diff --git a/en/builder/src/echarts/chart/graph/GraphSeries.js b/en/builder/src/echarts/chart/graph/GraphSeries.js
index 6a68e4e..a354166 100644
--- a/en/builder/src/echarts/chart/graph/GraphSeries.js
+++ b/en/builder/src/echarts/chart/graph/GraphSeries.js
@@ -206,7 +206,8 @@ var GraphSeries = echarts.extendSeriesModel({
     edgeSymbol: ['none', 'none'],
     edgeSymbolSize: 10,
     edgeLabel: {
-      position: 'middle'
+      position: 'middle',
+      distance: 5
     },
     draggable: false,
     roam: false,
diff --git a/en/builder/src/echarts/chart/graph/GraphView.js b/en/builder/src/echarts/chart/graph/GraphView.js
index c1fc4e8..47c353d 100644
--- a/en/builder/src/echarts/chart/graph/GraphView.js
+++ b/en/builder/src/echarts/chart/graph/GraphView.js
@@ -252,8 +252,7 @@ export default echarts.extendChartView({
     }
   },
   focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
-    var data = this._model.getData();
-
+    var data = seriesModel.getData();
     var graph = data.graph;
     var dataIndex = payload.dataIndex;
     var edgeDataIndex = payload.edgeDataIndex;
@@ -291,8 +290,7 @@ export default echarts.extendChartView({
     }
   },
   unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
-    var graph = this._model.getData().graph;
-
+    var graph = seriesModel.getData().graph;
     graph.eachNode(function (node) {
       fadeOutItem(node, nodeOpacityPath);
     });
diff --git a/en/builder/src/echarts/chart/helper/EffectLine.js b/en/builder/src/echarts/chart/helper/EffectLine.js
index 3e54a95..fe3c7e2 100644
--- a/en/builder/src/echarts/chart/helper/EffectLine.js
+++ b/en/builder/src/echarts/chart/helper/EffectLine.js
@@ -80,6 +80,7 @@ effectLineProto._updateEffectSymbol = function (lineData, idx) {
   symbol.setColor(color);
   symbol.attr('scale', size);
   this._symbolType = symbolType;
+  this._symbolScale = size;
 
   this._updateEffectAnimation(lineData, effectModel, idx);
 };
@@ -163,6 +164,7 @@ effectLineProto.updateSymbolPosition = function (symbol) {
   var cp1 = symbol.__cp1;
   var t = symbol.__t;
   var pos = symbol.position;
+  var lastPos = [pos[0], pos[1]];
   var quadraticAt = curveUtil.quadraticAt;
   var quadraticDerivativeAt = curveUtil.quadraticDerivativeAt;
   pos[0] = quadraticAt(p1[0], cp1[0], p2[0], t);
@@ -170,7 +172,27 @@ effectLineProto.updateSymbolPosition = function (symbol) {
 
   var tx = quadraticDerivativeAt(p1[0], cp1[0], p2[0], t);
   var ty = quadraticDerivativeAt(p1[1], cp1[1], p2[1], t);
-  symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2;
+  symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; // enable continuity trail for 'line', 'rect', 'roundRect' symbolType
+
+  if (this._symbolType === 'line' || this._symbolType === 'rect' || this._symbolType === 'roundRect') {
+    if (symbol.__lastT !== undefined && symbol.__lastT < symbol.__t) {
+      var scaleY = vec2.dist(lastPos, pos) * 1.05;
+      symbol.attr('scale', [symbol.scale[0], scaleY]); // make sure the last segment render within endPoint
+
+      if (t === 1) {
+        pos[0] = lastPos[0] + (pos[0] - lastPos[0]) / 2;
+        pos[1] = lastPos[1] + (pos[1] - lastPos[1]) / 2;
+      }
+    } else if (symbol.__lastT === 1) {
+      // After first loop, symbol.__t does NOT start with 0, so connect p1 to pos directly.
+      var scaleY = 2 * vec2.dist(p1, pos);
+      symbol.attr('scale', [symbol.scale[0], scaleY]);
+    } else {
+      symbol.attr('scale', this._symbolScale);
+    }
+  }
+
+  symbol.__lastT = symbol.__t;
   symbol.ignore = false;
 };
 
diff --git a/en/builder/src/echarts/chart/helper/Line.js b/en/builder/src/echarts/chart/helper/Line.js
index 1852a35..251ae41 100644
--- a/en/builder/src/echarts/chart/helper/Line.js
+++ b/en/builder/src/echarts/chart/helper/Line.js
@@ -133,40 +133,93 @@ function updateSymbolAndLabelBeforeLineUpdate() {
     var textPosition;
     var textAlign;
     var textVerticalAlign;
-    var distance = 5 * invScale; // End
-
-    if (label.__position === 'end') {
-      textPosition = [d[0] * distance + toPos[0], d[1] * distance + toPos[1]];
-      textAlign = d[0] > 0.8 ? 'left' : d[0] < -0.8 ? 'right' : 'center';
-      textVerticalAlign = d[1] > 0.8 ? 'top' : d[1] < -0.8 ? 'bottom' : 'middle';
-    } // Middle
-    else if (label.__position === 'middle') {
-        var halfPercent = percent / 2;
-        var tangent = line.tangentAt(halfPercent);
-        var n = [tangent[1], -tangent[0]];
-        var cp = line.pointAt(halfPercent);
-
-        if (n[1] > 0) {
-          n[0] = -n[0];
-          n[1] = -n[1];
-        }
-
-        textPosition = [cp[0] + n[0] * distance, cp[1] + n[1] * distance];
-        textAlign = 'center';
-        textVerticalAlign = 'bottom';
-        var rotation = -Math.atan2(tangent[1], tangent[0]);
+    var textOrigin;
+    var distance = label.__labelDistance;
+    var distanceX = distance[0] * invScale;
+    var distanceY = distance[1] * invScale;
+    var halfPercent = percent / 2;
+    var tangent = line.tangentAt(halfPercent);
+    var n = [tangent[1], -tangent[0]];
+    var cp = line.pointAt(halfPercent);
+
+    if (n[1] > 0) {
+      n[0] = -n[0];
+      n[1] = -n[1];
+    }
+
+    var dir = tangent[0] < 0 ? -1 : 1;
+
+    if (label.__position !== 'start' && label.__position !== 'end') {
+      var rotation = -Math.atan2(tangent[1], tangent[0]);
+
+      if (toPos[0] < fromPos[0]) {
+        rotation = Math.PI + rotation;
+      }
+
+      label.attr('rotation', rotation);
+    }
 
-        if (toPos[0] < fromPos[0]) {
-          rotation = Math.PI + rotation;
-        }
+    var dy;
 
-        label.attr('rotation', rotation);
-      } // Start
-      else {
-          textPosition = [-d[0] * distance + fromPos[0], -d[1] * distance + fromPos[1]];
-          textAlign = d[0] > 0.8 ? 'right' : d[0] < -0.8 ? 'left' : 'center';
-          textVerticalAlign = d[1] > 0.8 ? 'bottom' : d[1] < -0.8 ? 'top' : 'middle';
-        }
+    switch (label.__position) {
+      case 'insideStartTop':
+      case 'insideMiddleTop':
+      case 'insideEndTop':
+      case 'middle':
+        dy = -distanceY;
+        textVerticalAlign = 'bottom';
+        break;
+
+      case 'insideStartBottom':
+      case 'insideMiddleBottom':
+      case 'insideEndBottom':
+        dy = distanceY;
+        textVerticalAlign = 'top';
+        break;
+
+      default:
+        dy = 0;
+        textVerticalAlign = 'middle';
+    }
+
+    switch (label.__position) {
+      case 'end':
+        textPosition = [d[0] * distanceX + toPos[0], d[1] * distanceY + toPos[1]];
+        textAlign = d[0] > 0.8 ? 'left' : d[0] < -0.8 ? 'right' : 'center';
+        textVerticalAlign = d[1] > 0.8 ? 'top' : d[1] < -0.8 ? 'bottom' : 'middle';
+        break;
+
+      case 'start':
+        textPosition = [-d[0] * distanceX + fromPos[0], -d[1] * distanceY + fromPos[1]];
+        textAlign = d[0] > 0.8 ? 'right' : d[0] < -0.8 ? 'left' : 'center';
+        textVerticalAlign = d[1] > 0.8 ? 'bottom' : d[1] < -0.8 ? 'top' : 'middle';
+        break;
+
+      case 'insideStartTop':
+      case 'insideStart':
+      case 'insideStartBottom':
+        textPosition = [distanceX * dir + fromPos[0], fromPos[1] + dy];
+        textAlign = tangent[0] < 0 ? 'right' : 'left';
+        textOrigin = [-distanceX * dir, -dy];
+        break;
+
+      case 'insideMiddleTop':
+      case 'insideMiddle':
+      case 'insideMiddleBottom':
+      case 'middle':
+        textPosition = [cp[0], cp[1] + dy];
+        textAlign = 'center';
+        textOrigin = [0, -dy];
+        break;
+
+      case 'insideEndTop':
+      case 'insideEnd':
+      case 'insideEndBottom':
+        textPosition = [-distanceX * dir + toPos[0], toPos[1] + dy];
+        textAlign = tangent[0] >= 0 ? 'right' : 'left';
+        textOrigin = [distanceX * dir, -dy];
+        break;
+    }
 
     label.attr({
       style: {
@@ -175,7 +228,8 @@ function updateSymbolAndLabelBeforeLineUpdate() {
         textAlign: label.__textAlign || textAlign
       },
       position: textPosition,
-      scale: [invScale, invScale]
+      scale: [invScale, invScale],
+      origin: textOrigin
     });
   }
 }
@@ -319,6 +373,13 @@ lineProto._updateCommonStl = function (lineData, idx, seriesScope) {
     label.__verticalAlign = labelStyle.textVerticalAlign; // 'start', 'middle', 'end'
 
     label.__position = labelModel.get('position') || 'middle';
+    var distance = labelModel.get('distance');
+
+    if (!zrUtil.isArray(distance)) {
+      distance = [distance, distance];
+    }
+
+    label.__labelDistance = distance;
   }
 
   if (emphasisText != null) {
diff --git a/en/builder/src/echarts/chart/helper/createRenderPlanner.js b/en/builder/src/echarts/chart/helper/createRenderPlanner.js
index aeea62d..6444694 100644
--- a/en/builder/src/echarts/chart/helper/createRenderPlanner.js
+++ b/en/builder/src/echarts/chart/helper/createRenderPlanner.js
@@ -27,9 +27,12 @@ export default function () {
     var fields = inner(seriesModel);
     var pipelineContext = seriesModel.pipelineContext;
     var originalLarge = fields.large;
-    var originalProgressive = fields.progressiveRender;
-    var large = fields.large = pipelineContext.large;
-    var progressive = fields.progressiveRender = pipelineContext.progressiveRender;
+    var originalProgressive = fields.progressiveRender; // FIXME: if the planner works on a filtered series, `pipelineContext` does not
+    // exists. See #11611 . Probably we need to modify this structure, see the comment
+    // on `performRawSeries` in `Schedular.js`.
+
+    var large = fields.large = pipelineContext && pipelineContext.large;
+    var progressive = fields.progressiveRender = pipelineContext && pipelineContext.progressiveRender;
     return !!(originalLarge ^ large || originalProgressive ^ progressive) && 'reset';
   };
 }
\ No newline at end of file
diff --git a/en/builder/src/echarts/chart/pie/PieView.js b/en/builder/src/echarts/chart/pie/PieView.js
index 2658eee..d844e3a 100644
--- a/en/builder/src/echarts/chart/pie/PieView.js
+++ b/en/builder/src/echarts/chart/pie/PieView.js
@@ -136,7 +136,7 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
   var cursorStyle = itemModel.getShallow('cursor');
   cursorStyle && sector.attr('cursor', cursorStyle); // Toggle selected
 
-  toggleItemSelected(this, data.getItemLayout(idx), seriesModel.isSelected(null, idx), seriesModel.get('selectedOffset'), seriesModel.get('animation')); // Label and text animation should be applied only for transition type animation when update
+  toggleItemSelected(this, data.getItemLayout(idx), seriesModel.isSelected(data.getName(idx)), seriesModel.get('selectedOffset'), seriesModel.get('animation')); // Label and text animation should be applied only for transition type animation when update
 
   var withAnimation = !firstCreate && animationTypeUpdate === 'transition';
 
diff --git a/en/builder/src/echarts/chart/radar/RadarSeries.js b/en/builder/src/echarts/chart/radar/RadarSeries.js
index 25209d4..9b76c7b 100644
--- a/en/builder/src/echarts/chart/radar/RadarSeries.js
+++ b/en/builder/src/echarts/chart/radar/RadarSeries.js
@@ -47,6 +47,26 @@ var RadarSeries = SeriesModel.extend({
       return encodeHTML(axis.name + ' : ' + val);
     }).join('<br />');
   },
+
+  /**
+   * @implement
+   */
+  getTooltipPosition: function (dataIndex) {
+    if (dataIndex != null) {
+      var data = this.getData();
+      var coordSys = this.coordinateSystem;
+      var values = data.getValues(zrUtil.map(coordSys.dimensions, function (dim) {
+        return data.mapDimension(dim);
+      }), dataIndex, true);
+
+      for (var i = 0, len = values.length; i < len; i++) {
+        if (!isNaN(values[i])) {
+          var indicatorAxes = coordSys.getIndicatorAxes();
+          return coordSys.coordToPoint(indicatorAxes[i].dataToCoord(values[i]), i);
+        }
+      }
+    }
+  },
   defaultOption: {
     zlevel: 0,
     z: 2,
diff --git a/en/builder/src/echarts/chart/sankey/SankeySeries.js b/en/builder/src/echarts/chart/sankey/SankeySeries.js
index c85eb1a..e8e07b9 100644
--- a/en/builder/src/echarts/chart/sankey/SankeySeries.js
+++ b/en/builder/src/echarts/chart/sankey/SankeySeries.js
@@ -131,6 +131,18 @@ var SankeySeries = SeriesModel.extend({
       option.focusNodeAdjacency = 'allEdges';
     }
   },
+  // Override Series.getDataParams()
+  getDataParams: function (dataIndex, dataType) {
+    var params = SankeySeries.superCall(this, 'getDataParams', dataIndex, dataType);
+
+    if (params.value == null && dataType === 'node') {
+      var node = this.getGraph().getNodeByIndex(dataIndex);
+      var nodeValue = node.getLayout().value;
+      params.value = nodeValue;
+    }
+
+    return params;
+  },
   defaultOption: {
     zlevel: 0,
     z: 2,
@@ -176,7 +188,7 @@ var SankeySeries = SeriesModel.extend({
         show: true
       },
       lineStyle: {
-        opacity: 0.6
+        opacity: 0.5
       }
     },
     animationEasing: 'linear',
diff --git a/en/builder/src/echarts/chart/sankey/SankeyView.js b/en/builder/src/echarts/chart/sankey/SankeyView.js
index 64316e5..a642042 100644
--- a/en/builder/src/echarts/chart/sankey/SankeyView.js
+++ b/en/builder/src/echarts/chart/sankey/SankeyView.js
@@ -20,7 +20,9 @@ import * as graphic from '../../util/graphic';
 import * as echarts from '../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
 var nodeOpacityPath = ['itemStyle', 'opacity'];
+var hoverNodeOpacityPath = ['emphasis', 'itemStyle', 'opacity'];
 var lineOpacityPath = ['lineStyle', 'opacity'];
+var hoverLineOpacityPath = ['emphasis', 'lineStyle', 'opacity'];
 
 function getItemOpacity(item, opacityPath) {
   return item.getVisual('opacity') || item.getModel().get(opacityPath);
@@ -46,12 +48,13 @@ function fadeOutItem(item, opacityPath, opacityRatio) {
 function fadeInItem(item, opacityPath) {
   var opacity = getItemOpacity(item, opacityPath);
   var el = item.getGraphicEl();
-  el.highlight && el.highlight();
   el.traverse(function (child) {
     if (child.type !== 'group') {
       child.setStyle('opacity', opacity);
     }
-  });
+  }); // Support emphasis here.
+
+  el.highlight && el.highlight();
 }
 
 var SankeyShape = graphic.extendShape({
@@ -81,6 +84,12 @@ var SankeyShape = graphic.extendShape({
     }
 
     ctx.closePath();
+  },
+  highlight: function () {
+    this.trigger('emphasis');
+  },
+  downplay: function () {
+    this.trigger('normal');
   }
 });
 export default echarts.extendChartView({
@@ -242,8 +251,19 @@ export default echarts.extendChartView({
         el.cursor = 'move';
       }
 
+      el.highlight = function () {
+        this.trigger('emphasis');
+      };
+
+      el.downplay = function () {
+        this.trigger('normal');
+      };
+
+      el.focusNodeAdjHandler && el.off('mouseover', el.focusNodeAdjHandler);
+      el.unfocusNodeAdjHandler && el.off('mouseout', el.unfocusNodeAdjHandler);
+
       if (itemModel.get('focusNodeAdjacency')) {
-        el.off('mouseover').on('mouseover', function () {
+        el.on('mouseover', el.focusNodeAdjHandler = function () {
           if (!sankeyView._focusAdjacencyDisabled) {
             sankeyView._clearTimer();
 
@@ -254,7 +274,7 @@ export default echarts.extendChartView({
             });
           }
         });
-        el.off('mouseout').on('mouseout', function () {
+        el.on('mouseout', el.unfocusNodeAdjHandler = function () {
           if (!sankeyView._focusAdjacencyDisabled) {
             sankeyView._dispatchUnfocus(api);
           }
@@ -263,9 +283,11 @@ export default echarts.extendChartView({
     });
     edgeData.eachItemGraphicEl(function (el, dataIndex) {
       var edgeModel = edgeData.getItemModel(dataIndex);
+      el.focusNodeAdjHandler && el.off('mouseover', el.focusNodeAdjHandler);
+      el.unfocusNodeAdjHandler && el.off('mouseout', el.unfocusNodeAdjHandler);
 
       if (edgeModel.get('focusNodeAdjacency')) {
-        el.off('mouseover').on('mouseover', function () {
+        el.on('mouseover', el.focusNodeAdjHandler = function () {
           if (!sankeyView._focusAdjacencyDisabled) {
             sankeyView._clearTimer();
 
@@ -276,7 +298,7 @@ export default echarts.extendChartView({
             });
           }
         });
-        el.off('mouseout').on('mouseout', function () {
+        el.on('mouseout', el.unfocusNodeAdjHandler = function () {
           if (!sankeyView._focusAdjacencyDisabled) {
             sankeyView._dispatchUnfocus(api);
           }
@@ -315,8 +337,7 @@ export default echarts.extendChartView({
     }
   },
   focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
-    var data = this._model.getData();
-
+    var data = seriesModel.getData();
     var graph = data.graph;
     var dataIndex = payload.dataIndex;
     var itemModel = data.getItemModel(dataIndex);
@@ -336,7 +357,7 @@ export default echarts.extendChartView({
     });
 
     if (node) {
-      fadeInItem(node, nodeOpacityPath);
+      fadeInItem(node, hoverNodeOpacityPath);
       var focusNodeAdj = itemModel.get('focusNodeAdjacency');
 
       if (focusNodeAdj === 'outEdges') {
@@ -345,8 +366,8 @@ export default echarts.extendChartView({
             return;
           }
 
-          fadeInItem(edge, lineOpacityPath);
-          fadeInItem(edge.node2, nodeOpacityPath);
+          fadeInItem(edge, hoverLineOpacityPath);
+          fadeInItem(edge.node2, hoverNodeOpacityPath);
         });
       } else if (focusNodeAdj === 'inEdges') {
         zrUtil.each(node.inEdges, function (edge) {
@@ -354,8 +375,8 @@ export default echarts.extendChartView({
             return;
           }
 
-          fadeInItem(edge, lineOpacityPath);
-          fadeInItem(edge.node1, nodeOpacityPath);
+          fadeInItem(edge, hoverLineOpacityPath);
+          fadeInItem(edge.node1, hoverNodeOpacityPath);
         });
       } else if (focusNodeAdj === 'allEdges') {
         zrUtil.each(node.edges, function (edge) {
@@ -363,22 +384,21 @@ export default echarts.extendChartView({
             return;
           }
 
-          fadeInItem(edge, lineOpacityPath);
-          fadeInItem(edge.node1, nodeOpacityPath);
-          fadeInItem(edge.node2, nodeOpacityPath);
+          fadeInItem(edge, hoverLineOpacityPath);
+          edge.node1 !== node && fadeInItem(edge.node1, hoverNodeOpacityPath);
+          edge.node2 !== node && fadeInItem(edge.node2, hoverNodeOpacityPath);
         });
       }
     }
 
     if (edge) {
-      fadeInItem(edge, lineOpacityPath);
-      fadeInItem(edge.node1, nodeOpacityPath);
-      fadeInItem(edge.node2, nodeOpacityPath);
+      fadeInItem(edge, hoverLineOpacityPath);
+      fadeInItem(edge.node1, hoverNodeOpacityPath);
+      fadeInItem(edge.node2, hoverNodeOpacityPath);
     }
   },
   unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
-    var graph = this._model.getGraph();
-
+    var graph = seriesModel.getGraph();
     graph.eachNode(function (node) {
       fadeOutItem(node, nodeOpacityPath);
     });
@@ -399,8 +419,7 @@ function createGridClipShape(rect, seriesModel, cb) {
   });
   graphic.initProps(rectEl, {
     shape: {
-      width: rect.width + 20,
-      height: rect.height + 20
+      width: rect.width + 20
     }
   }, seriesModel, cb);
   return rectEl;
diff --git a/en/builder/src/echarts/chart/sankey/sankeyLayout.js b/en/builder/src/echarts/chart/sankey/sankeyLayout.js
index 84e7bca..56d303c 100644
--- a/en/builder/src/echarts/chart/sankey/sankeyLayout.js
+++ b/en/builder/src/echarts/chart/sankey/sankeyLayout.js
@@ -71,7 +71,8 @@ function computeNodeValues(nodes) {
   zrUtil.each(nodes, function (node) {
     var value1 = sum(node.outEdges, getEdgeValue);
     var value2 = sum(node.inEdges, getEdgeValue);
-    var value = Math.max(value1, value2);
+    var nodeRawValue = node.getValue() || 0;
+    var value = Math.max(value1, value2, nodeRawValue);
     node.setLayout({
       value: value
     }, true);
@@ -462,13 +463,13 @@ function getEdgeValue(edge) {
   return edge.getValue();
 }
 
-function sum(array, f, orient) {
+function sum(array, cb, orient) {
   var sum = 0;
   var len = array.length;
   var i = -1;
 
   while (++i < len) {
-    var value = +f.call(array, array[i], orient);
+    var value = +cb.call(array, array[i], orient);
 
     if (!isNaN(value)) {
       sum += value;
diff --git a/en/builder/src/echarts/chart/tree/TreeSeries.js b/en/builder/src/echarts/chart/tree/TreeSeries.js
index 7e2417e..de9dcd7 100644
--- a/en/builder/src/echarts/chart/tree/TreeSeries.js
+++ b/en/builder/src/echarts/chart/tree/TreeSeries.js
@@ -122,6 +122,9 @@ export default SeriesModel.extend({
     bottom: '12%',
     // the layout of the tree, two value can be selected, 'orthogonal' or 'radial'
     layout: 'orthogonal',
+    // value can be 'polyline'
+    edgeShape: 'curve',
+    edgeForkPosition: '50%',
     // true | false | 'move' | 'scale', see module:component/helper/RoamController.
     roam: false,
     // Symbol size scale ratio in roam
diff --git a/en/builder/src/echarts/chart/tree/TreeView.js b/en/builder/src/echarts/chart/tree/TreeView.js
index 750975e..8664b9a 100644
--- a/en/builder/src/echarts/chart/tree/TreeView.js
+++ b/en/builder/src/echarts/chart/tree/TreeView.js
@@ -26,6 +26,56 @@ import View from '../../coord/View';
 import * as roamHelper from '../../component/helper/roamHelper';
 import RoamController from '../../component/helper/RoamController';
 import { onIrrelevantElement } from '../../component/helper/cursorHelper';
+import { __DEV__ } from '../../config';
+import { parsePercent } from '../../util/number';
+var TreeShape = graphic.extendShape({
+  shape: {
+    parentPoint: [],
+    childPoints: [],
+    orient: '',
+    forkPosition: ''
+  },
+  style: {
+    stroke: '#000',
+    fill: null
+  },
+  buildPath: function (ctx, shape) {
+    var childPoints = shape.childPoints;
+    var childLen = childPoints.length;
+    var parentPoint = shape.parentPoint;
+    var firstChildPos = childPoints[0];
+    var lastChildPos = childPoints[childLen - 1];
+
+    if (childLen === 1) {
+      ctx.moveTo(parentPoint[0], parentPoint[1]);
+      ctx.lineTo(firstChildPos[0], firstChildPos[1]);
+      return;
+    }
+
+    var orient = shape.orient;
+    var forkDim = orient === 'TB' || orient === 'BT' ? 0 : 1;
+    var otherDim = 1 - forkDim;
+    var forkPosition = parsePercent(shape.forkPosition, 1);
+    var tmpPoint = [];
+    tmpPoint[forkDim] = parentPoint[forkDim];
+    tmpPoint[otherDim] = parentPoint[otherDim] + (lastChildPos[otherDim] - parentPoint[otherDim]) * forkPosition;
+    ctx.moveTo(parentPoint[0], parentPoint[1]);
+    ctx.lineTo(tmpPoint[0], tmpPoint[1]);
+    ctx.moveTo(firstChildPos[0], firstChildPos[1]);
+    tmpPoint[forkDim] = firstChildPos[forkDim];
+    ctx.lineTo(tmpPoint[0], tmpPoint[1]);
+    tmpPoint[forkDim] = lastChildPos[forkDim];
+    ctx.lineTo(tmpPoint[0], tmpPoint[1]);
+    ctx.lineTo(lastChildPos[0], lastChildPos[1]);
+
+    for (var i = 1; i < childLen - 1; i++) {
+      var point = childPoints[i];
+      ctx.moveTo(point[0], point[1]);
+      tmpPoint[forkDim] = point[forkDim];
+      ctx.lineTo(tmpPoint[0], tmpPoint[1]);
+    }
+  }
+});
 export default echarts.extendChartView({
   type: 'tree',
 
@@ -78,6 +128,8 @@ export default echarts.extendChartView({
     var seriesScope = {
       expandAndCollapse: seriesModel.get('expandAndCollapse'),
       layout: layout,
+      edgeShape: seriesModel.get('edgeShape'),
+      edgeForkPosition: seriesModel.get('edgeForkPosition'),
       orient: seriesModel.getOrient(),
       curvature: seriesModel.get('lineStyle.curveness'),
       symbolRotate: seriesModel.get('symbolRotate'),
@@ -353,27 +405,72 @@ function updateNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope)
     });
   }
 
-  if (node.parentNode && node.parentNode !== virtualRoot) {
-    var edge = symbolEl.__edge;
+  drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group, seriesScope);
+}
 
-    if (!edge) {
-      edge = symbolEl.__edge = new graphic.BezierCurve({
-        shape: getEdgeShape(seriesScope, sourceOldLayout, sourceOldLayout),
-        style: zrUtil.defaults({
-          opacity: 0,
-          strokeNoScale: true
-        }, seriesScope.lineStyle)
-      });
+function drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group, seriesScope) {
+  var edgeShape = seriesScope.edgeShape;
+  var edge = symbolEl.__edge;
+
+  if (edgeShape === 'curve') {
+    if (node.parentNode && node.parentNode !== virtualRoot) {
+      if (!edge) {
+        edge = symbolEl.__edge = new graphic.BezierCurve({
+          shape: getEdgeShape(seriesScope, sourceOldLayout, sourceOldLayout),
+          style: zrUtil.defaults({
+            opacity: 0,
+            strokeNoScale: true
+          }, seriesScope.lineStyle)
+        });
+      }
+
+      graphic.updateProps(edge, {
+        shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
+        style: {
+          opacity: 1
+        }
+      }, seriesModel);
     }
+  } else if (edgeShape === 'polyline') {
+    if (seriesScope.layout === 'orthogonal') {
+      if (node !== virtualRoot && node.children && node.children.length !== 0 && node.isExpand === true) {
+        var children = node.children;
+        var childPoints = [];
+
+        for (var i = 0; i < children.length; i++) {
+          var childLayout = children[i].getLayout();
+          childPoints.push([childLayout.x, childLayout.y]);
+        }
+
+        if (!edge) {
+          edge = symbolEl.__edge = new TreeShape({
+            shape: {
+              parentPoint: [targetLayout.x, targetLayout.y],
+              childPoints: [[targetLayout.x, targetLayout.y]],
+              orient: seriesScope.orient,
+              forkPosition: seriesScope.edgeForkPosition
+            },
+            style: zrUtil.defaults({
+              opacity: 0,
+              strokeNoScale: true
+            }, seriesScope.lineStyle)
+          });
+        }
 
-    graphic.updateProps(edge, {
-      shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
-      style: {
-        opacity: 1
+        graphic.updateProps(edge, {
+          shape: {
+            parentPoint: [targetLayout.x, targetLayout.y],
+            childPoints: childPoints
+          },
+          style: {
+            opacity: 1
+          }
+        }, seriesModel);
       }
-    }, seriesModel);
-    group.add(edge);
+    } else {}
   }
+
+  group.add(edge);
 }
 
 function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope) {
@@ -382,6 +479,7 @@ function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope)
   var itemModel = node.getModel();
   var seriesScope = getTreeNodeStyle(node, itemModel, seriesScope);
   var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
+  var edgeShape = seriesScope.edgeShape;
   var sourceLayout;
 
   while (sourceLayout = source.getLayout(), sourceLayout == null) {
@@ -397,17 +495,38 @@ function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope)
   symbolEl.fadeOut(null, {
     keepLabel: true
   });
-  var edge = symbolEl.__edge;
+  var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
+  var sourceEdge = sourceSymbolEl.__edge; // 1. when expand the sub tree, delete the children node should delete the edge of
+  // the source at the same time. because the polyline edge shape is only owned by the source.
+  // 2.when the node is the only children of the source, delete the node should delete the edge of
+  // the source at the same time. the same reason as above.
+
+  var edge = symbolEl.__edge || (source.isExpand === false || source.children.length === 1 ? sourceEdge : undefined);
+  var edgeShape = seriesScope.edgeShape;
 
   if (edge) {
-    graphic.updateProps(edge, {
-      shape: getEdgeShape(seriesScope, sourceLayout, sourceLayout),
-      style: {
-        opacity: 0
-      }
-    }, seriesModel, function () {
-      group.remove(edge);
-    });
+    if (edgeShape === 'curve') {
+      graphic.updateProps(edge, {
+        shape: getEdgeShape(seriesScope, sourceLayout, sourceLayout),
+        style: {
+          opacity: 0
+        }
+      }, seriesModel, function () {
+        group.remove(edge);
+      });
+    } else if (edgeShape === 'polyline' && seriesScope.layout === 'orthogonal') {
+      graphic.updateProps(edge, {
+        shape: {
+          parentPoint: [sourceLayout.x, sourceLayout.y],
+          childPoints: [[sourceLayout.x, sourceLayout.y]]
+        },
+        style: {
+          opacity: 0
+        }
+      }, seriesModel, function () {
+        group.remove(edge);
+      });
+    }
   }
 }
 
diff --git a/en/builder/src/echarts/chart/treemap/TreemapView.js b/en/builder/src/echarts/chart/treemap/TreemapView.js
index df7ca53..34030e7 100644
--- a/en/builder/src/echarts/chart/treemap/TreemapView.js
+++ b/en/builder/src/echarts/chart/treemap/TreemapView.js
@@ -641,6 +641,10 @@ function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimat
 
 
   var thisLayout = thisNode.getLayout();
+  var data = seriesModel.getData(); // Only for enabling highlight/downplay. Clear firstly.
+  // Because some node will not be rendered.
+
+  data.setItemGraphicEl(thisNode.dataIndex, null);
 
   if (!thisLayout || !thisLayout.isInView) {
     return;
@@ -674,15 +678,37 @@ function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimat
 
   if (thisLayout.isAboveViewRoot) {
     return group;
-  } // Background
+  }
 
+  var nodeModel = thisNode.getModel(); // Background
 
   var bg = giveGraphic('background', Rect, depth, Z_BG);
   bg && renderBackground(group, bg, isParent && thisLayout.upperHeight); // No children, render content.
 
-  if (!isParent) {
+  if (isParent) {
+    // Because of the implementation about "traverse" in graphic hover style, we
+    // can not set hover listener on the "group" of non-leaf node. Otherwise the
+    // hover event from the descendents will be listenered.
+    if (graphic.isHighDownDispatcher(group)) {
+      graphic.setAsHighDownDispatcher(group, false);
+    }
+
+    if (bg) {
+      graphic.setAsHighDownDispatcher(bg, true); // Only for enabling highlight/downplay.
+
+      data.setItemGraphicEl(thisNode.dataIndex, bg);
+    }
+  } else {
     var content = giveGraphic('content', Rect, depth, Z_CONTENT);
     content && renderContent(group, content);
+
+    if (bg && graphic.isHighDownDispatcher(bg)) {
+      graphic.setAsHighDownDispatcher(bg, false);
+    }
+
+    graphic.setAsHighDownDispatcher(group, true); // Only for enabling highlight/downplay.
+
+    data.setItemGraphicEl(thisNode.dataIndex, group);
   }
 
   return group; // ----------------------------
@@ -699,9 +725,16 @@ function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimat
       width: thisWidth,
       height: thisHeight
     });
-    var visualBorderColor = thisNode.getVisual('borderColor', true);
-    var emphasisBorderColor = itemStyleEmphasisModel.get('borderColor');
-    updateStyle(bg, function () {
+
+    if (thisInvisible) {
+      // If invisible, do not set visual, otherwise the element will
+      // change immediately before animation. We think it is OK to
+      // remain its origin color when moving out of the view window.
+      processInvisible(bg);
+    } else {
+      bg.invisible = false;
+      var visualBorderColor = thisNode.getVisual('borderColor', true);
+      var emphasisBorderColor = itemStyleEmphasisModel.get('borderColor');
       var normalStyle = getItemStyleNormal(itemStyleNormalModel);
       normalStyle.fill = visualBorderColor;
       var emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel);
@@ -721,8 +754,9 @@ function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimat
         }
 
       bg.setStyle(normalStyle);
-      graphic.setHoverStyle(bg, emphasisStyle);
-    });
+      graphic.setElementHoverStyle(bg, emphasisStyle);
+    }
+
     group.add(bg);
   }
 
@@ -739,37 +773,33 @@ function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimat
       width: contentWidth,
       height: contentHeight
     });
-    var visualColor = thisNode.getVisual('color', true);
-    updateStyle(content, function () {
+
+    if (thisInvisible) {
+      // If invisible, do not set visual, otherwise the element will
+      // change immediately before animation. We think it is OK to
+      // remain its origin color when moving out of the view window.
+      processInvisible(content);
+    } else {
+      content.invisible = false;
+      var visualColor = thisNode.getVisual('color', true);
       var normalStyle = getItemStyleNormal(itemStyleNormalModel);
       normalStyle.fill = visualColor;
       var emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel);
       prepareText(normalStyle, emphasisStyle, visualColor, contentWidth, contentHeight);
       content.setStyle(normalStyle);
-      graphic.setHoverStyle(content, emphasisStyle);
-    });
+      graphic.setElementHoverStyle(content, emphasisStyle);
+    }
+
     group.add(content);
   }
 
-  function updateStyle(element, cb) {
-    if (!thisInvisible) {
-      // If invisible, do not set visual, otherwise the element will
-      // change immediately before animation. We think it is OK to
-      // remain its origin color when moving out of the view window.
-      cb();
-
-      if (!element.__tmWillVisible) {
-        element.invisible = false;
-      }
-    } else {
-      // Delay invisible setting utill animation finished,
-      // avoid element vanish suddenly before animation.
-      !element.invisible && willInvisibleEls.push(element);
-    }
+  function processInvisible(element) {
+    // Delay invisible setting utill animation finished,
+    // avoid element vanish suddenly before animation.
+    !element.invisible && willInvisibleEls.push(element);
   }
 
   function prepareText(normalStyle, emphasisStyle, visualColor, width, height, upperLabelRect) {
-    var nodeModel = thisNode.getModel();
     var text = zrUtil.retrieve(seriesModel.getFormattedLabel(thisNode.dataIndex, 'normal', null, null, upperLabelRect ? 'upperLabel' : 'label'), nodeModel.get('name'));
 
     if (!upperLabelRect && thisLayout.isLeafRoot) {
diff --git a/en/builder/src/echarts/component/axis/AxisBuilder.js b/en/builder/src/echarts/component/axis/AxisBuilder.js
index dfb33d4..9e43c4e 100644
--- a/en/builder/src/echarts/component/axis/AxisBuilder.js
+++ b/en/builder/src/echarts/component/axis/AxisBuilder.js
@@ -16,7 +16,7 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-import { retrieve, defaults, extend, each, map } from 'zrender/src/core/util';
+import { retrieve, defaults, extend, each } from 'zrender/src/core/util';
 import * as formatUtil from '../../util/format';
 import * as graphic from '../../util/graphic';
 import Model from '../../model/Model';
diff --git a/en/builder/src/echarts/component/axis/CartesianAxisView.js b/en/builder/src/echarts/component/axis/CartesianAxisView.js
index ccf5c08..8d1e056 100644
--- a/en/builder/src/echarts/component/axis/CartesianAxisView.js
+++ b/en/builder/src/echarts/component/axis/CartesianAxisView.js
@@ -21,6 +21,7 @@ import * as graphic from '../../util/graphic';
 import AxisBuilder from './AxisBuilder';
 import AxisView from './AxisView';
 import * as cartesianAxisHelper from '../../coord/cartesian/cartesianAxisHelper';
+import { rectCoordAxisBuildSplitArea, rectCoordAxisHandleRemove } from './axisSplitHelper';
 var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName'];
 var selfBuilderAttrs = ['splitArea', 'splitLine', 'minorSplitLine'];
 var CartesianAxisView = AxisView.extend({
@@ -56,7 +57,7 @@ var CartesianAxisView = AxisView.extend({
     CartesianAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
   },
   remove: function () {
-    this._splitAreaColors = null;
+    rectCoordAxisHandleRemove(this);
   },
 
   /**
@@ -179,89 +180,7 @@ var CartesianAxisView = AxisView.extend({
    * @private
    */
   _splitArea: function (axisModel, gridModel) {
-    var axis = axisModel.axis;
-
-    if (axis.scale.isBlank()) {
-      return;
-    }
-
-    var splitAreaModel = axisModel.getModel('splitArea');
-    var areaStyleModel = splitAreaModel.getModel('areaStyle');
-    var areaColors = areaStyleModel.get('color');
-    var gridRect = gridModel.coordinateSystem.getRect();
-    var ticksCoords = axis.getTicksCoords({
-      tickModel: splitAreaModel,
-      clamp: true
-    });
-
-    if (!ticksCoords.length) {
-      return;
-    } // For Making appropriate splitArea animation, the color and anid
-    // should be corresponding to previous one if possible.
-
-
-    var areaColorsLen = areaColors.length;
-    var lastSplitAreaColors = this._splitAreaColors;
-    var newSplitAreaColors = zrUtil.createHashMap();
-    var colorIndex = 0;
-
-    if (lastSplitAreaColors) {
-      for (var i = 0; i < ticksCoords.length; i++) {
-        var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
-
-        if (cIndex != null) {
-          colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
-          break;
-        }
-      }
-    }
-
-    var prev = axis.toGlobalCoord(ticksCoords[0].coord);
-    var areaStyle = areaStyleModel.getAreaStyle();
-    areaColors = zrUtil.isArray(areaColors) ? areaColors : [areaColors];
-
-    for (var i = 1; i < ticksCoords.length; i++) {
-      var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
-      var x;
-      var y;
-      var width;
-      var height;
-
-      if (axis.isHorizontal()) {
-        x = prev;
-        y = gridRect.y;
-        width = tickCoord - x;
-        height = gridRect.height;
-        prev = x + width;
-      } else {
-        x = gridRect.x;
-        y = prev;
-        width = gridRect.width;
-        height = tickCoord - y;
-        prev = y + height;
-      }
-
-      var tickValue = ticksCoords[i - 1].tickValue;
-      tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
-
-      this._axisGroup.add(new graphic.Rect({
-        anid: tickValue != null ? 'area_' + tickValue : null,
-        shape: {
-          x: x,
-          y: y,
-          width: width,
-          height: height
-        },
-        style: zrUtil.defaults({
-          fill: areaColors[colorIndex]
-        }, areaStyle),
-        silent: true
-      }));
-
-      colorIndex = (colorIndex + 1) % areaColorsLen;
-    }
-
-    this._splitAreaColors = newSplitAreaColors;
+    rectCoordAxisBuildSplitArea(this, this._axisGroup, axisModel, gridModel);
   }
 });
 CartesianAxisView.extend({
diff --git a/en/builder/src/echarts/component/axis/SingleAxisView.js b/en/builder/src/echarts/component/axis/SingleAxisView.js
index 98179f0..72f091f 100644
--- a/en/builder/src/echarts/component/axis/SingleAxisView.js
+++ b/en/builder/src/echarts/component/axis/SingleAxisView.js
@@ -21,25 +21,33 @@ import AxisBuilder from './AxisBuilder';
 import * as graphic from '../../util/graphic';
 import * as singleAxisHelper from '../../coord/single/singleAxisHelper';
 import AxisView from './AxisView';
+import { rectCoordAxisBuildSplitArea, rectCoordAxisHandleRemove } from './axisSplitHelper';
 var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName'];
-var selfBuilderAttr = 'splitLine';
+var selfBuilderAttrs = ['splitArea', 'splitLine'];
 var SingleAxisView = AxisView.extend({
   type: 'singleAxis',
   axisPointerClass: 'SingleAxisPointer',
   render: function (axisModel, ecModel, api, payload) {
     var group = this.group;
     group.removeAll();
+    var oldAxisGroup = this._axisGroup;
+    this._axisGroup = new graphic.Group();
     var layout = singleAxisHelper.layout(axisModel);
     var axisBuilder = new AxisBuilder(axisModel, layout);
     zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder);
+    group.add(this._axisGroup);
     group.add(axisBuilder.getGroup());
-
-    if (axisModel.get(selfBuilderAttr + '.show')) {
-      this['_' + selfBuilderAttr](axisModel);
-    }
-
+    zrUtil.each(selfBuilderAttrs, function (name) {
+      if (axisModel.get(name + '.show')) {
+        this['_' + name](axisModel);
+      }
+    }, this);
+    graphic.groupTransition(oldAxisGroup, this._axisGroup, axisModel);
     SingleAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
   },
+  remove: function () {
+    rectCoordAxisHandleRemove(this);
+  },
   _splitLine: function (axisModel) {
     var axis = axisModel.axis;
 
@@ -104,6 +112,9 @@ var SingleAxisView = AxisView.extend({
         silent: true
       }));
     }
+  },
+  _splitArea: function (axisModel) {
+    rectCoordAxisBuildSplitArea(this, this._axisGroup, axisModel, axisModel);
   }
 });
 export default SingleAxisView;
\ No newline at end of file
diff --git a/en/builder/src/echarts/component/axis/axisSplitHelper.js b/en/builder/src/echarts/component/axis/axisSplitHelper.js
new file mode 100644
index 0000000..a3fe14d
--- /dev/null
+++ b/en/builder/src/echarts/component/axis/axisSplitHelper.js
@@ -0,0 +1,106 @@
+/*
+* 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 zrUtil from 'zrender/src/core/util';
+import * as graphic from '../../util/graphic';
+export function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) {
+  var axis = axisModel.axis;
+
+  if (axis.scale.isBlank()) {
+    return;
+  }
+
+  var splitAreaModel = axisModel.getModel('splitArea');
+  var areaStyleModel = splitAreaModel.getModel('areaStyle');
+  var areaColors = areaStyleModel.get('color');
+  var gridRect = gridModel.coordinateSystem.getRect();
+  var ticksCoords = axis.getTicksCoords({
+    tickModel: splitAreaModel,
+    clamp: true
+  });
+
+  if (!ticksCoords.length) {
+    return;
+  } // For Making appropriate splitArea animation, the color and anid
+  // should be corresponding to previous one if possible.
+
+
+  var areaColorsLen = areaColors.length;
+  var lastSplitAreaColors = axisView.__splitAreaColors;
+  var newSplitAreaColors = zrUtil.createHashMap();
+  var colorIndex = 0;
+
+  if (lastSplitAreaColors) {
+    for (var i = 0; i < ticksCoords.length; i++) {
+      var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
+
+      if (cIndex != null) {
+        colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
+        break;
+      }
+    }
+  }
+
+  var prev = axis.toGlobalCoord(ticksCoords[0].coord);
+  var areaStyle = areaStyleModel.getAreaStyle();
+  areaColors = zrUtil.isArray(areaColors) ? areaColors : [areaColors];
+
+  for (var i = 1; i < ticksCoords.length; i++) {
+    var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
+    var x;
+    var y;
+    var width;
+    var height;
+
+    if (axis.isHorizontal()) {
+      x = prev;
+      y = gridRect.y;
+      width = tickCoord - x;
+      height = gridRect.height;
+      prev = x + width;
+    } else {
+      x = gridRect.x;
+      y = prev;
+      width = gridRect.width;
+      height = tickCoord - y;
+      prev = y + height;
+    }
+
+    var tickValue = ticksCoords[i - 1].tickValue;
+    tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
+    axisGroup.add(new graphic.Rect({
+      anid: tickValue != null ? 'area_' + tickValue : null,
+      shape: {
+        x: x,
+        y: y,
+        width: width,
+        height: height
+      },
+      style: zrUtil.defaults({
+        fill: areaColors[colorIndex]
+      }, areaStyle),
+      silent: true
+    }));
+    colorIndex = (colorIndex + 1) % areaColorsLen;
+  }
+
+  axisView.__splitAreaColors = newSplitAreaColors;
+}
+export function rectCoordAxisHandleRemove(axisView) {
+  axisView.__splitAreaColors = null;
+}
\ No newline at end of file
diff --git a/en/builder/src/echarts/component/brush/BrushView.js b/en/builder/src/echarts/component/brush/BrushView.js
index 23929fe..1bbcec4 100644
--- a/en/builder/src/echarts/component/brush/BrushView.js
+++ b/en/builder/src/echarts/component/brush/BrushView.js
@@ -19,6 +19,7 @@
 import * as echarts from '../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
 import BrushController from '../helper/BrushController';
+import { layoutCovers } from './visualEncoding';
 export default echarts.extendComponentView({
   type: 'brush',
   init: function (ecModel, api) {
@@ -58,7 +59,13 @@ export default echarts.extendComponentView({
   /**
    * @override
    */
-  updateTransform: updateController,
+  updateTransform: function (brushModel, ecModel) {
+    // PENDING: `updateTransform` is a little tricky, whose layout need
+    // to be calculate mandatorily and other stages will not be performed.
+    // Take care the correctness of the logic. See #11754 .
+    layoutCovers(ecModel);
+    return updateController.apply(this, arguments);
+  },
 
   /**
    * @override
diff --git a/en/builder/src/echarts/component/brush/visualEncoding.js b/en/builder/src/echarts/component/brush/visualEncoding.js
index 067da50..3da6969 100644
--- a/en/builder/src/echarts/component/brush/visualEncoding.js
+++ b/en/builder/src/echarts/component/brush/visualEncoding.js
@@ -38,10 +38,17 @@ echarts.registerLayout(PRIORITY_BRUSH, function (ecModel, api, payload) {
     payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(payload.key === 'brush' ? payload.brushOption : {
       brushType: false
     });
+  });
+  layoutCovers(ecModel);
+});
+export function layoutCovers(ecModel) {
+  ecModel.eachComponent({
+    mainType: 'brush'
+  }, function (brushModel) {
     var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel);
     brushTargetManager.setInputRanges(brushModel.areas, ecModel);
   });
-});
+}
 /**
  * Register the visual encoding if this modules required.
  */
diff --git a/en/builder/src/echarts/component/helper/MapDraw.js b/en/builder/src/echarts/component/helper/MapDraw.js
index 84fe81b..b925334 100644
--- a/en/builder/src/echarts/component/helper/MapDraw.js
+++ b/en/builder/src/echarts/component/helper/MapDraw.js
@@ -176,14 +176,12 @@ MapDraw.prototype = {
 
     var regionsGroup = this._regionsGroup;
     var group = this.group;
-
-    if (geo._roamTransformable.transform) {
-      group.transform = geo._roamTransformable.transform.slice();
-      group.decomposeTransform();
-    }
-
-    var scale = geo._rawTransformable.scale;
-    var position = geo._rawTransformable.position;
+    var transformInfo = geo.getTransformInfo();
+    group.transform = transformInfo.roamTransform;
+    group.decomposeTransform();
+    group.dirty();
+    var scale = transformInfo.rawScale;
+    var position = transformInfo.rawPosition;
     regionsGroup.removeAll();
     var itemStyleAccessPath = ['itemStyle'];
     var hoverItemStyleAccessPath = ['emphasis', 'itemStyle'];
diff --git a/en/builder/src/echarts/component/legend/ScrollableLegendView.js b/en/builder/src/echarts/component/legend/ScrollableLegendView.js
index b15c96e..dc00046 100644
--- a/en/builder/src/echarts/component/legend/ScrollableLegendView.js
+++ b/en/builder/src/echarts/component/legend/ScrollableLegendView.js
@@ -394,28 +394,28 @@ var ScrollableLegendView = LegendView.extend({
     }
   },
   _findTargetItemIndex: function (targetDataIndex) {
+    if (!this._showController) {
+      return 0;
+    }
+
     var index;
     var contentGroup = this.getContentGroup();
     var defaultIndex;
+    contentGroup.eachChild(function (child, idx) {
+      var legendDataIdx = child.__legendDataIndex; // FIXME
+      // If the given targetDataIndex (from model) is illegal,
+      // we use defualtIndex. But the index on the legend model and
+      // action payload is still illegal. That case will not be
+      // changed until some scenario requires.
+
+      if (defaultIndex == null && legendDataIdx != null) {
+        defaultIndex = idx;
+      }
 
-    if (this._showController) {
-      contentGroup.eachChild(function (child, idx) {
-        var legendDataIdx = child.__legendDataIndex; // FIXME
-        // If the given targetDataIndex (from model) is illegal,
-        // we use defualtIndex. But the index on the legend model and
-        // action payload is still illegal. That case will not be
-        // changed until some scenario requires.
-
-        if (defaultIndex == null && legendDataIdx != null) {
-          defaultIndex = idx;
-        }
-
-        if (legendDataIdx === targetDataIndex) {
-          index = idx;
-        }
-      });
-    }
-
+      if (legendDataIdx === targetDataIndex) {
+        index = idx;
+      }
+    });
     return index != null ? index : defaultIndex;
   }
 });
diff --git a/en/builder/src/echarts/component/marker/MarkLineModel.js b/en/builder/src/echarts/component/marker/MarkLineModel.js
index e7066b1..24d2772 100644
--- a/en/builder/src/echarts/component/marker/MarkLineModel.js
+++ b/en/builder/src/echarts/component/marker/MarkLineModel.js
@@ -31,7 +31,8 @@ export default MarkerModel.extend({
     },
     label: {
       show: true,
-      position: 'end'
+      position: 'end',
+      distance: 5
     },
     lineStyle: {
       type: 'dashed'
diff --git a/en/builder/src/echarts/component/marker/markerHelper.js b/en/builder/src/echarts/component/marker/markerHelper.js
index 9116957..6d7ce8f 100644
--- a/en/builder/src/echarts/component/marker/markerHelper.js
+++ b/en/builder/src/echarts/component/marker/markerHelper.js
@@ -60,7 +60,8 @@ function markerTypeCalculatorWithExtent(mlType, data, otherDataDim, targetDataDi
   var value = numCalculate(data, calcDataDim, mlType);
   var dataIndex = data.indicesOfNearest(calcDataDim, value)[0];
   coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex);
-  coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex); // Make it simple, do not visit all stacked value to count precision.
+  coordArr[targetCoordIndex] = data.get(calcDataDim, dataIndex);
+  var coordArrValue = data.get(targetDataDim, dataIndex); // Make it simple, do not visit all stacked value to count precision.
 
   var precision = numberUtil.getPrecision(data.get(targetDataDim, dataIndex));
   precision = Math.min(precision, 20);
@@ -69,7 +70,7 @@ function markerTypeCalculatorWithExtent(mlType, data, otherDataDim, targetDataDi
     coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
   }
 
-  return coordArr;
+  return [coordArr, coordArrValue];
 }
 
 var curry = zrUtil.curry; // TODO Specified percent
@@ -126,9 +127,11 @@ export function dataTransform(seriesModel, item) {
     if (item.type && markerTypeCalculator[item.type] && axisInfo.baseAxis && axisInfo.valueAxis) {
       var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim);
       var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim);
-      item.coord = markerTypeCalculator[item.type](data, axisInfo.baseDataDim, axisInfo.valueDataDim, otherCoordIndex, targetCoordIndex); // Force to use the value of calculated value.
+      var coordInfo = markerTypeCalculator[item.type](data, axisInfo.baseDataDim, axisInfo.valueDataDim, otherCoordIndex, targetCoordIndex);
+      item.coord = coordInfo[0]; // Force to use the value of calculated value.
+      // let item use the value without stack.
 
-      item.value = item.coord[targetCoordIndex];
+      item.value = coordInfo[1];
     } else {
       // FIXME Only has one of xAxis and yAxis.
       var coord = [item.xAxis != null ? item.xAxis : item.radiusAxis, item.yAxis != null ? item.yAxis : item.angleAxis]; // Each coord support max, min, average
diff --git a/en/builder/src/echarts/component/tooltip/TooltipContent.js b/en/builder/src/echarts/component/tooltip/TooltipContent.js
index 20e0ee4..4a6b6e1 100644
--- a/en/builder/src/echarts/component/tooltip/TooltipContent.js
+++ b/en/builder/src/echarts/component/tooltip/TooltipContent.js
@@ -19,6 +19,7 @@
 import * as zrUtil from 'zrender/src/core/util';
 import * as zrColor from 'zrender/src/tool/color';
 import * as eventUtil from 'zrender/src/core/event';
+import * as domUtil from 'zrender/src/core/dom';
 import env from 'zrender/src/core/env';
 import * as formatUtil from '../../util/format';
 var each = zrUtil.each;
@@ -99,24 +100,65 @@ function assembleCssText(tooltipModel) {
   }
 
   return cssText.join(';') + ';';
+} // If not able to make, do not modify the input `out`.
+
+
+function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
+  var zrPainter = zr && zr.painter;
+
+  if (appendToBody) {
+    var zrViewportRoot = zrPainter && zrPainter.getViewportRoot();
+
+    if (zrViewportRoot) {
+      // Some APPs might use scale on body, so we support CSS transform here.
+      domUtil.transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY);
+    }
+  } else {
+    out[0] = zrX;
+    out[1] = zrY; // xy should be based on canvas root. But tooltipContent is
+    // the sibling of canvas root. So padding of ec container
+    // should be considered here.
+
+    var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset();
+
+    if (viewportRootOffset) {
+      out[0] += viewportRootOffset.offsetLeft;
+      out[1] += viewportRootOffset.offsetTop;
+    }
+  }
 }
 /**
  * @alias module:echarts/component/tooltip/TooltipContent
+ * @param {HTMLElement} container
+ * @param {ExtensionAPI} api
+ * @param {Object} [opt]
+ * @param {boolean} [opt.appendToBody]
+ *        `false`: the DOM element will be inside the container. Default value.
+ *        `true`: the DOM element will be appended to HTML body, which avoid
+ *                some overflow clip but intrude outside of the container.
  * @constructor
  */
 
 
-function TooltipContent(container, api) {
+function TooltipContent(container, api, opt) {
   if (env.wxa) {
     return null;
   }
 
   var el = document.createElement('div');
-  var zr = this._zr = api.getZr();
+  el.domBelongToZr = true;
   this.el = el;
-  this._x = api.getWidth() / 2;
-  this._y = api.getHeight() / 2;
-  container.appendChild(el);
+  var zr = this._zr = api.getZr();
+  var appendToBody = this._appendToBody = opt && opt.appendToBody;
+  this._styleCoord = [0, 0];
+  makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
+
+  if (appendToBody) {
+    document.body.appendChild(el);
+  } else {
+    container.appendChild(el);
+  }
+
   this._container = container;
   this._show = false;
   /**
@@ -150,7 +192,8 @@ function TooltipContent(container, api) {
       // Try trigger zrender event to avoid mouse
       // in and out shape too frequently
       var handler = zr.handler;
-      eventUtil.normalizeEvent(container, e, true);
+      var zrViewportRoot = zr.painter.getViewportRoot();
+      eventUtil.normalizeEvent(zrViewportRoot, e, true);
       handler.dispatch('mousemove', e);
     }
   };
@@ -195,10 +238,11 @@ TooltipContent.prototype = {
   show: function (tooltipModel) {
     clearTimeout(this._hideTimeout);
     var el = this.el;
+    var styleCoord = this._styleCoord;
     el.style.cssText = gCssText + assembleCssText(tooltipModel) // Because of the reason described in:
     // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
     // we should set initial value to `left` and `top`.
-    + ';left:' + this._x + 'px;top:' + this._y + 'px;' + (tooltipModel.get('extraCssText') || '');
+    + ';left:' + styleCoord[0] + 'px;top:' + styleCoord[1] + 'px;' + (tooltipModel.get('extraCssText') || '');
     el.style.display = el.innerHTML ? 'block' : 'none'; // If mouse occsionally move over the tooltip, a mouseout event will be
     // triggered by canvas, and cuase some unexpectable result like dragging
     // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
@@ -218,23 +262,12 @@ TooltipContent.prototype = {
     var el = this.el;
     return [el.clientWidth, el.clientHeight];
   },
-  moveTo: function (x, y) {
-    // xy should be based on canvas root. But tooltipContent is
-    // the sibling of canvas root. So padding of ec container
-    // should be considered here.
-    var zr = this._zr;
-    var viewportRootOffset;
-
-    if (zr && zr.painter && (viewportRootOffset = zr.painter.getViewportRootOffset())) {
-      x += viewportRootOffset.offsetLeft;
-      y += viewportRootOffset.offsetTop;
-    }
-
+  moveTo: function (zrX, zrY) {
+    var styleCoord = this._styleCoord;
+    makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY);
     var style = this.el.style;
-    style.left = x + 'px';
-    style.top = y + 'px';
-    this._x = x;
-    this._y = y;
+    style.left = styleCoord[0] + 'px';
+    style.top = styleCoord[1] + 'px';
   },
   hide: function () {
     this.el.style.display = 'none';
@@ -255,6 +288,9 @@ TooltipContent.prototype = {
   isShow: function () {
     return this._show;
   },
+  dispose: function () {
+    this.el.parentNode.removeChild(this.el);
+  },
   getOuterSize: function () {
     var width = this.el.clientWidth;
     var height = this.el.clientHeight; // Consider browser compatibility.
diff --git a/en/builder/src/echarts/component/tooltip/TooltipView.js b/en/builder/src/echarts/component/tooltip/TooltipView.js
index 4ed5387..6e6912f 100644
--- a/en/builder/src/echarts/component/tooltip/TooltipView.js
+++ b/en/builder/src/echarts/component/tooltip/TooltipView.js
@@ -55,7 +55,9 @@ export default echarts.extendComponentView({
     var tooltipContent;
 
     if (this._renderMode === 'html') {
-      tooltipContent = new TooltipContent(api.getDom(), api);
+      tooltipContent = new TooltipContent(api.getDom(), api, {
+        appendToBody: tooltipModel.get('appendToBody', true)
+      });
       this._newLine = '<br/>';
     } else {
       tooltipContent = new TooltipRichContent(api);
@@ -190,7 +192,6 @@ export default echarts.extendComponentView({
         offsetX: payload.x,
         offsetY: payload.y,
         position: payload.position,
-        event: {},
         dataByCoordSys: payload.dataByCoordSys,
         tooltipOption: payload.tooltipOption
       }, dispatchAction);
@@ -208,8 +209,7 @@ export default echarts.extendComponentView({
           offsetX: cx,
           offsetY: cy,
           position: payload.position,
-          target: pointInfo.el,
-          event: {}
+          target: pointInfo.el
         }, dispatchAction);
       }
     } else if (payload.x != null && payload.y != null) {
@@ -225,8 +225,7 @@ export default echarts.extendComponentView({
         offsetX: payload.x,
         offsetY: payload.y,
         position: payload.position,
-        target: api.getZr().findHover(payload.x, payload.y).target,
-        event: {}
+        target: api.getZr().findHover(payload.x, payload.y).target
       }, dispatchAction);
     }
   },
@@ -620,7 +619,7 @@ export default echarts.extendComponentView({
       return;
     }
 
-    this._tooltipContent.hide();
+    this._tooltipContent.dispose();
 
     globalListener.unregister('itemTooltip', api);
   }
diff --git a/en/builder/src/echarts/coord/View.js b/en/builder/src/echarts/coord/View.js
index fb5c5fb..228370f 100644
--- a/en/builder/src/echarts/coord/View.js
+++ b/en/builder/src/echarts/coord/View.js
@@ -205,6 +205,15 @@ View.prototype = {
     matrix.invert(this.invTransform, this.transform);
     this.decomposeTransform();
   },
+  getTransformInfo: function () {
+    var roamTransform = this._roamTransformable.transform;
+    var rawTransformable = this._rawTransformable;
+    return {
+      roamTransform: roamTransform ? zrUtil.slice(roamTransform) : matrix.create(),
+      rawScale: zrUtil.slice(rawTransformable.scale),
+      rawPosition: zrUtil.slice(rawTransformable.position)
+    };
+  },
 
   /**
    * @return {module:zrender/core/BoundingRect}
diff --git a/en/builder/src/echarts/coord/radar/Radar.js b/en/builder/src/echarts/coord/radar/Radar.js
index 749d6b8..77b4cad 100644
--- a/en/builder/src/echarts/coord/radar/Radar.js
+++ b/en/builder/src/echarts/coord/radar/Radar.js
@@ -218,12 +218,12 @@ Radar.prototype.update = function (ecModel, api) {
 
       if (nicedSplitNumber > splitNumber) {
         interval = increaseInterval(interval);
-      } // PENDING
+      } // TODO
 
 
-      var center = Math.round((rawExtent[0] + rawExtent[1]) / 2 / interval) * interval;
-      var halfSplitNumber = Math.round(splitNumber / 2);
-      scale.setExtent(numberUtil.round(center - halfSplitNumber * interval), numberUtil.round(center + (splitNumber - halfSplitNumber) * interval));
+      var max = Math.ceil(rawExtent[1] / interval) * interval;
+      var min = numberUtil.round(max - interval * splitNumber);
+      scale.setExtent(min, max);
       scale.setInterval(interval);
     }
   });
diff --git a/en/builder/src/echarts/echarts.js b/en/builder/src/echarts/echarts.js
index 5c56314..76ac79d 100644
--- a/en/builder/src/echarts/echarts.js
+++ b/en/builder/src/echarts/echarts.js
@@ -49,9 +49,9 @@ var each = zrUtil.each;
 var isFunction = zrUtil.isFunction;
 var isObject = zrUtil.isObject;
 var parseClassType = ComponentModel.parseClassType;
-export var version = '4.6.0';
+export var version = '4.7.0';
 export var dependencies = {
-  zrender: '4.2.0'
+  zrender: '4.3.0'
 };
 var TEST_FRAME_REMAIN_TIME = 1;
 var PRIORITY_PROCESSOR_FILTER = 1000;
diff --git a/en/builder/src/echarts/layout/barGrid.js b/en/builder/src/echarts/layout/barGrid.js
index 178cc05..adece5b 100644
--- a/en/builder/src/echarts/layout/barGrid.js
+++ b/en/builder/src/echarts/layout/barGrid.js
@@ -396,12 +396,7 @@ export function layout(seriesType, ecModel) {
 
     for (var idx = 0, len = data.count(); idx < len; idx++) {
       var value = data.get(valueDim, idx);
-      var baseValue = data.get(baseDim, idx); // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
-
-      if (isNaN(value) || isNaN(baseValue)) {
-        continue;
-      }
-
+      var baseValue = data.get(baseDim, idx);
       var sign = value >= 0 ? 'p' : 'n';
       var baseCoord = valueAxisStart; // Because of the barMinHeight, we can not use the value in
       // stackResultDimension directly.
@@ -435,9 +430,12 @@ export function layout(seriesType, ecModel) {
 
         if (Math.abs(width) < barMinHeight) {
           width = (width < 0 ? -1 : 1) * barMinHeight;
-        }
+        } // Ignore stack from NaN value
+
 
-        stacked && (lastStackCoords[stackId][baseValue][sign] += width);
+        if (!isNaN(width)) {
+          stacked && (lastStackCoords[stackId][baseValue][sign] += width);
+        }
       } else {
         var coord = cartesian.dataToPoint([baseValue, value]);
         x = coord[0] + columnOffset;
@@ -448,9 +446,12 @@ export function layout(seriesType, ecModel) {
         if (Math.abs(height) < barMinHeight) {
           // Include zero to has a positive bar
           height = (height <= 0 ? -1 : 1) * barMinHeight;
-        }
+        } // Ignore stack from NaN value
 
-        stacked && (lastStackCoords[stackId][baseValue][sign] += height);
+
+        if (!isNaN(height)) {
+          stacked && (lastStackCoords[stackId][baseValue][sign] += height);
+        }
       }
 
       data.setItemLayout(idx, {
@@ -473,6 +474,7 @@ export var largeLayout = {
 
     var data = seriesModel.getData();
     var cartesian = seriesModel.coordinateSystem;
+    var coordLayout = cartesian.grid.getRect();
     var baseAxis = cartesian.getBaseAxis();
     var valueAxis = cartesian.getOtherAxis(baseAxis);
     var valueDim = data.mapDimension(valueAxis.dim);
@@ -493,6 +495,7 @@ export var largeLayout = {
     function progress(params, data) {
       var count = params.count;
       var largePoints = new LargeArr(count * 2);
+      var largeBackgroundPoints = new LargeArr(count * 2);
       var largeDataIndices = new LargeArr(count);
       var dataIndex;
       var coord = [];
@@ -505,7 +508,9 @@ export var largeLayout = {
         valuePair[1 - valueDimIdx] = data.get(baseDim, dataIndex);
         coord = cartesian.dataToPoint(valuePair, null, coord); // Data index might not be in order, depends on `progressiveChunkMode`.
 
+        largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coordLayout.x + coordLayout.width : coord[0];
         largePoints[pointsOffset++] = coord[0];
+        largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coord[1] : coordLayout.y + coordLayout.height;
         largePoints[pointsOffset++] = coord[1];
         largeDataIndices[idxOffset++] = dataIndex;
       }
@@ -513,8 +518,10 @@ export var largeLayout = {
       data.setLayout({
         largePoints: largePoints,
         largeDataIndices: largeDataIndices,
+        largeBackgroundPoints: largeBackgroundPoints,
         barWidth: barWidth,
         valueAxisStart: getValueAxisStart(baseAxis, valueAxis, false),
+        backgroundStart: valueAxisHorizontal ? coordLayout.x : coordLayout.y,
         valueAxisHorizontal: valueAxisHorizontal
       });
     }
diff --git a/en/builder/src/echarts/layout/barPolar.js b/en/builder/src/echarts/layout/barPolar.js
index d76b556..6ead4f3 100644
--- a/en/builder/src/echarts/layout/barPolar.js
+++ b/en/builder/src/echarts/layout/barPolar.js
@@ -70,11 +70,6 @@ function barLayoutPolar(seriesType, ecModel, api) {
     for (var idx = 0, len = data.count(); idx < len; idx++) {
       var value = data.get(valueDim, idx);
       var baseValue = data.get(baseDim, idx);
-
-      if (isNaN(value)) {
-        continue;
-      }
-
       var sign = value >= 0 ? 'p' : 'n';
       var baseCoord = valueAxisStart; // Because of the barMinHeight, we can not use the value in
       // stackResultDimension directly.
diff --git a/en/builder/src/echarts/scale/Interval.js b/en/builder/src/echarts/scale/Interval.js
index b156129..069a4d4 100644
--- a/en/builder/src/echarts/scale/Interval.js
+++ b/en/builder/src/echarts/scale/Interval.js
@@ -92,7 +92,7 @@ var IntervalScale = Scale.extend({
 
     if (extent[0] < niceTickExtent[0]) {
       if (expandToNicedExtent) {
-        ticks.push(roundNumber(niceTickExtent[0] - interval));
+        ticks.push(roundNumber(niceTickExtent[0] - interval, intervalPrecision));
       } else {
         ticks.push(extent[0]);
       }
@@ -122,7 +122,7 @@ var IntervalScale = Scale.extend({
 
     if (extent[1] > lastNiceTick) {
       if (expandToNicedExtent) {
-        ticks.push(lastNiceTick + interval);
+        ticks.push(roundNumber(lastNiceTick + interval, intervalPrecision));
       } else {
         ticks.push(extent[1]);
       }
diff --git a/en/builder/src/echarts/stream/Scheduler.js b/en/builder/src/echarts/stream/Scheduler.js
index ba888f9..7a281f0 100644
--- a/en/builder/src/echarts/stream/Scheduler.js
+++ b/en/builder/src/echarts/stream/Scheduler.js
@@ -242,7 +242,15 @@ function performStageTasks(scheduler, stageHandlers, ecModel, payload, opt) {
           task.dirty();
         }
 
-        var performArgs = scheduler.getPerformArgs(task, opt.block);
+        var performArgs = scheduler.getPerformArgs(task, opt.block); // FIXME
+        // if intending to decalare `performRawSeries` in handlers, only
+        // stream-independent (specifically, data item independent) operations can be
+        // performed. Because is a series is filtered, most of the tasks will not
+        // be performed. A stream-dependent operation probably cause wrong biz logic.
+        // Perhaps we should not provide a separate callback for this case instead
+        // of providing the config `performRawSeries`. The stream-dependent operaions
+        // and stream-independent operations should better not be mixed.
+
         performArgs.skip = !stageHandler.performRawSeries && ecModel.isSeriesFiltered(task.context.model);
         updatePayload(task, payload);
         unfinished |= task.perform(performArgs);
diff --git a/en/builder/src/echarts/util/graphic.js b/en/builder/src/echarts/util/graphic.js
index 93ae10f..e31a002 100644
--- a/en/builder/src/echarts/util/graphic.js
+++ b/en/builder/src/echarts/util/graphic.js
@@ -1071,7 +1071,7 @@ function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb)
  * configuration in series.
  *
  * Caution: this method will stop previous animation.
- * So if do not use this method to one element twice before
+ * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  *
  * @param {module:zrender/Element} el
@@ -1098,7 +1098,7 @@ export function updateProps(el, props, animatableModel, dataIndex, cb) {
  * configuration in series.
  *
  * Caution: this method will stop previous animation.
- * So if do not use this method to one element twice before
+ * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  *
  * @param {module:zrender/Element} el
diff --git a/en/builder/src/zrender/animation/Animation.js b/en/builder/src/zrender/animation/Animation.js
index b912018..19201e6 100644
--- a/en/builder/src/zrender/animation/Animation.js
+++ b/en/builder/src/zrender/animation/Animation.js
@@ -1,5 +1,5 @@
 /**
- * 动画主类, 调度和管理所有动画控制器
+ * Animation main class, dispatch and manage all animation controllers
  *
  * @module zrender/animation/Animation
  * @author pissang(https://github.com/pissang)
@@ -60,7 +60,7 @@ Animation.prototype = {
   constructor: Animation,
 
   /**
-   * 添加 clip
+   * Add clip
    * @param {module:zrender/animation/Clip} clip
    */
   addClip: function (clip) {
@@ -68,7 +68,7 @@ Animation.prototype = {
   },
 
   /**
-   * 添加 animator
+   * Add animator
    * @param {module:zrender/animation/Animator} animator
    */
   addAnimator: function (animator) {
@@ -81,7 +81,7 @@ Animation.prototype = {
   },
 
   /**
-   * 删除动画片段
+   * Delete animation clip
    * @param {module:zrender/animation/Clip} clip
    */
   removeClip: function (clip) {
@@ -93,7 +93,7 @@ Animation.prototype = {
   },
 
   /**
-   * 删除动画片段
+   * Delete animation clip
    * @param {module:zrender/animation/Animator} animator
    */
   removeAnimator: function (animator) {
diff --git a/en/builder/src/zrender/animation/Animator.js b/en/builder/src/zrender/animation/Animator.js
index 324760b..cb72a1e 100644
--- a/en/builder/src/zrender/animation/Animator.js
+++ b/en/builder/src/zrender/animation/Animator.js
@@ -433,7 +433,7 @@ var Animator = function (target, loop, getter, setter) {
 
 Animator.prototype = {
   /**
-   * 设置动画关键帧
+   * Set Animation keyframe
    * @param  {number} time 关键帧时间,单位是ms
    * @param  {Object} props 关键帧的属性值,key-value表示
    * @return {module:zrender/animation/Animator}
@@ -520,7 +520,7 @@ Animator.prototype = {
   },
 
   /**
-   * 开始执行动画
+   * Start the animation
    * @param  {string|Function} [easing]
    *         动画缓动函数,详见{@link module:zrender/animation/easing}
    * @param  {boolean} forceAnimate
@@ -584,7 +584,7 @@ Animator.prototype = {
   },
 
   /**
-   * 停止动画
+   * Stop animation
    * @param {boolean} forwardToLast If move to last frame before stop
    */
   stop: function (forwardToLast) {
@@ -606,7 +606,7 @@ Animator.prototype = {
   },
 
   /**
-   * 设置动画延迟开始的时间
+   * Set when animation delay starts
    * @param  {number} time 单位ms
    * @return {module:zrender/animation/Animator}
    */
@@ -616,7 +616,7 @@ Animator.prototype = {
   },
 
   /**
-   * 添加动画结束的回调
+   * Add callback for animation end
    * @param  {Function} cb
    * @return {module:zrender/animation/Animator}
    */
diff --git a/zh/builder/src/zrender/animation/Animator.js b/en/builder/src/zrender/animation/track.js
old mode 100644
new mode 100755
similarity index 61%
copy from zh/builder/src/zrender/animation/Animator.js
copy to en/builder/src/zrender/animation/track.js
index 324760b..9056389
--- a/zh/builder/src/zrender/animation/Animator.js
+++ b/en/builder/src/zrender/animation/track.js
@@ -1,230 +1,32 @@
-/**
- * @module echarts/animation/Animator
- */
 import Clip from './Clip';
-import * as color from '../tool/color';
 import { isArrayLike } from '../core/util';
+import * as color from '../tool/color';
 var arraySlice = Array.prototype.slice;
-
-function defaultGetter(target, key) {
-  return target[key];
-}
-
-function defaultSetter(target, key, value) {
-  target[key] = value;
-}
-/**
- * @param  {number} p0
- * @param  {number} p1
- * @param  {number} percent
- * @return {number}
- */
-
-
-function interpolateNumber(p0, p1, percent) {
-  return (p1 - p0) * percent + p0;
-}
-/**
- * @param  {string} p0
- * @param  {string} p1
- * @param  {number} percent
- * @return {string}
- */
-
-
-function interpolateString(p0, p1, percent) {
-  return percent > 0.5 ? p1 : p0;
-}
-/**
- * @param  {Array} p0
- * @param  {Array} p1
- * @param  {number} percent
- * @param  {Array} out
- * @param  {number} arrDim
- */
-
-
-function interpolateArray(p0, p1, percent, out, arrDim) {
-  var len = p0.length;
-
-  if (arrDim === 1) {
-    for (var i = 0; i < len; i++) {
-      out[i] = interpolateNumber(p0[i], p1[i], percent);
-    }
-  } else {
-    var len2 = len && p0[0].length;
-
-    for (var i = 0; i < len; i++) {
-      for (var j = 0; j < len2; j++) {
-        out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent);
-      }
-    }
-  }
-} // arr0 is source array, arr1 is target array.
-// Do some preprocess to avoid error happened when interpolating from arr0 to arr1
-
-
-function fillArr(arr0, arr1, arrDim) {
-  var arr0Len = arr0.length;
-  var arr1Len = arr1.length;
-
-  if (arr0Len !== arr1Len) {
-    // FIXME Not work for TypedArray
-    var isPreviousLarger = arr0Len > arr1Len;
-
-    if (isPreviousLarger) {
-      // Cut the previous
-      arr0.length = arr1Len;
-    } else {
-      // Fill the previous
-      for (var i = arr0Len; i < arr1Len; i++) {
-        arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i]));
-      }
-    }
-  } // Handling NaN value
-
-
-  var len2 = arr0[0] && arr0[0].length;
-
-  for (var i = 0; i < arr0.length; i++) {
-    if (arrDim === 1) {
-      if (isNaN(arr0[i])) {
-        arr0[i] = arr1[i];
-      }
-    } else {
-      for (var j = 0; j < len2; j++) {
-        if (isNaN(arr0[i][j])) {
-          arr0[i][j] = arr1[i][j];
-        }
-      }
-    }
-  }
-}
-/**
- * @param  {Array} arr0
- * @param  {Array} arr1
- * @param  {number} arrDim
- * @return {boolean}
- */
-
-
-function isArraySame(arr0, arr1, arrDim) {
-  if (arr0 === arr1) {
-    return true;
-  }
-
-  var len = arr0.length;
-
-  if (len !== arr1.length) {
-    return false;
-  }
-
-  if (arrDim === 1) {
-    for (var i = 0; i < len; i++) {
-      if (arr0[i] !== arr1[i]) {
-        return false;
-      }
-    }
-  } else {
-    var len2 = arr0[0].length;
-
-    for (var i = 0; i < len; i++) {
-      for (var j = 0; j < len2; j++) {
-        if (arr0[i][j] !== arr1[i][j]) {
-          return false;
-        }
-      }
-    }
-  }
-
-  return true;
-}
-/**
- * Catmull Rom interpolate array
- * @param  {Array} p0
- * @param  {Array} p1
- * @param  {Array} p2
- * @param  {Array} p3
- * @param  {number} t
- * @param  {number} t2
- * @param  {number} t3
- * @param  {Array} out
- * @param  {number} arrDim
- */
-
-
-function catmullRomInterpolateArray(p0, p1, p2, p3, t, t2, t3, out, arrDim) {
-  var len = p0.length;
-
-  if (arrDim === 1) {
-    for (var i = 0; i < len; i++) {
-      out[i] = catmullRomInterpolate(p0[i], p1[i], p2[i], p3[i], t, t2, t3);
-    }
-  } else {
-    var len2 = p0[0].length;
-
-    for (var i = 0; i < len; i++) {
-      for (var j = 0; j < len2; j++) {
-        out[i][j] = catmullRomInterpolate(p0[i][j], p1[i][j], p2[i][j], p3[i][j], t, t2, t3);
-      }
-    }
-  }
-}
 /**
- * Catmull Rom interpolate number
- * @param  {number} p0
- * @param  {number} p1
- * @param  {number} p2
- * @param  {number} p3
- * @param  {number} t
- * @param  {number} t2
- * @param  {number} t3
- * @return {number}
+ * @param {Object} target
+ * @param {string} propName
+ * @param {Array.<Object>} keyframes
+ *        [{
+ *            time: number,
+ *            value: number | color string | Array.<number> | Array.<Array.<number>>
+ *        }, ...]
+ *        [Caveat]:
+ *        (1) The order should ensured by time.
+ *        (2) If `value` is `Array`, it must not be shared outside (espaciall el.shape, el.style),
+ *        in case that it be modified outside and cause incorrect interpolate result.
+ * @param {string} easing
+ * @param {boolean} [delay=false]
+ * @param {boolean} [loop=false]
+ * @param {boolean} [forceAnimate=false]
+ * @param {Function} [getter=defaultGetter]
+ * @param {Function} [setter=defaultSetter]
+ * @return {module:zrender/animation/Clip} clip
  */
 
-
-function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) {
-  var v0 = (p2 - p0) * 0.5;
-  var v1 = (p3 - p1) * 0.5;
-  return (2 * (p1 - p2) + v0 + v1) * t3 + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + v0 * t + p1;
-}
-
-function cloneValue(value) {
-  if (isArrayLike(value)) {
-    var len = value.length;
-
-    if (isArrayLike(value[0])) {
-      var ret = [];
-
-      for (var i = 0; i < len; i++) {
-        ret.push(arraySlice.call(value[i]));
-      }
-
-      return ret;
-    }
-
-    return arraySlice.call(value);
-  }
-
-  return value;
-}
-
-function rgba2String(rgba) {
-  rgba[0] = Math.floor(rgba[0]);
-  rgba[1] = Math.floor(rgba[1]);
-  rgba[2] = Math.floor(rgba[2]);
-  return 'rgba(' + rgba.join(',') + ')';
-}
-
-function getArrayDim(keyframes) {
-  var lastValue = keyframes[keyframes.length - 1].value;
-  return isArrayLike(lastValue && lastValue[0]) ? 2 : 1;
-}
-
-function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, forceAnimate) {
-  var getter = animator._getter;
-  var setter = animator._setter;
+export function createTrackClip(target, propName, keyframes, easing, delay, loop, forceAnimate, getter, setter) {
   var useSpline = easing === 'spline';
+  getter = getter || defaultGetter;
+  setter = setter || defaultSetter;
   var trackLen = keyframes.length;
 
   if (!trackLen) {
@@ -238,11 +40,7 @@ function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, fo
   var isValueString = false; // For vertices morphing
 
   var arrDim = isValueArray ? getArrayDim(keyframes) : 0;
-  var trackMaxTime; // Sort keyframe as ascending
-
-  keyframes.sort(function (a, b) {
-    return a.time - b.time;
-  });
+  var trackMaxTime;
   trackMaxTime = keyframes[trackLen - 1].time; // Percents of each keyframe
 
   var kfPercents = []; // Value of each keyframe
@@ -292,7 +90,7 @@ function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, fo
     }
   }
 
-  isValueArray && fillArr(getter(animator._target, propName), lastValue, arrDim); // Cache the key of last frame to speed up when
+  isValueArray && fillArr(getter(target, propName), lastValue, arrDim); // Cache the key of last frame to speed up when
   // animation playback is sequency
 
   var lastFrame = 0;
@@ -308,7 +106,7 @@ function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, fo
     var rgba = [0, 0, 0, 0];
   }
 
-  var onframe = function (target, percent) {
+  function hanleFrame(target, percent) {
     // Find the range keyframes
     // kf1-----kf2---------current--------kf3
     // find kf2 and kf3 and do interpolation
@@ -388,18 +186,21 @@ function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, fo
           value = interpolateNumber(kfValues[frame], kfValues[frame + 1], w);
         }
 
+        if (target.aaaa != null) {
+          console.log(target.uuid, value, propName);
+        }
+
         setter(target, propName, value);
       }
     }
-  };
+  }
 
   var clip = new Clip({
-    target: animator._target,
+    target: target,
     life: trackMaxTime,
-    loop: animator._loop,
-    delay: animator._delay,
-    onframe: onframe,
-    ondestroy: oneTrackDone
+    loop: loop,
+    delay: delay,
+    onframe: hanleFrame
   });
 
   if (easing && easing !== 'spline') {
@@ -408,231 +209,216 @@ function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, fo
 
   return clip;
 }
+
+function getArrayDim(keyframes) {
+  var lastValue = keyframes[keyframes.length - 1].value;
+  return isArrayLike(lastValue && lastValue[0]) ? 2 : 1;
+}
 /**
- * @alias module:zrender/animation/Animator
- * @constructor
- * @param {Object} target
- * @param {boolean} loop
- * @param {Function} getter
- * @param {Function} setter
+ * @param  {Array} arr0
+ * @param  {Array} arr1
+ * @param  {number} arrDim
+ * @return {boolean}
  */
 
 
-var Animator = function (target, loop, getter, setter) {
-  this._tracks = {};
-  this._target = target;
-  this._loop = loop || false;
-  this._getter = getter || defaultGetter;
-  this._setter = setter || defaultSetter;
-  this._clipCount = 0;
-  this._delay = 0;
-  this._doneList = [];
-  this._onframeList = [];
-  this._clipList = [];
-};
-
-Animator.prototype = {
-  /**
-   * 设置动画关键帧
-   * @param  {number} time 关键帧时间,单位是ms
-   * @param  {Object} props 关键帧的属性值,key-value表示
-   * @return {module:zrender/animation/Animator}
-   */
-  when: function (time
-  /* ms */
-  , props) {
-    var tracks = this._tracks;
-
-    for (var propName in props) {
-      if (!props.hasOwnProperty(propName)) {
-        continue;
-      }
-
-      if (!tracks[propName]) {
-        tracks[propName] = []; // Invalid value
+function isArraySame(arr0, arr1, arrDim) {
+  if (arr0 === arr1) {
+    return true;
+  }
 
-        var value = this._getter(this._target, propName);
+  var len = arr0.length;
 
-        if (value == null) {
-          // zrLog('Invalid property ' + propName);
-          continue;
-        } // If time is 0
-        //  Then props is given initialize value
-        // Else
-        //  Initialize value from current prop value
+  if (len !== arr1.length) {
+    return false;
+  }
 
+  if (arrDim === 1) {
+    for (var i = 0; i < len; i++) {
+      if (arr0[i] !== arr1[i]) {
+        return false;
+      }
+    }
+  } else {
+    var len2 = arr0[0].length;
 
-        if (time !== 0) {
-          tracks[propName].push({
-            time: 0,
-            value: cloneValue(value)
-          });
+    for (var i = 0; i < len; i++) {
+      for (var j = 0; j < len2; j++) {
+        if (arr0[i][j] !== arr1[i][j]) {
+          return false;
         }
       }
-
-      tracks[propName].push({
-        time: time,
-        value: props[propName]
-      });
     }
+  }
+
+  return true;
+} // arr0 is source array, arr1 is target array.
+// Do some preprocess to avoid error happened when interpolating from arr0 to arr1
+
+
+function fillArr(arr0, arr1, arrDim) {
+  var arr0Len = arr0.length;
+  var arr1Len = arr1.length;
 
-    return this;
-  },
-
-  /**
-   * 添加动画每一帧的回调函数
-   * @param  {Function} callback
-   * @return {module:zrender/animation/Animator}
-   */
-  during: function (callback) {
-    this._onframeList.push(callback);
-
-    return this;
-  },
-  pause: function () {
-    for (var i = 0; i < this._clipList.length; i++) {
-      this._clipList[i].pause();
+  if (arr0Len !== arr1Len) {
+    // FIXME Not work for TypedArray
+    var isPreviousLarger = arr0Len > arr1Len;
+
+    if (isPreviousLarger) {
+      // Cut the previous
+      arr0.length = arr1Len;
+    } else {
+      // Fill the previous
+      for (var i = arr0Len; i < arr1Len; i++) {
+        arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i]));
+      }
     }
+  } // Handling NaN value
+
+
+  var len2 = arr0[0] && arr0[0].length;
 
-    this._paused = true;
-  },
-  resume: function () {
-    for (var i = 0; i < this._clipList.length; i++) {
-      this._clipList[i].resume();
+  for (var i = 0; i < arr0.length; i++) {
+    if (arrDim === 1) {
+      if (isNaN(arr0[i])) {
+        arr0[i] = arr1[i];
+      }
+    } else {
+      for (var j = 0; j < len2; j++) {
+        if (isNaN(arr0[i][j])) {
+          arr0[i][j] = arr1[i][j];
+        }
+      }
     }
+  }
+}
+/**
+ * Catmull Rom interpolate array
+ * @param  {Array} p0
+ * @param  {Array} p1
+ * @param  {Array} p2
+ * @param  {Array} p3
+ * @param  {number} t
+ * @param  {number} t2
+ * @param  {number} t3
+ * @param  {Array} out
+ * @param  {number} arrDim
+ */
 
-    this._paused = false;
-  },
-  isPaused: function () {
-    return !!this._paused;
-  },
-  _doneCallback: function () {
-    // Clear all tracks
-    this._tracks = {}; // Clear all clips
 
-    this._clipList.length = 0;
-    var doneList = this._doneList;
-    var len = doneList.length;
+function catmullRomInterpolateArray(p0, p1, p2, p3, t, t2, t3, out, arrDim) {
+  var len = p0.length;
 
+  if (arrDim === 1) {
     for (var i = 0; i < len; i++) {
-      doneList[i].call(this);
+      out[i] = catmullRomInterpolate(p0[i], p1[i], p2[i], p3[i], t, t2, t3);
     }
-  },
-
-  /**
-   * 开始执行动画
-   * @param  {string|Function} [easing]
-   *         动画缓动函数,详见{@link module:zrender/animation/easing}
-   * @param  {boolean} forceAnimate
-   * @return {module:zrender/animation/Animator}
-   */
-  start: function (easing, forceAnimate) {
-    var self = this;
-    var clipCount = 0;
-
-    var oneTrackDone = function () {
-      clipCount--;
-
-      if (!clipCount) {
-        self._doneCallback();
-      }
-    };
-
-    var lastClip;
+  } else {
+    var len2 = p0[0].length;
 
-    for (var propName in this._tracks) {
-      if (!this._tracks.hasOwnProperty(propName)) {
-        continue;
+    for (var i = 0; i < len; i++) {
+      for (var j = 0; j < len2; j++) {
+        out[i][j] = catmullRomInterpolate(p0[i][j], p1[i][j], p2[i][j], p3[i][j], t, t2, t3);
       }
+    }
+  }
+}
+/**
+ * Catmull Rom interpolate number
+ * @param  {number} p0
+ * @param  {number} p1
+ * @param  {number} p2
+ * @param  {number} p3
+ * @param  {number} t
+ * @param  {number} t2
+ * @param  {number} t3
+ * @return {number}
+ */
 
-      var clip = createTrackClip(this, easing, oneTrackDone, this._tracks[propName], propName, forceAnimate);
-
-      if (clip) {
-        this._clipList.push(clip);
 
-        clipCount++; // If start after added to animation
+function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) {
+  var v0 = (p2 - p0) * 0.5;
+  var v1 = (p3 - p1) * 0.5;
+  return (2 * (p1 - p2) + v0 + v1) * t3 + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + v0 * t + p1;
+}
+/**
+ * @param  {number} p0
+ * @param  {number} p1
+ * @param  {number} percent
+ * @return {number}
+ */
 
-        if (this.animation) {
-          this.animation.addClip(clip);
-        }
 
-        lastClip = clip;
-      }
-    } // Add during callback on the last clip
+function interpolateNumber(p0, p1, percent) {
+  return (p1 - p0) * percent + p0;
+}
+/**
+ * @param  {string} p0
+ * @param  {string} p1
+ * @param  {number} percent
+ * @return {string}
+ */
 
 
-    if (lastClip) {
-      var oldOnFrame = lastClip.onframe;
+function interpolateString(p0, p1, percent) {
+  return percent > 0.5 ? p1 : p0;
+}
+/**
+ * @param  {Array} p0
+ * @param  {Array} p1
+ * @param  {number} percent
+ * @param  {Array} out
+ * @param  {number} arrDim
+ */
 
-      lastClip.onframe = function (target, percent) {
-        oldOnFrame(target, percent);
 
-        for (var i = 0; i < self._onframeList.length; i++) {
-          self._onframeList[i](target, percent);
-        }
-      };
-    } // This optimization will help the case that in the upper application
-    // the view may be refreshed frequently, where animation will be
-    // called repeatly but nothing changed.
+function interpolateArray(p0, p1, percent, out, arrDim) {
+  var len = p0.length;
 
+  if (arrDim === 1) {
+    for (var i = 0; i < len; i++) {
+      out[i] = interpolateNumber(p0[i], p1[i], percent);
+    }
+  } else {
+    var len2 = len && p0[0].length;
 
-    if (!clipCount) {
-      this._doneCallback();
+    for (var i = 0; i < len; i++) {
+      for (var j = 0; j < len2; j++) {
+        out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent);
+      }
     }
+  }
+}
 
-    return this;
-  },
+function rgba2String(rgba) {
+  rgba[0] = Math.floor(rgba[0]);
+  rgba[1] = Math.floor(rgba[1]);
+  rgba[2] = Math.floor(rgba[2]);
+  return 'rgba(' + rgba.join(',') + ')';
+}
 
-  /**
-   * 停止动画
-   * @param {boolean} forwardToLast If move to last frame before stop
-   */
-  stop: function (forwardToLast) {
-    var clipList = this._clipList;
-    var animation = this.animation;
+export function cloneFrameValue(value) {
+  if (isArrayLike(value)) {
+    var len = value.length;
 
-    for (var i = 0; i < clipList.length; i++) {
-      var clip = clipList[i];
+    if (isArrayLike(value[0])) {
+      var ret = [];
 
-      if (forwardToLast) {
-        // Move to last frame before stop
-        clip.onframe(this._target, 1);
+      for (var i = 0; i < len; i++) {
+        ret.push(arraySlice.call(value[i]));
       }
 
-      animation && animation.removeClip(clip);
-    }
-
-    clipList.length = 0;
-  },
-
-  /**
-   * 设置动画延迟开始的时间
-   * @param  {number} time 单位ms
-   * @return {module:zrender/animation/Animator}
-   */
-  delay: function (time) {
-    this._delay = time;
-    return this;
-  },
-
-  /**
-   * 添加动画结束的回调
-   * @param  {Function} cb
-   * @return {module:zrender/animation/Animator}
-   */
-  done: function (cb) {
-    if (cb) {
-      this._doneList.push(cb);
+      return ret;
     }
 
-    return this;
-  },
-
-  /**
-   * @return {Array.<module:zrender/animation/Clip>}
-   */
-  getClips: function () {
-    return this._clipList;
+    return arraySlice.call(value);
   }
-};
-export default Animator;
\ No newline at end of file
+
+  return value;
+}
+export function defaultGetter(target, key) {
+  return target[key];
+}
+export function defaultSetter(target, key, value) {
+  target[key] = value;
+}
\ No newline at end of file
diff --git a/en/builder/src/zrender/core/dom.js b/en/builder/src/zrender/core/dom.js
new file mode 100644
index 0000000..7ef471e
--- /dev/null
+++ b/en/builder/src/zrender/core/dom.js
@@ -0,0 +1,130 @@
+import env from './env';
+import { buildTransformer } from './fourPointsTransform';
+var EVENT_SAVED_PROP = '___zrEVENTSAVED';
+var _calcOut = [];
+/**
+ * Transform "local coord" from `elFrom` to `elTarget`.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support when CSS transform is used.
+ *
+ * Having the `out` (that is, `[outX, outY]`), we can create an DOM element
+ * and set the CSS style as "left: outX; top: outY;" and append it to `elTarge`
+ * to locate the element.
+ *
+ * For example, this code below positions a child of `document.body` on the event
+ * point, no matter whether `body` has `margin`/`paddin`/`transfrom`/... :
+ * ```js
+ * transformLocalCoord(out, container, document.body, event.offsetX, event.offsetY);
+ * if (!eqNaN(out[0])) {
+ *     // Then locate the tip element on the event point.
+ *     var tipEl = document.createElement('div');
+ *     tipEl.style.cssText = 'position: absolute; left:' + out[0] + ';top:' + out[1] + ';';
+ *     document.body.appendChild(tipEl);
+ * }
+ * ```
+ *
+ * Notice: In some env this method is not supported. If called, `out` will be `[NaN, NaN]`.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output..
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} elFrom The `[inX, inY]` is based on elFrom.
+ * @param {HTMLElement} elTarget The `out` is based on elTarget.
+ * @param {number} inX
+ * @param {number} inY
+ * @return {boolean} Whether transform successfully.
+ */
+
+export function transformLocalCoord(out, elFrom, elTarget, inX, inY) {
+  return transformCoordWithViewport(_calcOut, elFrom, inX, inY, true) && transformCoordWithViewport(out, elTarget, _calcOut[0], _calcOut[1]);
+}
+/**
+ * Transform between a "viewport coord" and a "local coord".
+ * "viewport coord": the coord based on the left-top corner of the viewport
+ *     of the browser.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support the case when CSS transform is used on el.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output. If `inverse: false`,
+ *        it represents "local coord", otherwise "vireport coord".
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} el The "local coord" is based on the `el`, see comment above.
+ * @param {number} inX If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {number} inY If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {boolean} [inverse=false]
+ *        `true`: from "viewport coord" to "local coord".
+ *        `false`: from "local coord" to "viewport coord".
+ * @return {boolean} Whether transform successfully.
+ */
+
+export function transformCoordWithViewport(out, el, inX, inY, inverse) {
+  if (el.getBoundingClientRect && env.domSupported && !isCanvasEl(el)) {
+    var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
+    var markers = prepareCoordMarkers(el, saved);
+    var transformer = preparePointerTransformer(markers, saved, inverse);
+
+    if (transformer) {
+      transformer(out, inX, inY);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+function prepareCoordMarkers(el, saved) {
+  var markers = saved.markers;
+
+  if (markers) {
+    return markers;
+  }
+
+  markers = saved.markers = [];
+  var propLR = ['left', 'right'];
+  var propTB = ['top', 'bottom'];
+
+  for (var i = 0; i < 4; i++) {
+    var marker = document.createElement('div');
+    var stl = marker.style;
+    var idxLR = i % 2;
+    var idxTB = (i >> 1) % 2;
+    stl.cssText = ['position: absolute', 'visibility: hidden', 'padding: 0', 'margin: 0', 'border-width: 0', 'user-select: none', 'width:0', 'height:0', // 'width: 5px',
+    // 'height: 5px',
+    propLR[idxLR] + ':0', propTB[idxTB] + ':0', propLR[1 - idxLR] + ':auto', propTB[1 - idxTB] + ':auto', ''].join('!important;');
+    el.appendChild(marker);
+    markers.push(marker);
+  }
+
+  return markers;
+}
+
+function preparePointerTransformer(markers, saved, inverse) {
+  var transformerName = inverse ? 'invTrans' : 'trans';
+  var transformer = saved[transformerName];
+  var oldSrcCoords = saved.srcCoords;
+  var oldCoordTheSame = true;
+  var srcCoords = [];
+  var destCoords = [];
+
+  for (var i = 0; i < 4; i++) {
+    var rect = markers[i].getBoundingClientRect();
+    var ii = 2 * i;
+    var x = rect.left;
+    var y = rect.top;
+    srcCoords.push(x, y);
+    oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
+    destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
+  } // Cache to avoid time consuming of `buildTransformer`.
+
+
+  return oldCoordTheSame && transformer ? transformer : (saved.srcCoords = srcCoords, saved[transformerName] = inverse ? buildTransformer(destCoords, srcCoords) : buildTransformer(srcCoords, destCoords));
+}
+
+export function isCanvasEl(el) {
+  return el.nodeName.toUpperCase() === 'CANVAS';
+}
\ No newline at end of file
diff --git a/en/builder/src/zrender/core/event.js b/en/builder/src/zrender/core/event.js
index dd2acac..f9ecd0b 100644
--- a/en/builder/src/zrender/core/event.js
+++ b/en/builder/src/zrender/core/event.js
@@ -3,10 +3,9 @@
  */
 import Eventful from '../mixin/Eventful';
 import env from './env';
-import { buildTransformer } from './fourPointsTransform';
+import { isCanvasEl, transformCoordWithViewport } from './dom';
 var isDomLevel2 = typeof window !== 'undefined' && !!window.addEventListener;
 var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
-var EVENT_SAVED_PROP = '___zrEVENTSAVED';
 var _calcOut = [];
 /**
  * Get the `zrX` and `zrY`, which are relative to the top-left of
@@ -66,11 +65,11 @@ export function clientToLocal(el, e, out, calculate) {
 
 function calculateZrXY(el, e, out) {
   // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect.
-  if (el.getBoundingClientRect && env.domSupported) {
+  if (env.domSupported && el.getBoundingClientRect) {
     var ex = e.clientX;
     var ey = e.clientY;
 
-    if (el.nodeName.toUpperCase() === 'CANVAS') {
+    if (isCanvasEl(el)) {
       // Original approach, which do not support CSS transform.
       // marker can not be locationed in a canvas container
       // (getBoundingClientRect is always 0). We do not support
@@ -81,11 +80,7 @@ function calculateZrXY(el, e, out) {
       out.zrY = ey - box.top;
       return;
     } else {
-      var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
-      var transformer = preparePointerTransformer(prepareCoordMarkers(el, saved), saved);
-
-      if (transformer) {
-        transformer(_calcOut, ex, ey);
+      if (transformCoordWithViewport(_calcOut, el, ex, ey)) {
         out.zrX = _calcOut[0];
         out.zrY = _calcOut[1];
         return;
@@ -95,53 +90,6 @@ function calculateZrXY(el, e, out) {
 
   out.zrX = out.zrY = 0;
 }
-
-function prepareCoordMarkers(el, saved) {
-  var markers = saved.markers;
-
-  if (markers) {
-    return markers;
-  }
-
-  markers = saved.markers = [];
-  var propLR = ['left', 'right'];
-  var propTB = ['top', 'bottom'];
-
-  for (var i = 0; i < 4; i++) {
-    var marker = document.createElement('div');
-    var stl = marker.style;
-    var idxLR = i % 2;
-    var idxTB = (i >> 1) % 2;
-    stl.cssText = ['position:absolute', 'visibility: hidden', 'padding: 0', 'margin: 0', 'border-width: 0', 'width:0', 'height:0', // 'width: 5px',
-    // 'height: 5px',
-    propLR[idxLR] + ':0', propTB[idxTB] + ':0', propLR[1 - idxLR] + ':auto', propTB[1 - idxTB] + ':auto', ''].join('!important;');
-    el.appendChild(marker);
-    markers.push(marker);
-  }
-
-  return markers;
-}
-
-function preparePointerTransformer(markers, saved) {
-  var transformer = saved.transformer;
-  var oldSrcCoords = saved.srcCoords;
-  var useOld = true;
-  var srcCoords = [];
-  var destCoords = [];
-
-  for (var i = 0; i < 4; i++) {
-    var rect = markers[i].getBoundingClientRect();
-    var ii = 2 * i;
-    var x = rect.left;
-    var y = rect.top;
-    srcCoords.push(x, y);
-    useOld &= oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
-    destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
-  } // Cache to avoid time consuming of `buildTransformer`.
-
-
-  return useOld ? transformer : (saved.srcCoords = srcCoords, saved.transformer = buildTransformer(srcCoords, destCoords));
-}
 /**
  * Find native event compat for legency IE.
  * Should be called at the begining of a native event listener.
diff --git a/en/builder/src/zrender/core/fourPointsTransform.js b/en/builder/src/zrender/core/fourPointsTransform.js
index fd8c03d..4b53301 100644
--- a/en/builder/src/zrender/core/fourPointsTransform.js
+++ b/en/builder/src/zrender/core/fourPointsTransform.js
@@ -68,6 +68,8 @@ export function buildTransformer(src, dest) {
   var det = determinant(mA, 8, 0, 0, 0, detCache);
 
   if (det === 0) {
+    // can not make transformer when and only when
+    // any three of the markers are collinear.
     return;
   } // `invert(mA) * dest`, that is, `adj(mA) / det * dest`.
 
diff --git a/en/builder/src/zrender/dom/HandlerProxy.js b/en/builder/src/zrender/dom/HandlerProxy.js
index d9c11ef..633bbf4 100644
--- a/en/builder/src/zrender/dom/HandlerProxy.js
+++ b/en/builder/src/zrender/dom/HandlerProxy.js
@@ -102,11 +102,12 @@ function normalizeGlobalEvent(instance, event) {
 
 
 function isLocalEl(instance, el) {
+  var elTmp = el;
   var isLocal = false;
 
-  do {
-    el = el && el.parentNode;
-  } while (el && el.nodeType !== 9 && !(isLocal = el === instance.painterRoot));
+  while (elTmp && elTmp.nodeType !== 9 && !(isLocal = elTmp.domBelongToZr || elTmp !== el && elTmp === instance.painterRoot)) {
+    elTmp = elTmp.parentNode;
+  }
 
   return isLocal;
 }
diff --git a/en/builder/src/zrender/graphic/helper/subPixelOptimize.js b/en/builder/src/zrender/graphic/helper/subPixelOptimize.js
index eab6d48..e68b7a5 100644
--- a/en/builder/src/zrender/graphic/helper/subPixelOptimize.js
+++ b/en/builder/src/zrender/graphic/helper/subPixelOptimize.js
@@ -16,13 +16,11 @@ var round = Math.round;
  * @param {number} [inputShape.x2]
  * @param {number} [inputShape.y2]
  * @param {Object} [style]
- * @param {number} [style.lineWidth]
+ * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
  */
 
 export function subPixelOptimizeLine(outputShape, inputShape, style) {
-  var lineWidth = style && style.lineWidth;
-
-  if (!inputShape || !lineWidth) {
+  if (!inputShape) {
     return;
   }
 
@@ -30,19 +28,22 @@ export function subPixelOptimizeLine(outputShape, inputShape, style) {
   var x2 = inputShape.x2;
   var y1 = inputShape.y1;
   var y2 = inputShape.y2;
+  outputShape.x1 = x1;
+  outputShape.x2 = x2;
+  outputShape.y1 = y1;
+  outputShape.y2 = y2;
+  var lineWidth = style && style.lineWidth;
+
+  if (!lineWidth) {
+    return;
+  }
 
   if (round(x1 * 2) === round(x2 * 2)) {
     outputShape.x1 = outputShape.x2 = subPixelOptimize(x1, lineWidth, true);
-  } else {
-    outputShape.x1 = x1;
-    outputShape.x2 = x2;
   }
 
   if (round(y1 * 2) === round(y2 * 2)) {
     outputShape.y1 = outputShape.y2 = subPixelOptimize(y1, lineWidth, true);
-  } else {
-    outputShape.y1 = y1;
-    outputShape.y2 = y2;
   }
 }
 /**
@@ -58,13 +59,11 @@ export function subPixelOptimizeLine(outputShape, inputShape, style) {
  * @param {number} [inputShape.width]
  * @param {number} [inputShape.height]
  * @param {Object} [style]
- * @param {number} [style.lineWidth]
+ * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
  */
 
 export function subPixelOptimizeRect(outputShape, inputShape, style) {
-  var lineWidth = style && style.lineWidth;
-
-  if (!inputShape || !lineWidth) {
+  if (!inputShape) {
     return;
   }
 
@@ -72,6 +71,16 @@ export function subPixelOptimizeRect(outputShape, inputShape, style) {
   var originY = inputShape.y;
   var originWidth = inputShape.width;
   var originHeight = inputShape.height;
+  outputShape.x = originX;
+  outputShape.y = originY;
+  outputShape.width = originWidth;
+  outputShape.height = originHeight;
+  var lineWidth = style && style.lineWidth;
+
+  if (!lineWidth) {
+    return;
+  }
+
   outputShape.x = subPixelOptimize(originX, lineWidth, true);
   outputShape.y = subPixelOptimize(originY, lineWidth, true);
   outputShape.width = Math.max(subPixelOptimize(originX + originWidth, lineWidth, false) - outputShape.x, originWidth === 0 ? 0 : 1);
@@ -81,14 +90,18 @@ export function subPixelOptimizeRect(outputShape, inputShape, style) {
  * Sub pixel optimize for canvas
  *
  * @param {number} position Coordinate, such as x, y
- * @param {number} lineWidth Should be nonnegative integer.
+ * @param {number} lineWidth If `null`/`undefined`/`0`, do not optimize.
  * @param {boolean=} positiveOrNegative Default false (negative).
  * @return {number} Optimized position.
  */
 
 export function subPixelOptimize(position, lineWidth, positiveOrNegative) {
-  // Assure that (position + lineWidth / 2) is near integer edge,
+  if (!lineWidth) {
+    return position;
+  } // Assure that (position + lineWidth / 2) is near integer edge,
   // otherwise line will be fuzzy in canvas.
+
+
   var doubledPosition = round(position * 2);
   return (doubledPosition + round(lineWidth)) % 2 === 0 ? doubledPosition / 2 : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
 }
\ No newline at end of file
diff --git a/en/builder/src/zrender/mixin/Animatable.js b/en/builder/src/zrender/mixin/Animatable.js
index b2605ab..7935202 100644
--- a/en/builder/src/zrender/mixin/Animatable.js
+++ b/en/builder/src/zrender/mixin/Animatable.js
@@ -2,7 +2,7 @@ import Animator from '../animation/Animator';
 import logError from '../core/log';
 import { isString, isFunction, isObject, isArrayLike, indexOf } from '../core/util';
 /**
- * @alias modue:zrender/mixin/Animatable
+ * @alias module:zrender/mixin/Animatable
  * @constructor
  */
 
diff --git a/en/builder/src/zrender/mixin/Draggable.js b/en/builder/src/zrender/mixin/Draggable.js
index c74adce..a03f7c2 100644
--- a/en/builder/src/zrender/mixin/Draggable.js
+++ b/en/builder/src/zrender/mixin/Draggable.js
@@ -16,9 +16,13 @@ function Draggable() {
 Draggable.prototype = {
   constructor: Draggable,
   _dragStart: function (e) {
-    var draggingTarget = e.target;
+    var draggingTarget = e.target; // Find if there is draggable in the ancestor
 
-    if (draggingTarget && draggingTarget.draggable) {
+    while (draggingTarget && !draggingTarget.draggable) {
+      draggingTarget = draggingTarget.parent;
+    }
+
+    if (draggingTarget) {
       this._draggingTarget = draggingTarget;
       draggingTarget.dragging = true;
       this._x = e.offsetX;
diff --git a/en/builder/src/zrender/zrender.js b/en/builder/src/zrender/zrender.js
index 6d8d2fa..40649b3 100644
--- a/en/builder/src/zrender/zrender.js
+++ b/en/builder/src/zrender/zrender.js
@@ -25,7 +25,7 @@ var instances = {}; // ZRender实例map索引
  * @type {string}
  */
 
-export var version = '4.2.0';
+export var version = '4.3.0';
 /**
  * Initializing a zrender instance
  * @param {HTMLElement} dom
diff --git a/en/changelog.html b/en/changelog.html
index 11ea14f..ad66dcd 100644
--- a/en/changelog.html
+++ b/en/changelog.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -7,35 +7,76 @@
     document.head.insertBefore(el, document.getElementById('font-hack'));
 }
 </script><title>Changelog - Apache ECharts (incubating)</title><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[if lte IE 8]><body class="lower-ie"><div id="lowie-main"><img src="./images/forie.png" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
+<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
 <div class="time"></div>
 
 <ul>
-<li><p>[Feature] Optimize label layout on pie. Add new <code>alignTo</code> option for aligning the labels. Check more detail in PR <a href="https://github.com/apache/incubator-echarts/pull/11715">#11715</a> (<a href="https://github.com/Ovilia">Wenli Zhang</a>)</p>
+<li><p>[Feature] Provide new layouts for markLine labels. <a href="https://github.com/apache/incubator-echarts/pull/11843">#11843</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
 </li>
-<li><p>[Feature] Add <code>minorTick</code>, <code>minorSplitLine</code> on axis. Check more detail in the PR <a href="https://github.com/apache/incubator-echarts/pull/11705">#11705</a> (<a href="https://github.com/pissang">Yi Shen</a>)</p>
+<li><p>[Feature] Support background option for bar series. <a href="https://github.com/apache/incubator-echarts/pull/11951">#11951</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
+</li>
+<li><p>[Feature] Support appending tooltip DOM to HTML body. <a href="https://github.com/apache/incubator-echarts/pull/8049">#8049</a> <a href="https://github.com/apache/incubator-echarts/pull/12024">#12024</a> (<a href="https://github.com/xinpureZhu">xinpureZhu</a>, <a href="https://github.com/100pah">Su Shuang</a>)</p>
+</li>
+<li><p>[Feature] Add draggable support to group elements. <a href="https://github.com/apache/incubator-echarts/pull/11959">#11959</a> (<a href="https://github.com/pissang">Shen Yi</a>)</p>
+</li>
+<li><p>[Feature] Add polyline edge layout for the tree chart. <a href="https://github.com/apache/incubator-echarts/pull/11808">#11808</a> (<a href="https://github.com/deqingli">Li Deqing</a>)</p>
+</li>
+<li><p>[Enhance] Enhance continuity line trail for effect line. <a href="https://github.com/apache/incubator-echarts/pull/11893">#11893</a> (<a href="https://github.com/alex2wong">alex2wong</a>)</p>
+</li>
+<li><p>[Fix] Fix markPoint position with stack line/bar. <a href="https://github.com/apache/incubator-echarts/pull/11965">#11965</a> (<a href="https://github.com/yikuangli">yikuangli</a>)</p>
+</li>
+<li><p>[Fix] Radar chart data may appear outside of the radar component. <a href="https://github.com/apache/incubator-echarts/pull/11841">#11841</a> (<a href="https://github.com/susiwen8">Su Siwen</a>)</p>
+</li>
+<li><p>[Fix] Fix treemap highlight action not triggered. <a href="https://github.com/apache/incubator-echarts/pull/12050">#12050</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
+</li>
+<li><p>[Fix] Fix geo cannot be restored. <a href="https://github.com/apache/incubator-echarts/pull/12035">#12035</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
+</li>
+<li><p>[Fix] Fix Array.prototype.slice is not defined on typed array <a href="https://github.com/apache/incubator-echarts/pull/11956">#11956</a> (<a href="https://github.com/pissang">Shen Yi</a>)</p>
+</li>
+<li><p>[Fix] Fix candlestick throw error when some series are filtered by legend. <a href="https://github.com/apache/incubator-echarts/pull/12027">#12027</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
+</li>
+<li><p>[Fix] Fix brush component not roam with the coordinate system. <a href="https://github.com/apache/incubator-echarts/pull/11998">#11998</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
+</li>
+<li><p>[Fix] Fix action <code>&#39;showTip&#39;</code> dispatched in radar chart. <a href="https://github.com/apache/incubator-echarts/pull/11985">#11985</a> (<a href="https://github.com/yufeng04">Yu Feng</a>)</p>
+</li>
+<li><p>[Fix] Fix singleAxis support splitArea option. <a href="https://github.com/apache/incubator-echarts/pull/11890">#11890</a> (<a href="https://github.com/newraina">newraina</a>)</p>
+</li>
+<li><p>[Fix] Fix legend pagination may disappear. <a href="https://github.com/apache/incubator-echarts/pull/11952">#11952</a> (<a href="https://github.com/yufeng04">Yu Feng</a>)</p>
+</li>
+<li><p>[Fix] Emphasis line style options with sankey chart. <a href="https://github.com/apache/incubator-echarts/pull/11729">#11729</a> (<a href="https://github.com/deqingli">Li Deqing</a>)</p>
+</li>
+<li><p>[Fix] Fix formatter tooltip has no value in sankey chart. <a href="https://github.com/apache/incubator-echarts/pull/11752">#11752</a> (<a href="https://github.com/deqingli">Li Deqing</a>)</p>
+</li>
+</ul>
+<h2 id="v4-6-0">v4.6.0</h2>
+<div class="time"></div>
+
+<ul>
+<li><p>[Feature] Optimize label layout on pie. Add new <code>alignTo</code> option for aligning the labels. Check more detail in PR <a href="https://github.com/apache/incubator-echarts/pull/11715">#11715</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
+</li>
+<li><p>[Feature] Add <code>minorTick</code>, <code>minorSplitLine</code> on axis. Check more detail in the PR <a href="https://github.com/apache/incubator-echarts/pull/11705">#11705</a> (<a href="https://github.com/pissang">Shen Yi</a>)</p>
 </li>
 <li><p>[Feature] Added more themes. <a href="https://github.com/apache/incubator-echarts/pull/11566">#11566</a> (<a href="https://github.com/WebCodePro719">WebCodePro719</a>)</p>
 </li>
-<li><p>[Enhance] Chart will keep the dragging status when mouse is out of the area. Which will provide a much better dragging experience. <a href="https://github.com/apache/incubator-echarts/pull/11710">#11710</a> (<a href="https://github.com/100pah">Shuang Su</a>)</p>
+<li><p>[Enhance] Chart will keep the dragging status when mouse is out of the area. Which will provide a much better dragging experience. <a href="https://github.com/apache/incubator-echarts/pull/11710">#11710</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
 </li>
-<li><p>[Enhance] Legend will display colors from <code>visualMap</code> component in <code>pie</code>/<code>funnel</code>/<code>radar</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11737">#11737</a> (<a href="https://github.com/pissang">Yi Shen</a>)</p>
+<li><p>[Enhance] Legend will display colors from <code>visualMap</code> component in <code>pie</code>/<code>funnel</code>/<code>radar</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11737">#11737</a> (<a href="https://github.com/pissang">Shen Yi</a>)</p>
 </li>
-<li><p>[Enhance] Enhance dataset default encode guess strategy. <a href="https://github.com/apache/incubator-echarts/pull/11746">#11746</a> (<a href="https://github.com/100pah">Shuang Su</a>)</p>
+<li><p>[Enhance] Enhance dataset default encode guess strategy. <a href="https://github.com/apache/incubator-echarts/pull/11746">#11746</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
 </li>
 <li><p>[Enhance] Stack icon on toolbox now is a toggle button. Removed tiled icon. <a href="https://github.com/apache/incubator-echarts/pull/11367">#11367</a> (<a href="https://github.com/alex2wong">alex2wong</a>)</p>
 </li>
-<li><p>[Enhance] Add a delay to avoid flashing when hovering on nodes and edges of <code>graph</code> and <code>sankey</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11572">11572</a> (<a href="https://github.com/apache/incubator-echarts/pull/11457">Deqing Li</a>)</p>
+<li><p>[Enhance] Add a delay to avoid flashing when hovering on nodes and edges of <code>graph</code> and <code>sankey</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11572">11572</a> (<a href="https://github.com/apache/incubator-echarts/pull/11457">Li Deqing</a>)</p>
 </li>
-<li><p>[Fix] Fix bar width calculation with <code>barMaxWidth</code> constraint and negative <code>barGap</code>. <a href="https://github.com/apache/incubator-echarts/pull/11713">#11713</a> (<a href="https://github.com/pissang">Yi Shen</a>)</p>
+<li><p>[Fix] Fix bar width calculation with <code>barMaxWidth</code> constraint and negative <code>barGap</code>. <a href="https://github.com/apache/incubator-echarts/pull/11713">#11713</a> (<a href="https://github.com/pissang">Shen Yi</a>)</p>
 </li>
-<li><p>[Fix] Fix seams in <code>heatmap</code> series. Which may cause unexpected gray lines. <a href="https://github.com/apache/incubator-echarts/pull/11689">#11689</a> (<a href="https://github.com/pissang">Yi Shen</a>)</p>
+<li><p>[Fix] Fix seams in <code>heatmap</code> series. Which may cause unexpected gray lines. <a href="https://github.com/apache/incubator-echarts/pull/11689">#11689</a> (<a href="https://github.com/pissang">Shen Yi</a>)</p>
 </li>
 <li><p>[Fix] Fix unexpected highlight state after inverse selection in <code>legend</code>. <a href="https://github.com/apache/incubator-echarts/pull/11547">#11547</a> (<a href="https://github.com/SnailSword">SnailSword</a>)</p>
 </li>
 <li><p>[Fix] Fix tooltip may highlight the point out of chart in <code>line</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11548">#11548</a> (<a href="https://github.com/SnailSword">SnailSword</a>)</p>
 </li>
-<li><p>[Fix] Fix label may not disappear on SVG renderer. <a href="https://github.com/ecomfe/zrender/pull/535">ecomfe/zrender#535</a> (<a href="https://github.com/Ovilia">Wenli Zhang</a>)</p>
+<li><p>[Fix] Fix label may not disappear on SVG renderer. <a href="https://github.com/ecomfe/zrender/pull/535">ecomfe/zrender#535</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
 </li>
 <li><p>[Fix] Not display bar on polar when value is <code>0</code>. <a href="https://github.com/apache/incubator-echarts/issues/11452">#11452</a> (<a href="https://github.com/foolzhang">foolzhang</a>)</p>
 </li>
@@ -45,9 +86,9 @@
 </li>
 <li><p>[Fix] Fix <code>markPoint</code> out of the chart may still display in the wrong position. <a href="https://github.com/apache/incubator-echarts/pull/11484">#11484</a> (<a href="https://github.com/susiwen8">susiwen8</a>)</p>
 </li>
-<li><p>[Fix] Fix tooltip shows multiple values around both sides of the pointer. <a href="https://github.com/apache/incubator-echarts/pull/11648">#11648</a> (<a href="https://github.com/100pah">Shuang Su</a>)</p>
+<li><p>[Fix] Fix tooltip shows multiple values around both sides of the pointer. <a href="https://github.com/apache/incubator-echarts/pull/11648">#11648</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
 </li>
-<li><p>[Fix] Fix <code>label.formatter</code> of leaves in <code>tree</code> series not work. <a href="https://github.com/apache/incubator-echarts/pull/11556">#11556</a> (<a href="https://github.com/apache/incubator-echarts/pull/11457">Deqing Li</a>)</p>
+<li><p>[Fix] Fix <code>label.formatter</code> of leaves in <code>tree</code> series not work. <a href="https://github.com/apache/incubator-echarts/pull/11556">#11556</a> (<a href="https://github.com/apache/incubator-echarts/pull/11457">Li Deqing</a>)</p>
 </li>
 <li><p>[Fix] Fix overflow symbol not display when <code>clip</code> is set <code>false</code> in <code>line</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11552">#11552</a> (<a href="https://github.com/SnailSword">SnailSword</a>)</p>
 </li>
@@ -56,11 +97,11 @@
 <div class="time">2019-11-18</div>
 
 <ul>
-<li><p>[Feature] Add <code>roundCap</code> option for round corners on <code>bar</code> series width <code>polar</code> coordinate system. <a href="https://github.com/apache/incubator-echarts/pull/11393">#11393</a> (<a href="https://github.com/Ovilia">Wenli Zhang</a>)</p>
+<li><p>[Feature] Add <code>roundCap</code> option for round corners on <code>bar</code> series width <code>polar</code> coordinate system. <a href="https://github.com/apache/incubator-echarts/pull/11393">#11393</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
 </li>
 <li><p>[Feature] Add event <code>brushEnd</code> for <code>brush</code> component <a href="https://github.com/apache/incubator-echarts/pull/11285">#11285</a>(<a href="https://github.com/cuijian-dexter">Jian Cui</a>)</p>
 </li>
-<li><p>[Feature] Add <code>friction</code> option in force layout of <code>graph</code>. <a href="https://github.com/apache/incubator-echarts/pull/11276">#11276</a> (<a href="https://github.com/pissang">Yi Shen</a>)</p>
+<li><p>[Feature] Add <code>friction</code> option in force layout of <code>graph</code>. <a href="https://github.com/apache/incubator-echarts/pull/11276">#11276</a> (<a href="https://github.com/pissang">Shen Yi</a>)</p>
 </li>
 <li><p>[Feature] Add <code>ignoreFoceLayout</code> option in the <code>graph</code> links. <a href="https://github.com/apache/incubator-echarts/pull/11445">#11445</a> (<a href="https://github.com/TYzzt">TYzzt</a>)</p>
 </li>
@@ -68,37 +109,37 @@
 </li>
 </ul>
 <ul>
-<li><p>[Feature] Add <code>clip</code> option in <code>candllestick</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11529">#11529</a> (<a href="https://github.com/pissang">Yi Shen</a>)</p>
+<li><p>[Feature] Add <code>clip</code> option in <code>candllestick</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11529">#11529</a> (<a href="https://github.com/pissang">Shen Yi</a>)</p>
 </li>
-<li><p>[Fix] Fix lots of label positioning issues in SVG renderer. <a href="https://github.com/ecomfe/zrender/pull/519">ecomfe/zrender#519</a> (<a href="https://github.com/100pah">Shuang Su</a>)</p>
+<li><p>[Fix] Fix lots of label positioning issues in SVG renderer. <a href="https://github.com/ecomfe/zrender/pull/519">ecomfe/zrender#519</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
 </li>
 <li><p>[Fix] Fix interval issues related to category axis tick. Like <code>areaStyle.color</code> is incorrect in <a href="https://github.com/apache/incubator-echarts/issues/10948">#10948</a>, <code>xAxis.axisTick.interval</code> is calculated incorrectly in <a href="https://github.com/apache/incubator-echarts/pull/11176">#11176</a> . <a href="https://github.com/apache/incubator-echarts/pull/11186">#11186</a> (<a href="https://github.com/foolzhang">foolzhang</a>)</p>
 </li>
 <li><p>[Fix] Fix <code>bar</code> series can&#39;t display on the <code>log</code> axis. <a href="https://github.com/apache/incubator-echarts/pull/11472">#11472</a>(<a href="https://github.com/SnailSword">SnailSword</a>)</p>
 </li>
-<li><p>[Fix] Fix tooltip may be covered by the canvas when <code>-webkit-overflow-scrolling: touch</code> on iOS 13. <a href="https://github.com/ecomfe/zrender/pull/522">ecomfe/zrender#522</a> (<a href="https://github.com/100pah">Shuang Su</a>)</p>
+<li><p>[Fix] Fix tooltip may be covered by the canvas when <code>-webkit-overflow-scrolling: touch</code> on iOS 13. <a href="https://github.com/ecomfe/zrender/pull/522">ecomfe/zrender#522</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
 </li>
-<li><p>[Fix] Fix some of labels on category axis may disappear forever after chart resized. <a href="https://github.com/apache/incubator-echarts/pull/11536">#11536</a> (<a href="https://github.com/100pah">Shuang Su</a>)</p>
+<li><p>[Fix] Fix some of labels on category axis may disappear forever after chart resized. <a href="https://github.com/apache/incubator-echarts/pull/11536">#11536</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
 </li>
-<li><p>[Fix] Fix brush drag gets stuck when the mouse leaves the chart area. <a href="https://github.com/apache/incubator-echarts/pull/11516">#11516</a> (<a href="https://github.com/100pah">Shuang Su</a>)</p>
+<li><p>[Fix] Fix brush drag gets stuck when the mouse leaves the chart area. <a href="https://github.com/apache/incubator-echarts/pull/11516">#11516</a> (<a href="https://github.com/100pah">Su Shuang</a>)</p>
 </li>
-<li><p>[Fix] Fix image symbol may disappear forever after legend toggled. <a href="https://github.com/apache/incubator-echarts/pull/11515">#11515</a> (<a href="https://github.com/yufeng04">Feng Yu</a>)</p>
+<li><p>[Fix] Fix image symbol may disappear forever after legend toggled. <a href="https://github.com/apache/incubator-echarts/pull/11515">#11515</a> (<a href="https://github.com/yufeng04">Yu Feng</a>)</p>
 </li>
-<li><p>[Fix] Fix changing from <code>&#39;scroll&#39;</code> type to <code>&#39;plain&#39;</code> type not work bug in legend. <a href="https://github.com/apache/incubator-echarts/pull/11504">#11504</a> (<a href="https://github.com/yufeng04">Feng Yu</a>)</p>
+<li><p>[Fix] Fix changing from <code>&#39;scroll&#39;</code> type to <code>&#39;plain&#39;</code> type not work bug in legend. <a href="https://github.com/apache/incubator-echarts/pull/11504">#11504</a> (<a href="https://github.com/yufeng04">Yu Feng</a>)</p>
 </li>
-<li><p>[Fix] Optimize layout and bar width of <code>bar</code> series on <code>time</code> axis and <code>value</code> axis. Make the <code>barMaxWidth</code> has higher priority than <code>barWidth</code>. Add <code>barMinWidth</code> for <code>bar</code> series on <code>time</code> axis and <code>value</code> axis. <a href="https://github.com/apache/incubator-echarts/pull/11479">#11479</a> (<a href="https://github.com/Ovilia">Wenli Zhang</a>, <a href="https://github.com/100pah">Shuang  [...]
+<li><p>[Fix] Optimize layout and bar width of <code>bar</code> series on <code>time</code> axis and <code>value</code> axis. Make the <code>barMaxWidth</code> has higher priority than <code>barWidth</code>. Add <code>barMinWidth</code> for <code>bar</code> series on <code>time</code> axis and <code>value</code> axis. <a href="https://github.com/apache/incubator-echarts/pull/11479">#11479</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>, <a href="https://github.com/100pah">Su Shua [...]
 </li>
-<li><p>[Fix] Fix title of toolbox icon may be cut by the container. <a href="https://github.com/apache/incubator-echarts/pull/11456">#11456</a> (<a href="https://github.com/Ovilia">Wenli Zhang</a>)</p>
+<li><p>[Fix] Fix title of toolbox icon may be cut by the container. <a href="https://github.com/apache/incubator-echarts/pull/11456">#11456</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
 </li>
-<li><p>[Fix] Fix precision issue in the ticks calculating. <a href="https://github.com/apache/incubator-echarts/pull/11488">#11488</a> (<a href="https://github.com/Ovilia">Wenli Zhang</a>)</p>
+<li><p>[Fix] Fix precision issue in the ticks calculating. <a href="https://github.com/apache/incubator-echarts/pull/11488">#11488</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
 </li>
-<li><p>[Fix] Fix <code>rotate</code> property of label not work in <code>tree</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11457">#11457</a> (<a href="https://github.com/apache/incubator-echarts/pull/11457">Deqing Li</a>)</p>
+<li><p>[Fix] Fix <code>rotate</code> property of label not work in <code>tree</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11457">#11457</a> (<a href="https://github.com/apache/incubator-echarts/pull/11457">Li Deqing</a>)</p>
 </li>
-<li><p>[Fix] Fix edge won&#39;t disappear after collapsed if the <code>id</code> is duplicated in <code>tree</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11447">#11447</a> (<a href="https://github.com/apache/incubator-echarts/pull/11457">Deqing Li</a>)</p>
+<li><p>[Fix] Fix edge won&#39;t disappear after collapsed if the <code>id</code> is duplicated in <code>tree</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11447">#11447</a> (<a href="https://github.com/apache/incubator-echarts/pull/11457">Li Deqing</a>)</p>
 </li>
-<li><p>[Fix] Fix data disappear when updating with <code>dataset</code> in <code>gauge</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11373">#11373</a> (<a href="https://github.com/Ovilia">Wenli Zhang</a>)</p>
+<li><p>[Fix] Fix data disappear when updating with <code>dataset</code> in <code>gauge</code> series. <a href="https://github.com/apache/incubator-echarts/pull/11373">#11373</a> (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
 </li>
-<li><p>[Fix] Fix gradient on bar leaked to label in SVG Renderer. (<a href="https://github.com/Ovilia">Wenli Zhang</a>) </p>
+<li><p>[Fix] Fix gradient on bar leaked to label in SVG Renderer. (<a href="https://github.com/Ovilia">Zhang Wenli</a>)</p>
 </li>
 </ul>
 <h2 id="v4-4-0">v4.4.0</h2>
@@ -1224,7 +1265,9 @@ window.addEventListener('hashchange', function() {
 });</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/cheat-sheet.html b/en/cheat-sheet.html
index d89b2f7..61ed00c 100644
--- a/en/cheat-sheet.html
+++ b/en/cheat-sheet.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -11,7 +11,9 @@
 </script><script src="./vendors/echarts/echarts-20190709.min.js"></script><script src="./js/cheat-sheet-en.js"></script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/coding-standard.html b/en/coding-standard.html
index d5b3373..171c0f7 100644
--- a/en/coding-standard.html
+++ b/en/coding-standard.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -608,7 +608,9 @@ $('.page-detail pre code').each(function (index, el) {
 prettyPrint();</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/committers.html b/en/committers.html
index 9e26191..5689cbd 100644
--- a/en/committers.html
+++ b/en/committers.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -7,11 +7,13 @@
     document.head.insertBefore(el, document.getElementById('font-hack'));
 }
 </script><title>Committers - Apache ECharts (incubating)</title><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[if lte IE 8]><body class="lower-ie"><div id="lowie-main"><img src="./images/forie.png" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
+<!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
 </div></section><section class="container company"><h4 class="group companie">Companies using ECharts</h4><div class="row"><div class="col-md-3 col-sm-4 col-xs-6"><img src="images/company/company1.jpg"></div><div class="col-md-3 col-sm-4 col-xs-6"><img src="images/company/company2.jpg"></div><div class="col-md-3 col-sm-4 col-xs-6"><img src="images/company/company3.jpg"></div><div class="col-md-3 col-sm-4 col-xs-6"><img src="images/company/company4.jpg"></div><div class="col-md-3 col-sm-4 [...]
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/css/doc-bundle.css b/en/css/doc-bundle.css
index 3159b8f..a203df1 100644
--- a/en/css/doc-bundle.css
+++ b/en/css/doc-bundle.css
@@ -184,6 +184,9 @@
   position: relative;
   padding: 15px 0;
 }
+.doc-content-item-card.current {
+    border-top: 1px solid #b03a5b;
+}
 .doc-content-item-card .hierarchy-line {
     position: absolute;
     top: 35px;
diff --git a/en/css/doc-bundle.css.map b/en/css/doc-bundle.css.map
index 2aaee43..fad5e9b 100644
--- a/en/css/doc-bundle.css.map
+++ b/en/css/doc-bundle.css.map
@@ -1 +1 @@
-{"version":3,"sources":["webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/popover.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/base.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/drawer.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/tooltip.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/input.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/autocomplete.css","webpac [...]
\ No newline at end of file
+{"version":3,"sources":["webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/popover.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/base.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/drawer.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/tooltip.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/input.css","webpack://echartsDoc/./node_modules/element-ui/lib/theme-chalk/autocomplete.css","webpac [...]
\ No newline at end of file
diff --git a/en/dependencies.html b/en/dependencies.html
index 391a24e..79e8723 100644
--- a/en/dependencies.html
+++ b/en/dependencies.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
+<!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!--  [...]
 </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -10,7 +10,9 @@
 <!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="lo [...]
 (function() {
 var hm = document.createElement("script");
+
 hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395";
+
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(hm, s);
 })();
diff --git a/en/dist/echarts-en.common.js b/en/dist/echarts-en.common.js
index 305307e..beb0f26 100644
--- a/en/dist/echarts-en.common.js
+++ b/en/dist/echarts-en.common.js
@@ -1285,7 +1285,11 @@ Draggable.prototype = {
 
     _dragStart: function (e) {
         var draggingTarget = e.target;
-        if (draggingTarget && draggingTarget.draggable) {
+        // Find if there is draggable in the ancestor
+        while (draggingTarget && !draggingTarget.draggable) {
+            draggingTarget = draggingTarget.parent;
+        }
+        if (draggingTarget) {
             this._draggingTarget = draggingTarget;
             draggingTarget.dragging = true;
             this._x = e.offsetX;
@@ -1714,6 +1718,8 @@ function buildTransformer(src, dest) {
     var detCache = {};
     var det = determinant(mA, 8, 0, 0, 0, detCache);
     if (det === 0) {
+        // can not make transformer when and only when
+        // any three of the markers are collinear.
         return;
     }
 
@@ -1736,6 +1742,153 @@ function buildTransformer(src, dest) {
     };
 }
 
+var EVENT_SAVED_PROP = '___zrEVENTSAVED';
+var _calcOut$1 = [];
+
+/**
+ * Transform "local coord" from `elFrom` to `elTarget`.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support when CSS transform is used.
+ *
+ * Having the `out` (that is, `[outX, outY]`), we can create an DOM element
+ * and set the CSS style as "left: outX; top: outY;" and append it to `elTarge`
+ * to locate the element.
+ *
+ * For example, this code below positions a child of `document.body` on the event
+ * point, no matter whether `body` has `margin`/`paddin`/`transfrom`/... :
+ * ```js
+ * transformLocalCoord(out, container, document.body, event.offsetX, event.offsetY);
+ * if (!eqNaN(out[0])) {
+ *     // Then locate the tip element on the event point.
+ *     var tipEl = document.createElement('div');
+ *     tipEl.style.cssText = 'position: absolute; left:' + out[0] + ';top:' + out[1] + ';';
+ *     document.body.appendChild(tipEl);
+ * }
+ * ```
+ *
+ * Notice: In some env this method is not supported. If called, `out` will be `[NaN, NaN]`.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output..
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} elFrom The `[inX, inY]` is based on elFrom.
+ * @param {HTMLElement} elTarget The `out` is based on elTarget.
+ * @param {number} inX
+ * @param {number} inY
+ * @return {boolean} Whether transform successfully.
+ */
+function transformLocalCoord(out, elFrom, elTarget, inX, inY) {
+    return transformCoordWithViewport(_calcOut$1, elFrom, inX, inY, true)
+        && transformCoordWithViewport(out, elTarget, _calcOut$1[0], _calcOut$1[1]);
+}
+
+/**
+ * Transform between a "viewport coord" and a "local coord".
+ * "viewport coord": the coord based on the left-top corner of the viewport
+ *     of the browser.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support the case when CSS transform is used on el.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output. If `inverse: false`,
+ *        it represents "local coord", otherwise "vireport coord".
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} el The "local coord" is based on the `el`, see comment above.
+ * @param {number} inX If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {number} inY If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {boolean} [inverse=false]
+ *        `true`: from "viewport coord" to "local coord".
+ *        `false`: from "local coord" to "viewport coord".
+ * @return {boolean} Whether transform successfully.
+ */
+function transformCoordWithViewport(out, el, inX, inY, inverse) {
+    if (el.getBoundingClientRect && env$1.domSupported && !isCanvasEl(el)) {
+        var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
+        var markers = prepareCoordMarkers(el, saved);
+        var transformer = preparePointerTransformer(markers, saved, inverse);
+        if (transformer) {
+            transformer(out, inX, inY);
+            return true;
+        }
+    }
+    return false;
+}
+
+function prepareCoordMarkers(el, saved) {
+    var markers = saved.markers;
+    if (markers) {
+        return markers;
+    }
+
+    markers = saved.markers = [];
+    var propLR = ['left', 'right'];
+    var propTB = ['top', 'bottom'];
+
+    for (var i = 0; i < 4; i++) {
+        var marker = document.createElement('div');
+        var stl = marker.style;
+        var idxLR = i % 2;
+        var idxTB = (i >> 1) % 2;
+        stl.cssText = [
+            'position: absolute',
+            'visibility: hidden',
+            'padding: 0',
+            'margin: 0',
+            'border-width: 0',
+            'user-select: none',
+            'width:0',
+            'height:0',
+            // 'width: 5px',
+            // 'height: 5px',
+            propLR[idxLR] + ':0',
+            propTB[idxTB] + ':0',
+            propLR[1 - idxLR] + ':auto',
+            propTB[1 - idxTB] + ':auto',
+            ''
+        ].join('!important;');
+        el.appendChild(marker);
+        markers.push(marker);
+    }
+
+    return markers;
+}
+
+function preparePointerTransformer(markers, saved, inverse) {
+    var transformerName = inverse ? 'invTrans' : 'trans';
+    var transformer = saved[transformerName];
+    var oldSrcCoords = saved.srcCoords;
+    var oldCoordTheSame = true;
+    var srcCoords = [];
+    var destCoords = [];
+
+    for (var i = 0; i < 4; i++) {
+        var rect = markers[i].getBoundingClientRect();
+        var ii = 2 * i;
+        var x = rect.left;
+        var y = rect.top;
+        srcCoords.push(x, y);
+        oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
+        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
+    }
+    // Cache to avoid time consuming of `buildTransformer`.
+    return (oldCoordTheSame && transformer)
+        ? transformer
+        : (
+            saved.srcCoords = srcCoords,
+            saved[transformerName] = inverse
+                ? buildTransformer(destCoords, srcCoords)
+                : buildTransformer(srcCoords, destCoords)
+        );
+}
+
+function isCanvasEl(el) {
+    return el.nodeName.toUpperCase() === 'CANVAS';
+}
+
 /**
  * Utilities for mouse or touch events.
  */
@@ -1743,7 +1896,6 @@ function buildTransformer(src, dest) {
 var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener;
 
 var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
-var EVENT_SAVED_PROP = '___zrEVENTSAVED';
 var _calcOut = [];
 
 /**
@@ -1808,11 +1960,11 @@ function clientToLocal(el, e, out, calculate) {
 
 function calculateZrXY(el, e, out) {
     // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect.
-    if (el.getBoundingClientRect && env$1.domSupported) {
+    if (env$1.domSupported && el.getBoundingClientRect) {
         var ex = e.clientX;
         var ey = e.clientY;
 
-        if (el.nodeName.toUpperCase() === 'CANVAS') {
+        if (isCanvasEl(el)) {
             // Original approach, which do not support CSS transform.
             // marker can not be locationed in a canvas container
             // (getBoundingClientRect is always 0). We do not support
@@ -1824,10 +1976,7 @@ function calculateZrXY(el, e, out) {
             return;
         }
         else {
-            var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
-            var transformer = preparePointerTransformer(prepareCoordMarkers(el, saved), saved);
-            if (transformer) {
-                transformer(_calcOut, ex, ey);
+            if (transformCoordWithViewport(_calcOut, el, ex, ey)) {
                 out.zrX = _calcOut[0];
                 out.zrY = _calcOut[1];
                 return;
@@ -1837,70 +1986,6 @@ function calculateZrXY(el, e, out) {
     out.zrX = out.zrY = 0;
 }
 
-function prepareCoordMarkers(el, saved) {
-    var markers = saved.markers;
-    if (markers) {
-        return markers;
-    }
-
-    markers = saved.markers = [];
-    var propLR = ['left', 'right'];
-    var propTB = ['top', 'bottom'];
-
-    for (var i = 0; i < 4; i++) {
-        var marker = document.createElement('div');
-        var stl = marker.style;
-        var idxLR = i % 2;
-        var idxTB = (i >> 1) % 2;
-        stl.cssText = [
-            'position:absolute',
-            'visibility: hidden',
-            'padding: 0',
-            'margin: 0',
-            'border-width: 0',
-            'width:0',
-            'height:0',
-            // 'width: 5px',
-            // 'height: 5px',
-            propLR[idxLR] + ':0',
-            propTB[idxTB] + ':0',
-            propLR[1 - idxLR] + ':auto',
-            propTB[1 - idxTB] + ':auto',
-            ''
-        ].join('!important;');
-        el.appendChild(marker);
-        markers.push(marker);
-    }
-
-    return markers;
-}
-
-function preparePointerTransformer(markers, saved) {
-    var transformer = saved.transformer;
-    var oldSrcCoords = saved.srcCoords;
-    var useOld = true;
-    var srcCoords = [];
-    var destCoords = [];
-
-    for (var i = 0; i < 4; i++) {
-        var rect = markers[i].getBoundingClientRect();
-        var ii = 2 * i;
-        var x = rect.left;
-        var y = rect.top;
-        srcCoords.push(x, y);
-        useOld &= oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
-        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
-    }
-
-    // Cache to avoid time consuming of `buildTransformer`.
-    return useOld
-        ? transformer
-        : (
-            saved.srcCoords = srcCoords,
-            saved.transformer = buildTransformer(srcCoords, destCoords)
-        );
-}
-
 /**
  * Find native event compat for legency IE.
  * Should be called at the begining of a native event listener.
@@ -4770,7 +4855,7 @@ var Animator = function (target, loop, getter, setter) {
 
 Animator.prototype = {
     /**
-     * 设置动画关键帧
+     * Set Animation keyframe
      * @param  {number} time 关键帧时间,单位是ms
      * @param  {Object} props 关键帧的属性值,key-value表示
      * @return {module:zrender/animation/Animator}
@@ -4849,7 +4934,7 @@ Animator.prototype = {
         }
     },
     /**
-     * 开始执行动画
+     * Start the animation
      * @param  {string|Function} [easing]
      *         动画缓动函数,详见{@link module:zrender/animation/easing}
      * @param  {boolean} forceAnimate
@@ -4910,7 +4995,7 @@ Animator.prototype = {
         return this;
     },
     /**
-     * 停止动画
+     * Stop animation
      * @param {boolean} forwardToLast If move to last frame before stop
      */
     stop: function (forwardToLast) {
@@ -4927,7 +5012,7 @@ Animator.prototype = {
         clipList.length = 0;
     },
     /**
-     * 设置动画延迟开始的时间
+     * Set when animation delay starts
      * @param  {number} time 单位ms
      * @return {module:zrender/animation/Animator}
      */
@@ -4936,7 +5021,7 @@ Animator.prototype = {
         return this;
     },
     /**
-     * 添加动画结束的回调
+     * Add callback for animation end
      * @param  {Function} cb
      * @return {module:zrender/animation/Animator}
      */
@@ -4988,7 +5073,7 @@ if (debugMode === 1) {
 var logError$1 = logError;
 
 /**
- * @alias modue:zrender/mixin/Animatable
+ * @alias module:zrender/mixin/Animatable
  * @constructor
  */
 var Animatable = function () {
@@ -10666,7 +10751,7 @@ Painter.prototype = {
 };
 
 /**
- * 动画主类, 调度和管理所有动画控制器
+ * Animation main class, dispatch and manage all animation controllers
  *
  * @module zrender/animation/Animation
  * @author pissang(https://github.com/pissang)
@@ -10731,14 +10816,14 @@ Animation.prototype = {
 
     constructor: Animation,
     /**
-     * 添加 clip
+     * Add clip
      * @param {module:zrender/animation/Clip} clip
      */
     addClip: function (clip) {
         this._clips.push(clip);
     },
     /**
-     * 添加 animator
+     * Add animator
      * @param {module:zrender/animation/Animator} animator
      */
     addAnimator: function (animator) {
@@ -10749,7 +10834,7 @@ Animation.prototype = {
         }
     },
     /**
-     * 删除动画片段
+     * Delete animation clip
      * @param {module:zrender/animation/Clip} clip
      */
     removeClip: function (clip) {
@@ -10760,7 +10845,7 @@ Animation.prototype = {
     },
 
     /**
-     * 删除动画片段
+     * Delete animation clip
      * @param {module:zrender/animation/Animator} animator
      */
     removeAnimator: function (animator) {
@@ -11027,13 +11112,16 @@ function normalizeGlobalEvent(instance, event) {
  * Detect whether the given el is in `painterRoot`.
  */
 function isLocalEl(instance, el) {
+    var elTmp = el;
     var isLocal = false;
-    do {
-        el = el && el.parentNode;
+    while (elTmp && elTmp.nodeType !== 9
+        && !(
+            isLocal = elTmp.domBelongToZr
+                || (elTmp !== el && elTmp === instance.painterRoot)
+        )
+    ) {
+        elTmp = elTmp.parentNode;
     }
-    while (el && el.nodeType !== 9 && !(
-        isLocal = el === instance.painterRoot
-    ));
     return isLocal;
 }
 
@@ -11488,7 +11576,7 @@ var instances$1 = {};    // ZRender实例map索引
 /**
  * @type {string}
  */
-var version$1 = '4.2.0';
+var version$1 = '4.3.0';
 
 /**
  * Initializing a zrender instance
@@ -16377,12 +16465,10 @@ var round = Math.round;
  * @param {number} [inputShape.x2]
  * @param {number} [inputShape.y2]
  * @param {Object} [style]
- * @param {number} [style.lineWidth]
+ * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
  */
 function subPixelOptimizeLine$1(outputShape, inputShape, style) {
-    var lineWidth = style && style.lineWidth;
-
-    if (!inputShape || !lineWidth) {
+    if (!inputShape) {
         return;
     }
 
@@ -16391,20 +16477,22 @@ function subPixelOptimizeLine$1(outputShape, inputShape, style) {
     var y1 = inputShape.y1;
     var y2 = inputShape.y2;
 
+    outputShape.x1 = x1;
+    outputShape.x2 = x2;
+    outputShape.y1 = y1;
+    outputShape.y2 = y2;
+
+    var lineWidth = style && style.lineWidth;
+    if (!lineWidth) {
+        return;
+    }
+
     if (round(x1 * 2) === round(x2 * 2)) {
         outputShape.x1 = outputShape.x2 = subPixelOptimize$1(x1, lineWidth, true);
     }
-    else {
-        outputShape.x1 = x1;
-        outputShape.x2 = x2;
-    }
     if (round(y1 * 2) === round(y2 * 2)) {
         outputShape.y1 = outputShape.y2 = subPixelOptimize$1(y1, lineWidth, true);
     }
-    else {
-        outputShape.y1 = y1;
-        outputShape.y2 = y2;
-    }
 }
 
 /**
@@ -16420,12 +16508,10 @@ function subPixelOptimizeLine$1(outputShape, inputShape, style) {
  * @param {number} [inputShape.width]
  * @param {number} [inputShape.height]
  * @param {Object} [style]
- * @param {number} [style.lineWidth]
+ * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
  */
 function subPixelOptimizeRect$1(outputShape, inputShape, style) {
-    var lineWidth = style && style.lineWidth;
-
-    if (!inputShape || !lineWidth) {
+    if (!inputShape) {
         return;
     }
 
@@ -16434,6 +16520,16 @@ function subPixelOptimizeRect$1(outputShape, inputShape, style) {
     var originWidth = inputShape.width;
     var originHeight = inputShape.height;
 
+    outputShape.x = originX;
+    outputShape.y = originY;
+    outputShape.width = originWidth;
+    outputShape.height = originHeight;
+
+    var lineWidth = style && style.lineWidth;
+    if (!lineWidth) {
+        return;
+    }
+
     outputShape.x = subPixelOptimize$1(originX, lineWidth, true);
     outputShape.y = subPixelOptimize$1(originY, lineWidth, true);
     outputShape.width = Math.max(
@@ -16450,11 +16546,14 @@ function subPixelOptimizeRect$1(outputShape, inputShape, style) {
  * Sub pixel optimize for canvas
  *
  * @param {number} position Coordinate, such as x, y
- * @param {number} lineWidth Should be nonnegative integer.
+ * @param {number} lineWidth If `null`/`undefined`/`0`, do not optimize.
  * @param {boolean=} positiveOrNegative Default false (negative).
  * @return {number} Optimized position.
  */
 function subPixelOptimize$1(position, lineWidth, positiveOrNegative) {
+    if (!lineWidth) {
+        return position;
+    }
     // Assure that (position + lineWidth / 2) is near integer edge,
     // otherwise line will be fuzzy in canvas.
     var doubledPosition = round(position * 2);
@@ -18155,7 +18254,7 @@ function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb)
  * configuration in series.
  *
  * Caution: this method will stop previous animation.
- * So if do not use this method to one element twice before
+ * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  *
  * @param {module:zrender/Element} el
@@ -18181,7 +18280,7 @@ function updateProps(el, props, animatableModel, dataIndex, cb) {
  * configuration in series.
  *
  * Caution: this method will stop previous animation.
- * So if do not use this method to one element twice before
+ * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  *
  * @param {module:zrender/Element} el
@@ -25019,8 +25118,11 @@ var createRenderPlanner = function () {
         var originalLarge = fields.large;
         var originalProgressive = fields.progressiveRender;
 
-        var large = fields.large = pipelineContext.large;
-        var progressive = fields.progressiveRender = pipelineContext.progressiveRender;
+        // FIXME: if the planner works on a filtered series, `pipelineContext` does not
+        // exists. See #11611 . Probably we need to modify this structure, see the comment
+        // on `performRawSeries` in `Schedular.js`.
+        var large = fields.large = pipelineContext && pipelineContext.large;
+        var progressive = fields.progressiveRender = pipelineContext && pipelineContext.progressiveRender;
 
         return !!((originalLarge ^ large) || (originalProgressive ^ progressive)) && 'reset';
     };
@@ -26169,6 +26271,14 @@ function performStageTasks(scheduler, stageHandlers, ecModel, payload, opt) {
                     task.dirty();
                 }
                 var performArgs = scheduler.getPerformArgs(task, opt.block);
+                // FIXME
+                // if intending to decalare `performRawSeries` in handlers, only
+                // stream-independent (specifically, data item independent) operations can be
+                // performed. Because is a series is filtered, most of the tasks will not
+                // be performed. A stream-dependent operation probably cause wrong biz logic.
+                // Perhaps we should not provide a separate callback for this case instead
+                // of providing the config `performRawSeries`. The stream-dependent operaions
+                // and stream-independent operations should better not be mixed.
                 performArgs.skip = !stageHandler.performRawSeries
                     && ecModel.isSeriesFiltered(task.context.model);
                 updatePayload(task, payload);
@@ -27543,10 +27653,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.6.0';
+var version = '4.7.0';
 
 var dependencies = {
-    zrender: '4.2.0'
+    zrender: '4.3.0'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -33831,7 +33941,7 @@ var IntervalScale = Scale.extend({
 
         if (extent[0] < niceTickExtent[0]) {
             if (expandToNicedExtent) {
-                ticks.push(roundNumber(niceTickExtent[0] - interval));
+                ticks.push(roundNumber(niceTickExtent[0] - interval, intervalPrecision));
             }
             else {
                 ticks.push(extent[0]);
@@ -33857,7 +33967,7 @@ var IntervalScale = Scale.extend({
         var lastNiceTick = ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1];
         if (extent[1] > lastNiceTick) {
             if (expandToNicedExtent) {
-                ticks.push(lastNiceTick + interval);
+                ticks.push(roundNumber(lastNiceTick + interval, intervalPrecision));
             }
             else {
                 ticks.push(extent[1]);
@@ -34405,11 +34515,6 @@ function layout(seriesType, ecModel) {
             var value = data.get(valueDim, idx);
             var baseValue = data.get(baseDim, idx);
 
-            // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
-            if (isNaN(value) || isNaN(baseValue)) {
-                continue;
-            }
-
             var sign = value >= 0 ? 'p' : 'n';
             var baseCoord = valueAxisStart;
 
@@ -34442,7 +34547,10 @@ function layout(seriesType, ecModel) {
                 if (Math.abs(width) < barMinHeight) {
                     width = (width < 0 ? -1 : 1) * barMinHeight;
                 }
-                stacked && (lastStackCoords[stackId][baseValue][sign] += width);
+                // Ignore stack from NaN value
+                if (!isNaN(width)) {
+                    stacked && (lastStackCoords[stackId][baseValue][sign] += width);
+                }
             }
             else {
                 var coord = cartesian.dataToPoint([baseValue, value]);
@@ -34455,7 +34563,10 @@ function layout(seriesType, ecModel) {
                     // Include zero to has a positive bar
                     height = (height <= 0 ? -1 : 1) * barMinHeight;
                 }
-                stacked && (lastStackCoords[stackId][baseValue][sign] += height);
+                // Ignore stack from NaN value
+                if (!isNaN(height)) {
+                    stacked && (lastStackCoords[stackId][baseValue][sign] += height);
+                }
             }
 
             data.setItemLayout(idx, {
@@ -34483,6 +34594,7 @@ var largeLayout = {
 
         var data = seriesModel.getData();
         var cartesian = seriesModel.coordinateSystem;
+        var coordLayout = cartesian.grid.getRect();
         var baseAxis = cartesian.getBaseAxis();
         var valueAxis = cartesian.getOtherAxis(baseAxis);
         var valueDim = data.mapDimension(valueAxis.dim);
@@ -34502,6 +34614,7 @@ var largeLayout = {
         function progress(params, data) {
             var count = params.count;
             var largePoints = new LargeArr(count * 2);
+            var largeBackgroundPoints = new LargeArr(count * 2);
             var largeDataIndices = new LargeArr(count);
             var dataIndex;
             var coord = [];
@@ -34515,7 +34628,9 @@ var largeLayout = {
 
                 coord = cartesian.dataToPoint(valuePair, null, coord);
                 // Data index might not be in order, depends on `progressiveChunkMode`.
+                largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coordLayout.x + coordLayout.width : coord[0];
                 largePoints[pointsOffset++] = coord[0];
+                largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coord[1] : coordLayout.y + coordLayout.height;
                 largePoints[pointsOffset++] = coord[1];
                 largeDataIndices[idxOffset++] = dataIndex;
             }
@@ -34523,8 +34638,10 @@ var largeLayout = {
             data.setLayout({
                 largePoints: largePoints,
                 largeDataIndices: largeDataIndices,
+                largeBackgroundPoints: largeBackgroundPoints,
                 barWidth: barWidth,
                 valueAxisStart: getValueAxisStart(baseAxis, valueAxis, false),
+                backgroundStart: valueAxisHorizontal ? coordLayout.x : coordLayout.y,
                 valueAxisHorizontal: valueAxisHorizontal
             });
         }
@@ -42411,6 +42528,117 @@ function layout$1(gridModel, axisModel, opt) {
 * under the License.
 */
 
+function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) {
+    var axis = axisModel.axis;
+
+    if (axis.scale.isBlank()) {
+        return;
+    }
+
+    var splitAreaModel = axisModel.getModel('splitArea');
+    var areaStyleModel = splitAreaModel.getModel('areaStyle');
+    var areaColors = areaStyleModel.get('color');
+
+    var gridRect = gridModel.coordinateSystem.getRect();
+
+    var ticksCoords = axis.getTicksCoords({
+        tickModel: splitAreaModel,
+        clamp: true
+    });
+
+    if (!ticksCoords.length) {
+        return;
+    }
+
+    // For Making appropriate splitArea animation, the color and anid
+    // should be corresponding to previous one if possible.
+    var areaColorsLen = areaColors.length;
+    var lastSplitAreaColors = axisView.__splitAreaColors;
+    var newSplitAreaColors = createHashMap();
+    var colorIndex = 0;
+    if (lastSplitAreaColors) {
+        for (var i = 0; i < ticksCoords.length; i++) {
+            var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
+            if (cIndex != null) {
+                colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
+                break;
+            }
+        }
+    }
+
+    var prev = axis.toGlobalCoord(ticksCoords[0].coord);
+
+    var areaStyle = areaStyleModel.getAreaStyle();
+    areaColors = isArray(areaColors) ? areaColors : [areaColors];
+
+    for (var i = 1; i < ticksCoords.length; i++) {
+        var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
+
+        var x;
+        var y;
+        var width;
+        var height;
+        if (axis.isHorizontal()) {
+            x = prev;
+            y = gridRect.y;
+            width = tickCoord - x;
+            height = gridRect.height;
+            prev = x + width;
+        }
+        else {
+            x = gridRect.x;
+            y = prev;
+            width = gridRect.width;
+            height = tickCoord - y;
+            prev = y + height;
+        }
+
+        var tickValue = ticksCoords[i - 1].tickValue;
+        tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
+
+        axisGroup.add(new Rect({
+            anid: tickValue != null ? 'area_' + tickValue : null,
+            shape: {
+                x: x,
+                y: y,
+                width: width,
+                height: height
+            },
+            style: defaults({
+                fill: areaColors[colorIndex]
+            }, areaStyle),
+            silent: true
+        }));
+
+        colorIndex = (colorIndex + 1) % areaColorsLen;
+    }
+
+    axisView.__splitAreaColors = newSplitAreaColors;
+}
+
+function rectCoordAxisHandleRemove(axisView) {
+    axisView.__splitAreaColors = null;
+}
+
+/*
+* 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.
+*/
+
 var axisBuilderAttrs = [
     'axisLine', 'axisTickLabel', 'axisName'
 ];
@@ -42462,7 +42690,7 @@ var CartesianAxisView = AxisView.extend({
     },
 
     remove: function () {
-        this._splitAreaColors = null;
+        rectCoordAxisHandleRemove(this);
     },
 
     /**
@@ -42594,91 +42822,7 @@ var CartesianAxisView = AxisView.extend({
      * @private
      */
     _splitArea: function (axisModel, gridModel) {
-        var axis = axisModel.axis;
-
-        if (axis.scale.isBlank()) {
-            return;
-        }
-
-        var splitAreaModel = axisModel.getModel('splitArea');
-        var areaStyleModel = splitAreaModel.getModel('areaStyle');
-        var areaColors = areaStyleModel.get('color');
-
-        var gridRect = gridModel.coordinateSystem.getRect();
-
-        var ticksCoords = axis.getTicksCoords({
-            tickModel: splitAreaModel,
-            clamp: true
-        });
-
-        if (!ticksCoords.length) {
-            return;
-        }
-
-        // For Making appropriate splitArea animation, the color and anid
-        // should be corresponding to previous one if possible.
-        var areaColorsLen = areaColors.length;
-        var lastSplitAreaColors = this._splitAreaColors;
-        var newSplitAreaColors = createHashMap();
-        var colorIndex = 0;
-        if (lastSplitAreaColors) {
-            for (var i = 0; i < ticksCoords.length; i++) {
-                var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
-                if (cIndex != null) {
-                    colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
-                    break;
-                }
-            }
-        }
-
-        var prev = axis.toGlobalCoord(ticksCoords[0].coord);
-
-        var areaStyle = areaStyleModel.getAreaStyle();
-        areaColors = isArray(areaColors) ? areaColors : [areaColors];
-
-        for (var i = 1; i < ticksCoords.length; i++) {
-            var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
-
-            var x;
-            var y;
-            var width;
-            var height;
-            if (axis.isHorizontal()) {
-                x = prev;
-                y = gridRect.y;
-                width = tickCoord - x;
-                height = gridRect.height;
-                prev = x + width;
-            }
-            else {
-                x = gridRect.x;
-                y = prev;
-                width = gridRect.width;
-                height = tickCoord - y;
-                prev = y + height;
-            }
-
-            var tickValue = ticksCoords[i - 1].tickValue;
-            tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
-
-            this._axisGroup.add(new Rect({
-                anid: tickValue != null ? 'area_' + tickValue : null,
-                shape: {
-                    x: x,
-                    y: y,
-                    width: width,
-                    height: height
-                },
-                style: defaults({
-                    fill: areaColors[colorIndex]
-                }, areaStyle),
-                silent: true
-            }));
-
-            colorIndex = (colorIndex + 1) % areaColorsLen;
-        }
-
-        this._splitAreaColors = newSplitAreaColors;
+        rectCoordAxisBuildSplitArea(this, this._axisGroup, axisModel, gridModel);
     }
 });
 
@@ -42924,7 +43068,21 @@ BaseBarSeries.extend({
 
         // If use caps on two sides of bars
         // Only available on tangential polar bar
-        roundCap: false
+        roundCap: false,
+
+        showBackground: false,
+        backgroundStyle: {
+            color: 'rgba(180, 180, 180, 0.2)',
+            borderColor: null,
+            borderWidth: 0,
+            borderType: 'solid',
+            borderRadius: 0,
+            shadowBlur: 0,
+            shadowColor: null,
+            shadowOffsetX: 0,
+            shadowOffsetY: 0,
+            opacity: 1
+        }
     }
 });
 
@@ -43229,15 +43387,28 @@ extendChartView({
 
         var roundCap = seriesModel.get('roundCap', true);
 
+        var drawBackground = seriesModel.get('showBackground', true);
+        var backgroundModel = seriesModel.getModel('backgroundStyle');
+
+        var bgEls = [];
+        var oldBgEls = this._backgroundEls || [];
+
         data.diff(oldData)
             .add(function (dataIndex) {
+                var itemModel = data.getItemModel(dataIndex);
+                var layout = getLayout[coord.type](data, dataIndex, itemModel);
+
+                if (drawBackground) {
+                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, layout);
+                    bgEl.useStyle(backgroundModel.getBarItemStyle());
+                    bgEls[dataIndex] = bgEl;
+                }
+
+                // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
                 if (!data.hasValue(dataIndex)) {
                     return;
                 }
 
-                var itemModel = data.getItemModel(dataIndex);
-                var layout = getLayout[coord.type](data, dataIndex, itemModel);
-
                 if (needsClip) {
                     // Clip will modify the layout params.
                     // And return a boolean to determine if the shape are fully clipped.
@@ -43260,16 +43431,24 @@ extendChartView({
                 );
             })
             .update(function (newIndex, oldIndex) {
-                var el = oldData.getItemGraphicEl(oldIndex);
+                var itemModel = data.getItemModel(newIndex);
+                var layout = getLayout[coord.type](data, newIndex, itemModel);
+
+                if (drawBackground) {
+                    var bgEl = oldBgEls[oldIndex];
+                    bgEl.useStyle(backgroundModel.getBarItemStyle());
+                    bgEls[newIndex] = bgEl;
 
+                    var shape = createBackgroundShape(isHorizontalOrRadial, layout, coord);
+                    updateProps(bgEl, { shape: shape }, animationModel, newIndex);
+                }
+
+                var el = oldData.getItemGraphicEl(oldIndex);
                 if (!data.hasValue(newIndex)) {
                     group.remove(el);
                     return;
                 }
 
-                var itemModel = data.getItemModel(newIndex);
-                var layout = getLayout[coord.type](data, newIndex, itemModel);
-
                 if (needsClip) {
                     var isClipped = clip[coord.type](coordSysClipArea, layout);
                     if (isClipped) {
@@ -43307,6 +43486,15 @@ extendChartView({
             })
             .execute();
 
+        var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group());
+        bgGroup.removeAll();
+
+        for (var i = 0; i < bgEls.length; ++i) {
+            bgGroup.add(bgEls[i]);
+        }
+        group.add(bgGroup);
+        this._backgroundEls = bgEls;
+
         this._data = data;
     },
 
@@ -43327,6 +43515,7 @@ extendChartView({
     },
 
     _incrementalRenderLarge: function (params, seriesModel) {
+        this._removeBackground();
         createLarge(seriesModel, this.group, true);
     },
 
@@ -43340,6 +43529,9 @@ extendChartView({
         var group = this.group;
         var data = this._data;
         if (ecModel && ecModel.get('animation') && data && !this._isLargeDraw) {
+            this._removeBackground();
+            this._backgroundEls = [];
+
             data.eachItemGraphicEl(function (el) {
                 if (el.type === 'sector') {
                     removeSector(el.dataIndex, ecModel, el);
@@ -43353,6 +43545,11 @@ extendChartView({
             group.removeAll();
         }
         this._data = null;
+    },
+
+    _removeBackground: function () {
+        this.group.remove(this._backgroundGroup);
+        this._backgroundGroup = null;
     }
 
 });
@@ -43410,7 +43607,12 @@ var elementCreator = {
         dataIndex, layout, isHorizontal,
         animationModel, isUpdate
     ) {
-        var rect = new Rect({shape: extend({}, layout)});
+        var rect = new Rect({
+            shape: extend({}, layout),
+            z2: 1
+        });
+
+        rect.name = 'item';
 
         // Animation
         if (animationModel) {
@@ -43440,9 +43642,12 @@ var elementCreator = {
         var ShapeClass = (!isRadial && roundCap) ? Sausage : Sector;
 
         var sector = new ShapeClass({
-            shape: defaults({clockwise: clockwise}, layout)
+            shape: defaults({clockwise: clockwise}, layout),
+            z2: 1
         });
 
+        sector.name = 'item';
+
         // Animation
         if (animationModel) {
             var sectorShape = sector.shape;
@@ -43562,7 +43767,10 @@ function updateStyle(
 // In case width or height are too small.
 function getLineWidth(itemModel, rawLayout) {
     var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
-    return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height));
+    // width or height may be NaN for empty data
+    var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width);
+    var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height);
+    return Math.min(lineWidth, width, height);
 }
 
 
@@ -43594,13 +43802,38 @@ function createLarge(seriesModel, group, incremental) {
     var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
     startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart');
 
+    var largeDataIndices = data.getLayout('largeDataIndices');
+    var barWidth = data.getLayout('barWidth');
+
+    var backgroundModel = seriesModel.getModel('backgroundStyle');
+    var drawBackground = seriesModel.get('showBackground', true);
+
+    if (drawBackground) {
+        var points = data.getLayout('largeBackgroundPoints');
+        var backgroundStartPoint = [];
+        backgroundStartPoint[1 - baseDimIdx] = data.getLayout('backgroundStart');
+
+        var bgEl = new LargePath({
+            shape: {points: points},
+            incremental: !!incremental,
+            __startPoint: backgroundStartPoint,
+            __baseDimIdx: baseDimIdx,
+            __largeDataIndices: largeDataIndices,
+            __barWidth: barWidth,
+            silent: true,
+            z2: 0
+        });
+        setLargeBackgroundStyle(bgEl, backgroundModel, data);
+        group.add(bgEl);
+    }
+
     var el = new LargePath({
         shape: {points: data.getLayout('largePoints')},
         incremental: !!incremental,
         __startPoint: startPoint,
         __baseDimIdx: baseDimIdx,
-        __largeDataIndices: data.getLayout('largeDataIndices'),
-        __barWidth: data.getLayout('barWidth')
+        __largeDataIndices: largeDataIndices,
+        __barWidth: barWidth
     });
     group.add(el);
     setLargeStyle(el, seriesModel, data);
@@ -43665,6 +43898,55 @@ function setLargeStyle(el, seriesModel, data) {
     el.style.lineWidth = data.getLayout('barWidth');
 }
 
+function setLargeBackgroundStyle(el, backgroundModel, data) {
+    var borderColor = backgroundModel.get('borderColor') || backgroundModel.get('color');
+    var itemStyle = backgroundModel.getItemStyle(['color', 'borderColor']);
+
+    el.useStyle(itemStyle);
+    el.style.fill = null;
+    el.style.stroke = borderColor;
+    el.style.lineWidth = data.getLayout('barWidth');
+}
+
+function createBackgroundShape(isHorizontalOrRadial, layout, coord) {
+    var coordLayout;
+    var isPolar = coord.type === 'polar';
+    if (isPolar) {
+        coordLayout = coord.getArea();
+    }
+    else {
+        coordLayout = coord.grid.getRect();
+    }
+
+    if (isPolar) {
+        return {
+            cx: coordLayout.cx,
+            cy: coordLayout.cy,
+            r0: isHorizontalOrRadial ? coordLayout.r0 : layout.r0,
+            r: isHorizontalOrRadial ? coordLayout.r : layout.r,
+            startAngle: isHorizontalOrRadial ? layout.startAngle : 0,
+            endAngle: isHorizontalOrRadial ? layout.endAngle : Math.PI * 2
+        };
+    }
+    else {
+        return {
+            x: isHorizontalOrRadial ? layout.x : coordLayout.x,
+            y: isHorizontalOrRadial ? coordLayout.y : layout.y,
+            width: isHorizontalOrRadial ? layout.width : coordLayout.width,
+            height: isHorizontalOrRadial ? coordLayout.height : layout.height
+        };
+    }
+}
+
+function createBackgroundEl(coord, isHorizontalOrRadial, layout) {
+    var ElementClz = coord.type === 'polar' ? Sector : Rect;
+    return new ElementClz({
+        shape: createBackgroundShape(isHorizontalOrRadial, layout, coord),
+        silent: true,
+        z2: 0
+    });
+}
+
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -44274,7 +44556,7 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
     toggleItemSelected(
         this,
         data.getItemLayout(idx),
-        seriesModel.isSelected(null, idx),
+        seriesModel.isSelected(data.getName(idx)),
         seriesModel.get('selectedOffset'),
         seriesModel.get('animation')
     );
@@ -45026,7 +45308,7 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, viewLeft, vie
             inside: isLabelInside,
             labelDistance: labelDistance,
             labelAlignTo: labelAlignTo,
-            labelMargin:labelMargin,
+            labelMargin: labelMargin,
             bleedMargin: bleedMargin,
             textRect: textRect,
             text: text,
@@ -48391,24 +48673,63 @@ function assembleCssText(tooltipModel) {
     return cssText.join(';') + ';';
 }
 
+// If not able to make, do not modify the input `out`.
+function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
+    var zrPainter = zr && zr.painter;
+
+    if (appendToBody) {
+        var zrViewportRoot = zrPainter && zrPainter.getViewportRoot();
+        if (zrViewportRoot) {
+            // Some APPs might use scale on body, so we support CSS transform here.
+            transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY);
+        }
+    }
+    else {
+        out[0] = zrX;
+        out[1] = zrY;
+        // xy should be based on canvas root. But tooltipContent is
+        // the sibling of canvas root. So padding of ec container
+        // should be considered here.
+        var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset();
+        if (viewportRootOffset) {
+            out[0] += viewportRootOffset.offsetLeft;
+            out[1] += viewportRootOffset.offsetTop;
+        }
+    }
+}
+
 /**
  * @alias module:echarts/component/tooltip/TooltipContent
+ * @param {HTMLElement} container
+ * @param {ExtensionAPI} api
+ * @param {Object} [opt]
+ * @param {boolean} [opt.appendToBody]
+ *        `false`: the DOM element will be inside the container. Default value.
+ *        `true`: the DOM element will be appended to HTML body, which avoid
+ *                some overflow clip but intrude outside of the container.
  * @constructor
  */
-function TooltipContent(container, api) {
+function TooltipContent(container, api, opt) {
     if (env$1.wxa) {
         return null;
     }
 
     var el = document.createElement('div');
+    el.domBelongToZr = true;
+    this.el = el;
     var zr = this._zr = api.getZr();
+    var appendToBody = this._appendToBody = opt && opt.appendToBody;
 
-    this.el = el;
+    this._styleCoord = [0, 0];
 
-    this._x = api.getWidth() / 2;
-    this._y = api.getHeight() / 2;
+    makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
 
-    container.appendChild(el);
+    if (appendToBody) {
+        document.body.appendChild(el);
+    }
+    else {
+        container.appendChild(el);
+    }
 
     this._container = container;
 
@@ -48442,7 +48763,8 @@ function TooltipContent(container, api) {
             // Try trigger zrender event to avoid mouse
             // in and out shape too frequently
             var handler = zr.handler;
-            normalizeEvent(container, e, true);
+            var zrViewportRoot = zr.painter.getViewportRoot();
+            normalizeEvent(zrViewportRoot, e, true);
             handler.dispatch('mousemove', e);
         }
     };
@@ -48487,12 +48809,13 @@ TooltipContent.prototype = {
     show: function (tooltipModel) {
         clearTimeout(this._hideTimeout);
         var el = this.el;
+        var styleCoord = this._styleCoord;
 
         el.style.cssText = gCssText + assembleCssText(tooltipModel)
             // Because of the reason described in:
             // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
             // we should set initial value to `left` and `top`.
-            + ';left:' + this._x + 'px;top:' + this._y + 'px;'
+            + ';left:' + styleCoord[0] + 'px;top:' + styleCoord[1] + 'px;'
             + (tooltipModel.get('extraCssText') || '');
 
         el.style.display = el.innerHTML ? 'block' : 'none';
@@ -48520,23 +48843,13 @@ TooltipContent.prototype = {
         return [el.clientWidth, el.clientHeight];
     },
 
-    moveTo: function (x, y) {
-        // xy should be based on canvas root. But tooltipContent is
-        // the sibling of canvas root. So padding of ec container
-        // should be considered here.
-        var zr = this._zr;
-        var viewportRootOffset;
-        if (zr && zr.painter && (viewportRootOffset = zr.painter.getViewportRootOffset())) {
-            x += viewportRootOffset.offsetLeft;
-            y += viewportRootOffset.offsetTop;
-        }
+    moveTo: function (zrX, zrY) {
+        var styleCoord = this._styleCoord;
+        makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY);
 
         var style = this.el.style;
-        style.left = x + 'px';
-        style.top = y + 'px';
-
-        this._x = x;
-        this._y = y;
+        style.left = styleCoord[0] + 'px';
+        style.top = styleCoord[1] + 'px';
     },
 
     hide: function () {
@@ -48562,6 +48875,10 @@ TooltipContent.prototype = {
         return this._show;
     },
 
+    dispose: function () {
+        this.el.parentNode.removeChild(this.el);
+    },
+
     getOuterSize: function () {
         var width = this.el.clientWidth;
         var height = this.el.clientHeight;
@@ -48578,6 +48895,7 @@ TooltipContent.prototype = {
 
         return {width: width, height: height};
     }
+
 };
 
 /*
@@ -48809,7 +49127,9 @@ extendComponentView({
 
         var tooltipContent;
         if (this._renderMode === 'html') {
-            tooltipContent = new TooltipContent(api.getDom(), api);
+            tooltipContent = new TooltipContent(api.getDom(), api, {
+                appendToBody: tooltipModel.get('appendToBody', true)
+            });
             this._newLine = '<br/>';
         }
         else {
@@ -48962,7 +49282,6 @@ extendComponentView({
                 offsetX: payload.x,
                 offsetY: payload.y,
                 position: payload.position,
-                event: {},
                 dataByCoordSys: payload.dataByCoordSys,
                 tooltipOption: payload.tooltipOption
             }, dispatchAction);
@@ -48981,8 +49300,7 @@ extendComponentView({
                     offsetX: cx,
                     offsetY: cy,
                     position: payload.position,
-                    target: pointInfo.el,
-                    event: {}
+                    target: pointInfo.el
                 }, dispatchAction);
             }
         }
@@ -48999,8 +49317,7 @@ extendComponentView({
                 offsetX: payload.x,
                 offsetY: payload.y,
                 position: payload.position,
-                target: api.getZr().findHover(payload.x, payload.y).target,
-                event: {}
+                target: api.getZr().findHover(payload.x, payload.y).target
             }, dispatchAction);
         }
     },
@@ -49106,7 +49423,9 @@ extendComponentView({
     _showAxisTooltip: function (dataByCoordSys, e) {
         var ecModel = this._ecModel;
         var globalTooltipModel = this._tooltipModel;
+
         var point = [e.offsetX, e.offsetY];
+
         var singleDefaultHTML = [];
         var singleParamsList = [];
         var singleTooltipModel = buildTooltipModel([
@@ -49362,6 +49681,7 @@ extendComponentView({
     _updatePosition: function (tooltipModel, positionExpr, x, y, content, params, el) {
         var viewWidth = this._api.getWidth();
         var viewHeight = this._api.getHeight();
+
         positionExpr = positionExpr || tooltipModel.get('position');
 
         var contentSize = content.getSize();
@@ -49480,7 +49800,7 @@ extendComponentView({
         if (env$1.node) {
             return;
         }
-        this._tooltipContent.hide();
+        this._tooltipContent.dispose();
         unregister('itemTooltip', api);
     }
 });
@@ -51325,26 +51645,28 @@ var ScrollableLegendView = LegendView.extend({
     },
 
     _findTargetItemIndex: function (targetDataIndex) {
+        if (!this._showController) {
+            return 0;
+        }
+
         var index;
         var contentGroup = this.getContentGroup();
         var defaultIndex;
 
-        if (this._showController) {
-            contentGroup.eachChild(function (child, idx) {
-                var legendDataIdx = child.__legendDataIndex;
-                // FIXME
-                // If the given targetDataIndex (from model) is illegal,
-                // we use defualtIndex. But the index on the legend model and
-                // action payload is still illegal. That case will not be
-                // changed until some scenario requires.
-                if (defaultIndex == null && legendDataIdx != null) {
-                    defaultIndex = idx;
-                }
-                if (legendDataIdx === targetDataIndex) {
-                    index = idx;
-                }
-            });
-        }
+        contentGroup.eachChild(function (child, idx) {
+            var legendDataIdx = child.__legendDataIndex;
+            // FIXME
+            // If the given targetDataIndex (from model) is illegal,
+            // we use defualtIndex. But the index on the legend model and
+            // action payload is still illegal. That case will not be
+            // changed until some scenario requires.
+            if (defaultIndex == null && legendDataIdx != null) {
+                defaultIndex = idx;
+            }
+            if (legendDataIdx === targetDataIndex) {
+                index = idx;
+            }
+        });
 
         return index != null ? index : defaultIndex;
     }
@@ -51926,8 +52248,8 @@ function markerTypeCalculatorWithExtent(
 
     var dataIndex = data.indicesOfNearest(calcDataDim, value)[0];
     coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex);
-    coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex);
-
+    coordArr[targetCoordIndex] = data.get(calcDataDim, dataIndex);
+    var coordArrValue = data.get(targetDataDim, dataIndex);
     // Make it simple, do not visit all stacked value to count precision.
     var precision = getPrecision(data.get(targetDataDim, dataIndex));
     precision = Math.min(precision, 20);
@@ -51935,7 +52257,7 @@ function markerTypeCalculatorWithExtent(
         coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
     }
 
-    return coordArr;
+    return [coordArr, coordArrValue];
 }
 
 var curry$4 = curry;
@@ -51998,12 +52320,15 @@ function dataTransform(seriesModel, item) {
             var otherCoordIndex = indexOf$1(dims, axisInfo.baseAxis.dim);
             var targetCoordIndex = indexOf$1(dims, axisInfo.valueAxis.dim);
 
-            item.coord = markerTypeCalculator[item.type](
+            var coordInfo = markerTypeCalculator[item.type](
                 data, axisInfo.baseDataDim, axisInfo.valueDataDim,
                 otherCoordIndex, targetCoordIndex
             );
+            item.coord = coordInfo[0];
             // Force to use the value of calculated value.
-            item.value = item.coord[targetCoordIndex];
+            // let item use the value without stack.
+            item.value = coordInfo[1];
+
         }
         else {
             // FIXME Only has one of xAxis and yAxis.
@@ -52395,7 +52720,8 @@ MarkerModel.extend({
         },
         label: {
             show: true,
-            position: 'end'
+            position: 'end',
+            distance: 5
         },
         lineStyle: {
             type: 'dashed'
@@ -52620,39 +52946,90 @@ function updateSymbolAndLabelBeforeLineUpdate() {
         var textPosition;
         var textAlign;
         var textVerticalAlign;
-
-        var distance$$1 = 5 * invScale;
-        // End
-        if (label.__position === 'end') {
-            textPosition = [d[0] * distance$$1 + toPos[0], d[1] * distance$$1 + toPos[1]];
-            textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center');
-            textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle');
-        }
-        // Middle
-        else if (label.__position === 'middle') {
-            var halfPercent = percent / 2;
-            var tangent = line.tangentAt(halfPercent);
-            var n = [tangent[1], -tangent[0]];
-            var cp = line.pointAt(halfPercent);
-            if (n[1] > 0) {
-                n[0] = -n[0];
-                n[1] = -n[1];
-            }
-            textPosition = [cp[0] + n[0] * distance$$1, cp[1] + n[1] * distance$$1];
-            textAlign = 'center';
-            textVerticalAlign = 'bottom';
+        var textOrigin;
+
+        var distance$$1 = label.__labelDistance;
+        var distanceX = distance$$1[0] * invScale;
+        var distanceY = distance$$1[1] * invScale;
+        var halfPercent = percent / 2;
+        var tangent = line.tangentAt(halfPercent);
+        var n = [tangent[1], -tangent[0]];
+        var cp = line.pointAt(halfPercent);
+        if (n[1] > 0) {
+            n[0] = -n[0];
+            n[1] = -n[1];
+        }
+        var dir = tangent[0] < 0 ? -1 : 1;
+
+        if (label.__position !== 'start' && label.__position !== 'end') {
             var rotation = -Math.atan2(tangent[1], tangent[0]);
             if (toPos[0] < fromPos[0]) {
                 rotation = Math.PI + rotation;
             }
             label.attr('rotation', rotation);
         }
-        // Start
-        else {
-            textPosition = [-d[0] * distance$$1 + fromPos[0], -d[1] * distance$$1 + fromPos[1]];
-            textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center');
-            textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle');
+
+        var dy;
+        switch (label.__position) {
+            case 'insideStartTop':
+            case 'insideMiddleTop':
+            case 'insideEndTop':
+            case 'middle':
+                dy = -distanceY;
+                textVerticalAlign = 'bottom';
+                break;
+
+            case 'insideStartBottom':
+            case 'insideMiddleBottom':
+            case 'insideEndBottom':
+                dy = distanceY;
+                textVerticalAlign = 'top';
+                break;
+
+            default:
+                dy = 0;
+                textVerticalAlign = 'middle';
+        }
+
+        switch (label.__position) {
+            case 'end':
+                textPosition = [d[0] * distanceX + toPos[0], d[1] * distanceY + toPos[1]];
+                textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center');
+                textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle');
+                break;
+
+            case 'start':
+                textPosition = [-d[0] * distanceX + fromPos[0], -d[1] * distanceY + fromPos[1]];
+                textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center');
+                textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle');
+                break;
+
+            case 'insideStartTop':
+            case 'insideStart':
+            case 'insideStartBottom':
+                textPosition = [distanceX * dir + fromPos[0], fromPos[1] + dy];
+                textAlign = tangent[0] < 0 ? 'right' : 'left';
+                textOrigin = [-distanceX * dir, -dy];
+                break;
+
+            case 'insideMiddleTop':
+            case 'insideMiddle':
+            case 'insideMiddleBottom':
+            case 'middle':
+                textPosition = [cp[0], cp[1] + dy];
+                textAlign = 'center';
+                textOrigin = [0, -dy];
+                break;
+
+            case 'insideEndTop':
+            case 'insideEnd':
+            case 'insideEndBottom':
+                textPosition = [-distanceX * dir + toPos[0], toPos[1] + dy];
+                textAlign = tangent[0] >= 0 ? 'right' : 'left';
+                textOrigin = [distanceX * dir, -dy];
+                break;
         }
+
         label.attr({
             style: {
                 // Use the user specified text align and baseline first
@@ -52660,7 +53037,8 @@ function updateSymbolAndLabelBeforeLineUpdate() {
                 textAlign: label.__textAlign || textAlign
             },
             position: textPosition,
-            scale: [invScale, invScale]
+            scale: [invScale, invScale],
+            origin: textOrigin
         });
     }
 }
@@ -52836,6 +53214,12 @@ lineProto._updateCommonStl = function (lineData, idx, seriesScope) {
         label.__verticalAlign = labelStyle.textVerticalAlign;
         // 'start', 'middle', 'end'
         label.__position = labelModel.get('position') || 'middle';
+
+        var distance$$1 = labelModel.get('distance');
+        if (!isArray(distance$$1)) {
+            distance$$1 = [distance$$1, distance$$1];
+        }
+        label.__labelDistance = distance$$1;
     }
 
     if (emphasisText != null) {
diff --git a/en/dist/echarts-en.common.min.js b/en/dist/echarts-en.common.min.js
index 4d2d1fb..012873f 100644
--- a/en/dist/echarts-en.common.min.js
+++ b/en/dist/echarts-en.common.min.js
@@ -19,4 +19,4 @@
 */
 
 
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,i=function(){return e++},v="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasS [...]
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,i=function(){return e++},v="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasS [...]
diff --git a/en/dist/echarts-en.js b/en/dist/echarts-en.js
index 0db470c..34f3d5b 100644
--- a/en/dist/echarts-en.js
+++ b/en/dist/echarts-en.js
@@ -1285,7 +1285,11 @@ Draggable.prototype = {
 
     _dragStart: function (e) {
         var draggingTarget = e.target;
-        if (draggingTarget && draggingTarget.draggable) {
+        // Find if there is draggable in the ancestor
+        while (draggingTarget && !draggingTarget.draggable) {
+            draggingTarget = draggingTarget.parent;
+        }
+        if (draggingTarget) {
             this._draggingTarget = draggingTarget;
             draggingTarget.dragging = true;
             this._x = e.offsetX;
@@ -1714,6 +1718,8 @@ function buildTransformer(src, dest) {
     var detCache = {};
     var det = determinant(mA, 8, 0, 0, 0, detCache);
     if (det === 0) {
+        // can not make transformer when and only when
+        // any three of the markers are collinear.
         return;
     }
 
@@ -1736,6 +1742,153 @@ function buildTransformer(src, dest) {
     };
 }
 
+var EVENT_SAVED_PROP = '___zrEVENTSAVED';
+var _calcOut$1 = [];
+
+/**
+ * Transform "local coord" from `elFrom` to `elTarget`.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support when CSS transform is used.
+ *
+ * Having the `out` (that is, `[outX, outY]`), we can create an DOM element
+ * and set the CSS style as "left: outX; top: outY;" and append it to `elTarge`
+ * to locate the element.
+ *
+ * For example, this code below positions a child of `document.body` on the event
+ * point, no matter whether `body` has `margin`/`paddin`/`transfrom`/... :
+ * ```js
+ * transformLocalCoord(out, container, document.body, event.offsetX, event.offsetY);
+ * if (!eqNaN(out[0])) {
+ *     // Then locate the tip element on the event point.
+ *     var tipEl = document.createElement('div');
+ *     tipEl.style.cssText = 'position: absolute; left:' + out[0] + ';top:' + out[1] + ';';
+ *     document.body.appendChild(tipEl);
+ * }
+ * ```
+ *
+ * Notice: In some env this method is not supported. If called, `out` will be `[NaN, NaN]`.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output..
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} elFrom The `[inX, inY]` is based on elFrom.
+ * @param {HTMLElement} elTarget The `out` is based on elTarget.
+ * @param {number} inX
+ * @param {number} inY
+ * @return {boolean} Whether transform successfully.
+ */
+function transformLocalCoord(out, elFrom, elTarget, inX, inY) {
+    return transformCoordWithViewport(_calcOut$1, elFrom, inX, inY, true)
+        && transformCoordWithViewport(out, elTarget, _calcOut$1[0], _calcOut$1[1]);
+}
+
+/**
+ * Transform between a "viewport coord" and a "local coord".
+ * "viewport coord": the coord based on the left-top corner of the viewport
+ *     of the browser.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support the case when CSS transform is used on el.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output. If `inverse: false`,
+ *        it represents "local coord", otherwise "vireport coord".
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} el The "local coord" is based on the `el`, see comment above.
+ * @param {number} inX If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {number} inY If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {boolean} [inverse=false]
+ *        `true`: from "viewport coord" to "local coord".
+ *        `false`: from "local coord" to "viewport coord".
+ * @return {boolean} Whether transform successfully.
+ */
+function transformCoordWithViewport(out, el, inX, inY, inverse) {
+    if (el.getBoundingClientRect && env$1.domSupported && !isCanvasEl(el)) {
+        var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
+        var markers = prepareCoordMarkers(el, saved);
+        var transformer = preparePointerTransformer(markers, saved, inverse);
+        if (transformer) {
+            transformer(out, inX, inY);
+            return true;
+        }
+    }
+    return false;
+}
+
+function prepareCoordMarkers(el, saved) {
+    var markers = saved.markers;
+    if (markers) {
+        return markers;
+    }
+
+    markers = saved.markers = [];
+    var propLR = ['left', 'right'];
+    var propTB = ['top', 'bottom'];
+
+    for (var i = 0; i < 4; i++) {
+        var marker = document.createElement('div');
+        var stl = marker.style;
+        var idxLR = i % 2;
+        var idxTB = (i >> 1) % 2;
+        stl.cssText = [
+            'position: absolute',
+            'visibility: hidden',
+            'padding: 0',
+            'margin: 0',
+            'border-width: 0',
+            'user-select: none',
+            'width:0',
+            'height:0',
+            // 'width: 5px',
+            // 'height: 5px',
+            propLR[idxLR] + ':0',
+            propTB[idxTB] + ':0',
+            propLR[1 - idxLR] + ':auto',
+            propTB[1 - idxTB] + ':auto',
+            ''
+        ].join('!important;');
+        el.appendChild(marker);
+        markers.push(marker);
+    }
+
+    return markers;
+}
+
+function preparePointerTransformer(markers, saved, inverse) {
+    var transformerName = inverse ? 'invTrans' : 'trans';
+    var transformer = saved[transformerName];
+    var oldSrcCoords = saved.srcCoords;
+    var oldCoordTheSame = true;
+    var srcCoords = [];
+    var destCoords = [];
+
+    for (var i = 0; i < 4; i++) {
+        var rect = markers[i].getBoundingClientRect();
+        var ii = 2 * i;
+        var x = rect.left;
+        var y = rect.top;
+        srcCoords.push(x, y);
+        oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
+        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
+    }
+    // Cache to avoid time consuming of `buildTransformer`.
+    return (oldCoordTheSame && transformer)
+        ? transformer
+        : (
+            saved.srcCoords = srcCoords,
+            saved[transformerName] = inverse
+                ? buildTransformer(destCoords, srcCoords)
+                : buildTransformer(srcCoords, destCoords)
+        );
+}
+
+function isCanvasEl(el) {
+    return el.nodeName.toUpperCase() === 'CANVAS';
+}
+
 /**
  * Utilities for mouse or touch events.
  */
@@ -1743,7 +1896,6 @@ function buildTransformer(src, dest) {
 var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener;
 
 var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
-var EVENT_SAVED_PROP = '___zrEVENTSAVED';
 var _calcOut = [];
 
 /**
@@ -1808,11 +1960,11 @@ function clientToLocal(el, e, out, calculate) {
 
 function calculateZrXY(el, e, out) {
     // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect.
-    if (el.getBoundingClientRect && env$1.domSupported) {
+    if (env$1.domSupported && el.getBoundingClientRect) {
         var ex = e.clientX;
         var ey = e.clientY;
 
-        if (el.nodeName.toUpperCase() === 'CANVAS') {
+        if (isCanvasEl(el)) {
             // Original approach, which do not support CSS transform.
             // marker can not be locationed in a canvas container
             // (getBoundingClientRect is always 0). We do not support
@@ -1824,10 +1976,7 @@ function calculateZrXY(el, e, out) {
             return;
         }
         else {
-            var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
-            var transformer = preparePointerTransformer(prepareCoordMarkers(el, saved), saved);
-            if (transformer) {
-                transformer(_calcOut, ex, ey);
+            if (transformCoordWithViewport(_calcOut, el, ex, ey)) {
                 out.zrX = _calcOut[0];
                 out.zrY = _calcOut[1];
                 return;
@@ -1837,70 +1986,6 @@ function calculateZrXY(el, e, out) {
     out.zrX = out.zrY = 0;
 }
 
-function prepareCoordMarkers(el, saved) {
-    var markers = saved.markers;
-    if (markers) {
-        return markers;
-    }
-
-    markers = saved.markers = [];
-    var propLR = ['left', 'right'];
-    var propTB = ['top', 'bottom'];
-
-    for (var i = 0; i < 4; i++) {
-        var marker = document.createElement('div');
-        var stl = marker.style;
-        var idxLR = i % 2;
-        var idxTB = (i >> 1) % 2;
-        stl.cssText = [
-            'position:absolute',
-            'visibility: hidden',
-            'padding: 0',
-            'margin: 0',
-            'border-width: 0',
-            'width:0',
-            'height:0',
-            // 'width: 5px',
-            // 'height: 5px',
-            propLR[idxLR] + ':0',
-            propTB[idxTB] + ':0',
-            propLR[1 - idxLR] + ':auto',
-            propTB[1 - idxTB] + ':auto',
-            ''
-        ].join('!important;');
-        el.appendChild(marker);
-        markers.push(marker);
-    }
-
-    return markers;
-}
-
-function preparePointerTransformer(markers, saved) {
-    var transformer = saved.transformer;
-    var oldSrcCoords = saved.srcCoords;
-    var useOld = true;
-    var srcCoords = [];
-    var destCoords = [];
-
-    for (var i = 0; i < 4; i++) {
-        var rect = markers[i].getBoundingClientRect();
-        var ii = 2 * i;
-        var x = rect.left;
-        var y = rect.top;
-        srcCoords.push(x, y);
-        useOld &= oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
-        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
-    }
-
-    // Cache to avoid time consuming of `buildTransformer`.
-    return useOld
-        ? transformer
-        : (
-            saved.srcCoords = srcCoords,
-            saved.transformer = buildTransformer(srcCoords, destCoords)
-        );
-}
-
 /**
  * Find native event compat for legency IE.
  * Should be called at the begining of a native event listener.
@@ -4770,7 +4855,7 @@ var Animator = function (target, loop, getter, setter) {
 
 Animator.prototype = {
     /**
-     * 设置动画关键帧
+     * Set Animation keyframe
      * @param  {number} time 关键帧时间,单位是ms
      * @param  {Object} props 关键帧的属性值,key-value表示
      * @return {module:zrender/animation/Animator}
@@ -4849,7 +4934,7 @@ Animator.prototype = {
         }
     },
     /**
-     * 开始执行动画
+     * Start the animation
      * @param  {string|Function} [easing]
      *         动画缓动函数,详见{@link module:zrender/animation/easing}
      * @param  {boolean} forceAnimate
@@ -4910,7 +4995,7 @@ Animator.prototype = {
         return this;
     },
     /**
-     * 停止动画
+     * Stop animation
      * @param {boolean} forwardToLast If move to last frame before stop
      */
     stop: function (forwardToLast) {
@@ -4927,7 +5012,7 @@ Animator.prototype = {
         clipList.length = 0;
     },
     /**
-     * 设置动画延迟开始的时间
+     * Set when animation delay starts
      * @param  {number} time 单位ms
      * @return {module:zrender/animation/Animator}
      */
@@ -4936,7 +5021,7 @@ Animator.prototype = {
         return this;
     },
     /**
-     * 添加动画结束的回调
+     * Add callback for animation end
      * @param  {Function} cb
      * @return {module:zrender/animation/Animator}
      */
@@ -4988,7 +5073,7 @@ if (debugMode === 1) {
 var logError$1 = logError;
 
 /**
- * @alias modue:zrender/mixin/Animatable
+ * @alias module:zrender/mixin/Animatable
  * @constructor
  */
 var Animatable = function () {
@@ -10666,7 +10751,7 @@ Painter.prototype = {
 };
 
 /**
- * 动画主类, 调度和管理所有动画控制器
+ * Animation main class, dispatch and manage all animation controllers
  *
  * @module zrender/animation/Animation
  * @author pissang(https://github.com/pissang)
@@ -10731,14 +10816,14 @@ Animation.prototype = {
 
     constructor: Animation,
     /**
-     * 添加 clip
+     * Add clip
      * @param {module:zrender/animation/Clip} clip
      */
     addClip: function (clip) {
         this._clips.push(clip);
     },
     /**
-     * 添加 animator
+     * Add animator
      * @param {module:zrender/animation/Animator} animator
      */
     addAnimator: function (animator) {
@@ -10749,7 +10834,7 @@ Animation.prototype = {
         }
     },
     /**
-     * 删除动画片段
+     * Delete animation clip
      * @param {module:zrender/animation/Clip} clip
      */
     removeClip: function (clip) {
@@ -10760,7 +10845,7 @@ Animation.prototype = {
     },
 
     /**
-     * 删除动画片段
+     * Delete animation clip
      * @param {module:zrender/animation/Animator} animator
      */
     removeAnimator: function (animator) {
@@ -11027,13 +11112,16 @@ function normalizeGlobalEvent(instance, event) {
  * Detect whether the given el is in `painterRoot`.
  */
 function isLocalEl(instance, el) {
+    var elTmp = el;
     var isLocal = false;
-    do {
-        el = el && el.parentNode;
+    while (elTmp && elTmp.nodeType !== 9
+        && !(
+            isLocal = elTmp.domBelongToZr
+                || (elTmp !== el && elTmp === instance.painterRoot)
+        )
+    ) {
+        elTmp = elTmp.parentNode;
     }
-    while (el && el.nodeType !== 9 && !(
-        isLocal = el === instance.painterRoot
-    ));
     return isLocal;
 }
 
@@ -11488,7 +11576,7 @@ var instances$1 = {};    // ZRender实例map索引
 /**
  * @type {string}
  */
-var version$1 = '4.2.0';
+var version$1 = '4.3.0';
 
 /**
  * Initializing a zrender instance
@@ -16433,12 +16521,10 @@ var round = Math.round;
  * @param {number} [inputShape.x2]
  * @param {number} [inputShape.y2]
  * @param {Object} [style]
- * @param {number} [style.lineWidth]
+ * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
  */
 function subPixelOptimizeLine$1(outputShape, inputShape, style) {
-    var lineWidth = style && style.lineWidth;
-
-    if (!inputShape || !lineWidth) {
+    if (!inputShape) {
         return;
     }
 
@@ -16447,20 +16533,22 @@ function subPixelOptimizeLine$1(outputShape, inputShape, style) {
     var y1 = inputShape.y1;
     var y2 = inputShape.y2;
 
+    outputShape.x1 = x1;
+    outputShape.x2 = x2;
+    outputShape.y1 = y1;
+    outputShape.y2 = y2;
+
+    var lineWidth = style && style.lineWidth;
+    if (!lineWidth) {
+        return;
+    }
+
     if (round(x1 * 2) === round(x2 * 2)) {
         outputShape.x1 = outputShape.x2 = subPixelOptimize$1(x1, lineWidth, true);
     }
-    else {
-        outputShape.x1 = x1;
-        outputShape.x2 = x2;
-    }
     if (round(y1 * 2) === round(y2 * 2)) {
         outputShape.y1 = outputShape.y2 = subPixelOptimize$1(y1, lineWidth, true);
     }
-    else {
-        outputShape.y1 = y1;
-        outputShape.y2 = y2;
-    }
 }
 
 /**
@@ -16476,12 +16564,10 @@ function subPixelOptimizeLine$1(outputShape, inputShape, style) {
  * @param {number} [inputShape.width]
  * @param {number} [inputShape.height]
  * @param {Object} [style]
- * @param {number} [style.lineWidth]
+ * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
  */
 function subPixelOptimizeRect$1(outputShape, inputShape, style) {
-    var lineWidth = style && style.lineWidth;
-
-    if (!inputShape || !lineWidth) {
+    if (!inputShape) {
         return;
     }
 
@@ -16490,6 +16576,16 @@ function subPixelOptimizeRect$1(outputShape, inputShape, style) {
     var originWidth = inputShape.width;
     var originHeight = inputShape.height;
 
+    outputShape.x = originX;
+    outputShape.y = originY;
+    outputShape.width = originWidth;
+    outputShape.height = originHeight;
+
+    var lineWidth = style && style.lineWidth;
+    if (!lineWidth) {
+        return;
+    }
+
     outputShape.x = subPixelOptimize$1(originX, lineWidth, true);
     outputShape.y = subPixelOptimize$1(originY, lineWidth, true);
     outputShape.width = Math.max(
@@ -16506,11 +16602,14 @@ function subPixelOptimizeRect$1(outputShape, inputShape, style) {
  * Sub pixel optimize for canvas
  *
  * @param {number} position Coordinate, such as x, y
- * @param {number} lineWidth Should be nonnegative integer.
+ * @param {number} lineWidth If `null`/`undefined`/`0`, do not optimize.
  * @param {boolean=} positiveOrNegative Default false (negative).
  * @return {number} Optimized position.
  */
 function subPixelOptimize$1(position, lineWidth, positiveOrNegative) {
+    if (!lineWidth) {
+        return position;
+    }
     // Assure that (position + lineWidth / 2) is near integer edge,
     // otherwise line will be fuzzy in canvas.
     var doubledPosition = round(position * 2);
@@ -18211,7 +18310,7 @@ function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb)
  * configuration in series.
  *
  * Caution: this method will stop previous animation.
- * So if do not use this method to one element twice before
+ * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  *
  * @param {module:zrender/Element} el
@@ -18237,7 +18336,7 @@ function updateProps(el, props, animatableModel, dataIndex, cb) {
  * configuration in series.
  *
  * Caution: this method will stop previous animation.
- * So if do not use this method to one element twice before
+ * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  *
  * @param {module:zrender/Element} el
@@ -25098,8 +25197,11 @@ var createRenderPlanner = function () {
         var originalLarge = fields.large;
         var originalProgressive = fields.progressiveRender;
 
-        var large = fields.large = pipelineContext.large;
-        var progressive = fields.progressiveRender = pipelineContext.progressiveRender;
+        // FIXME: if the planner works on a filtered series, `pipelineContext` does not
+        // exists. See #11611 . Probably we need to modify this structure, see the comment
+        // on `performRawSeries` in `Schedular.js`.
+        var large = fields.large = pipelineContext && pipelineContext.large;
+        var progressive = fields.progressiveRender = pipelineContext && pipelineContext.progressiveRender;
 
         return !!((originalLarge ^ large) || (originalProgressive ^ progressive)) && 'reset';
     };
@@ -26248,6 +26350,14 @@ function performStageTasks(scheduler, stageHandlers, ecModel, payload, opt) {
                     task.dirty();
                 }
                 var performArgs = scheduler.getPerformArgs(task, opt.block);
+                // FIXME
+                // if intending to decalare `performRawSeries` in handlers, only
+                // stream-independent (specifically, data item independent) operations can be
+                // performed. Because is a series is filtered, most of the tasks will not
+                // be performed. A stream-dependent operation probably cause wrong biz logic.
+                // Perhaps we should not provide a separate callback for this case instead
+                // of providing the config `performRawSeries`. The stream-dependent operaions
+                // and stream-independent operations should better not be mixed.
                 performArgs.skip = !stageHandler.performRawSeries
                     && ecModel.isSeriesFiltered(task.context.model);
                 updatePayload(task, payload);
@@ -27626,10 +27736,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.6.0';
+var version = '4.7.0';
 
 var dependencies = {
-    zrender: '4.2.0'
+    zrender: '4.3.0'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -33914,7 +34024,7 @@ var IntervalScale = Scale.extend({
 
         if (extent[0] < niceTickExtent[0]) {
             if (expandToNicedExtent) {
-                ticks.push(roundNumber(niceTickExtent[0] - interval));
+                ticks.push(roundNumber(niceTickExtent[0] - interval, intervalPrecision));
             }
             else {
                 ticks.push(extent[0]);
@@ -33940,7 +34050,7 @@ var IntervalScale = Scale.extend({
         var lastNiceTick = ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1];
         if (extent[1] > lastNiceTick) {
             if (expandToNicedExtent) {
-                ticks.push(lastNiceTick + interval);
+                ticks.push(roundNumber(lastNiceTick + interval, intervalPrecision));
             }
             else {
                 ticks.push(extent[1]);
@@ -34515,11 +34625,6 @@ function layout(seriesType, ecModel) {
             var value = data.get(valueDim, idx);
             var baseValue = data.get(baseDim, idx);
 
-            // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
-            if (isNaN(value) || isNaN(baseValue)) {
-                continue;
-            }
-
             var sign = value >= 0 ? 'p' : 'n';
             var baseCoord = valueAxisStart;
 
@@ -34552,7 +34657,10 @@ function layout(seriesType, ecModel) {
                 if (Math.abs(width) < barMinHeight) {
                     width = (width < 0 ? -1 : 1) * barMinHeight;
                 }
-                stacked && (lastStackCoords[stackId][baseValue][sign] += width);
+                // Ignore stack from NaN value
+                if (!isNaN(width)) {
+                    stacked && (lastStackCoords[stackId][baseValue][sign] += width);
+                }
             }
             else {
                 var coord = cartesian.dataToPoint([baseValue, value]);
@@ -34565,7 +34673,10 @@ function layout(seriesType, ecModel) {
                     // Include zero to has a positive bar
                     height = (height <= 0 ? -1 : 1) * barMinHeight;
                 }
-                stacked && (lastStackCoords[stackId][baseValue][sign] += height);
+                // Ignore stack from NaN value
+                if (!isNaN(height)) {
+                    stacked && (lastStackCoords[stackId][baseValue][sign] += height);
+                }
             }
 
             data.setItemLayout(idx, {
@@ -34593,6 +34704,7 @@ var largeLayout = {
 
         var data = seriesModel.getData();
         var cartesian = seriesModel.coordinateSystem;
+        var coordLayout = cartesian.grid.getRect();
         var baseAxis = cartesian.getBaseAxis();
         var valueAxis = cartesian.getOtherAxis(baseAxis);
         var valueDim = data.mapDimension(valueAxis.dim);
@@ -34612,6 +34724,7 @@ var largeLayout = {
         function progress(params, data) {
             var count = params.count;
             var largePoints = new LargeArr(count * 2);
+            var largeBackgroundPoints = new LargeArr(count * 2);
             var largeDataIndices = new LargeArr(count);
             var dataIndex;
             var coord = [];
@@ -34625,7 +34738,9 @@ var largeLayout = {
 
                 coord = cartesian.dataToPoint(valuePair, null, coord);
                 // Data index might not be in order, depends on `progressiveChunkMode`.
+                largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coordLayout.x + coordLayout.width : coord[0];
                 largePoints[pointsOffset++] = coord[0];
+                largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coord[1] : coordLayout.y + coordLayout.height;
                 largePoints[pointsOffset++] = coord[1];
                 largeDataIndices[idxOffset++] = dataIndex;
             }
@@ -34633,8 +34748,10 @@ var largeLayout = {
             data.setLayout({
                 largePoints: largePoints,
                 largeDataIndices: largeDataIndices,
+                largeBackgroundPoints: largeBackgroundPoints,
                 barWidth: barWidth,
                 valueAxisStart: getValueAxisStart(baseAxis, valueAxis, false),
+                backgroundStart: valueAxisHorizontal ? coordLayout.x : coordLayout.y,
                 valueAxisHorizontal: valueAxisHorizontal
             });
         }
@@ -42521,6 +42638,117 @@ function layout$1(gridModel, axisModel, opt) {
 * under the License.
 */
 
+function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) {
+    var axis = axisModel.axis;
+
+    if (axis.scale.isBlank()) {
+        return;
+    }
+
+    var splitAreaModel = axisModel.getModel('splitArea');
+    var areaStyleModel = splitAreaModel.getModel('areaStyle');
+    var areaColors = areaStyleModel.get('color');
+
+    var gridRect = gridModel.coordinateSystem.getRect();
+
+    var ticksCoords = axis.getTicksCoords({
+        tickModel: splitAreaModel,
+        clamp: true
+    });
+
+    if (!ticksCoords.length) {
+        return;
+    }
+
+    // For Making appropriate splitArea animation, the color and anid
+    // should be corresponding to previous one if possible.
+    var areaColorsLen = areaColors.length;
+    var lastSplitAreaColors = axisView.__splitAreaColors;
+    var newSplitAreaColors = createHashMap();
+    var colorIndex = 0;
+    if (lastSplitAreaColors) {
+        for (var i = 0; i < ticksCoords.length; i++) {
+            var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
+            if (cIndex != null) {
+                colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
+                break;
+            }
+        }
+    }
+
+    var prev = axis.toGlobalCoord(ticksCoords[0].coord);
+
+    var areaStyle = areaStyleModel.getAreaStyle();
+    areaColors = isArray(areaColors) ? areaColors : [areaColors];
+
+    for (var i = 1; i < ticksCoords.length; i++) {
+        var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
+
+        var x;
+        var y;
+        var width;
+        var height;
+        if (axis.isHorizontal()) {
+            x = prev;
+            y = gridRect.y;
+            width = tickCoord - x;
+            height = gridRect.height;
+            prev = x + width;
+        }
+        else {
+            x = gridRect.x;
+            y = prev;
+            width = gridRect.width;
+            height = tickCoord - y;
+            prev = y + height;
+        }
+
+        var tickValue = ticksCoords[i - 1].tickValue;
+        tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
+
+        axisGroup.add(new Rect({
+            anid: tickValue != null ? 'area_' + tickValue : null,
+            shape: {
+                x: x,
+                y: y,
+                width: width,
+                height: height
+            },
+            style: defaults({
+                fill: areaColors[colorIndex]
+            }, areaStyle),
+            silent: true
+        }));
+
+        colorIndex = (colorIndex + 1) % areaColorsLen;
+    }
+
+    axisView.__splitAreaColors = newSplitAreaColors;
+}
+
+function rectCoordAxisHandleRemove(axisView) {
+    axisView.__splitAreaColors = null;
+}
+
+/*
+* 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.
+*/
+
 var axisBuilderAttrs = [
     'axisLine', 'axisTickLabel', 'axisName'
 ];
@@ -42572,7 +42800,7 @@ var CartesianAxisView = AxisView.extend({
     },
 
     remove: function () {
-        this._splitAreaColors = null;
+        rectCoordAxisHandleRemove(this);
     },
 
     /**
@@ -42704,91 +42932,7 @@ var CartesianAxisView = AxisView.extend({
      * @private
      */
     _splitArea: function (axisModel, gridModel) {
-        var axis = axisModel.axis;
-
-        if (axis.scale.isBlank()) {
-            return;
-        }
-
-        var splitAreaModel = axisModel.getModel('splitArea');
-        var areaStyleModel = splitAreaModel.getModel('areaStyle');
-        var areaColors = areaStyleModel.get('color');
-
-        var gridRect = gridModel.coordinateSystem.getRect();
-
-        var ticksCoords = axis.getTicksCoords({
-            tickModel: splitAreaModel,
-            clamp: true
-        });
-
-        if (!ticksCoords.length) {
-            return;
-        }
-
-        // For Making appropriate splitArea animation, the color and anid
-        // should be corresponding to previous one if possible.
-        var areaColorsLen = areaColors.length;
-        var lastSplitAreaColors = this._splitAreaColors;
-        var newSplitAreaColors = createHashMap();
-        var colorIndex = 0;
-        if (lastSplitAreaColors) {
-            for (var i = 0; i < ticksCoords.length; i++) {
-                var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
-                if (cIndex != null) {
-                    colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
-                    break;
-                }
-            }
-        }
-
-        var prev = axis.toGlobalCoord(ticksCoords[0].coord);
-
-        var areaStyle = areaStyleModel.getAreaStyle();
-        areaColors = isArray(areaColors) ? areaColors : [areaColors];
-
-        for (var i = 1; i < ticksCoords.length; i++) {
-            var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
-
-            var x;
-            var y;
-            var width;
-            var height;
-            if (axis.isHorizontal()) {
-                x = prev;
-                y = gridRect.y;
-                width = tickCoord - x;
-                height = gridRect.height;
-                prev = x + width;
-            }
-            else {
-                x = gridRect.x;
-                y = prev;
-                width = gridRect.width;
-                height = tickCoord - y;
-                prev = y + height;
-            }
-
-            var tickValue = ticksCoords[i - 1].tickValue;
-            tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
-
-            this._axisGroup.add(new Rect({
-                anid: tickValue != null ? 'area_' + tickValue : null,
-                shape: {
-                    x: x,
-                    y: y,
-                    width: width,
-                    height: height
-                },
-                style: defaults({
-                    fill: areaColors[colorIndex]
-                }, areaStyle),
-                silent: true
-            }));
-
-            colorIndex = (colorIndex + 1) % areaColorsLen;
-        }
-
-        this._splitAreaColors = newSplitAreaColors;
+        rectCoordAxisBuildSplitArea(this, this._axisGroup, axisModel, gridModel);
     }
 });
 
@@ -43034,7 +43178,21 @@ BaseBarSeries.extend({
 
         // If use caps on two sides of bars
         // Only available on tangential polar bar
-        roundCap: false
+        roundCap: false,
+
+        showBackground: false,
+        backgroundStyle: {
+            color: 'rgba(180, 180, 180, 0.2)',
+            borderColor: null,
+            borderWidth: 0,
+            borderType: 'solid',
+            borderRadius: 0,
+            shadowBlur: 0,
+            shadowColor: null,
+            shadowOffsetX: 0,
+            shadowOffsetY: 0,
+            opacity: 1
+        }
     }
 });
 
@@ -43339,15 +43497,28 @@ extendChartView({
 
         var roundCap = seriesModel.get('roundCap', true);
 
+        var drawBackground = seriesModel.get('showBackground', true);
+        var backgroundModel = seriesModel.getModel('backgroundStyle');
+
+        var bgEls = [];
+        var oldBgEls = this._backgroundEls || [];
+
         data.diff(oldData)
             .add(function (dataIndex) {
+                var itemModel = data.getItemModel(dataIndex);
+                var layout = getLayout[coord.type](data, dataIndex, itemModel);
+
+                if (drawBackground) {
+                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, layout);
+                    bgEl.useStyle(backgroundModel.getBarItemStyle());
+                    bgEls[dataIndex] = bgEl;
+                }
+
+                // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
                 if (!data.hasValue(dataIndex)) {
                     return;
                 }
 
-                var itemModel = data.getItemModel(dataIndex);
-                var layout = getLayout[coord.type](data, dataIndex, itemModel);
-
                 if (needsClip) {
                     // Clip will modify the layout params.
                     // And return a boolean to determine if the shape are fully clipped.
@@ -43370,16 +43541,24 @@ extendChartView({
                 );
             })
             .update(function (newIndex, oldIndex) {
-                var el = oldData.getItemGraphicEl(oldIndex);
+                var itemModel = data.getItemModel(newIndex);
+                var layout = getLayout[coord.type](data, newIndex, itemModel);
+
+                if (drawBackground) {
+                    var bgEl = oldBgEls[oldIndex];
+                    bgEl.useStyle(backgroundModel.getBarItemStyle());
+                    bgEls[newIndex] = bgEl;
 
+                    var shape = createBackgroundShape(isHorizontalOrRadial, layout, coord);
+                    updateProps(bgEl, { shape: shape }, animationModel, newIndex);
+                }
+
+                var el = oldData.getItemGraphicEl(oldIndex);
                 if (!data.hasValue(newIndex)) {
                     group.remove(el);
                     return;
                 }
 
-                var itemModel = data.getItemModel(newIndex);
-                var layout = getLayout[coord.type](data, newIndex, itemModel);
-
                 if (needsClip) {
                     var isClipped = clip[coord.type](coordSysClipArea, layout);
                     if (isClipped) {
@@ -43417,6 +43596,15 @@ extendChartView({
             })
             .execute();
 
+        var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group());
+        bgGroup.removeAll();
+
+        for (var i = 0; i < bgEls.length; ++i) {
+            bgGroup.add(bgEls[i]);
+        }
+        group.add(bgGroup);
+        this._backgroundEls = bgEls;
+
         this._data = data;
     },
 
@@ -43437,6 +43625,7 @@ extendChartView({
     },
 
     _incrementalRenderLarge: function (params, seriesModel) {
+        this._removeBackground();
         createLarge(seriesModel, this.group, true);
     },
 
@@ -43450,6 +43639,9 @@ extendChartView({
         var group = this.group;
         var data = this._data;
         if (ecModel && ecModel.get('animation') && data && !this._isLargeDraw) {
+            this._removeBackground();
+            this._backgroundEls = [];
+
             data.eachItemGraphicEl(function (el) {
                 if (el.type === 'sector') {
                     removeSector(el.dataIndex, ecModel, el);
@@ -43463,6 +43655,11 @@ extendChartView({
             group.removeAll();
         }
         this._data = null;
+    },
+
+    _removeBackground: function () {
+        this.group.remove(this._backgroundGroup);
+        this._backgroundGroup = null;
     }
 
 });
@@ -43520,7 +43717,12 @@ var elementCreator = {
         dataIndex, layout, isHorizontal,
         animationModel, isUpdate
     ) {
-        var rect = new Rect({shape: extend({}, layout)});
+        var rect = new Rect({
+            shape: extend({}, layout),
+            z2: 1
+        });
+
+        rect.name = 'item';
 
         // Animation
         if (animationModel) {
@@ -43550,9 +43752,12 @@ var elementCreator = {
         var ShapeClass = (!isRadial && roundCap) ? Sausage : Sector;
 
         var sector = new ShapeClass({
-            shape: defaults({clockwise: clockwise}, layout)
+            shape: defaults({clockwise: clockwise}, layout),
+            z2: 1
         });
 
+        sector.name = 'item';
+
         // Animation
         if (animationModel) {
             var sectorShape = sector.shape;
@@ -43672,7 +43877,10 @@ function updateStyle(
 // In case width or height are too small.
 function getLineWidth(itemModel, rawLayout) {
     var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
-    return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height));
+    // width or height may be NaN for empty data
+    var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width);
+    var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height);
+    return Math.min(lineWidth, width, height);
 }
 
 
@@ -43704,13 +43912,38 @@ function createLarge(seriesModel, group, incremental) {
     var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
     startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart');
 
+    var largeDataIndices = data.getLayout('largeDataIndices');
+    var barWidth = data.getLayout('barWidth');
+
+    var backgroundModel = seriesModel.getModel('backgroundStyle');
+    var drawBackground = seriesModel.get('showBackground', true);
+
+    if (drawBackground) {
+        var points = data.getLayout('largeBackgroundPoints');
+        var backgroundStartPoint = [];
+        backgroundStartPoint[1 - baseDimIdx] = data.getLayout('backgroundStart');
+
+        var bgEl = new LargePath({
+            shape: {points: points},
+            incremental: !!incremental,
+            __startPoint: backgroundStartPoint,
+            __baseDimIdx: baseDimIdx,
+            __largeDataIndices: largeDataIndices,
+            __barWidth: barWidth,
+            silent: true,
+            z2: 0
+        });
+        setLargeBackgroundStyle(bgEl, backgroundModel, data);
+        group.add(bgEl);
+    }
+
     var el = new LargePath({
         shape: {points: data.getLayout('largePoints')},
         incremental: !!incremental,
         __startPoint: startPoint,
         __baseDimIdx: baseDimIdx,
-        __largeDataIndices: data.getLayout('largeDataIndices'),
-        __barWidth: data.getLayout('barWidth')
+        __largeDataIndices: largeDataIndices,
+        __barWidth: barWidth
     });
     group.add(el);
     setLargeStyle(el, seriesModel, data);
@@ -43775,6 +44008,55 @@ function setLargeStyle(el, seriesModel, data) {
     el.style.lineWidth = data.getLayout('barWidth');
 }
 
+function setLargeBackgroundStyle(el, backgroundModel, data) {
+    var borderColor = backgroundModel.get('borderColor') || backgroundModel.get('color');
+    var itemStyle = backgroundModel.getItemStyle(['color', 'borderColor']);
+
+    el.useStyle(itemStyle);
+    el.style.fill = null;
+    el.style.stroke = borderColor;
+    el.style.lineWidth = data.getLayout('barWidth');
+}
+
+function createBackgroundShape(isHorizontalOrRadial, layout, coord) {
+    var coordLayout;
+    var isPolar = coord.type === 'polar';
+    if (isPolar) {
+        coordLayout = coord.getArea();
+    }
+    else {
+        coordLayout = coord.grid.getRect();
+    }
+
+    if (isPolar) {
+        return {
+            cx: coordLayout.cx,
+            cy: coordLayout.cy,
+            r0: isHorizontalOrRadial ? coordLayout.r0 : layout.r0,
+            r: isHorizontalOrRadial ? coordLayout.r : layout.r,
+            startAngle: isHorizontalOrRadial ? layout.startAngle : 0,
+            endAngle: isHorizontalOrRadial ? layout.endAngle : Math.PI * 2
+        };
+    }
+    else {
+        return {
+            x: isHorizontalOrRadial ? layout.x : coordLayout.x,
+            y: isHorizontalOrRadial ? coordLayout.y : layout.y,
+            width: isHorizontalOrRadial ? layout.width : coordLayout.width,
+            height: isHorizontalOrRadial ? coordLayout.height : layout.height
+        };
+    }
+}
+
+function createBackgroundEl(coord, isHorizontalOrRadial, layout) {
+    var ElementClz = coord.type === 'polar' ? Sector : Rect;
+    return new ElementClz({
+        shape: createBackgroundShape(isHorizontalOrRadial, layout, coord),
+        silent: true,
+        z2: 0
+    });
+}
+
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -44384,7 +44666,7 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
     toggleItemSelected(
         this,
         data.getItemLayout(idx),
-        seriesModel.isSelected(null, idx),
+        seriesModel.isSelected(data.getName(idx)),
         seriesModel.get('selectedOffset'),
         seriesModel.get('animation')
     );
@@ -45136,7 +45418,7 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, viewLeft, vie
             inside: isLabelInside,
             labelDistance: labelDistance,
             labelAlignTo: labelAlignTo,
-            labelMargin:labelMargin,
+            labelMargin: labelMargin,
             bleedMargin: bleedMargin,
             textRect: textRect,
             text: text,
@@ -46179,6 +46461,7 @@ Radar.prototype.update = function (ecModel, api) {
         var fixedMax = axisModel.getMax();
         var interval = scale.getInterval();
 
+
         if (fixedMin != null && fixedMax != null) {
             // User set min, max, divide to get new interval
             scale.setExtent(+fixedMin, +fixedMax);
@@ -46214,13 +46497,10 @@ Radar.prototype.update = function (ecModel, api) {
             if (nicedSplitNumber > splitNumber) {
                 interval = increaseInterval(interval);
             }
-            // PENDING
-            var center = Math.round((rawExtent[0] + rawExtent[1]) / 2 / interval) * interval;
-            var halfSplitNumber = Math.round(splitNumber / 2);
-            scale.setExtent(
-                round$1(center - halfSplitNumber * interval),
-                round$1(center + (splitNumber - halfSplitNumber) * interval)
-            );
+            // TODO
+            var max = Math.ceil(rawExtent[1] / interval) * interval;
+            var min = round$1(max - interval * splitNumber);
+            scale.setExtent(min, max);
             scale.setInterval(interval);
         }
     });
@@ -46668,6 +46948,28 @@ var RadarSeries = SeriesModel.extend({
             }).join('<br />');
     },
 
+    /**
+     * @implement
+     */
+    getTooltipPosition: function (dataIndex) {
+        if (dataIndex != null) {
+            var data = this.getData();
+            var coordSys = this.coordinateSystem;
+            var values = data.getValues(
+                map(coordSys.dimensions, function (dim) {
+                    return data.mapDimension(dim);
+                }), dataIndex, true
+            );
+
+            for (var i = 0, len = values.length; i < len; i++) {
+                if (!isNaN(values[i])) {
+                    var indicatorAxes = coordSys.getIndicatorAxes();
+                    return coordSys.coordToPoint(indicatorAxes[i].dataToCoord(values[i]), i);
+                }
+            }
+        }
+    },
+
     defaultOption: {
         zlevel: 0,
         z: 2,
@@ -48442,13 +48744,13 @@ MapDraw.prototype = {
         var regionsGroup = this._regionsGroup;
         var group = this.group;
 
-        if (geo._roamTransformable.transform) {
-            group.transform = geo._roamTransformable.transform.slice();
-            group.decomposeTransform();
-        }
+        var transformInfo = geo.getTransformInfo();
+        group.transform = transformInfo.roamTransform;
+        group.decomposeTransform();
+        group.dirty();
 
-        var scale = geo._rawTransformable.scale;
-        var position = geo._rawTransformable.position;
+        var scale = transformInfo.rawScale;
+        var position = transformInfo.rawPosition;
 
         regionsGroup.removeAll();
 
@@ -49254,7 +49556,6 @@ View.prototype = {
     /**
      * Remove roam
      */
-
     _updateCenterAndZoom: function () {
         // Must update after view transform updated
         var rawTransformMatrix = this._rawTransformable.getLocalTransform();
@@ -49298,6 +49599,16 @@ View.prototype = {
         this.decomposeTransform();
     },
 
+    getTransformInfo: function () {
+        var roamTransform = this._roamTransformable.transform;
+        var rawTransformable = this._rawTransformable;
+        return {
+            roamTransform: roamTransform ? slice(roamTransform) : create$1(),
+            rawScale: slice(rawTransformable.scale),
+            rawPosition: slice(rawTransformable.position)
+        };
+    },
+
     /**
      * @return {module:zrender/core/BoundingRect}
      */
@@ -50914,6 +51225,11 @@ SeriesModel.extend({
         // the layout of the tree, two value can be selected, 'orthogonal' or 'radial'
         layout: 'orthogonal',
 
+        // value can be 'polyline'
+        edgeShape: 'curve',
+
+        edgeForkPosition: '50%',
+
         // true | false | 'move' | 'scale', see module:component/helper/RoamController.
         roam: false,
 
@@ -51318,6 +51634,58 @@ function defaultSeparation(node1, node2) {
 * under the License.
 */
 
+var TreeShape = extendShape({
+    shape: {
+        parentPoint: [],
+        childPoints: [],
+        orient: '',
+        forkPosition: ''
+    },
+
+    style: {
+        stroke: '#000',
+        fill: null
+    },
+
+    buildPath: function (ctx, shape) {
+        var childPoints = shape.childPoints;
+        var childLen = childPoints.length;
+        var parentPoint = shape.parentPoint;
+        var firstChildPos = childPoints[0];
+        var lastChildPos = childPoints[childLen - 1];
+
+        if (childLen === 1) {
+            ctx.moveTo(parentPoint[0], parentPoint[1]);
+            ctx.lineTo(firstChildPos[0], firstChildPos[1]);
+            return;
+        }
+
+        var orient = shape.orient;
+        var forkDim = (orient === 'TB' || orient === 'BT') ? 0 : 1;
+        var otherDim = 1 - forkDim;
+        var forkPosition = parsePercent$1(shape.forkPosition, 1);
+        var tmpPoint = [];
+        tmpPoint[forkDim] = parentPoint[forkDim];
+        tmpPoint[otherDim] = parentPoint[otherDim] + (lastChildPos[otherDim] - parentPoint[otherDim]) * forkPosition;
+
+        ctx.moveTo(parentPoint[0], parentPoint[1]);
+        ctx.lineTo(tmpPoint[0], tmpPoint[1]);
+        ctx.moveTo(firstChildPos[0], firstChildPos[1]);
+        tmpPoint[forkDim] = firstChildPos[forkDim];
+        ctx.lineTo(tmpPoint[0], tmpPoint[1]);
+        tmpPoint[forkDim] = lastChildPos[forkDim];
+        ctx.lineTo(tmpPoint[0], tmpPoint[1]);
+        ctx.lineTo(lastChildPos[0], lastChildPos[1]);
+
+        for (var i = 1; i < childLen - 1; i++) {
+            var point = childPoints[i];
+            ctx.moveTo(point[0], point[1]);
+            tmpPoint[forkDim] = point[forkDim];
+            ctx.lineTo(tmpPoint[0], tmpPoint[1]);
+        }
+    }
+});
+
 extendChartView({
 
     type: 'tree',
@@ -51377,6 +51745,8 @@ extendChartView({
         var seriesScope = {
             expandAndCollapse: seriesModel.get('expandAndCollapse'),
             layout: layout,
+            edgeShape: seriesModel.get('edgeShape'),
+            edgeForkPosition: seriesModel.get('edgeForkPosition'),
             orient: seriesModel.getOrient(),
             curvature: seriesModel.get('lineStyle.curveness'),
             symbolRotate: seriesModel.get('symbolRotate'),
@@ -51678,22 +52048,72 @@ function updateNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope)
         });
     }
 
-    if (node.parentNode && node.parentNode !== virtualRoot) {
-        var edge = symbolEl.__edge;
-        if (!edge) {
-            edge = symbolEl.__edge = new BezierCurve({
-                shape: getEdgeShape(seriesScope, sourceOldLayout, sourceOldLayout),
-                style: defaults({opacity: 0, strokeNoScale: true}, seriesScope.lineStyle)
-            });
-        }
+    drawEdge(
+        seriesModel, node, virtualRoot, symbolEl, sourceOldLayout,
+        sourceLayout, targetLayout, group, seriesScope
+    );
 
-        updateProps(edge, {
-            shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
-            style: {opacity: 1}
-        }, seriesModel);
+}
+
+function drawEdge(
+    seriesModel, node, virtualRoot, symbolEl, sourceOldLayout,
+    sourceLayout, targetLayout, group, seriesScope
+) {
+
+    var edgeShape = seriesScope.edgeShape;
+    var edge = symbolEl.__edge;
+    if (edgeShape === 'curve') {
+        if (node.parentNode && node.parentNode !== virtualRoot) {
+            if (!edge) {
+                edge = symbolEl.__edge = new BezierCurve({
+                    shape: getEdgeShape(seriesScope, sourceOldLayout, sourceOldLayout),
+                    style: defaults({opacity: 0, strokeNoScale: true}, seriesScope.lineStyle)
+                });
+            }
+
+            updateProps(edge, {
+                shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
+                style: {opacity: 1}
+            }, seriesModel);
+        }
+    }
+    else if (edgeShape === 'polyline') {
+        if (seriesScope.layout === 'orthogonal') {
+            if (node !== virtualRoot && node.children && (node.children.length !== 0) && (node.isExpand === true)) {
+                var children = node.children;
+                var childPoints = [];
+                for (var i = 0; i < children.length; i++) {
+                    var childLayout = children[i].getLayout();
+                    childPoints.push([childLayout.x, childLayout.y]);
+                }
 
-        group.add(edge);
+                if (!edge) {
+                    edge = symbolEl.__edge = new TreeShape({
+                        shape: {
+                            parentPoint: [targetLayout.x, targetLayout.y],
+                            childPoints: [[targetLayout.x, targetLayout.y]],
+                            orient: seriesScope.orient,
+                            forkPosition: seriesScope.edgeForkPosition
+                        },
+                        style: defaults({opacity: 0, strokeNoScale: true}, seriesScope.lineStyle)
+                    });
+                }
+                updateProps(edge, {
+                    shape: {
+                        parentPoint: [targetLayout.x, targetLayout.y],
+                        childPoints: childPoints
+                    },
+                    style: {opacity: 1}
+                }, seriesModel);
+            }
+        }
+        else {
+            if (__DEV__) {
+                throw new Error('The polyline edgeShape can only be used in orthogonal layout');
+            }
+        }
     }
+    group.add(edge);
 }
 
 function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope) {
@@ -51703,6 +52123,7 @@ function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope)
     var seriesScope = getTreeNodeStyle(node, itemModel, seriesScope);
 
     var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
+    var edgeShape = seriesScope.edgeShape;
     var sourceLayout;
     while (sourceLayout = source.getLayout(), sourceLayout == null) {
         source = source.parentNode === virtualRoot ? source : source.parentNode || source;
@@ -51717,16 +52138,42 @@ function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope)
 
     symbolEl.fadeOut(null, {keepLabel: true});
 
-    var edge = symbolEl.__edge;
+    var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
+    var sourceEdge = sourceSymbolEl.__edge;
+
+    // 1. when expand the sub tree, delete the children node should delete the edge of
+    // the source at the same time. because the polyline edge shape is only owned by the source.
+    // 2.when the node is the only children of the source, delete the node should delete the edge of
+    // the source at the same time. the same reason as above.
+    var edge = symbolEl.__edge
+        || ((source.isExpand === false || source.children.length === 1) ? sourceEdge : undefined);
+
+    var edgeShape = seriesScope.edgeShape;
+
     if (edge) {
-        updateProps(edge, {
-            shape: getEdgeShape(seriesScope, sourceLayout, sourceLayout),
-            style: {
-                opacity: 0
-            }
-        }, seriesModel, function () {
-            group.remove(edge);
-        });
+        if (edgeShape === 'curve') {
+            updateProps(edge, {
+                shape: getEdgeShape(seriesScope, sourceLayout, sourceLayout),
+                style: {
+                    opacity: 0
+                }
+            }, seriesModel, function () {
+                group.remove(edge);
+            });
+        }
+        else if (edgeShape === 'polyline' && seriesScope.layout === 'orthogonal') {
+            updateProps(edge, {
+                shape: {
+                    parentPoint: [sourceLayout.x, sourceLayout.y],
+                    childPoints: [[sourceLayout.x, sourceLayout.y]]
+                },
+                style: {
+                    opacity: 0
+                }
+            }, seriesModel, function () {
+                group.remove(edge);
+            });
+        }
     }
 }
 
@@ -52968,6 +53415,7 @@ extendChartView({
         var thisStorage = createStorage();
         var oldStorage = this._storage;
         var willInvisibleEls = [];
+
         var doRenderNode = curry(
             renderNode, seriesModel,
             thisStorage, oldStorage, reRoot,
@@ -53466,6 +53914,11 @@ function renderNode(
     // Start of closure variables available in "Procedures in renderNode".
 
     var thisLayout = thisNode.getLayout();
+    var data = seriesModel.getData();
+
+    // Only for enabling highlight/downplay. Clear firstly.
+    // Because some node will not be rendered.
+    data.setItemGraphicEl(thisNode.dataIndex, null);
 
     if (!thisLayout || !thisLayout.isInView) {
         return;
@@ -53505,14 +53958,36 @@ function renderNode(
         return group;
     }
 
+    var nodeModel = thisNode.getModel();
+
     // Background
     var bg = giveGraphic('background', Rect$1, depth, Z_BG);
     bg && renderBackground(group, bg, isParent && thisLayout.upperHeight);
 
     // No children, render content.
-    if (!isParent) {
+    if (isParent) {
+        // Because of the implementation about "traverse" in graphic hover style, we
+        // can not set hover listener on the "group" of non-leaf node. Otherwise the
+        // hover event from the descendents will be listenered.
+        if (isHighDownDispatcher(group)) {
+            setAsHighDownDispatcher(group, false);
+        }
+        if (bg) {
+            setAsHighDownDispatcher(bg, true);
+            // Only for enabling highlight/downplay.
+            data.setItemGraphicEl(thisNode.dataIndex, bg);
+        }
+    }
+    else {
         var content = giveGraphic('content', Rect$1, depth, Z_CONTENT);
         content && renderContent(group, content);
+
+        if (bg && isHighDownDispatcher(bg)) {
+            setAsHighDownDispatcher(bg, false);
+        }
+        setAsHighDownDispatcher(group, true);
+        // Only for enabling highlight/downplay.
+        data.setItemGraphicEl(thisNode.dataIndex, group);
     }
 
     return group;
@@ -53527,10 +54002,17 @@ function renderNode(
         bg.seriesIndex = seriesModel.seriesIndex;
 
         bg.setShape({x: 0, y: 0, width: thisWidth, height: thisHeight});
-        var visualBorderColor = thisNode.getVisual('borderColor', true);
-        var emphasisBorderColor = itemStyleEmphasisModel.get('borderColor');
 
-        updateStyle(bg, function () {
+        if (thisInvisible) {
+            // If invisible, do not set visual, otherwise the element will
+            // change immediately before animation. We think it is OK to
+            // remain its origin color when moving out of the view window.
+            processInvisible(bg);
+        }
+        else {
+            bg.invisible = false;
+            var visualBorderColor = thisNode.getVisual('borderColor', true);
+            var emphasisBorderColor = itemStyleEmphasisModel.get('borderColor');
             var normalStyle = getItemStyleNormal(itemStyleNormalModel);
             normalStyle.fill = visualBorderColor;
             var emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel);
@@ -53550,8 +54032,8 @@ function renderNode(
             }
 
             bg.setStyle(normalStyle);
-            setHoverStyle(bg, emphasisStyle);
-        });
+            setElementHoverStyle(bg, emphasisStyle);
+        }
 
         group.add(bg);
     }
@@ -53572,8 +54054,15 @@ function renderNode(
             height: contentHeight
         });
 
-        var visualColor = thisNode.getVisual('color', true);
-        updateStyle(content, function () {
+        if (thisInvisible) {
+            // If invisible, do not set visual, otherwise the element will
+            // change immediately before animation. We think it is OK to
+            // remain its origin color when moving out of the view window.
+            processInvisible(content);
+        }
+        else {
+            content.invisible = false;
+            var visualColor = thisNode.getVisual('color', true);
             var normalStyle = getItemStyleNormal(itemStyleNormalModel);
             normalStyle.fill = visualColor;
             var emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel);
@@ -53581,32 +54070,19 @@ function renderNode(
             prepareText(normalStyle, emphasisStyle, visualColor, contentWidth, contentHeight);
 
             content.setStyle(normalStyle);
-            setHoverStyle(content, emphasisStyle);
-        });
+            setElementHoverStyle(content, emphasisStyle);
+        }
 
         group.add(content);
     }
 
-    function updateStyle(element, cb) {
-        if (!thisInvisible) {
-            // If invisible, do not set visual, otherwise the element will
-            // change immediately before animation. We think it is OK to
-            // remain its origin color when moving out of the view window.
-            cb();
-
-            if (!element.__tmWillVisible) {
-                element.invisible = false;
-            }
-        }
-        else {
-            // Delay invisible setting utill animation finished,
-            // avoid element vanish suddenly before animation.
-            !element.invisible && willInvisibleEls.push(element);
-        }
+    function processInvisible(element) {
+        // Delay invisible setting utill animation finished,
+        // avoid element vanish suddenly before animation.
+        !element.invisible && willInvisibleEls.push(element);
     }
 
     function prepareText(normalStyle, emphasisStyle, visualColor, width, height, upperLabelRect) {
-        var nodeModel = thisNode.getModel();
         var text = retrieve(
             seriesModel.getFormattedLabel(
                 thisNode.dataIndex, 'normal', null, null, upperLabelRect ? 'upperLabel' : 'label'
@@ -53703,6 +54179,7 @@ function renderNode(
         // Fade in, user can be aware that these nodes are new.
         lastCfg.fadein = storageName !== 'nodeGroup';
     }
+
 }
 
 // We can not set all backgroud with the same z, Because the behaviour of
@@ -56118,7 +56595,8 @@ var GraphSeries = extendSeriesModel({
         edgeSymbol: ['none', 'none'],
         edgeSymbolSize: 10,
         edgeLabel: {
-            position: 'middle'
+            position: 'middle',
+            distance: 5
         },
 
         draggable: false,
@@ -56372,39 +56850,90 @@ function updateSymbolAndLabelBeforeLineUpdate() {
         var textPosition;
         var textAlign;
         var textVerticalAlign;
-
-        var distance$$1 = 5 * invScale;
-        // End
-        if (label.__position === 'end') {
-            textPosition = [d[0] * distance$$1 + toPos[0], d[1] * distance$$1 + toPos[1]];
-            textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center');
-            textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle');
-        }
-        // Middle
-        else if (label.__position === 'middle') {
-            var halfPercent = percent / 2;
-            var tangent = line.tangentAt(halfPercent);
-            var n = [tangent[1], -tangent[0]];
-            var cp = line.pointAt(halfPercent);
-            if (n[1] > 0) {
-                n[0] = -n[0];
-                n[1] = -n[1];
-            }
-            textPosition = [cp[0] + n[0] * distance$$1, cp[1] + n[1] * distance$$1];
-            textAlign = 'center';
-            textVerticalAlign = 'bottom';
+        var textOrigin;
+
+        var distance$$1 = label.__labelDistance;
+        var distanceX = distance$$1[0] * invScale;
+        var distanceY = distance$$1[1] * invScale;
+        var halfPercent = percent / 2;
+        var tangent = line.tangentAt(halfPercent);
+        var n = [tangent[1], -tangent[0]];
+        var cp = line.pointAt(halfPercent);
+        if (n[1] > 0) {
+            n[0] = -n[0];
+            n[1] = -n[1];
+        }
+        var dir = tangent[0] < 0 ? -1 : 1;
+
+        if (label.__position !== 'start' && label.__position !== 'end') {
             var rotation = -Math.atan2(tangent[1], tangent[0]);
             if (toPos[0] < fromPos[0]) {
                 rotation = Math.PI + rotation;
             }
             label.attr('rotation', rotation);
         }
-        // Start
-        else {
-            textPosition = [-d[0] * distance$$1 + fromPos[0], -d[1] * distance$$1 + fromPos[1]];
-            textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center');
-            textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle');
+
+        var dy;
+        switch (label.__position) {
+            case 'insideStartTop':
+            case 'insideMiddleTop':
+            case 'insideEndTop':
+            case 'middle':
+                dy = -distanceY;
+                textVerticalAlign = 'bottom';
+                break;
+
+            case 'insideStartBottom':
+            case 'insideMiddleBottom':
+            case 'insideEndBottom':
+                dy = distanceY;
+                textVerticalAlign = 'top';
+                break;
+
+            default:
+                dy = 0;
+                textVerticalAlign = 'middle';
+        }
+
+        switch (label.__position) {
+            case 'end':
+                textPosition = [d[0] * distanceX + toPos[0], d[1] * distanceY + toPos[1]];
+                textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center');
+                textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle');
+                break;
+
+            case 'start':
+                textPosition = [-d[0] * distanceX + fromPos[0], -d[1] * distanceY + fromPos[1]];
+                textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center');
+                textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle');
+                break;
+
+            case 'insideStartTop':
+            case 'insideStart':
+            case 'insideStartBottom':
+                textPosition = [distanceX * dir + fromPos[0], fromPos[1] + dy];
+                textAlign = tangent[0] < 0 ? 'right' : 'left';
+                textOrigin = [-distanceX * dir, -dy];
+                break;
+
+            case 'insideMiddleTop':
+            case 'insideMiddle':
+            case 'insideMiddleBottom':
+            case 'middle':
+                textPosition = [cp[0], cp[1] + dy];
+                textAlign = 'center';
+                textOrigin = [0, -dy];
+                break;
+
+            case 'insideEndTop':
+            case 'insideEnd':
+            case 'insideEndBottom':
+                textPosition = [-distanceX * dir + toPos[0], toPos[1] + dy];
+                textAlign = tangent[0] >= 0 ? 'right' : 'left';
+                textOrigin = [distanceX * dir, -dy];
+                break;
         }
+
         label.attr({
             style: {
                 // Use the user specified text align and baseline first
@@ -56412,7 +56941,8 @@ function updateSymbolAndLabelBeforeLineUpdate() {
                 textAlign: label.__textAlign || textAlign
             },
             position: textPosition,
-            scale: [invScale, invScale]
+            scale: [invScale, invScale],
+            origin: textOrigin
         });
     }
 }
@@ -56588,6 +57118,12 @@ lineProto._updateCommonStl = function (lineData, idx, seriesScope) {
         label.__verticalAlign = labelStyle.textVerticalAlign;
         // 'start', 'middle', 'end'
         label.__position = labelModel.get('position') || 'middle';
+
+        var distance$$1 = labelModel.get('distance');
+        if (!isArray(distance$$1)) {
+            distance$$1 = [distance$$1, distance$$1];
+        }
+        label.__labelDistance = distance$$1;
     }
 
     if (emphasisText != null) {
@@ -57282,7 +57818,7 @@ extendChartView({
     },
 
     focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
-        var data = this._model.getData();
+        var data = seriesModel.getData();
         var graph = data.graph;
         var dataIndex = payload.dataIndex;
         var edgeDataIndex = payload.edgeDataIndex;
@@ -57320,7 +57856,7 @@ extendChartView({
     },
 
     unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
-        var graph = this._model.getData().graph;
+        var graph = seriesModel.getData().graph;
 
         graph.eachNode(function (node) {
             fadeOutItem(node, nodeOpacityPath);
@@ -62836,6 +63372,17 @@ var SankeySeries = SeriesModel.extend({
         }
     },
 
+    // Override Series.getDataParams()
+    getDataParams: function (dataIndex, dataType) {
+        var params = SankeySeries.superCall(this, 'getDataParams', dataIndex, dataType);
+        if (params.value == null && dataType === 'node') {
+            var node = this.getGraph().getNodeByIndex(dataIndex);
+            var nodeValue = node.getLayout().value;
+            params.value = nodeValue;
+        }
+        return params;
+    },
+
     defaultOption: {
         zlevel: 0,
         z: 2,
@@ -62896,7 +63443,7 @@ var SankeySeries = SeriesModel.extend({
                 show: true
             },
             lineStyle: {
-                opacity: 0.6
+                opacity: 0.5
             }
         },
 
@@ -62927,7 +63474,9 @@ var SankeySeries = SeriesModel.extend({
 */
 
 var nodeOpacityPath$1 = ['itemStyle', 'opacity'];
+var hoverNodeOpacityPath = ['emphasis', 'itemStyle', 'opacity'];
 var lineOpacityPath$1 = ['lineStyle', 'opacity'];
+var hoverLineOpacityPath = ['emphasis', 'lineStyle', 'opacity'];
 
 function getItemOpacity$1(item, opacityPath) {
     return item.getVisual('opacity') || item.getModel().get(opacityPath);
@@ -62935,8 +63484,8 @@ function getItemOpacity$1(item, opacityPath) {
 
 function fadeOutItem$1(item, opacityPath, opacityRatio) {
     var el = item.getGraphicEl();
-
     var opacity = getItemOpacity$1(item, opacityPath);
+
     if (opacityRatio != null) {
         opacity == null && (opacity = 1);
         opacity *= opacityRatio;
@@ -62954,12 +63503,14 @@ function fadeInItem$1(item, opacityPath) {
     var opacity = getItemOpacity$1(item, opacityPath);
     var el = item.getGraphicEl();
 
-    el.highlight && el.highlight();
     el.traverse(function (child) {
         if (child.type !== 'group') {
             child.setStyle('opacity', opacity);
         }
     });
+
+    // Support emphasis here.
+    el.highlight && el.highlight();
 }
 
 var SankeyShape = extendShape({
@@ -62997,6 +63548,14 @@ var SankeyShape = extendShape({
             );
         }
         ctx.closePath();
+    },
+
+    highlight: function () {
+        this.trigger('emphasis');
+    },
+
+    downplay: function () {
+        this.trigger('normal');
     }
 });
 
@@ -63179,8 +63738,19 @@ extendChartView({
                 el.cursor = 'move';
             }
 
+            el.highlight = function () {
+                this.trigger('emphasis');
+            };
+
+            el.downplay = function () {
+                this.trigger('normal');
+            };
+
+            el.focusNodeAdjHandler && el.off('mouseover', el.focusNodeAdjHandler);
+            el.unfocusNodeAdjHandler && el.off('mouseout', el.unfocusNodeAdjHandler);
+
             if (itemModel.get('focusNodeAdjacency')) {
-                el.off('mouseover').on('mouseover', function () {
+                el.on('mouseover', el.focusNodeAdjHandler = function () {
                     if (!sankeyView._focusAdjacencyDisabled) {
                         sankeyView._clearTimer();
                         api.dispatchAction({
@@ -63190,7 +63760,8 @@ extendChartView({
                         });
                     }
                 });
-                el.off('mouseout').on('mouseout', function () {
+
+                el.on('mouseout', el.unfocusNodeAdjHandler = function () {
                     if (!sankeyView._focusAdjacencyDisabled) {
                         sankeyView._dispatchUnfocus(api);
                     }
@@ -63200,8 +63771,12 @@ extendChartView({
 
         edgeData.eachItemGraphicEl(function (el, dataIndex) {
             var edgeModel = edgeData.getItemModel(dataIndex);
+
+            el.focusNodeAdjHandler && el.off('mouseover', el.focusNodeAdjHandler);
+            el.unfocusNodeAdjHandler && el.off('mouseout', el.unfocusNodeAdjHandler);
+
             if (edgeModel.get('focusNodeAdjacency')) {
-                el.off('mouseover').on('mouseover', function () {
+                el.on('mouseover', el.focusNodeAdjHandler = function () {
                     if (!sankeyView._focusAdjacencyDisabled) {
                         sankeyView._clearTimer();
                         api.dispatchAction({
@@ -63211,7 +63786,8 @@ extendChartView({
                         });
                     }
                 });
-                el.off('mouseout').on('mouseout', function () {
+
+                el.on('mouseout', el.unfocusNodeAdjHandler = function () {
                     if (!sankeyView._focusAdjacencyDisabled) {
                         sankeyView._dispatchUnfocus(api);
                     }
@@ -63252,7 +63828,7 @@ extendChartView({
     },
 
     focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
-        var data = this._model.getData();
+        var data = seriesModel.getData();
         var graph = data.graph;
         var dataIndex = payload.dataIndex;
         var itemModel = data.getItemModel(dataIndex);
@@ -63272,15 +63848,15 @@ extendChartView({
         });
 
         if (node) {
-            fadeInItem$1(node, nodeOpacityPath$1);
+            fadeInItem$1(node, hoverNodeOpacityPath);
             var focusNodeAdj = itemModel.get('focusNodeAdjacency');
             if (focusNodeAdj === 'outEdges') {
                 each$1(node.outEdges, function (edge) {
                     if (edge.dataIndex < 0) {
                         return;
                     }
-                    fadeInItem$1(edge, lineOpacityPath$1);
-                    fadeInItem$1(edge.node2, nodeOpacityPath$1);
+                    fadeInItem$1(edge, hoverLineOpacityPath);
+                    fadeInItem$1(edge.node2, hoverNodeOpacityPath);
                 });
             }
             else if (focusNodeAdj === 'inEdges') {
@@ -63288,8 +63864,8 @@ extendChartView({
                     if (edge.dataIndex < 0) {
                         return;
                     }
-                    fadeInItem$1(edge, lineOpacityPath$1);
-                    fadeInItem$1(edge.node1, nodeOpacityPath$1);
+                    fadeInItem$1(edge, hoverLineOpacityPath);
+                    fadeInItem$1(edge.node1, hoverNodeOpacityPath);
                 });
             }
             else if (focusNodeAdj === 'allEdges') {
@@ -63297,21 +63873,21 @@ extendChartView({
                     if (edge.dataIndex < 0) {
                         return;
                     }
-                    fadeInItem$1(edge, lineOpacityPath$1);
-                    fadeInItem$1(edge.node1, nodeOpacityPath$1);
-                    fadeInItem$1(edge.node2, nodeOpacityPath$1);
+                    fadeInItem$1(edge, hoverLineOpacityPath);
+                    (edge.node1 !== node) && fadeInItem$1(edge.node1, hoverNodeOpacityPath);
+                    (edge.node2 !== node) && fadeInItem$1(edge.node2, hoverNodeOpacityPath);
                 });
             }
         }
         if (edge) {
-            fadeInItem$1(edge, lineOpacityPath$1);
-            fadeInItem$1(edge.node1, nodeOpacityPath$1);
-            fadeInItem$1(edge.node2, nodeOpacityPath$1);
+            fadeInItem$1(edge, hoverLineOpacityPath);
+            fadeInItem$1(edge.node1, hoverNodeOpacityPath);
+            fadeInItem$1(edge.node2, hoverNodeOpacityPath);
         }
     },
 
     unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
-        var graph = this._model.getGraph();
+        var graph = seriesModel.getGraph();
 
         graph.eachNode(function (node) {
             fadeOutItem$1(node, nodeOpacityPath$1);
@@ -63334,8 +63910,7 @@ function createGridClipShape$1(rect, seriesModel, cb) {
     });
     initProps(rectEl, {
         shape: {
-            width: rect.width + 20,
-            height: rect.height + 20
+            width: rect.width + 20
         }
     }, seriesModel, cb);
 
@@ -63457,7 +64032,8 @@ function computeNodeValues(nodes) {
     each$1(nodes, function (node) {
         var value1 = sum(node.outEdges, getEdgeValue);
         var value2 = sum(node.inEdges, getEdgeValue);
-        var value = Math.max(value1, value2);
+        var nodeRawValue = node.getValue() || 0;
+        var value = Math.max(value1, value2, nodeRawValue);
         node.setLayout({value: value}, true);
     });
 }
@@ -63801,12 +64377,12 @@ function getEdgeValue(edge) {
     return edge.getValue();
 }
 
-function sum(array, f, orient) {
+function sum(array, cb, orient) {
     var sum = 0;
     var len = array.length;
     var i = -1;
     while (++i < len) {
-        var value = +f.call(array, array[i], orient);
+        var value = +cb.call(array, array[i], orient);
         if (!isNaN(value)) {
             sum += value;
         }
@@ -65107,7 +65683,6 @@ var candlestickVisual = {
     reset: function (seriesModel, ecModel) {
 
         var data = seriesModel.getData();
-        var isLargeRender = seriesModel.pipelineContext.large;
 
         data.setVisual({
             legendSymbol: 'roundRect',
@@ -65122,6 +65697,7 @@ var candlestickVisual = {
             return;
         }
 
+        var isLargeRender = seriesModel.pipelineContext.large;
         return !isLargeRender && {progress: progress};
 
 
@@ -66218,6 +66794,7 @@ effectLineProto._updateEffectSymbol = function (lineData, idx) {
     symbol.attr('scale', size);
 
     this._symbolType = symbolType;
+    this._symbolScale = size;
 
     this._updateEffectAnimation(lineData, effectModel, idx);
 };
@@ -66308,6 +66885,7 @@ effectLineProto.updateSymbolPosition = function (symbol) {
     var cp1 = symbol.__cp1;
     var t = symbol.__t;
     var pos = symbol.position;
+    var lastPos = [pos[0], pos[1]];
     var quadraticAt$$1 = quadraticAt;
     var quadraticDerivativeAt$$1 = quadraticDerivativeAt;
     pos[0] = quadraticAt$$1(p1[0], cp1[0], p2[0], t);
@@ -66318,7 +66896,27 @@ effectLineProto.updateSymbolPosition = function (symbol) {
     var ty = quadraticDerivativeAt$$1(p1[1], cp1[1], p2[1], t);
 
     symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2;
-
+    // enable continuity trail for 'line', 'rect', 'roundRect' symbolType
+    if (this._symbolType === 'line' || this._symbolType === 'rect' || this._symbolType === 'roundRect') {
+        if (symbol.__lastT !== undefined && symbol.__lastT < symbol.__t) {
+            var scaleY = dist(lastPos, pos) * 1.05;
+            symbol.attr('scale', [symbol.scale[0], scaleY]);
+            // make sure the last segment render within endPoint
+            if (t === 1) {
+                pos[0] = lastPos[0] + (pos[0] - lastPos[0]) / 2;
+                pos[1] = lastPos[1] + (pos[1] - lastPos[1]) / 2;
+            }
+        }
+        else if (symbol.__lastT === 1) {
+            // After first loop, symbol.__t does NOT start with 0, so connect p1 to pos directly.
+            var scaleY = 2 * dist(p1, pos);
+            symbol.attr('scale', [symbol.scale[0], scaleY ]);
+        }
+        else {
+            symbol.attr('scale', this._symbolScale);
+        }
+    }
+    symbol.__lastT = symbol.__t;
     symbol.ignore = false;
 };
 
@@ -69144,7 +69742,7 @@ var axisBuilderAttrs$2 = [
     'axisLine', 'axisTickLabel', 'axisName'
 ];
 
-var selfBuilderAttr = 'splitLine';
+var selfBuilderAttrs$1 = ['splitArea', 'splitLine'];
 
 var SingleAxisView = AxisView.extend({
 
@@ -69158,21 +69756,33 @@ var SingleAxisView = AxisView.extend({
 
         group.removeAll();
 
+        var oldAxisGroup = this._axisGroup;
+        this._axisGroup = new Group();
+
         var layout = layout$2(axisModel);
 
         var axisBuilder = new AxisBuilder(axisModel, layout);
 
         each$1(axisBuilderAttrs$2, axisBuilder.add, axisBuilder);
 
+        group.add(this._axisGroup);
         group.add(axisBuilder.getGroup());
 
-        if (axisModel.get(selfBuilderAttr + '.show')) {
-            this['_' + selfBuilderAttr](axisModel);
-        }
+        each$1(selfBuilderAttrs$1, function (name) {
+            if (axisModel.get(name + '.show')) {
+                this['_' + name](axisModel);
+            }
+        }, this);
+
+        groupTransition(oldAxisGroup, this._axisGroup, axisModel);
 
         SingleAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
     },
 
+    remove: function () {
+        rectCoordAxisHandleRemove(this);
+    },
+
     _splitLine: function (axisModel) {
         var axis = axisModel.axis;
 
@@ -69241,6 +69851,10 @@ var SingleAxisView = AxisView.extend({
                 silent: true
             }));
         }
+    },
+
+    _splitArea: function (axisModel) {
+        rectCoordAxisBuildSplitArea(this, this._axisGroup, axisModel, axisModel);
     }
 });
 
@@ -74267,10 +74881,6 @@ function barLayoutPolar(seriesType, ecModel, api) {
             var value = data.get(valueDim, idx);
             var baseValue = data.get(baseDim, idx);
 
-            if (isNaN(value)) {
-                continue;
-            }
-
             var sign = value >= 0 ? 'p' : 'n';
             var baseCoord = valueAxisStart;
 
@@ -75659,7 +76269,7 @@ AxisView.extend({
 var axisBuilderAttrs$3 = [
     'axisLine', 'axisTickLabel', 'axisName'
 ];
-var selfBuilderAttrs$1 = [
+var selfBuilderAttrs$2 = [
     'splitLine', 'splitArea', 'minorSplitLine'
 ];
 
@@ -75687,7 +76297,7 @@ AxisView.extend({
         each$1(axisBuilderAttrs$3, axisBuilder.add, axisBuilder);
         this.group.add(axisBuilder.getGroup());
 
-        each$1(selfBuilderAttrs$1, function (name) {
+        each$1(selfBuilderAttrs$2, function (name) {
             if (radiusAxisModel.get(name + '.show') && !radiusAxis.scale.isBlank()) {
                 this['_' + name](radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords);
             }
@@ -82090,24 +82700,63 @@ function assembleCssText(tooltipModel) {
     return cssText.join(';') + ';';
 }
 
+// If not able to make, do not modify the input `out`.
+function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
+    var zrPainter = zr && zr.painter;
+
+    if (appendToBody) {
+        var zrViewportRoot = zrPainter && zrPainter.getViewportRoot();
+        if (zrViewportRoot) {
+            // Some APPs might use scale on body, so we support CSS transform here.
+            transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY);
+        }
+    }
+    else {
+        out[0] = zrX;
+        out[1] = zrY;
+        // xy should be based on canvas root. But tooltipContent is
+        // the sibling of canvas root. So padding of ec container
+        // should be considered here.
+        var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset();
+        if (viewportRootOffset) {
+            out[0] += viewportRootOffset.offsetLeft;
+            out[1] += viewportRootOffset.offsetTop;
+        }
+    }
+}
+
 /**
  * @alias module:echarts/component/tooltip/TooltipContent
+ * @param {HTMLElement} container
+ * @param {ExtensionAPI} api
+ * @param {Object} [opt]
+ * @param {boolean} [opt.appendToBody]
+ *        `false`: the DOM element will be inside the container. Default value.
+ *        `true`: the DOM element will be appended to HTML body, which avoid
+ *                some overflow clip but intrude outside of the container.
  * @constructor
  */
-function TooltipContent(container, api) {
+function TooltipContent(container, api, opt) {
     if (env$1.wxa) {
         return null;
     }
 
     var el = document.createElement('div');
+    el.domBelongToZr = true;
+    this.el = el;
     var zr = this._zr = api.getZr();
+    var appendToBody = this._appendToBody = opt && opt.appendToBody;
 
-    this.el = el;
+    this._styleCoord = [0, 0];
 
-    this._x = api.getWidth() / 2;
-    this._y = api.getHeight() / 2;
+    makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
 
-    container.appendChild(el);
+    if (appendToBody) {
+        document.body.appendChild(el);
+    }
+    else {
+        container.appendChild(el);
+    }
 
     this._container = container;
 
@@ -82141,7 +82790,8 @@ function TooltipContent(container, api) {
             // Try trigger zrender event to avoid mouse
             // in and out shape too frequently
             var handler = zr.handler;
-            normalizeEvent(container, e, true);
+            var zrViewportRoot = zr.painter.getViewportRoot();
+            normalizeEvent(zrViewportRoot, e, true);
             handler.dispatch('mousemove', e);
         }
     };
@@ -82186,12 +82836,13 @@ TooltipContent.prototype = {
     show: function (tooltipModel) {
         clearTimeout(this._hideTimeout);
         var el = this.el;
+        var styleCoord = this._styleCoord;
 
         el.style.cssText = gCssText + assembleCssText(tooltipModel)
             // Because of the reason described in:
             // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
             // we should set initial value to `left` and `top`.
-            + ';left:' + this._x + 'px;top:' + this._y + 'px;'
+            + ';left:' + styleCoord[0] + 'px;top:' + styleCoord[1] + 'px;'
             + (tooltipModel.get('extraCssText') || '');
 
         el.style.display = el.innerHTML ? 'block' : 'none';
@@ -82219,23 +82870,13 @@ TooltipContent.prototype = {
         return [el.clientWidth, el.clientHeight];
     },
 
-    moveTo: function (x, y) {
-        // xy should be based on canvas root. But tooltipContent is
-        // the sibling of canvas root. So padding of ec container
-        // should be considered here.
-        var zr = this._zr;
-        var viewportRootOffset;
-        if (zr && zr.painter && (viewportRootOffset = zr.painter.getViewportRootOffset())) {
-            x += viewportRootOffset.offsetLeft;
-            y += viewportRootOffset.offsetTop;
-        }
+    moveTo: function (zrX, zrY) {
+        var styleCoord = this._styleCoord;
+        makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY);
 
         var style = this.el.style;
-        style.left = x + 'px';
-        style.top = y + 'px';
-
-        this._x = x;
-        this._y = y;
+        style.left = styleCoord[0] + 'px';
+        style.top = styleCoord[1] + 'px';
     },
 
     hide: function () {
@@ -82261,6 +82902,10 @@ TooltipContent.prototype = {
         return this._show;
     },
 
+    dispose: function () {
+        this.el.parentNode.removeChild(this.el);
+    },
+
     getOuterSize: function () {
         var width = this.el.clientWidth;
         var height = this.el.clientHeight;
@@ -82277,6 +82922,7 @@ TooltipContent.prototype = {
 
         return {width: width, height: height};
     }
+
 };
 
 /*
@@ -82508,7 +83154,9 @@ extendComponentView({
 
         var tooltipContent;
         if (this._renderMode === 'html') {
-            tooltipContent = new TooltipContent(api.getDom(), api);
+            tooltipContent = new TooltipContent(api.getDom(), api, {
+                appendToBody: tooltipModel.get('appendToBody', true)
+            });
             this._newLine = '<br/>';
         }
         else {
@@ -82661,7 +83309,6 @@ extendComponentView({
                 offsetX: payload.x,
                 offsetY: payload.y,
                 position: payload.position,
-                event: {},
                 dataByCoordSys: payload.dataByCoordSys,
                 tooltipOption: payload.tooltipOption
             }, dispatchAction);
@@ -82680,8 +83327,7 @@ extendComponentView({
                     offsetX: cx,
                     offsetY: cy,
                     position: payload.position,
-                    target: pointInfo.el,
-                    event: {}
+                    target: pointInfo.el
                 }, dispatchAction);
             }
         }
@@ -82698,8 +83344,7 @@ extendComponentView({
                 offsetX: payload.x,
                 offsetY: payload.y,
                 position: payload.position,
-                target: api.getZr().findHover(payload.x, payload.y).target,
-                event: {}
+                target: api.getZr().findHover(payload.x, payload.y).target
             }, dispatchAction);
         }
     },
@@ -82805,7 +83450,9 @@ extendComponentView({
     _showAxisTooltip: function (dataByCoordSys, e) {
         var ecModel = this._ecModel;
         var globalTooltipModel = this._tooltipModel;
+
         var point = [e.offsetX, e.offsetY];
+
         var singleDefaultHTML = [];
         var singleParamsList = [];
         var singleTooltipModel = buildTooltipModel([
@@ -83061,6 +83708,7 @@ extendComponentView({
     _updatePosition: function (tooltipModel, positionExpr, x, y, content, params, el) {
         var viewWidth = this._api.getWidth();
         var viewHeight = this._api.getHeight();
+
         positionExpr = positionExpr || tooltipModel.get('position');
 
         var contentSize = content.getSize();
@@ -83179,7 +83827,7 @@ extendComponentView({
         if (env$1.node) {
             return;
         }
-        this._tooltipContent.hide();
+        this._tooltipContent.dispose();
         unregister('itemTooltip', api);
     }
 });
@@ -83764,16 +84412,19 @@ var PRIORITY_BRUSH = PRIORITY.VISUAL.BRUSH;
  */
 registerLayout(PRIORITY_BRUSH, function (ecModel, api, payload) {
     ecModel.eachComponent({mainType: 'brush'}, function (brushModel) {
-
         payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(
             payload.key === 'brush' ? payload.brushOption : {brushType: false}
         );
+    });
+    layoutCovers(ecModel);
+});
 
+function layoutCovers(ecModel) {
+    ecModel.eachComponent({mainType: 'brush'}, function (brushModel) {
         var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel);
-
         brushTargetManager.setInputRanges(brushModel.areas, ecModel);
     });
-});
+}
 
 /**
  * Register the visual encoding if this modules required.
@@ -84288,7 +84939,13 @@ extendComponentView({
     /**
      * @override
      */
-    updateTransform: updateController,
+    updateTransform: function (brushModel, ecModel) {
+        // PENDING: `updateTransform` is a little tricky, whose layout need
+        // to be calculate mandatorily and other stages will not be performed.
+        // Take care the correctness of the logic. See #11754 .
+        layoutCovers(ecModel);
+        return updateController.apply(this, arguments);
+    },
 
     /**
      * @override
@@ -86380,8 +87037,8 @@ function markerTypeCalculatorWithExtent(
 
     var dataIndex = data.indicesOfNearest(calcDataDim, value)[0];
     coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex);
-    coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex);
-
+    coordArr[targetCoordIndex] = data.get(calcDataDim, dataIndex);
+    var coordArrValue = data.get(targetDataDim, dataIndex);
     // Make it simple, do not visit all stacked value to count precision.
     var precision = getPrecision(data.get(targetDataDim, dataIndex));
     precision = Math.min(precision, 20);
@@ -86389,7 +87046,7 @@ function markerTypeCalculatorWithExtent(
         coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
     }
 
-    return coordArr;
+    return [coordArr, coordArrValue];
 }
 
 var curry$5 = curry;
@@ -86452,12 +87109,15 @@ function dataTransform(seriesModel, item) {
             var otherCoordIndex = indexOf$2(dims, axisInfo.baseAxis.dim);
             var targetCoordIndex = indexOf$2(dims, axisInfo.valueAxis.dim);
 
-            item.coord = markerTypeCalculator[item.type](
+            var coordInfo = markerTypeCalculator[item.type](
                 data, axisInfo.baseDataDim, axisInfo.valueDataDim,
                 otherCoordIndex, targetCoordIndex
             );
+            item.coord = coordInfo[0];
             // Force to use the value of calculated value.
-            item.value = item.coord[targetCoordIndex];
+            // let item use the value without stack.
+            item.value = coordInfo[1];
+
         }
         else {
             // FIXME Only has one of xAxis and yAxis.
@@ -86849,7 +87509,8 @@ MarkerModel.extend({
         },
         label: {
             show: true,
-            position: 'end'
+            position: 'end',
+            distance: 5
         },
         lineStyle: {
             type: 'dashed'
@@ -89299,26 +89960,28 @@ var ScrollableLegendView = LegendView.extend({
     },
 
     _findTargetItemIndex: function (targetDataIndex) {
+        if (!this._showController) {
+            return 0;
+        }
+
         var index;
         var contentGroup = this.getContentGroup();
         var defaultIndex;
 
-        if (this._showController) {
-            contentGroup.eachChild(function (child, idx) {
-                var legendDataIdx = child.__legendDataIndex;
-                // FIXME
-                // If the given targetDataIndex (from model) is illegal,
-                // we use defualtIndex. But the index on the legend model and
-                // action payload is still illegal. That case will not be
-                // changed until some scenario requires.
-                if (defaultIndex == null && legendDataIdx != null) {
-                    defaultIndex = idx;
-                }
-                if (legendDataIdx === targetDataIndex) {
-                    index = idx;
-                }
-            });
-        }
+        contentGroup.eachChild(function (child, idx) {
+            var legendDataIdx = child.__legendDataIndex;
+            // FIXME
+            // If the given targetDataIndex (from model) is illegal,
+            // we use defualtIndex. But the index on the legend model and
+            // action payload is still illegal. That case will not be
+            // changed until some scenario requires.
+            if (defaultIndex == null && legendDataIdx != null) {
+                defaultIndex = idx;
+            }
+            if (legendDataIdx === targetDataIndex) {
+                index = idx;
+            }
+        });
 
         return index != null ? index : defaultIndex;
     }
diff --git a/en/dist/echarts-en.js.map b/en/dist/echarts-en.js.map
index a994ff2..81951f0 100644
--- a/en/dist/echarts-en.js.map
+++ b/en/dist/echarts-en.js.map
@@ -1 +1 @@
-{"version":3,"file":"echarts-en.js","sources":["../src/config.js","../../zrender/src/core/guid.js","../../zrender/src/core/env.js","../../zrender/src/core/util.js","../../zrender/src/core/vector.js","../../zrender/src/mixin/Draggable.js","../../zrender/src/mixin/Eventful.js","../../zrender/src/core/fourPointsTransform.js","../../zrender/src/core/event.js","../../zrender/src/core/GestureMgr.js","../../zrender/src/Handler.js","../../zrender/src/core/matrix.js","../../zrender/src/mixin/Tran [...]
\ No newline at end of file
+{"version":3,"file":"echarts-en.js","sources":["../src/config.js","../../zrender/src/core/guid.js","../../zrender/src/core/env.js","../../zrender/src/core/util.js","../../zrender/src/core/vector.js","../../zrender/src/mixin/Draggable.js","../../zrender/src/mixin/Eventful.js","../../zrender/src/core/fourPointsTransform.js","../../zrender/src/core/dom.js","../../zrender/src/core/event.js","../../zrender/src/core/GestureMgr.js","../../zrender/src/Handler.js","../../zrender/src/core/matrix.j [...]
\ No newline at end of file
diff --git a/en/dist/echarts-en.min.js b/en/dist/echarts-en.min.js
index 456243b..d118440 100644
--- a/en/dist/echarts-en.min.js
+++ b/en/dist/echarts-en.min.js
@@ -19,4 +19,4 @@
 */
 
 
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,n=function(){return e++},v="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasS [...]
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,n=function(){return e++},v="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasS [...]
diff --git a/en/dist/echarts-en.simple.js b/en/dist/echarts-en.simple.js
index cd00713..c282195 100644
--- a/en/dist/echarts-en.simple.js
+++ b/en/dist/echarts-en.simple.js
@@ -1172,7 +1172,11 @@ Draggable.prototype = {
 
     _dragStart: function (e) {
         var draggingTarget = e.target;
-        if (draggingTarget && draggingTarget.draggable) {
+        // Find if there is draggable in the ancestor
+        while (draggingTarget && !draggingTarget.draggable) {
+            draggingTarget = draggingTarget.parent;
+        }
+        if (draggingTarget) {
             this._draggingTarget = draggingTarget;
             draggingTarget.dragging = true;
             this._x = e.offsetX;
@@ -1601,6 +1605,8 @@ function buildTransformer(src, dest) {
     var detCache = {};
     var det = determinant(mA, 8, 0, 0, 0, detCache);
     if (det === 0) {
+        // can not make transformer when and only when
+        // any three of the markers are collinear.
         return;
     }
 
@@ -1623,6 +1629,148 @@ function buildTransformer(src, dest) {
     };
 }
 
+var EVENT_SAVED_PROP = '___zrEVENTSAVED';
+/**
+ * Transform "local coord" from `elFrom` to `elTarget`.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support when CSS transform is used.
+ *
+ * Having the `out` (that is, `[outX, outY]`), we can create an DOM element
+ * and set the CSS style as "left: outX; top: outY;" and append it to `elTarge`
+ * to locate the element.
+ *
+ * For example, this code below positions a child of `document.body` on the event
+ * point, no matter whether `body` has `margin`/`paddin`/`transfrom`/... :
+ * ```js
+ * transformLocalCoord(out, container, document.body, event.offsetX, event.offsetY);
+ * if (!eqNaN(out[0])) {
+ *     // Then locate the tip element on the event point.
+ *     var tipEl = document.createElement('div');
+ *     tipEl.style.cssText = 'position: absolute; left:' + out[0] + ';top:' + out[1] + ';';
+ *     document.body.appendChild(tipEl);
+ * }
+ * ```
+ *
+ * Notice: In some env this method is not supported. If called, `out` will be `[NaN, NaN]`.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output..
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} elFrom The `[inX, inY]` is based on elFrom.
+ * @param {HTMLElement} elTarget The `out` is based on elTarget.
+ * @param {number} inX
+ * @param {number} inY
+ * @return {boolean} Whether transform successfully.
+ */
+
+
+/**
+ * Transform between a "viewport coord" and a "local coord".
+ * "viewport coord": the coord based on the left-top corner of the viewport
+ *     of the browser.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support the case when CSS transform is used on el.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output. If `inverse: false`,
+ *        it represents "local coord", otherwise "vireport coord".
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} el The "local coord" is based on the `el`, see comment above.
+ * @param {number} inX If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {number} inY If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {boolean} [inverse=false]
+ *        `true`: from "viewport coord" to "local coord".
+ *        `false`: from "local coord" to "viewport coord".
+ * @return {boolean} Whether transform successfully.
+ */
+function transformCoordWithViewport(out, el, inX, inY, inverse) {
+    if (el.getBoundingClientRect && env$1.domSupported && !isCanvasEl(el)) {
+        var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
+        var markers = prepareCoordMarkers(el, saved);
+        var transformer = preparePointerTransformer(markers, saved, inverse);
+        if (transformer) {
+            transformer(out, inX, inY);
+            return true;
+        }
+    }
+    return false;
+}
+
+function prepareCoordMarkers(el, saved) {
+    var markers = saved.markers;
+    if (markers) {
+        return markers;
+    }
+
+    markers = saved.markers = [];
+    var propLR = ['left', 'right'];
+    var propTB = ['top', 'bottom'];
+
+    for (var i = 0; i < 4; i++) {
+        var marker = document.createElement('div');
+        var stl = marker.style;
+        var idxLR = i % 2;
+        var idxTB = (i >> 1) % 2;
+        stl.cssText = [
+            'position: absolute',
+            'visibility: hidden',
+            'padding: 0',
+            'margin: 0',
+            'border-width: 0',
+            'user-select: none',
+            'width:0',
+            'height:0',
+            // 'width: 5px',
+            // 'height: 5px',
+            propLR[idxLR] + ':0',
+            propTB[idxTB] + ':0',
+            propLR[1 - idxLR] + ':auto',
+            propTB[1 - idxTB] + ':auto',
+            ''
+        ].join('!important;');
+        el.appendChild(marker);
+        markers.push(marker);
+    }
+
+    return markers;
+}
+
+function preparePointerTransformer(markers, saved, inverse) {
+    var transformerName = inverse ? 'invTrans' : 'trans';
+    var transformer = saved[transformerName];
+    var oldSrcCoords = saved.srcCoords;
+    var oldCoordTheSame = true;
+    var srcCoords = [];
+    var destCoords = [];
+
+    for (var i = 0; i < 4; i++) {
+        var rect = markers[i].getBoundingClientRect();
+        var ii = 2 * i;
+        var x = rect.left;
+        var y = rect.top;
+        srcCoords.push(x, y);
+        oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
+        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
+    }
+    // Cache to avoid time consuming of `buildTransformer`.
+    return (oldCoordTheSame && transformer)
+        ? transformer
+        : (
+            saved.srcCoords = srcCoords,
+            saved[transformerName] = inverse
+                ? buildTransformer(destCoords, srcCoords)
+                : buildTransformer(srcCoords, destCoords)
+        );
+}
+
+function isCanvasEl(el) {
+    return el.nodeName.toUpperCase() === 'CANVAS';
+}
+
 /**
  * Utilities for mouse or touch events.
  */
@@ -1630,7 +1778,6 @@ function buildTransformer(src, dest) {
 var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener;
 
 var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
-var EVENT_SAVED_PROP = '___zrEVENTSAVED';
 var _calcOut = [];
 
 /**
@@ -1695,11 +1842,11 @@ function clientToLocal(el, e, out, calculate) {
 
 function calculateZrXY(el, e, out) {
     // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect.
-    if (el.getBoundingClientRect && env$1.domSupported) {
+    if (env$1.domSupported && el.getBoundingClientRect) {
         var ex = e.clientX;
         var ey = e.clientY;
 
-        if (el.nodeName.toUpperCase() === 'CANVAS') {
+        if (isCanvasEl(el)) {
             // Original approach, which do not support CSS transform.
             // marker can not be locationed in a canvas container
             // (getBoundingClientRect is always 0). We do not support
@@ -1711,10 +1858,7 @@ function calculateZrXY(el, e, out) {
             return;
         }
         else {
-            var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
-            var transformer = preparePointerTransformer(prepareCoordMarkers(el, saved), saved);
-            if (transformer) {
-                transformer(_calcOut, ex, ey);
+            if (transformCoordWithViewport(_calcOut, el, ex, ey)) {
                 out.zrX = _calcOut[0];
                 out.zrY = _calcOut[1];
                 return;
@@ -1724,70 +1868,6 @@ function calculateZrXY(el, e, out) {
     out.zrX = out.zrY = 0;
 }
 
-function prepareCoordMarkers(el, saved) {
-    var markers = saved.markers;
-    if (markers) {
-        return markers;
-    }
-
-    markers = saved.markers = [];
-    var propLR = ['left', 'right'];
-    var propTB = ['top', 'bottom'];
-
-    for (var i = 0; i < 4; i++) {
-        var marker = document.createElement('div');
-        var stl = marker.style;
-        var idxLR = i % 2;
-        var idxTB = (i >> 1) % 2;
-        stl.cssText = [
-            'position:absolute',
-            'visibility: hidden',
-            'padding: 0',
-            'margin: 0',
-            'border-width: 0',
-            'width:0',
-            'height:0',
-            // 'width: 5px',
-            // 'height: 5px',
-            propLR[idxLR] + ':0',
-            propTB[idxTB] + ':0',
-            propLR[1 - idxLR] + ':auto',
-            propTB[1 - idxTB] + ':auto',
-            ''
-        ].join('!important;');
-        el.appendChild(marker);
-        markers.push(marker);
-    }
-
-    return markers;
-}
-
-function preparePointerTransformer(markers, saved) {
-    var transformer = saved.transformer;
-    var oldSrcCoords = saved.srcCoords;
-    var useOld = true;
-    var srcCoords = [];
-    var destCoords = [];
-
-    for (var i = 0; i < 4; i++) {
-        var rect = markers[i].getBoundingClientRect();
-        var ii = 2 * i;
-        var x = rect.left;
-        var y = rect.top;
-        srcCoords.push(x, y);
-        useOld &= oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
-        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
-    }
-
-    // Cache to avoid time consuming of `buildTransformer`.
-    return useOld
-        ? transformer
-        : (
-            saved.srcCoords = srcCoords,
-            saved.transformer = buildTransformer(srcCoords, destCoords)
-        );
-}
-
 /**
  * Find native event compat for legency IE.
  * Should be called at the begining of a native event listener.
@@ -4473,7 +4553,7 @@ var Animator = function (target, loop, getter, setter) {
 
 Animator.prototype = {
     /**
-     * 设置动画关键帧
+     * Set Animation keyframe
      * @param  {number} time 关键帧时间,单位是ms
      * @param  {Object} props 关键帧的属性值,key-value表示
      * @return {module:zrender/animation/Animator}
@@ -4552,7 +4632,7 @@ Animator.prototype = {
         }
     },
     /**
-     * 开始执行动画
+     * Start the animation
      * @param  {string|Function} [easing]
      *         动画缓动函数,详见{@link module:zrender/animation/easing}
      * @param  {boolean} forceAnimate
@@ -4613,7 +4693,7 @@ Animator.prototype = {
         return this;
     },
     /**
-     * 停止动画
+     * Stop animation
      * @param {boolean} forwardToLast If move to last frame before stop
      */
     stop: function (forwardToLast) {
@@ -4630,7 +4710,7 @@ Animator.prototype = {
         clipList.length = 0;
     },
     /**
-     * 设置动画延迟开始的时间
+     * Set when animation delay starts
      * @param  {number} time 单位ms
      * @return {module:zrender/animation/Animator}
      */
@@ -4639,7 +4719,7 @@ Animator.prototype = {
         return this;
     },
     /**
-     * 添加动画结束的回调
+     * Add callback for animation end
      * @param  {Function} cb
      * @return {module:zrender/animation/Animator}
      */
@@ -4691,7 +4771,7 @@ if (debugMode === 1) {
 var logError$1 = logError;
 
 /**
- * @alias modue:zrender/mixin/Animatable
+ * @alias module:zrender/mixin/Animatable
  * @constructor
  */
 var Animatable = function () {
@@ -10367,7 +10447,7 @@ Painter.prototype = {
 };
 
 /**
- * 动画主类, 调度和管理所有动画控制器
+ * Animation main class, dispatch and manage all animation controllers
  *
  * @module zrender/animation/Animation
  * @author pissang(https://github.com/pissang)
@@ -10432,14 +10512,14 @@ Animation.prototype = {
 
     constructor: Animation,
     /**
-     * 添加 clip
+     * Add clip
      * @param {module:zrender/animation/Clip} clip
      */
     addClip: function (clip) {
         this._clips.push(clip);
     },
     /**
-     * 添加 animator
+     * Add animator
      * @param {module:zrender/animation/Animator} animator
      */
     addAnimator: function (animator) {
@@ -10450,7 +10530,7 @@ Animation.prototype = {
         }
     },
     /**
-     * 删除动画片段
+     * Delete animation clip
      * @param {module:zrender/animation/Clip} clip
      */
     removeClip: function (clip) {
@@ -10461,7 +10541,7 @@ Animation.prototype = {
     },
 
     /**
-     * 删除动画片段
+     * Delete animation clip
      * @param {module:zrender/animation/Animator} animator
      */
     removeAnimator: function (animator) {
@@ -10728,13 +10808,16 @@ function normalizeGlobalEvent(instance, event) {
  * Detect whether the given el is in `painterRoot`.
  */
 function isLocalEl(instance, el) {
+    var elTmp = el;
     var isLocal = false;
-    do {
-        el = el && el.parentNode;
+    while (elTmp && elTmp.nodeType !== 9
+        && !(
+            isLocal = elTmp.domBelongToZr
+                || (elTmp !== el && elTmp === instance.painterRoot)
+        )
+    ) {
+        elTmp = elTmp.parentNode;
     }
-    while (el && el.nodeType !== 9 && !(
-        isLocal = el === instance.painterRoot
-    ));
     return isLocal;
 }
 
@@ -11187,7 +11270,7 @@ var painterCtors = {
 /**
  * @type {string}
  */
-var version$1 = '4.2.0';
+var version$1 = '4.3.0';
 
 /**
  * Initializing a zrender instance
@@ -16020,12 +16103,10 @@ var round = Math.round;
  * @param {number} [inputShape.x2]
  * @param {number} [inputShape.y2]
  * @param {Object} [style]
- * @param {number} [style.lineWidth]
+ * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
  */
 function subPixelOptimizeLine$1(outputShape, inputShape, style) {
-    var lineWidth = style && style.lineWidth;
-
-    if (!inputShape || !lineWidth) {
+    if (!inputShape) {
         return;
     }
 
@@ -16034,20 +16115,22 @@ function subPixelOptimizeLine$1(outputShape, inputShape, style) {
     var y1 = inputShape.y1;
     var y2 = inputShape.y2;
 
+    outputShape.x1 = x1;
+    outputShape.x2 = x2;
+    outputShape.y1 = y1;
+    outputShape.y2 = y2;
+
+    var lineWidth = style && style.lineWidth;
+    if (!lineWidth) {
+        return;
+    }
+
     if (round(x1 * 2) === round(x2 * 2)) {
         outputShape.x1 = outputShape.x2 = subPixelOptimize$1(x1, lineWidth, true);
     }
-    else {
-        outputShape.x1 = x1;
-        outputShape.x2 = x2;
-    }
     if (round(y1 * 2) === round(y2 * 2)) {
         outputShape.y1 = outputShape.y2 = subPixelOptimize$1(y1, lineWidth, true);
     }
-    else {
-        outputShape.y1 = y1;
-        outputShape.y2 = y2;
-    }
 }
 
 /**
@@ -16063,12 +16146,10 @@ function subPixelOptimizeLine$1(outputShape, inputShape, style) {
  * @param {number} [inputShape.width]
  * @param {number} [inputShape.height]
  * @param {Object} [style]
- * @param {number} [style.lineWidth]
+ * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
  */
 function subPixelOptimizeRect$1(outputShape, inputShape, style) {
-    var lineWidth = style && style.lineWidth;
-
-    if (!inputShape || !lineWidth) {
+    if (!inputShape) {
         return;
     }
 
@@ -16077,6 +16158,16 @@ function subPixelOptimizeRect$1(outputShape, inputShape, style) {
     var originWidth = inputShape.width;
     var originHeight = inputShape.height;
 
+    outputShape.x = originX;
+    outputShape.y = originY;
+    outputShape.width = originWidth;
+    outputShape.height = originHeight;
+
+    var lineWidth = style && style.lineWidth;
+    if (!lineWidth) {
+        return;
+    }
+
     outputShape.x = subPixelOptimize$1(originX, lineWidth, true);
     outputShape.y = subPixelOptimize$1(originY, lineWidth, true);
     outputShape.width = Math.max(
@@ -16093,11 +16184,14 @@ function subPixelOptimizeRect$1(outputShape, inputShape, style) {
  * Sub pixel optimize for canvas
  *
  * @param {number} position Coordinate, such as x, y
- * @param {number} lineWidth Should be nonnegative integer.
+ * @param {number} lineWidth If `null`/`undefined`/`0`, do not optimize.
  * @param {boolean=} positiveOrNegative Default false (negative).
  * @return {number} Optimized position.
  */
 function subPixelOptimize$1(position, lineWidth, positiveOrNegative) {
+    if (!lineWidth) {
+        return position;
+    }
     // Assure that (position + lineWidth / 2) is near integer edge,
     // otherwise line will be fuzzy in canvas.
     var doubledPosition = round(position * 2);
@@ -17798,7 +17892,7 @@ function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb)
  * configuration in series.
  *
  * Caution: this method will stop previous animation.
- * So if do not use this method to one element twice before
+ * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  *
  * @param {module:zrender/Element} el
@@ -17824,7 +17918,7 @@ function updateProps(el, props, animatableModel, dataIndex, cb) {
  * configuration in series.
  *
  * Caution: this method will stop previous animation.
- * So if do not use this method to one element twice before
+ * So do not use this method to one element twice before
  * animation starts, unless you know what you are doing.
  *
  * @param {module:zrender/Element} el
@@ -24472,8 +24566,11 @@ var createRenderPlanner = function () {
         var originalLarge = fields.large;
         var originalProgressive = fields.progressiveRender;
 
-        var large = fields.large = pipelineContext.large;
-        var progressive = fields.progressiveRender = pipelineContext.progressiveRender;
+        // FIXME: if the planner works on a filtered series, `pipelineContext` does not
+        // exists. See #11611 . Probably we need to modify this structure, see the comment
+        // on `performRawSeries` in `Schedular.js`.
+        var large = fields.large = pipelineContext && pipelineContext.large;
+        var progressive = fields.progressiveRender = pipelineContext && pipelineContext.progressiveRender;
 
         return !!((originalLarge ^ large) || (originalProgressive ^ progressive)) && 'reset';
     };
@@ -25587,6 +25684,14 @@ function performStageTasks(scheduler, stageHandlers, ecModel, payload, opt) {
                     task.dirty();
                 }
                 var performArgs = scheduler.getPerformArgs(task, opt.block);
+                // FIXME
+                // if intending to decalare `performRawSeries` in handlers, only
+                // stream-independent (specifically, data item independent) operations can be
+                // performed. Because is a series is filtered, most of the tasks will not
+                // be performed. A stream-dependent operation probably cause wrong biz logic.
+                // Perhaps we should not provide a separate callback for this case instead
+                // of providing the config `performRawSeries`. The stream-dependent operaions
+                // and stream-independent operations should better not be mixed.
                 performArgs.skip = !stageHandler.performRawSeries
                     && ecModel.isSeriesFiltered(task.context.model);
                 updatePayload(task, payload);
@@ -26961,10 +27066,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.6.0';
+var version = '4.7.0';
 
 var dependencies = {
-    zrender: '4.2.0'
+    zrender: '4.3.0'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -36152,7 +36257,7 @@ var IntervalScale = Scale.extend({
 
         if (extent[0] < niceTickExtent[0]) {
             if (expandToNicedExtent) {
-                ticks.push(roundNumber(niceTickExtent[0] - interval));
+                ticks.push(roundNumber(niceTickExtent[0] - interval, intervalPrecision));
             }
             else {
                 ticks.push(extent[0]);
@@ -36178,7 +36283,7 @@ var IntervalScale = Scale.extend({
         var lastNiceTick = ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1];
         if (extent[1] > lastNiceTick) {
             if (expandToNicedExtent) {
-                ticks.push(lastNiceTick + interval);
+                ticks.push(roundNumber(lastNiceTick + interval, intervalPrecision));
             }
             else {
                 ticks.push(extent[1]);
@@ -36726,11 +36831,6 @@ function layout(seriesType, ecModel) {
             var value = data.get(valueDim, idx);
             var baseValue = data.get(baseDim, idx);
 
-            // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
-            if (isNaN(value) || isNaN(baseValue)) {
-                continue;
-            }
-
             var sign = value >= 0 ? 'p' : 'n';
             var baseCoord = valueAxisStart;
 
@@ -36763,7 +36863,10 @@ function layout(seriesType, ecModel) {
                 if (Math.abs(width) < barMinHeight) {
                     width = (width < 0 ? -1 : 1) * barMinHeight;
                 }
-                stacked && (lastStackCoords[stackId][baseValue][sign] += width);
+                // Ignore stack from NaN value
+                if (!isNaN(width)) {
+                    stacked && (lastStackCoords[stackId][baseValue][sign] += width);
+                }
             }
             else {
                 var coord = cartesian.dataToPoint([baseValue, value]);
@@ -36776,7 +36879,10 @@ function layout(seriesType, ecModel) {
                     // Include zero to has a positive bar
                     height = (height <= 0 ? -1 : 1) * barMinHeight;
                 }
-                stacked && (lastStackCoords[stackId][baseValue][sign] += height);
+                // Ignore stack from NaN value
+                if (!isNaN(height)) {
+                    stacked && (lastStackCoords[stackId][baseValue][sign] += height);
+                }
             }
 
             data.setItemLayout(idx, {
@@ -36804,6 +36910,7 @@ var largeLayout = {
 
         var data = seriesModel.getData();
         var cartesian = seriesModel.coordinateSystem;
+        var coordLayout = cartesian.grid.getRect();
         var baseAxis = cartesian.getBaseAxis();
         var valueAxis = cartesian.getOtherAxis(baseAxis);
         var valueDim = data.mapDimension(valueAxis.dim);
@@ -36823,6 +36930,7 @@ var largeLayout = {
         function progress(params, data) {
             var count = params.count;
             var largePoints = new LargeArr(count * 2);
+            var largeBackgroundPoints = new LargeArr(count * 2);
             var largeDataIndices = new LargeArr(count);
             var dataIndex;
             var coord = [];
@@ -36836,7 +36944,9 @@ var largeLayout = {
 
                 coord = cartesian.dataToPoint(valuePair, null, coord);
                 // Data index might not be in order, depends on `progressiveChunkMode`.
+                largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coordLayout.x + coordLayout.width : coord[0];
                 largePoints[pointsOffset++] = coord[0];
+                largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coord[1] : coordLayout.y + coordLayout.height;
                 largePoints[pointsOffset++] = coord[1];
                 largeDataIndices[idxOffset++] = dataIndex;
             }
@@ -36844,8 +36954,10 @@ var largeLayout = {
             data.setLayout({
                 largePoints: largePoints,
                 largeDataIndices: largeDataIndices,
+                largeBackgroundPoints: largeBackgroundPoints,
                 barWidth: barWidth,
                 valueAxisStart: getValueAxisStart(baseAxis, valueAxis, false),
+                backgroundStart: valueAxisHorizontal ? coordLayout.x : coordLayout.y,
                 valueAxisHorizontal: valueAxisHorizontal
             });
         }
@@ -41082,6 +41194,117 @@ function layout$1(gridModel, axisModel, opt) {
 * under the License.
 */
 
+function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) {
+    var axis = axisModel.axis;
+
+    if (axis.scale.isBlank()) {
+        return;
+    }
+
+    var splitAreaModel = axisModel.getModel('splitArea');
+    var areaStyleModel = splitAreaModel.getModel('areaStyle');
+    var areaColors = areaStyleModel.get('color');
+
+    var gridRect = gridModel.coordinateSystem.getRect();
+
+    var ticksCoords = axis.getTicksCoords({
+        tickModel: splitAreaModel,
+        clamp: true
+    });
+
+    if (!ticksCoords.length) {
+        return;
+    }
+
+    // For Making appropriate splitArea animation, the color and anid
+    // should be corresponding to previous one if possible.
+    var areaColorsLen = areaColors.length;
+    var lastSplitAreaColors = axisView.__splitAreaColors;
+    var newSplitAreaColors = createHashMap();
+    var colorIndex = 0;
+    if (lastSplitAreaColors) {
+        for (var i = 0; i < ticksCoords.length; i++) {
+            var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
+            if (cIndex != null) {
+                colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
+                break;
+            }
+        }
+    }
+
+    var prev = axis.toGlobalCoord(ticksCoords[0].coord);
+
+    var areaStyle = areaStyleModel.getAreaStyle();
+    areaColors = isArray(areaColors) ? areaColors : [areaColors];
+
+    for (var i = 1; i < ticksCoords.length; i++) {
+        var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
+
+        var x;
+        var y;
+        var width;
+        var height;
+        if (axis.isHorizontal()) {
+            x = prev;
+            y = gridRect.y;
+            width = tickCoord - x;
+            height = gridRect.height;
+            prev = x + width;
+        }
+        else {
+            x = gridRect.x;
+            y = prev;
+            width = gridRect.width;
+            height = tickCoord - y;
+            prev = y + height;
+        }
+
+        var tickValue = ticksCoords[i - 1].tickValue;
+        tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
+
+        axisGroup.add(new Rect({
+            anid: tickValue != null ? 'area_' + tickValue : null,
+            shape: {
+                x: x,
+                y: y,
+                width: width,
+                height: height
+            },
+            style: defaults({
+                fill: areaColors[colorIndex]
+            }, areaStyle),
+            silent: true
+        }));
+
+        colorIndex = (colorIndex + 1) % areaColorsLen;
+    }
+
+    axisView.__splitAreaColors = newSplitAreaColors;
+}
+
+function rectCoordAxisHandleRemove(axisView) {
+    axisView.__splitAreaColors = null;
+}
+
+/*
+* 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.
+*/
+
 var axisBuilderAttrs = [
     'axisLine', 'axisTickLabel', 'axisName'
 ];
@@ -41133,7 +41356,7 @@ var CartesianAxisView = AxisView.extend({
     },
 
     remove: function () {
-        this._splitAreaColors = null;
+        rectCoordAxisHandleRemove(this);
     },
 
     /**
@@ -41265,91 +41488,7 @@ var CartesianAxisView = AxisView.extend({
      * @private
      */
     _splitArea: function (axisModel, gridModel) {
-        var axis = axisModel.axis;
-
-        if (axis.scale.isBlank()) {
-            return;
-        }
-
-        var splitAreaModel = axisModel.getModel('splitArea');
-        var areaStyleModel = splitAreaModel.getModel('areaStyle');
-        var areaColors = areaStyleModel.get('color');
-
-        var gridRect = gridModel.coordinateSystem.getRect();
-
-        var ticksCoords = axis.getTicksCoords({
-            tickModel: splitAreaModel,
-            clamp: true
-        });
-
-        if (!ticksCoords.length) {
-            return;
-        }
-
-        // For Making appropriate splitArea animation, the color and anid
-        // should be corresponding to previous one if possible.
-        var areaColorsLen = areaColors.length;
-        var lastSplitAreaColors = this._splitAreaColors;
-        var newSplitAreaColors = createHashMap();
-        var colorIndex = 0;
-        if (lastSplitAreaColors) {
-            for (var i = 0; i < ticksCoords.length; i++) {
-                var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
-                if (cIndex != null) {
-                    colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
-                    break;
-                }
-            }
-        }
-
-        var prev = axis.toGlobalCoord(ticksCoords[0].coord);
-
-        var areaStyle = areaStyleModel.getAreaStyle();
-        areaColors = isArray(areaColors) ? areaColors : [areaColors];
-
-        for (var i = 1; i < ticksCoords.length; i++) {
-            var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
-
-            var x;
-            var y;
-            var width;
-            var height;
-            if (axis.isHorizontal()) {
-                x = prev;
-                y = gridRect.y;
-                width = tickCoord - x;
-                height = gridRect.height;
-                prev = x + width;
-            }
-            else {
-                x = gridRect.x;
-                y = prev;
-                width = gridRect.width;
-                height = tickCoord - y;
-                prev = y + height;
-            }
-
-            var tickValue = ticksCoords[i - 1].tickValue;
-            tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
-
-            this._axisGroup.add(new Rect({
-                anid: tickValue != null ? 'area_' + tickValue : null,
-                shape: {
-                    x: x,
-                    y: y,
-                    width: width,
-                    height: height
-                },
-                style: defaults({
-                    fill: areaColors[colorIndex]
-                }, areaStyle),
-                silent: true
-            }));
-
-            colorIndex = (colorIndex + 1) % areaColorsLen;
-        }
-
-        this._splitAreaColors = newSplitAreaColors;
+        rectCoordAxisBuildSplitArea(this, this._axisGroup, axisModel, gridModel);
     }
 });
 
@@ -41595,7 +41734,21 @@ BaseBarSeries.extend({
 
         // If use caps on two sides of bars
         // Only available on tangential polar bar
-        roundCap: false
+        roundCap: false,
+
+        showBackground: false,
+        backgroundStyle: {
+            color: 'rgba(180, 180, 180, 0.2)',
+            borderColor: null,
+            borderWidth: 0,
+            borderType: 'solid',
+            borderRadius: 0,
+            shadowBlur: 0,
+            shadowColor: null,
+            shadowOffsetX: 0,
+            shadowOffsetY: 0,
+            opacity: 1
+        }
     }
 });
 
@@ -41900,15 +42053,28 @@ extendChartView({
 
         var roundCap = seriesModel.get('roundCap', true);
 
+        var drawBackground = seriesModel.get('showBackground', true);
+        var backgroundModel = seriesModel.getModel('backgroundStyle');
+
+        var bgEls = [];
+        var oldBgEls = this._backgroundEls || [];
+
         data.diff(oldData)
             .add(function (dataIndex) {
+                var itemModel = data.getItemModel(dataIndex);
+                var layout = getLayout[coord.type](data, dataIndex, itemModel);
+
+                if (drawBackground) {
+                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, layout);
+                    bgEl.useStyle(backgroundModel.getBarItemStyle());
+                    bgEls[dataIndex] = bgEl;
+                }
+
+                // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
                 if (!data.hasValue(dataIndex)) {
                     return;
                 }
 
-                var itemModel = data.getItemModel(dataIndex);
-                var layout = getLayout[coord.type](data, dataIndex, itemModel);
-
                 if (needsClip) {
                     // Clip will modify the layout params.
                     // And return a boolean to determine if the shape are fully clipped.
@@ -41931,16 +42097,24 @@ extendChartView({
                 );
             })
             .update(function (newIndex, oldIndex) {
-                var el = oldData.getItemGraphicEl(oldIndex);
+                var itemModel = data.getItemModel(newIndex);
+                var layout = getLayout[coord.type](data, newIndex, itemModel);
+
+                if (drawBackground) {
+                    var bgEl = oldBgEls[oldIndex];
+                    bgEl.useStyle(backgroundModel.getBarItemStyle());
+                    bgEls[newIndex] = bgEl;
 
+                    var shape = createBackgroundShape(isHorizontalOrRadial, layout, coord);
+                    updateProps(bgEl, { shape: shape }, animationModel, newIndex);
+                }
+
+                var el = oldData.getItemGraphicEl(oldIndex);
                 if (!data.hasValue(newIndex)) {
                     group.remove(el);
                     return;
                 }
 
-                var itemModel = data.getItemModel(newIndex);
-                var layout = getLayout[coord.type](data, newIndex, itemModel);
-
                 if (needsClip) {
                     var isClipped = clip[coord.type](coordSysClipArea, layout);
                     if (isClipped) {
@@ -41978,6 +42152,15 @@ extendChartView({
             })
             .execute();
 
+        var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group());
+        bgGroup.removeAll();
+
+        for (var i = 0; i < bgEls.length; ++i) {
+            bgGroup.add(bgEls[i]);
+        }
+        group.add(bgGroup);
+        this._backgroundEls = bgEls;
+
         this._data = data;
     },
 
@@ -41998,6 +42181,7 @@ extendChartView({
     },
 
     _incrementalRenderLarge: function (params, seriesModel) {
+        this._removeBackground();
         createLarge(seriesModel, this.group, true);
     },
 
@@ -42011,6 +42195,9 @@ extendChartView({
         var group = this.group;
         var data = this._data;
         if (ecModel && ecModel.get('animation') && data && !this._isLargeDraw) {
+            this._removeBackground();
+            this._backgroundEls = [];
+
             data.eachItemGraphicEl(function (el) {
                 if (el.type === 'sector') {
                     removeSector(el.dataIndex, ecModel, el);
@@ -42024,6 +42211,11 @@ extendChartView({
             group.removeAll();
         }
         this._data = null;
+    },
+
+    _removeBackground: function () {
+        this.group.remove(this._backgroundGroup);
+        this._backgroundGroup = null;
     }
 
 });
@@ -42081,7 +42273,12 @@ var elementCreator = {
         dataIndex, layout, isHorizontal,
         animationModel, isUpdate
     ) {
-        var rect = new Rect({shape: extend({}, layout)});
+        var rect = new Rect({
+            shape: extend({}, layout),
+            z2: 1
+        });
+
+        rect.name = 'item';
 
         // Animation
         if (animationModel) {
@@ -42111,9 +42308,12 @@ var elementCreator = {
         var ShapeClass = (!isRadial && roundCap) ? Sausage : Sector;
 
         var sector = new ShapeClass({
-            shape: defaults({clockwise: clockwise}, layout)
+            shape: defaults({clockwise: clockwise}, layout),
+            z2: 1
         });
 
+        sector.name = 'item';
+
         // Animation
         if (animationModel) {
             var sectorShape = sector.shape;
@@ -42233,7 +42433,10 @@ function updateStyle(
 // In case width or height are too small.
 function getLineWidth(itemModel, rawLayout) {
     var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
-    return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height));
+    // width or height may be NaN for empty data
+    var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width);
+    var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height);
+    return Math.min(lineWidth, width, height);
 }
 
 
@@ -42265,13 +42468,38 @@ function createLarge(seriesModel, group, incremental) {
     var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
     startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart');
 
+    var largeDataIndices = data.getLayout('largeDataIndices');
+    var barWidth = data.getLayout('barWidth');
+
+    var backgroundModel = seriesModel.getModel('backgroundStyle');
+    var drawBackground = seriesModel.get('showBackground', true);
+
+    if (drawBackground) {
+        var points = data.getLayout('largeBackgroundPoints');
+        var backgroundStartPoint = [];
+        backgroundStartPoint[1 - baseDimIdx] = data.getLayout('backgroundStart');
+
+        var bgEl = new LargePath({
+            shape: {points: points},
+            incremental: !!incremental,
+            __startPoint: backgroundStartPoint,
+            __baseDimIdx: baseDimIdx,
+            __largeDataIndices: largeDataIndices,
+            __barWidth: barWidth,
+            silent: true,
+            z2: 0
+        });
+        setLargeBackgroundStyle(bgEl, backgroundModel, data);
+        group.add(bgEl);
+    }
+
     var el = new LargePath({
         shape: {points: data.getLayout('largePoints')},
         incremental: !!incremental,
         __startPoint: startPoint,
         __baseDimIdx: baseDimIdx,
-        __largeDataIndices: data.getLayout('largeDataIndices'),
-        __barWidth: data.getLayout('barWidth')
+        __largeDataIndices: largeDataIndices,
+        __barWidth: barWidth
     });
     group.add(el);
     setLargeStyle(el, seriesModel, data);
@@ -42336,6 +42564,55 @@ function setLargeStyle(el, seriesModel, data) {
     el.style.lineWidth = data.getLayout('barWidth');
 }
 
+function setLargeBackgroundStyle(el, backgroundModel, data) {
+    var borderColor = backgroundModel.get('borderColor') || backgroundModel.get('color');
+    var itemStyle = backgroundModel.getItemStyle(['color', 'borderColor']);
+
+    el.useStyle(itemStyle);
+    el.style.fill = null;
+    el.style.stroke = borderColor;
+    el.style.lineWidth = data.getLayout('barWidth');
+}
+
+function createBackgroundShape(isHorizontalOrRadial, layout, coord) {
+    var coordLayout;
+    var isPolar = coord.type === 'polar';
+    if (isPolar) {
+        coordLayout = coord.getArea();
+    }
+    else {
+        coordLayout = coord.grid.getRect();
+    }
+
+    if (isPolar) {
+        return {
+            cx: coordLayout.cx,
+            cy: coordLayout.cy,
+            r0: isHorizontalOrRadial ? coordLayout.r0 : layout.r0,
+            r: isHorizontalOrRadial ? coordLayout.r : layout.r,
+            startAngle: isHorizontalOrRadial ? layout.startAngle : 0,
+            endAngle: isHorizontalOrRadial ? layout.endAngle : Math.PI * 2
+        };
+    }
+    else {
+        return {
+            x: isHorizontalOrRadial ? layout.x : coordLayout.x,
+            y: isHorizontalOrRadial ? coordLayout.y : layout.y,
+            width: isHorizontalOrRadial ? layout.width : coordLayout.width,
+            height: isHorizontalOrRadial ? coordLayout.height : layout.height
+        };
+    }
+}
+
+function createBackgroundEl(coord, isHorizontalOrRadial, layout) {
+    var ElementClz = coord.type === 'polar' ? Sector : Rect;
+    return new ElementClz({
+        shape: createBackgroundShape(isHorizontalOrRadial, layout, coord),
+        silent: true,
+        z2: 0
+    });
+}
+
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -42945,7 +43222,7 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
     toggleItemSelected(
         this,
         data.getItemLayout(idx),
-        seriesModel.isSelected(null, idx),
+        seriesModel.isSelected(data.getName(idx)),
         seriesModel.get('selectedOffset'),
         seriesModel.get('animation')
     );
@@ -43697,7 +43974,7 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, viewLeft, vie
             inside: isLabelInside,
             labelDistance: labelDistance,
             labelAlignTo: labelAlignTo,
-            labelMargin:labelMargin,
+            labelMargin: labelMargin,
             bleedMargin: bleedMargin,
             textRect: textRect,
             text: text,
diff --git a/en/dist/echarts-en.simple.min.js b/en/dist/echarts-en.simple.min.js
index 4e2af9b..f289ecd 100644
--- a/en/dist/echarts-en.simple.min.js
+++ b/en/dist/echarts-en.simple.min.js
@@ -19,4 +19,4 @@
 */
 
 
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,n=function(){return e++},m="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasS [...]
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,n=function(){return e++},m="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasS [...]
diff --git a/en/dist/echarts.common.js b/en/dist/echarts.common.js
index 2c53f99..96417af 100644
--- a/en/dist/echarts.common.js
+++ b/en/dist/echarts.common.js
@@ -1285,7 +1285,11 @@ Draggable.prototype = {
 
     _dragStart: function (e) {
         var draggingTarget = e.target;
-        if (draggingTarget && draggingTarget.draggable) {
+        // Find if there is draggable in the ancestor
+        while (draggingTarget && !draggingTarget.draggable) {
+            draggingTarget = draggingTarget.parent;
+        }
+        if (draggingTarget) {
             this._draggingTarget = draggingTarget;
             draggingTarget.dragging = true;
             this._x = e.offsetX;
@@ -1714,6 +1718,8 @@ function buildTransformer(src, dest) {
     var detCache = {};
     var det = determinant(mA, 8, 0, 0, 0, detCache);
     if (det === 0) {
+        // can not make transformer when and only when
+        // any three of the markers are collinear.
         return;
     }
 
@@ -1736,6 +1742,153 @@ function buildTransformer(src, dest) {
     };
 }
 
+var EVENT_SAVED_PROP = '___zrEVENTSAVED';
+var _calcOut$1 = [];
+
+/**
+ * Transform "local coord" from `elFrom` to `elTarget`.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support when CSS transform is used.
+ *
+ * Having the `out` (that is, `[outX, outY]`), we can create an DOM element
+ * and set the CSS style as "left: outX; top: outY;" and append it to `elTarge`
+ * to locate the element.
+ *
+ * For example, this code below positions a child of `document.body` on the event
+ * point, no matter whether `body` has `margin`/`paddin`/`transfrom`/... :
+ * ```js
+ * transformLocalCoord(out, container, document.body, event.offsetX, event.offsetY);
+ * if (!eqNaN(out[0])) {
+ *     // Then locate the tip element on the event point.
+ *     var tipEl = document.createElement('div');
+ *     tipEl.style.cssText = 'position: absolute; left:' + out[0] + ';top:' + out[1] + ';';
+ *     document.body.appendChild(tipEl);
+ * }
+ * ```
+ *
+ * Notice: In some env this method is not supported. If called, `out` will be `[NaN, NaN]`.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output..
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} elFrom The `[inX, inY]` is based on elFrom.
+ * @param {HTMLElement} elTarget The `out` is based on elTarget.
+ * @param {number} inX
+ * @param {number} inY
+ * @return {boolean} Whether transform successfully.
+ */
+function transformLocalCoord(out, elFrom, elTarget, inX, inY) {
+    return transformCoordWithViewport(_calcOut$1, elFrom, inX, inY, true)
+        && transformCoordWithViewport(out, elTarget, _calcOut$1[0], _calcOut$1[1]);
+}
+
+/**
+ * Transform between a "viewport coord" and a "local coord".
+ * "viewport coord": the coord based on the left-top corner of the viewport
+ *     of the browser.
+ * "local coord": the coord based on the input `el`. The origin point is at
+ *     the position of "left: 0; top: 0;" in the `el`.
+ *
+ * Support the case when CSS transform is used on el.
+ *
+ * @param {Array.<number>} out [inX: number, inY: number] The output. If `inverse: false`,
+ *        it represents "local coord", otherwise "vireport coord".
+ *        If can not transform, `out` will not be modified but return `false`.
+ * @param {HTMLElement} el The "local coord" is based on the `el`, see comment above.
+ * @param {number} inX If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {number} inY If `inverse: false`,
+ *        it represents "vireport coord", otherwise "local coord".
+ * @param {boolean} [inverse=false]
+ *        `true`: from "viewport coord" to "local coord".
+ *        `false`: from "local coord" to "viewport coord".
+ * @return {boolean} Whether transform successfully.
+ */
+function transformCoordWithViewport(out, el, inX, inY, inverse) {
+    if (el.getBoundingClientRect && env$1.domSupported && !isCanvasEl(el)) {
+        var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
+        var markers = prepareCoordMarkers(el, saved);
+        var transformer = preparePointerTransformer(markers, saved, inverse);
+        if (transformer) {
+            transformer(out, inX, inY);
+            return true;
+        }
+    }
+    return false;
+}
+
+function prepareCoordMarkers(el, saved) {
+    var markers = saved.markers;
+    if (markers) {
+        return markers;
+    }
+
+    markers = saved.markers = [];
+    var propLR = ['left', 'right'];
+    var propTB = ['top', 'bottom'];
+
+    for (var i = 0; i < 4; i++) {
+        var marker = document.createElement('div');
+        var stl = marker.style;
+        var idxLR = i % 2;
+        var idxTB = (i >> 1) % 2;
+        stl.cssText = [
+            'position: absolute',
+            'visibility: hidden',
+            'padding: 0',
+            'margin: 0',
+            'border-width: 0',
+            'user-select: none',
+            'width:0',
+            'height:0',
+            // 'width: 5px',
+            // 'height: 5px',
+            propLR[idxLR] + ':0',
+            propTB[idxTB] + ':0',
+            propLR[1 - idxLR] + ':auto',
+            propTB[1 - idxTB] + ':auto',
+            ''
+        ].join('!important;');
+        el.appendChild(marker);
+        markers.push(marker);
+    }
+
+    return markers;
+}
+
+function preparePointerTransformer(markers, saved, inverse) {
+    var transformerName = inverse ? 'invTrans' : 'trans';
+    var transformer = saved[transformerName];
+    var oldSrcCoords = saved.srcCoords;
+    var oldCoordTheSame = true;
+    var srcCoords = [];
+    var destCoords = [];
+
+    for (var i = 0; i < 4; i++) {
+        var rect = markers[i].getBoundingClientRect();
+        var ii = 2 * i;
+        var x = rect.left;
+        var y = rect.top;
+        srcCoords.push(x, y);
+        oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
+        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
+    }
+    // Cache to avoid time consuming of `buildTransformer`.
+    return (oldCoordTheSame && transformer)
+        ? transformer
+        : (
+            saved.srcCoords = srcCoords,
+            saved[transformerName] = inverse
+                ? buildTransformer(destCoords, srcCoords)
+                : buildTransformer(srcCoords, destCoords)
+        );
+}
+
+function isCanvasEl(el) {
+    return el.nodeName.toUpperCase() === 'CANVAS';
+}
+
 /**
  * Utilities for mouse or touch events.
  */
@@ -1743,7 +1896,6 @@ function buildTransformer(src, dest) {
 var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener;
 
 var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
-var EVENT_SAVED_PROP = '___zrEVENTSAVED';
 var _calcOut = [];
 
 /**
@@ -1808,11 +1960,11 @@ function clientToLocal(el, e, out, calculate) {
 
 function calculateZrXY(el, e, out) {
     // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect.
-    if (el.getBoundingClientRect && env$1.domSupported) {
+    if (env$1.domSupported && el.getBoundingClientRect) {
         var ex = e.clientX;
         var ey = e.clientY;
 
-        if (el.nodeName.toUpperCase() === 'CANVAS') {
+        if (isCanvasEl(el)) {
             // Original approach, which do not support CSS transform.
             // marker can not be locationed in a canvas container
             // (getBoundingClientRect is always 0). We do not support
@@ -1824,10 +1976,7 @@ function calculateZrXY(el, e, out) {
             return;
         }
         else {
-            var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
-            var transformer = preparePointerTransformer(prepareCoordMarkers(el, saved), saved);
-            if (transformer) {
-                transformer(_calcOut, ex, ey);
+            if (transformCoordWithViewport(_calcOut, el, ex, ey)) {
                 out.zrX = _calcOut[0];
                 out.zrY = _calcOut[1];
                 return;
@@ -1837,70 +1986,6 @@ function calculateZrXY(el, e, out) {
     out.zrX = out.zrY = 0;
 }
 
-function prepareCoordMarkers(el, saved) {
-    var markers = saved.markers;
-    if (markers) {
-        return markers;
-    }
-
-    markers = saved.markers = [];
-    var propLR = ['left', 'right'];
-    var propTB = ['top', 'bottom'];
-
-    for (var i = 0; i < 4; i++) {
-        var marker = document.createElement('div');
-        var stl = marker.style;
-        var idxLR = i % 2;
-        var idxTB = (i >> 1) % 2;
-        stl.cssText = [
-            'position:absolute',
-            'visibility: hidden',
-            'padding: 0',
-            'margin: 0',
-            'border-width: 0',
-            'width:0',
-            'height:0',
-            // 'width: 5px',
-            // 'height: 5px',
-            propLR[idxLR] + ':0',
-            propTB[idxTB] + ':0',
-            propLR[1 - idxLR] + ':auto',
-            propTB[1 - idxTB] + ':auto',
-            ''
-        ].join('!important;');
-        el.appendChild(marker);
-        markers.push(marker);
-    }
-
-    return markers;
-}
-
-function preparePointerTransformer(markers, saved) {
-    var transformer = saved.transformer;
-    var oldSrcCoords = saved.srcCoords;
-    var useOld = true;
-    var srcCoords = [];
-    var destCoords = [];
-
-    for (var i = 0; i < 4; i++) {
-        var rect = markers[i].getBoundingClientRect();
-        var ii = 2 * i;
-        var x = rect.left;
-        var y = rect.top;
-        srcCoords.push(x, y);
-        useOld &= oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
-        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
-    }
-
-    // Cache to avoid time consuming of `buildTransformer`.
-    return useOld
-        ? transformer
-        : (
-            saved.srcCoords = srcCoords,
-            saved.transformer = buildTransformer(srcCoords, destCoords)
-        );
-}
-
 /**
  * Find native event compat for legency IE.
  * Should be called at the begining of a native event listener.
@@ -4770,7 +4855,7 @@ var Animator = function (target, loop, getter, setter) {
 
 Animator.prototype = {
     /**
-     * 设置动画关键帧
+     * Set Animation keyframe
      * @param  {number} time 关键帧时间,单位是ms
      * @param  {Object} props 关键帧的属性值,key-value表示
      * @return {module:zrender/animation/Animator}
@@ -4849,7 +4934,7 @@ Animator.prototype = {
         }
     },
     /**
-     * 开始执行动画
+     * Start the animation
      * @param  {string|Function} [easing]
      *         动画缓动函数,详见{@link module:zrender/animation/easing}
      * @param  {boolean} forceAnimate
@@ -4910,7 +4995,7 @@ Animator.prototype = {
         return this;
     },
     /**
-     * 停止动画
+     * Stop animation
      * @param {boolean} forwardToLast If move to last frame before stop
      */
     stop: function (forwardToLast) {
@@ -4927,7 +5012,7 @@ Animator.prototype = {
         clipList.length = 0;
     },
     /**
-     * 设置动画延迟开始的时间
+     * Set when animation delay starts
      * @param  {number} time 单位ms
      * @return {module:zrender/animation/Animator}
      */
@@ -4936,7 +5021,7 @@ Animator.prototype = {
         return this;
     },
     /**
-     * 添加动画结束的回调
+     * Add callback for animation end
      * @param  {Function} cb
      * @return {module:zrender/animation/Animator}
      */
@@ -4988,7 +5073,7 @@ if (debugMode === 1) {
 var logError$1 = logError;
 
 /**
- * @alias modue:zrender/mixin/Animatable
+ * @alias module:zrender/mixin/Animatable
  * @constructor
  */
 var Animatable = function () {
@@ -10666,7 +10751,7 @@ Painter.prototype = {
 };
 
 /**
- * 动画主类, 调度和管理所有动画控制器
+ * Animation main class, dispatch and manage all animation controllers
  *
  * @module zrender/animation/Animation
  * @author pissang(https://github.com/pissang)
@@ -10731,14 +10816,14 @@ Animation.prototype = {
 
     constructor: Animation,
     /**
-     * 添加 clip
+     * Add clip
      * @param {module:zrender/animation/Clip} clip
      */
     addClip: function (clip) {
         this._clips.push(clip);
     },
     /**
-     * 添加 animator
+     * Add animator
      * @param {module:zrender/animation/Animator} animator
      */
     addAnimator: function (animator) {
@@ -10749,7 +10834,7 @@ Animation.prototype = {
         }
     },
     /**
-     * 删除动画片段
+     * Delete animation clip
      * @param {module:zrender/animation/Clip} clip
      */
     removeClip: function (clip) {
@@ -10760,7 +10845,7 @@ Animation.prototype = {
     },
 
     /**
-     * 删除动画片段
+     * Delete animation clip
      * @param {module:zrender/animation/Animator} animator
      */
     removeAnimator: function (animator) {
@@ -11027,13 +11112,16 @@ function normalizeGlobalEvent(instance, event) {
  * Detect whether the given el is in `painterRoot`.
  */
 function isLocalEl(instance, el) {
+    var elTmp = el;
     var isLocal = false;
-    do {
-        el = el && el.parentNode;
+    while (elTmp && elTmp.nodeType !== 9
+        && !(
+            isLocal = elTmp.domBelongToZr
+                || (elTmp !== el && elTmp === instance.painterRoot)
+        )
+    ) {
+        elTmp = elTmp.parentNode;
     }
-    while (el && el.nodeType !== 9 && !(
-        isLocal = el === instance.painterRoot
-    ));
     return isLocal;
... 28725 lines suppressed ...


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