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/08/31 20:06:43 UTC

[incubator-echarts-website] branch asf-site updated: release 4.9.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 dbe0e8f  release 4.9.0
dbe0e8f is described below

commit dbe0e8fd65f31f52f86a7cebf37653a96d0933b8
Author: 100pah <su...@gmail.com>
AuthorDate: Tue Sep 1 04:06:19 2020 +0800

    release 4.9.0
---
 components/builder.html                            |    8 +-
 components/download.html                           |    8 +-
 en/404.html                                        |    4 +-
 en/api.html                                        |    8 +-
 en/builder.html                                    |    8 +-
 en/builder/echarts.html                            |    2 +-
 en/builder/src/echarts/chart/bar/BarView.js        |   65 +-
 .../src/echarts/chart/bar/PictorialBarSeries.js    |    2 +-
 .../src/echarts/chart/funnel/FunnelSeries.js       |    1 +
 .../src/echarts/chart/funnel/funnelLayout.js       |  205 +++-
 en/builder/src/echarts/chart/graph/GraphSeries.js  |   10 +-
 .../echarts/chart/graph/circularLayoutHelper.js    |    6 +-
 en/builder/src/echarts/chart/graph/forceLayout.js  |    4 +-
 en/builder/src/echarts/chart/graph/simpleLayout.js |    2 +-
 .../src/echarts/chart/graph/simpleLayoutHelper.js  |   10 +-
 en/builder/src/echarts/chart/helper/Line.js        |   44 +-
 en/builder/src/echarts/chart/helper/Symbol.js      |    2 +-
 .../chart/helper/multipleGraphEdgeHelper.js        |  231 ++++
 en/builder/src/echarts/chart/lines/LinesSeries.js  |    2 -
 en/builder/src/echarts/chart/map/MapSeries.js      |    5 +-
 en/builder/src/echarts/chart/radar/RadarSeries.js  |    7 +-
 en/builder/src/echarts/chart/radar/RadarView.js    |    4 +-
 .../src/echarts/chart/sunburst/SunburstPiece.js    |    5 +-
 .../src/echarts/chart/sunburst/SunburstSeries.js   |   21 +-
 .../echarts/chart/themeRiver/ThemeRiverSeries.js   |   51 +-
 en/builder/src/echarts/chart/tree/TreeSeries.js    |    2 +-
 en/builder/src/echarts/chart/tree/TreeView.js      |    8 +-
 .../src/echarts/chart/treemap/TreemapSeries.js     |   19 +-
 .../src/echarts/chart/treemap/treemapLayout.js     |    2 +-
 .../src/echarts/chart/treemap/treemapVisual.js     |   24 +-
 .../echarts/component/axisPointer/axisTrigger.js   |    2 +-
 .../component/legend/ScrollableLegendView.js       |    2 +-
 .../src/echarts/component/marker/MarkAreaView.js   |   68 +-
 .../src/echarts/component/marker/MarkLineView.js   |    3 +
 .../src/echarts/component/marker/MarkPointView.js  |    9 +-
 .../src/echarts/component/marker/MarkerModel.js    |    5 +-
 .../component/timeline/SliderTimelineView.js       |    8 +-
 en/builder/src/echarts/component/title.js          |    2 +-
 .../echarts/component/toolbox/feature/DataView.js  |   31 +-
 .../echarts/component/toolbox/feature/DataZoom.js  |   12 +-
 .../component/toolbox/feature/SaveAsImage.js       |    3 +-
 .../echarts/component/tooltip/TooltipContent.js    |   50 +-
 .../component/tooltip/TooltipRichContent.js        |   64 +-
 .../src/echarts/component/tooltip/TooltipView.js   |    8 +-
 .../echarts/component/visualMap/VisualMapModel.js  |    2 +-
 en/builder/src/echarts/coord/axisDefault.js        |    2 +-
 en/builder/src/echarts/coord/axisHelper.js         |    4 +-
 en/builder/src/echarts/coord/geo/GeoModel.js       |    3 +-
 en/builder/src/echarts/data/Graph.js               |    7 +-
 en/builder/src/echarts/data/List.js                |    2 +-
 en/builder/src/echarts/data/Tree.js                |   34 +-
 en/builder/src/echarts/echarts.js                  |    4 +-
 en/builder/src/echarts/layout/barPolar.js          |    2 +-
 en/builder/src/echarts/processor/dataSample.js     |    2 +-
 en/builder/src/echarts/stream/Scheduler.js         |    2 +-
 en/builder/src/echarts/visual/VisualMapping.js     |    2 +-
 en/builder/src/zrender/animation/track.js          |    4 -
 .../src/zrender/svg/helper/GradientManager.js      |    2 +-
 en/builder/src/zrender/zrender.js                  |    2 +-
 en/changelog.html                                  |   53 +-
 en/cheat-sheet.html                                |    6 +-
 en/coding-standard.html                            |    4 +-
 en/committers.html                                 |    4 +-
 en/contributing.html                               |    4 +-
 en/dependencies.html                               |    4 +-
 en/dist/echarts-en.common.js                       |  377 +++++--
 en/dist/echarts-en.common.min.js                   |    2 +-
 en/dist/echarts-en.js                              | 1100 +++++++++++++++-----
 en/dist/echarts-en.js.map                          |    2 +-
 en/dist/echarts-en.min.js                          |    2 +-
 en/dist/echarts-en.simple.js                       |   86 +-
 en/dist/echarts-en.simple.min.js                   |    2 +-
 en/dist/echarts.common.js                          |  377 +++++--
 en/dist/echarts.common.min.js                      |    2 +-
 en/dist/echarts.js                                 | 1100 +++++++++++++++-----
 en/dist/echarts.js.map                             |    2 +-
 en/dist/echarts.min.js                             |    2 +-
 en/dist/echarts.simple.js                          |   86 +-
 en/dist/echarts.simple.min.js                      |    2 +-
 en/dist/extension/bmap.js                          |  378 +------
 en/dist/extension/bmap.js.map                      |    2 +-
 en/dist/extension/bmap.min.js                      |    2 +-
 en/dist/extension/dataTool.js.map                  |    2 +-
 en/documents/option-parts/option-outline.js        |    2 +-
 en/documents/option-parts/option-outline.json      |    2 +-
 en/documents/option-parts/option.series-funnel.js  |   11 +-
 .../option-parts/option.series-funnel.json         |   11 +-
 en/documents/option-parts/option.series-graph.js   |    3 +
 en/documents/option-parts/option.series-graph.json |    3 +
 en/documents/option-parts/option.toolbox.js        |   74 ++
 en/documents/option-parts/option.toolbox.json      |   74 ++
 en/documents/option.json                           |    2 +-
 en/download-extension.html                         |    4 +-
 en/download-map.html                               |    4 +-
 en/download-theme.html                             |    4 +-
 en/download.html                                   |    4 +-
 en/faq.html                                        |    4 +-
 en/feature.html                                    |    4 +-
 en/index.html                                      |    6 +-
 en/js/download.js                                  |    2 +-
 en/maillist.html                                   |    4 +-
 en/option-gl.html                                  |    8 +-
 en/option.html                                     |    8 +-
 en/option3.html                                    |    4 +-
 en/resources.html                                  |    4 +-
 en/security.html                                   |    4 +-
 en/spreadsheet.html                                |   10 +-
 en/theme-builder.html                              |    4 +-
 en/tutorial.html                                   |    8 +-
 examples/data/thumb-dark/calendar-charts.jpg       |  Bin 19456 -> 19395 bytes
 .../data/thumb-dark/calendar-effectscatter.jpg     |  Bin 45020 -> 45005 bytes
 examples/data/thumb-dark/custom-profile.jpg        |  Bin 19289 -> 19121 bytes
 examples/data/thumb-dark/dynamic-data.jpg          |  Bin 23974 -> 24285 bytes
 examples/data/thumb-dark/effectScatter-bmap.jpg    |  Bin 14762 -> 14755 bytes
 examples/data/thumb-dark/effectScatter-map.jpg     |  Bin 18289 -> 18293 bytes
 examples/data/thumb-dark/geo-lines.jpg             |  Bin 13764 -> 13761 bytes
 examples/data/thumb-dark/graph-force.jpg           |  Bin 24193 -> 24172 bytes
 examples/data/thumb-dark/graph-life-expectancy.jpg |  Bin 25279 -> 25276 bytes
 examples/data/thumb-dark/graph-webkit-dep.jpg      |  Bin 46107 -> 45137 bytes
 examples/data/thumb-dark/graph.jpg                 |  Bin 28118 -> 28102 bytes
 examples/data/thumb-dark/map-polygon.jpg           |  Bin 31250 -> 36430 bytes
 examples/data/thumb-dark/mix-timeline-finance.jpg  |  Bin 35302 -> 35242 bytes
 examples/data/thumb-dark/pictorialBar-dotted.jpg   |  Bin 25017 -> 25057 bytes
 .../data/thumb-dark/scatter-clustering-process.jpg |  Bin 21266 -> 21240 bytes
 examples/data/thumb-dark/scatter-effect.jpg        |  Bin 22847 -> 22833 bytes
 .../scatter-life-expectancy-timeline.jpg           |  Bin 17892 -> 17828 bytes
 examples/data/thumb-dark/scatter-nebula.jpg        |  Bin 35267 -> 35325 bytes
 .../data/thumb-dark/scatter-nutrients-matrix.jpg   |  Bin 28133 -> 28135 bytes
 examples/data/thumb-dark/scatter-nutrients.jpg     |  Bin 10796 -> 10809 bytes
 examples/data/thumb-dark/scatter-weibo.jpg         |  Bin 33738 -> 33794 bytes
 examples/data/thumb-light/calendar-charts.jpg      |  Bin 21208 -> 21139 bytes
 .../data/thumb-light/calendar-effectscatter.jpg    |  Bin 45006 -> 44988 bytes
 examples/data/thumb-light/confidence-band.jpg      |  Bin 12817 -> 12846 bytes
 examples/data/thumb-light/custom-profile.jpg       |  Bin 16588 -> 16780 bytes
 examples/data/thumb-light/dynamic-data.jpg         |  Bin 22156 -> 22432 bytes
 examples/data/thumb-light/effectScatter-bmap.jpg   |  Bin 30067 -> 43407 bytes
 examples/data/thumb-light/effectScatter-map.jpg    |  Bin 18303 -> 18308 bytes
 examples/data/thumb-light/geo-lines.jpg            |  Bin 13430 -> 13354 bytes
 examples/data/thumb-light/graph-force.jpg          |  Bin 22238 -> 22215 bytes
 .../data/thumb-light/graph-life-expectancy.jpg     |  Bin 16404 -> 16399 bytes
 examples/data/thumb-light/graph-webkit-dep.jpg     |  Bin 37816 -> 37928 bytes
 examples/data/thumb-light/graph.jpg                |  Bin 24502 -> 24523 bytes
 examples/data/thumb-light/heatmap-bmap.jpg         |  Bin 50397 -> 49953 bytes
 examples/data/thumb-light/lines-bmap-bus.jpg       |  Bin 52867 -> 68632 bytes
 examples/data/thumb-light/lines-bmap.jpg           |  Bin 39366 -> 54690 bytes
 examples/data/thumb-light/map-bin.jpg              |  Bin 43084 -> 43869 bytes
 examples/data/thumb-light/map-polygon.jpg          |  Bin 31598 -> 36899 bytes
 examples/data/thumb-light/mix-timeline-finance.jpg |  Bin 31902 -> 31856 bytes
 examples/data/thumb-light/pictorialBar-dotted.jpg  |  Bin 23766 -> 23805 bytes
 .../thumb-light/scatter-clustering-process.jpg     |  Bin 18141 -> 18092 bytes
 examples/data/thumb-light/scatter-effect.jpg       |  Bin 16885 -> 16870 bytes
 .../scatter-life-expectancy-timeline.jpg           |  Bin 17469 -> 17426 bytes
 examples/data/thumb-light/scatter-nebula.jpg       |  Bin 33232 -> 33221 bytes
 .../data/thumb-light/scatter-nutrients-matrix.jpg  |  Bin 27140 -> 27133 bytes
 examples/data/thumb-light/scatter-nutrients.jpg    |  Bin 10830 -> 10824 bytes
 examples/data/thumb-light/scatter-weibo.jpg        |  Bin 33696 -> 33794 bytes
 examples/data/thumb/calendar-charts.jpg            |  Bin 21272 -> 21221 bytes
 examples/data/thumb/calendar-effectscatter.jpg     |  Bin 45034 -> 45007 bytes
 examples/data/thumb/custom-profile.jpg             |  Bin 16657 -> 16677 bytes
 examples/data/thumb/dynamic-data.jpg               |  Bin 22674 -> 22946 bytes
 examples/data/thumb/effectScatter-bmap.jpg         |  Bin 30061 -> 43356 bytes
 examples/data/thumb/effectScatter-map.jpg          |  Bin 18301 -> 18315 bytes
 examples/data/thumb/geo-lines.jpg                  |  Bin 13339 -> 13348 bytes
 examples/data/thumb/graph-force.jpg                |  Bin 22344 -> 22628 bytes
 examples/data/thumb/graph-life-expectancy.jpg      |  Bin 16442 -> 16423 bytes
 examples/data/thumb/graph-webkit-dep.jpg           |  Bin 41155 -> 40711 bytes
 examples/data/thumb/heatmap-bmap.jpg               |  Bin 50397 -> 49953 bytes
 examples/data/thumb/lines-bmap-bus.jpg             |  Bin 52867 -> 68632 bytes
 examples/data/thumb/lines-bmap.jpg                 |  Bin 39366 -> 54690 bytes
 examples/data/thumb/map-bin.jpg                    |  Bin 43084 -> 43869 bytes
 examples/data/thumb/map-polygon.jpg                |  Bin 31467 -> 36490 bytes
 examples/data/thumb/mix-timeline-finance.jpg       |  Bin 31724 -> 31644 bytes
 examples/data/thumb/pictorialBar-dotted.jpg        |  Bin 24200 -> 24239 bytes
 examples/data/thumb/scatter-clustering-process.jpg |  Bin 18758 -> 18713 bytes
 examples/data/thumb/scatter-effect.jpg             |  Bin 21239 -> 21234 bytes
 .../thumb/scatter-life-expectancy-timeline.jpg     |  Bin 17466 -> 17412 bytes
 examples/data/thumb/scatter-nebula.jpg             |  Bin 33213 -> 33221 bytes
 examples/data/thumb/scatter-nutrients-matrix.jpg   |  Bin 27161 -> 27132 bytes
 examples/data/thumb/scatter-nutrients.jpg          |  Bin 10822 -> 10827 bytes
 examples/en/editor.html                            |    6 +-
 examples/en/index.html                             |    6 +-
 examples/en/view.html                              |    6 +-
 examples/vendors/echarts/echarts.js                | 1100 +++++++++++++++-----
 examples/vendors/echarts/echarts.min.js            |    2 +-
 examples/vendors/echarts/extension/bmap.js         |  378 +------
 examples/vendors/echarts/extension/bmap.js.map     |    2 +-
 examples/vendors/echarts/extension/bmap.min.js     |    2 +-
 examples/vendors/echarts/extension/dataTool.js.map |    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                                   |    8 +-
 layouts/next-doc.html                              |    8 +-
 layouts/next-example-simple.html                   |    8 +-
 layouts/next-example.html                          |    8 +-
 manually-redirect.html                             |    2 +-
 next/en/api.html                                   |    8 +-
 next/en/option-gl.html                             |    8 +-
 next/en/option.html                                |    8 +-
 next/en/tutorial.html                              |    8 +-
 next/examples/en/editor.html                       |    8 +-
 next/examples/en/index.html                        |    8 +-
 next/examples/en/view.html                         |    8 +-
 next/examples/zh/editor.html                       |    8 +-
 next/examples/zh/index.html                        |    8 +-
 next/examples/zh/view.html                         |    8 +-
 next/zh/api.html                                   |    8 +-
 next/zh/option-gl.html                             |    8 +-
 next/zh/option.html                                |    8 +-
 next/zh/tutorial.html                              |    8 +-
 zh/404.html                                        |    4 +-
 zh/api.html                                        |    8 +-
 zh/builder.html                                    |    8 +-
 zh/builder/echarts.html                            |    2 +-
 zh/builder/src/echarts/chart/bar/BarView.js        |   65 +-
 .../src/echarts/chart/bar/PictorialBarSeries.js    |    2 +-
 .../src/echarts/chart/funnel/FunnelSeries.js       |    1 +
 .../src/echarts/chart/funnel/funnelLayout.js       |  205 +++-
 zh/builder/src/echarts/chart/graph/GraphSeries.js  |   10 +-
 .../echarts/chart/graph/circularLayoutHelper.js    |    6 +-
 zh/builder/src/echarts/chart/graph/forceLayout.js  |    4 +-
 zh/builder/src/echarts/chart/graph/simpleLayout.js |    2 +-
 .../src/echarts/chart/graph/simpleLayoutHelper.js  |   10 +-
 zh/builder/src/echarts/chart/helper/Line.js        |   44 +-
 zh/builder/src/echarts/chart/helper/Symbol.js      |    2 +-
 .../chart/helper/multipleGraphEdgeHelper.js        |  231 ++++
 zh/builder/src/echarts/chart/lines/LinesSeries.js  |    2 -
 zh/builder/src/echarts/chart/map/MapSeries.js      |    5 +-
 zh/builder/src/echarts/chart/radar/RadarSeries.js  |    7 +-
 zh/builder/src/echarts/chart/radar/RadarView.js    |    4 +-
 .../src/echarts/chart/sunburst/SunburstPiece.js    |    5 +-
 .../src/echarts/chart/sunburst/SunburstSeries.js   |   21 +-
 .../echarts/chart/themeRiver/ThemeRiverSeries.js   |   51 +-
 zh/builder/src/echarts/chart/tree/TreeSeries.js    |    2 +-
 zh/builder/src/echarts/chart/tree/TreeView.js      |    8 +-
 .../src/echarts/chart/treemap/TreemapSeries.js     |   19 +-
 .../src/echarts/chart/treemap/treemapLayout.js     |    2 +-
 .../src/echarts/chart/treemap/treemapVisual.js     |   24 +-
 .../echarts/component/axisPointer/axisTrigger.js   |    2 +-
 .../component/legend/ScrollableLegendView.js       |    2 +-
 .../src/echarts/component/marker/MarkAreaView.js   |   68 +-
 .../src/echarts/component/marker/MarkLineView.js   |    3 +
 .../src/echarts/component/marker/MarkPointView.js  |    9 +-
 .../src/echarts/component/marker/MarkerModel.js    |    5 +-
 .../component/timeline/SliderTimelineView.js       |    8 +-
 zh/builder/src/echarts/component/title.js          |    2 +-
 .../echarts/component/toolbox/feature/DataView.js  |   31 +-
 .../echarts/component/toolbox/feature/DataZoom.js  |   12 +-
 .../component/toolbox/feature/SaveAsImage.js       |    3 +-
 .../echarts/component/tooltip/TooltipContent.js    |   50 +-
 .../component/tooltip/TooltipRichContent.js        |   64 +-
 .../src/echarts/component/tooltip/TooltipView.js   |    8 +-
 .../echarts/component/visualMap/VisualMapModel.js  |    2 +-
 zh/builder/src/echarts/coord/axisDefault.js        |    2 +-
 zh/builder/src/echarts/coord/axisHelper.js         |    4 +-
 zh/builder/src/echarts/coord/geo/GeoModel.js       |    3 +-
 zh/builder/src/echarts/data/Graph.js               |    7 +-
 zh/builder/src/echarts/data/List.js                |    2 +-
 zh/builder/src/echarts/data/Tree.js                |   34 +-
 zh/builder/src/echarts/echarts.js                  |    4 +-
 zh/builder/src/echarts/layout/barPolar.js          |    2 +-
 zh/builder/src/echarts/processor/dataSample.js     |    2 +-
 zh/builder/src/echarts/stream/Scheduler.js         |    2 +-
 zh/builder/src/echarts/visual/VisualMapping.js     |    2 +-
 zh/builder/src/zrender/animation/track.js          |    4 -
 .../src/zrender/svg/helper/GradientManager.js      |    2 +-
 zh/builder/src/zrender/zrender.js                  |    2 +-
 zh/builder3.html                                   |    4 +-
 zh/changelog.html                                  |   53 +-
 zh/cheat-sheet.html                                |    6 +-
 zh/coding-standard.html                            |    4 +-
 zh/committers.html                                 |    4 +-
 zh/contributing.html                               |    4 +-
 zh/css/only_for_cdn_ready_check.css                |    2 +-
 zh/demo.html                                       |    6 +-
 zh/dependencies.html                               |    4 +-
 zh/dist/echarts-en.common.js                       |  377 +++++--
 zh/dist/echarts-en.common.min.js                   |    2 +-
 zh/dist/echarts-en.js                              | 1100 +++++++++++++++-----
 zh/dist/echarts-en.js.map                          |    2 +-
 zh/dist/echarts-en.min.js                          |    2 +-
 zh/dist/echarts-en.simple.js                       |   86 +-
 zh/dist/echarts-en.simple.min.js                   |    2 +-
 zh/dist/echarts.common.js                          |  377 +++++--
 zh/dist/echarts.common.min.js                      |    2 +-
 zh/dist/echarts.js                                 | 1100 +++++++++++++++-----
 zh/dist/echarts.js.map                             |    2 +-
 zh/dist/echarts.min.js                             |    2 +-
 zh/dist/echarts.simple.js                          |   86 +-
 zh/dist/echarts.simple.min.js                      |    2 +-
 zh/dist/extension/bmap.js                          |  378 +------
 zh/dist/extension/bmap.js.map                      |    2 +-
 zh/dist/extension/bmap.min.js                      |    2 +-
 zh/dist/extension/dataTool.js.map                  |    2 +-
 zh/documents/option-parts/option-outline.js        |    2 +-
 zh/documents/option-parts/option-outline.json      |    2 +-
 zh/documents/option-parts/option.series-bar.js     |    2 +-
 zh/documents/option-parts/option.series-bar.json   |    2 +-
 zh/documents/option-parts/option.series-funnel.js  |   11 +-
 .../option-parts/option.series-funnel.json         |   11 +-
 zh/documents/option-parts/option.series-graph.js   |    3 +
 zh/documents/option-parts/option.series-graph.json |    3 +
 zh/documents/option-parts/option.toolbox.js        |   74 ++
 zh/documents/option-parts/option.toolbox.json      |   74 ++
 zh/documents/option.json                           |    2 +-
 zh/download-extension.html                         |    4 +-
 zh/download-map.html                               |    4 +-
 zh/download-theme.html                             |    4 +-
 zh/download.html                                   |    8 +-
 zh/download3.html                                  |    4 +-
 zh/examples.html                                   |    6 +-
 zh/faq.html                                        |    4 +-
 zh/feature.html                                    |    4 +-
 zh/index.html                                      |    6 +-
 zh/js/download.js                                  |    2 +-
 zh/maillist.html                                   |    4 +-
 zh/option-gl.html                                  |    8 +-
 zh/option.html                                     |    8 +-
 zh/option3.html                                    |   10 +-
 zh/resources.html                                  |    4 +-
 zh/security.html                                   |    4 +-
 zh/spreadsheet.html                                |   10 +-
 zh/theme-builder.html                              |    4 +-
 zh/tutorial.html                                   |    8 +-
 326 files changed, 7903 insertions(+), 3759 deletions(-)

diff --git a/components/builder.html b/components/builder.html
index a496d50..612980f 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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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="https://echarts.apache.org/zh/images/forie.png?_v_=20200710_1" 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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close [...]
+<!--[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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close [...]
     $('#charts input, #components input, #coords input').each(function () {
         $(this).attr('checked', $(this).parent().hasClass('checked'));
     });
@@ -52,14 +52,14 @@ $("#build").click(function () {
     }
 
     parameters += '&version=3'
-        + '&versionCode=4.8.0';
+        + '&versionCode=4.9.0';
 
     //- var email = $('#email').val();
     var log = parameters;
     //- if (email) {
     //-     log += '&email=' + email;
     //- }
-    _hmt.push(['_trackEvent', 'builder', 'build', '4.8.0', log]);
+    _hmt.push(['_trackEvent', 'builder', 'build', '4.9.0', log]);
 
     window.open('https://echarts.apache.org/zh/builder/echarts.html?' + parameters);
 });</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
diff --git a/components/download.html b/components/download.html
index 250d457..9a80599 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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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 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="https://echarts.apache.org/zh/images/forie.png?_v_=20200710_1" 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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close [...]
+<!--[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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close [...]
 
 //- $('.download-echarts').click(function (e) {
 //-     var el = document.createElement('div');
@@ -23,10 +23,10 @@
 //-         title: 'Notice',
 //-         content: el
 //-     });
-//-     _hmt.push(['_trackEvent', 'download', 'download', '4.8.0']);
+//-     _hmt.push(['_trackEvent', 'download', 'download', '4.9.0']);
 //- });
 //- $('.download-theme').click(function () {
-//-     _hmt.push(['_trackEvent', 'download', 'download-theme', '4.8.0']);
+//-     _hmt.push(['_trackEvent', 'download', 'download-theme', '4.9.0']);
 //- });</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
diff --git a/en/404.html b/en/404.html
index 5b2e496..9b5fcc1 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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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><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="https://echarts.apache.org/zh/images/forie.png?_v_=20200710_1" 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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close [...]
+<!--[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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/api.html b/en/api.html
index 92c2b3a..792566e 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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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,8 +9,8 @@
 </script><title>Documentation - Apache ECharts(incubating)</title><style>html, body {
     /* position: sticky should not have overflow parents.*/
     overflow-x: hidden;
-}</style><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css"><link rel="stylesheet" href="https://echarts.apache.org/en/css/doc-bundle.css?_v_=1598523895644"><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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="https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css"><link rel="stylesheet" href="https://echarts.apache.org/en/css/doc-bundle.css?_v_=1598903776431"><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 </script><script type="text/javascript">window.globalArgsExtra = {
     baseUrl: 'documents/api-parts',
     docType: 'api',
@@ -19,7 +19,7 @@
 if (window.EC_WWW_CDN_PAY_ROOT) {
     window.globalArgsExtra.cdnRoot = window.EC_WWW_CDN_PAY_ROOT + '/en/' + window.globalArgsExtra.baseUrl
 }</script><script type="text/javascript">document.getElementById('nav-doc').className = 'active';
-window.globalArgsExtra.version = '1598523895644';
+window.globalArgsExtra.version = '1598903776431';
 echartsDoc.init('#ec-doc-main', window.globalArgsExtra);</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
diff --git a/en/builder.html b/en/builder.html
index 7c5582a..96cfcff 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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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,14 +52,14 @@ $("#build").click(function () {
     }
 
     parameters += '&version=4'
-        + '&versionCode=4.8.0';
+        + '&versionCode=4.9.0';
 
     //- var email = $('#email').val();
     var log = parameters;
     //- if (email) {
     //-     log += '&email=' + email;
     //- }
-    _hmt.push(['_trackEvent', 'builder', 'build', '4.8.0', log]);
+    _hmt.push(['_trackEvent', 'builder', 'build', '4.9.0', log]);
 
     window.open('https://echarts.apache.org/en/builder/echarts.html?' + parameters);
 });</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
diff --git a/en/builder/echarts.html b/en/builder/echarts.html
index 82e8e93..1e7d04a 100644
--- a/en/builder/echarts.html
+++ b/en/builder/echarts.html
@@ -56,7 +56,7 @@
                 'esprima': 'lib/esprima',
                 'estraverse': 'lib/estraverse'
             },
-            urlArgs: 'v=1598523895644'
+            urlArgs: 'v=1598903776431'
         });
 
         require(['build']);
diff --git a/en/builder/src/echarts/chart/bar/BarView.js b/en/builder/src/echarts/chart/bar/BarView.js
index b663213..7fc9c7f 100644
--- a/en/builder/src/echarts/chart/bar/BarView.js
+++ b/en/builder/src/echarts/chart/bar/BarView.js
@@ -116,20 +116,26 @@ export default echarts.extendChartView({
     var barBorderRadius = backgroundModel.get('barBorderRadius') || 0;
     var bgEls = [];
     var oldBgEls = this._backgroundEls || [];
+
+    var createBackground = function (dataIndex) {
+      var bgLayout = getLayout[coord.type](data, dataIndex);
+      var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
+      bgEl.useStyle(backgroundModel.getBarItemStyle()); // Only cartesian2d support borderRadius.
+
+      if (coord.type === 'cartesian2d') {
+        bgEl.setShape('r', barBorderRadius);
+      }
+
+      bgEls[dataIndex] = bgEl;
+      return bgEl;
+    };
+
     data.diff(oldData).add(function (dataIndex) {
       var itemModel = data.getItemModel(dataIndex);
       var layout = getLayout[coord.type](data, dataIndex, itemModel);
 
       if (drawBackground) {
-        var bgLayout = getLayout[coord.type](data, dataIndex);
-        var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
-        bgEl.useStyle(backgroundModel.getBarItemStyle()); // Only cartesian2d support borderRadius.
-
-        if (coord.type === 'cartesian2d') {
-          bgEl.setShape('r', barBorderRadius);
-        }
-
-        bgEls[dataIndex] = bgEl;
+        createBackground(dataIndex);
       } // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
 
 
@@ -157,14 +163,21 @@ export default echarts.extendChartView({
       var layout = getLayout[coord.type](data, newIndex, itemModel);
 
       if (drawBackground) {
-        var bgEl = oldBgEls[oldIndex];
-        bgEl.useStyle(backgroundModel.getBarItemStyle()); // Only cartesian2d support borderRadius.
+        var bgEl;
 
-        if (coord.type === 'cartesian2d') {
-          bgEl.setShape('r', barBorderRadius);
+        if (oldBgEls.length === 0) {
+          bgEl = createBackground(oldIndex);
+        } else {
+          bgEl = oldBgEls[oldIndex];
+          bgEl.useStyle(backgroundModel.getBarItemStyle()); // Only cartesian2d support borderRadius.
+
+          if (coord.type === 'cartesian2d') {
+            bgEl.setShape('r', barBorderRadius);
+          }
+
+          bgEls[newIndex] = bgEl;
         }
 
-        bgEls[newIndex] = bgEl;
         var bgLayout = getLayout[coord.type](data, newIndex);
         var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
         graphic.updateProps(bgEl, {
@@ -307,8 +320,28 @@ var clip = {
 
     return clipped;
   },
-  polar: function (coordSysClipArea) {
-    return false;
+  polar: function (coordSysClipArea, layout) {
+    var signR = layout.r0 <= layout.r ? 1 : -1; // Make sure r is larger than r0
+
+    if (signR < 0) {
+      var r = layout.r;
+      layout.r = layout.r0;
+      layout.r0 = r;
+    }
+
+    var r = mathMin(layout.r, coordSysClipArea.r);
+    var r0 = mathMax(layout.r0, coordSysClipArea.r0);
+    layout.r = r;
+    layout.r0 = r0;
+    var clipped = r - r0 < 0; // Reverse back
+
+    if (signR < 0) {
+      var r = layout.r;
+      layout.r = layout.r0;
+      layout.r0 = r;
+    }
+
+    return clipped;
   }
 };
 var elementCreator = {
diff --git a/en/builder/src/echarts/chart/bar/PictorialBarSeries.js b/en/builder/src/echarts/chart/bar/PictorialBarSeries.js
index c1d7013..8c01c44 100644
--- a/en/builder/src/echarts/chart/bar/PictorialBarSeries.js
+++ b/en/builder/src/echarts/chart/bar/PictorialBarSeries.js
@@ -31,7 +31,7 @@ var PictorialBarSeries = BaseBarSeries.extend({
     symbolOffset: null,
     symbolMargin: null,
     // start margin and end margin. Can be a number or a percent string.
-    // Auto margin by defualt.
+    // Auto margin by default.
     symbolRepeat: false,
     // false/null/undefined, means no repeat.
     // Can be true, means auto calculate repeat times and cut by data.
diff --git a/en/builder/src/echarts/chart/funnel/FunnelSeries.js b/en/builder/src/echarts/chart/funnel/FunnelSeries.js
index f728aa1..344ef76 100644
--- a/en/builder/src/echarts/chart/funnel/FunnelSeries.js
+++ b/en/builder/src/echarts/chart/funnel/FunnelSeries.js
@@ -77,6 +77,7 @@ var FunnelSeries = echarts.extendSeriesModel({
     maxSize: '100%',
     sort: 'descending',
     // 'ascending', 'descending'
+    orient: 'vertical',
     gap: 0,
     funnelAlign: 'center',
     label: {
diff --git a/en/builder/src/echarts/chart/funnel/funnelLayout.js b/en/builder/src/echarts/chart/funnel/funnelLayout.js
index d262702..44f87b1 100644
--- a/en/builder/src/echarts/chart/funnel/funnelLayout.js
+++ b/en/builder/src/echarts/chart/funnel/funnelLayout.js
@@ -16,6 +16,7 @@
 * specific language governing permissions and limitations
 * under the License.
 */
+import { __DEV__ } from '../../config';
 import * as layout from '../../util/layout';
 import { parsePercent, linearMap } from '../../util/number';
 
@@ -55,6 +56,7 @@ function labelLayout(data) {
     var itemModel = data.getItemModel(idx);
     var labelModel = itemModel.getModel('label');
     var labelPosition = labelModel.get('position');
+    var orient = itemModel.get('orient');
     var labelLineModel = itemModel.getModel('labelLine');
     var layout = data.getItemLayout(idx);
     var points = layout.points;
@@ -84,6 +86,7 @@ function labelLayout(data) {
       var x1;
       var y1;
       var x2;
+      var y2;
       var labelLineLen = labelLineModel.get('length');
 
       if (labelPosition === 'left') {
@@ -100,46 +103,101 @@ function labelLayout(data) {
         x2 = x1 + labelLineLen;
         textX = x2 + 5;
         textAlign = 'left';
+      } else if (labelPosition === 'top') {
+        // Top side
+        x1 = (points[3][0] + points[0][0]) / 2;
+        y1 = (points[3][1] + points[0][1]) / 2;
+        y2 = y1 - labelLineLen;
+        textY = y2 - 5;
+        textAlign = 'center';
+      } else if (labelPosition === 'bottom') {
+        // Bottom side
+        x1 = (points[1][0] + points[2][0]) / 2;
+        y1 = (points[1][1] + points[2][1]) / 2;
+        y2 = y1 + labelLineLen;
+        textY = y2 + 5;
+        textAlign = 'center';
       } else if (labelPosition === 'rightTop') {
         // RightTop side
-        x1 = points[1][0];
-        y1 = points[1][1];
-        x2 = x1 + labelLineLen;
-        textX = x2 + 5;
-        textAlign = 'top';
+        x1 = orient === 'horizontal' ? points[3][0] : points[1][0];
+        y1 = orient === 'horizontal' ? points[3][1] : points[1][1];
+
+        if (orient === 'horizontal') {
+          y2 = y1 - labelLineLen;
+          textY = y2 - 5;
+          textAlign = 'center';
+        } else {
+          x2 = x1 + labelLineLen;
+          textX = x2 + 5;
+          textAlign = 'top';
+        }
       } else if (labelPosition === 'rightBottom') {
         // RightBottom side
         x1 = points[2][0];
         y1 = points[2][1];
-        x2 = x1 + labelLineLen;
-        textX = x2 + 5;
-        textAlign = 'bottom';
+
+        if (orient === 'horizontal') {
+          y2 = y1 + labelLineLen;
+          textY = y2 + 5;
+          textAlign = 'center';
+        } else {
+          x2 = x1 + labelLineLen;
+          textX = x2 + 5;
+          textAlign = 'bottom';
+        }
       } else if (labelPosition === 'leftTop') {
         // LeftTop side
         x1 = points[0][0];
-        y1 = points[1][1];
-        x2 = x1 - labelLineLen;
-        textX = x2 - 5;
-        textAlign = 'right';
+        y1 = orient === 'horizontal' ? points[0][1] : points[1][1];
+
+        if (orient === 'horizontal') {
+          y2 = y1 - labelLineLen;
+          textY = y2 - 5;
+          textAlign = 'center';
+        } else {
+          x2 = x1 - labelLineLen;
+          textX = x2 - 5;
+          textAlign = 'right';
+        }
       } else if (labelPosition === 'leftBottom') {
         // LeftBottom side
-        x1 = points[3][0];
-        y1 = points[2][1];
-        x2 = x1 - labelLineLen;
-        textX = x2 - 5;
-        textAlign = 'right';
+        x1 = orient === 'horizontal' ? points[1][0] : points[3][0];
+        y1 = orient === 'horizontal' ? points[1][1] : points[2][1];
+
+        if (orient === 'horizontal') {
+          y2 = y1 + labelLineLen;
+          textY = y2 + 5;
+          textAlign = 'center';
+        } else {
+          x2 = x1 - labelLineLen;
+          textX = x2 - 5;
+          textAlign = 'right';
+        }
       } else {
-        // Right side
+        // Right side or Bottom side
         x1 = (points[1][0] + points[2][0]) / 2;
         y1 = (points[1][1] + points[2][1]) / 2;
-        x2 = x1 + labelLineLen;
-        textX = x2 + 5;
-        textAlign = 'left';
+
+        if (orient === 'horizontal') {
+          y2 = y1 + labelLineLen;
+          textY = y2 + 5;
+          textAlign = 'center';
+        } else {
+          x2 = x1 + labelLineLen;
+          textX = x2 + 5;
+          textAlign = 'left';
+        }
+      }
+
+      if (orient === 'horizontal') {
+        x2 = x1;
+        textX = x2;
+      } else {
+        y2 = y1;
+        textY = y2;
       }
 
-      var y2 = y1;
       linePoints = [[x1, y1], [x2, y2]];
-      textY = y2;
     }
 
     layout.label = {
@@ -160,7 +218,12 @@ export default function (ecModel, api, payload) {
     var sort = seriesModel.get('sort');
     var viewRect = getViewRect(seriesModel, api);
     var indices = getSortedIndices(data, sort);
-    var sizeExtent = [parsePercent(seriesModel.get('minSize'), viewRect.width), parsePercent(seriesModel.get('maxSize'), viewRect.width)];
+    var orient = seriesModel.get('orient');
+    var viewWidth = viewRect.width;
+    var viewHeight = viewRect.height;
+    var x = viewRect.x;
+    var y = viewRect.y;
+    var sizeExtent = orient === 'horizontal' ? [parsePercent(seriesModel.get('minSize'), viewHeight), parsePercent(seriesModel.get('maxSize'), viewHeight)] : [parsePercent(seriesModel.get('minSize'), viewWidth), parsePercent(seriesModel.get('maxSize'), viewWidth)];
     var dataExtent = data.getDataExtent(valueDim);
     var min = seriesModel.get('min');
     var max = seriesModel.get('max');
@@ -175,37 +238,65 @@ export default function (ecModel, api, payload) {
 
     var funnelAlign = seriesModel.get('funnelAlign');
     var gap = seriesModel.get('gap');
-    var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count();
-    var y = viewRect.y;
+    var viewSize = orient === 'horizontal' ? viewWidth : viewHeight;
+    var itemSize = (viewSize - gap * (data.count() - 1)) / data.count();
 
-    var getLinePoints = function (idx, offY) {
+    var getLinePoints = function (idx, offset) {
       // End point index is data.count() and we assign it 0
+      if (orient === 'horizontal') {
+        var val = data.get(valueDim, idx) || 0;
+        var itemHeight = linearMap(val, [min, max], sizeExtent, true);
+        var y0;
+
+        switch (funnelAlign) {
+          case 'top':
+            y0 = y;
+            break;
+
+          case 'center':
+            y0 = y + (viewHeight - itemHeight) / 2;
+            break;
+
+          case 'bottom':
+            y0 = y + (viewHeight - itemHeight);
+            break;
+        }
+
+        return [[offset, y0], [offset, y0 + itemHeight]];
+      }
+
       var val = data.get(valueDim, idx) || 0;
       var itemWidth = linearMap(val, [min, max], sizeExtent, true);
       var x0;
 
       switch (funnelAlign) {
         case 'left':
-          x0 = viewRect.x;
+          x0 = x;
           break;
 
         case 'center':
-          x0 = viewRect.x + (viewRect.width - itemWidth) / 2;
+          x0 = x + (viewWidth - itemWidth) / 2;
           break;
 
         case 'right':
-          x0 = viewRect.x + viewRect.width - itemWidth;
+          x0 = x + viewWidth - itemWidth;
           break;
       }
 
-      return [[x0, offY], [x0 + itemWidth, offY]];
+      return [[x0, offset], [x0 + itemWidth, offset]];
     };
 
     if (sort === 'ascending') {
       // From bottom to top
-      itemHeight = -itemHeight;
+      itemSize = -itemSize;
       gap = -gap;
-      y += viewRect.height;
+
+      if (orient === 'horizontal') {
+        x += viewWidth;
+      } else {
+        y += viewHeight;
+      }
+
       indices = indices.reverse();
     }
 
@@ -213,24 +304,46 @@ export default function (ecModel, api, payload) {
       var idx = indices[i];
       var nextIdx = indices[i + 1];
       var itemModel = data.getItemModel(idx);
-      var height = itemModel.get('itemStyle.height');
 
-      if (height == null) {
-        height = itemHeight;
+      if (orient === 'horizontal') {
+        var width = itemModel.get('itemStyle.width');
+
+        if (width == null) {
+          width = itemSize;
+        } else {
+          width = parsePercent(width, viewWidth);
+
+          if (sort === 'ascending') {
+            width = -width;
+          }
+        }
+
+        var start = getLinePoints(idx, x);
+        var end = getLinePoints(nextIdx, x + width);
+        x += width + gap;
+        data.setItemLayout(idx, {
+          points: start.concat(end.slice().reverse())
+        });
       } else {
-        height = parsePercent(height, viewRect.height);
+        var height = itemModel.get('itemStyle.height');
 
-        if (sort === 'ascending') {
-          height = -height;
+        if (height == null) {
+          height = itemSize;
+        } else {
+          height = parsePercent(height, viewHeight);
+
+          if (sort === 'ascending') {
+            height = -height;
+          }
         }
-      }
 
-      var start = getLinePoints(idx, y);
-      var end = getLinePoints(nextIdx, y + height);
-      y += height + gap;
-      data.setItemLayout(idx, {
-        points: start.concat(end.slice().reverse())
-      });
+        var start = orient === 'horizontal' ? getLinePoints(idx, x) : getLinePoints(idx, y);
+        var end = orient === 'horizontal' ? getLinePoints(nextIdx, x + width) : getLinePoints(nextIdx, y + height);
+        y += height + gap;
+        data.setItemLayout(idx, {
+          points: start.concat(end.slice().reverse())
+        });
+      }
     }
 
     labelLayout(data);
diff --git a/en/builder/src/echarts/chart/graph/GraphSeries.js b/en/builder/src/echarts/chart/graph/GraphSeries.js
index a354166..a41a6d7 100644
--- a/en/builder/src/echarts/chart/graph/GraphSeries.js
+++ b/en/builder/src/echarts/chart/graph/GraphSeries.js
@@ -24,6 +24,7 @@ import Model from '../../model/Model';
 import { encodeHTML } from '../../util/format';
 import createGraphFromNodeEdge from '../helper/createGraphFromNodeEdge';
 import LegendVisualProvider from '../../visual/LegendVisualProvider';
+import { initCurvenessList, createEdgeMapForCurveness } from '../helper/multipleGraphEdgeHelper';
 var GraphSeries = echarts.extendSeriesModel({
   type: 'series.graph',
   init: function (option) {
@@ -56,7 +57,13 @@ var GraphSeries = echarts.extendSeriesModel({
     var self = this;
 
     if (nodes && edges) {
-      return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data;
+      // auto curveness
+      initCurvenessList(this);
+      var graph = createGraphFromNodeEdge(nodes, edges, this, true, beforeLink);
+      zrUtil.each(graph.edges, function (edge) {
+        createEdgeMapForCurveness(edge.node1, edge.node2, this, edge.dataIndex);
+      }, this);
+      return graph.data;
     }
 
     function beforeLink(nodeData, edgeData) {
@@ -233,7 +240,6 @@ var GraphSeries = echarts.extendSeriesModel({
     lineStyle: {
       color: '#aaa',
       width: 1,
-      curveness: 0,
       opacity: 0.5
     },
     emphasis: {
diff --git a/en/builder/src/echarts/chart/graph/circularLayoutHelper.js b/en/builder/src/echarts/chart/graph/circularLayoutHelper.js
index 3a57efc..298aa0e 100644
--- a/en/builder/src/echarts/chart/graph/circularLayoutHelper.js
+++ b/en/builder/src/echarts/chart/graph/circularLayoutHelper.js
@@ -18,6 +18,8 @@
 */
 import * as vec2 from 'zrender/src/core/vector';
 import { getSymbolSize, getNodeGlobalScale } from './graphHelper';
+import * as zrUtil from 'zrender/src/core/util';
+import { getCurvenessForEdge } from '../helper/multipleGraphEdgeHelper';
 var PI = Math.PI;
 var _symbolRadiansHalf = [];
 /**
@@ -68,8 +70,8 @@ export function circularLayout(seriesModel, basedOn) {
 
   _layoutNodesBasedOn[basedOn](seriesModel, coordSys, graph, nodeData, r, cx, cy, count);
 
-  graph.eachEdge(function (edge) {
-    var curveness = edge.getModel().get('lineStyle.curveness') || 0;
+  graph.eachEdge(function (edge, index) {
+    var curveness = zrUtil.retrieve3(edge.getModel().get('lineStyle.curveness'), getCurvenessForEdge(edge, seriesModel, index), 0);
     var p1 = vec2.clone(edge.node1.getLayout());
     var p2 = vec2.clone(edge.node2.getLayout());
     var cp1;
diff --git a/en/builder/src/echarts/chart/graph/forceLayout.js b/en/builder/src/echarts/chart/graph/forceLayout.js
index 97a8fbb..7af79f7 100644
--- a/en/builder/src/echarts/chart/graph/forceLayout.js
+++ b/en/builder/src/echarts/chart/graph/forceLayout.js
@@ -22,6 +22,7 @@ import { circularLayout } from './circularLayoutHelper';
 import { linearMap } from '../../util/number';
 import * as vec2 from 'zrender/src/core/vector';
 import * as zrUtil from 'zrender/src/core/util';
+import { getCurvenessForEdge } from '../helper/multipleGraphEdgeHelper';
 export default function (ecModel) {
   ecModel.eachSeriesByType('graph', function (graphSeries) {
     var coordSys = graphSeries.coordinateSystem;
@@ -89,11 +90,12 @@ export default function (ecModel) {
         }
 
         var edgeModel = edge.getModel();
+        var curveness = zrUtil.retrieve3(edgeModel.get('lineStyle.curveness'), -getCurvenessForEdge(edge, graphSeries, idx, true), 0);
         return {
           n1: nodes[edge.node1.dataIndex],
           n2: nodes[edge.node2.dataIndex],
           d: d,
-          curveness: edgeModel.get('lineStyle.curveness') || 0,
+          curveness: curveness,
           ignoreForceLayout: edgeModel.get('ignoreForceLayout')
         };
       });
diff --git a/en/builder/src/echarts/chart/graph/simpleLayout.js b/en/builder/src/echarts/chart/graph/simpleLayout.js
index d18a5c7..bd6ce42 100644
--- a/en/builder/src/echarts/chart/graph/simpleLayout.js
+++ b/en/builder/src/echarts/chart/graph/simpleLayout.js
@@ -52,7 +52,7 @@ export default function (ecModel, api) {
         }
       }
 
-      simpleLayoutEdge(data.graph);
+      simpleLayoutEdge(data.graph, seriesModel);
     } else if (!layout || layout === 'none') {
       simpleLayout(seriesModel);
     }
diff --git a/en/builder/src/echarts/chart/graph/simpleLayoutHelper.js b/en/builder/src/echarts/chart/graph/simpleLayoutHelper.js
index 4e66702..05cf6d8 100644
--- a/en/builder/src/echarts/chart/graph/simpleLayoutHelper.js
+++ b/en/builder/src/echarts/chart/graph/simpleLayoutHelper.js
@@ -17,6 +17,8 @@
 * under the License.
 */
 import * as vec2 from 'zrender/src/core/vector';
+import * as zrUtil from 'zrender/src/core/util';
+import { getCurvenessForEdge } from '../helper/multipleGraphEdgeHelper';
 export function simpleLayout(seriesModel) {
   var coordSys = seriesModel.coordinateSystem;
 
@@ -29,11 +31,11 @@ export function simpleLayout(seriesModel) {
     var model = node.getModel();
     node.setLayout([+model.get('x'), +model.get('y')]);
   });
-  simpleLayoutEdge(graph);
+  simpleLayoutEdge(graph, seriesModel);
 }
-export function simpleLayoutEdge(graph) {
-  graph.eachEdge(function (edge) {
-    var curveness = edge.getModel().get('lineStyle.curveness') || 0;
+export function simpleLayoutEdge(graph, seriesModel) {
+  graph.eachEdge(function (edge, index) {
+    var curveness = zrUtil.retrieve3(edge.getModel().get('lineStyle.curveness'), -getCurvenessForEdge(edge, seriesModel, index, true), 0);
     var p1 = vec2.clone(edge.node1.getLayout());
     var p2 = vec2.clone(edge.node2.getLayout());
     var points = [p1, p2];
diff --git a/en/builder/src/echarts/chart/helper/Line.js b/en/builder/src/echarts/chart/helper/Line.js
index 251ae41..78167e3 100644
--- a/en/builder/src/echarts/chart/helper/Line.js
+++ b/en/builder/src/echarts/chart/helper/Line.js
@@ -37,19 +37,23 @@ function makeSymbolTypeKey(symbolCategory) {
 
 
 function createSymbol(name, lineData, idx) {
-  var color = lineData.getItemVisual(idx, 'color');
   var symbolType = lineData.getItemVisual(idx, name);
-  var symbolSize = lineData.getItemVisual(idx, name + 'Size');
 
   if (!symbolType || symbolType === 'none') {
     return;
   }
 
+  var color = lineData.getItemVisual(idx, 'color');
+  var symbolSize = lineData.getItemVisual(idx, name + 'Size');
+  var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate');
+
   if (!zrUtil.isArray(symbolSize)) {
     symbolSize = [symbolSize, symbolSize];
   }
 
-  var symbolPath = symbolUtil.createSymbol(symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2, symbolSize[0], symbolSize[1], color);
+  var symbolPath = symbolUtil.createSymbol(symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2, symbolSize[0], symbolSize[1], color); // rotate by default if symbolRotate is not specified or NaN
+
+  symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate) ? void 0 : +symbolRotate * Math.PI / 180 || 0;
   symbolPath.name = name;
   return symbolPath;
 }
@@ -115,16 +119,38 @@ function updateSymbolAndLabelBeforeLineUpdate() {
   vector.normalize(d, d);
 
   if (symbolFrom) {
-    symbolFrom.attr('position', fromPos);
-    var tangent = line.tangentAt(0);
-    symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(tangent[1], tangent[0]));
+    symbolFrom.attr('position', fromPos); // Fix #12388
+    // when symbol is set to be 'arrow' in markLine,
+    // symbolRotate value will be ignored, and compulsively use tangent angle.
+    // rotate by default if symbol rotation is not specified
+
+    var specifiedRotation = symbolFrom.__specifiedRotation;
+
+    if (specifiedRotation == null) {
+      var tangent = line.tangentAt(0);
+      symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(tangent[1], tangent[0]));
+    } else {
+      symbolFrom.attr('rotation', specifiedRotation);
+    }
+
     symbolFrom.attr('scale', [invScale * percent, invScale * percent]);
   }
 
   if (symbolTo) {
-    symbolTo.attr('position', toPos);
-    var tangent = line.tangentAt(1);
-    symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(tangent[1], tangent[0]));
+    symbolTo.attr('position', toPos); // Fix #12388
+    // when symbol is set to be 'arrow' in markLine,
+    // symbolRotate value will be ignored, and compulsively use tangent angle.
+    // rotate by default if symbol rotation is not specified
+
+    var specifiedRotation = symbolTo.__specifiedRotation;
+
+    if (specifiedRotation == null) {
+      var tangent = line.tangentAt(1);
+      symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(tangent[1], tangent[0]));
+    } else {
+      symbolTo.attr('rotation', specifiedRotation);
+    }
+
     symbolTo.attr('scale', [invScale * percent, invScale * percent]);
   }
 
diff --git a/en/builder/src/echarts/chart/helper/Symbol.js b/en/builder/src/echarts/chart/helper/Symbol.js
index 939edb0..5b1407f 100644
--- a/en/builder/src/echarts/chart/helper/Symbol.js
+++ b/en/builder/src/echarts/chart/helper/Symbol.js
@@ -226,7 +226,7 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     });
   } else {
     symbolPath.setStyle({
-      opacity: null,
+      opacity: 1,
       shadowBlur: null,
       shadowOffsetX: null,
       shadowOffsetY: null,
diff --git a/en/builder/src/echarts/chart/helper/multipleGraphEdgeHelper.js b/en/builder/src/echarts/chart/helper/multipleGraphEdgeHelper.js
new file mode 100644
index 0000000..eaccb7e
--- /dev/null
+++ b/en/builder/src/echarts/chart/helper/multipleGraphEdgeHelper.js
@@ -0,0 +1,231 @@
+/*
+* 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';
+var KEY_DELIMITER = '-->';
+/**
+ * params handler
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @returns {*}
+ */
+
+var getAutoCurvenessParams = function (seriesModel) {
+  return seriesModel.get('autoCurveness') || null;
+};
+/**
+ * Generate a list of edge curvatures, 20 is the default
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param {number} appendLength
+ * @return  20 => [0, -0.2, 0.2, -0.4, 0.4, -0.6, 0.6, -0.8, 0.8, -1, 1, -1.2, 1.2, -1.4, 1.4, -1.6, 1.6, -1.8, 1.8, -2]
+ */
+
+
+var createCurveness = function (seriesModel, appendLength) {
+  var autoCurvenessParmas = getAutoCurvenessParams(seriesModel);
+  var length = 20;
+  var curvenessList = []; // handler the function set
+
+  if (typeof autoCurvenessParmas === 'number') {
+    length = autoCurvenessParmas;
+  } else if (zrUtil.isArray(autoCurvenessParmas)) {
+    seriesModel.__curvenessList = autoCurvenessParmas;
+    return;
+  } // append length
+
+
+  if (appendLength > length) {
+    length = appendLength;
+  } // make sure the length is even
+
+
+  var len = length % 2 ? length + 2 : length + 3;
+  curvenessList = [];
+
+  for (var i = 0; i < len; i++) {
+    curvenessList.push((i % 2 ? i + 1 : i) / 10 * (i % 2 ? -1 : 1));
+  }
+
+  seriesModel.__curvenessList = curvenessList;
+};
+/**
+ * Create different cache key data in the positive and negative directions, in order to set the curvature later
+ * @param {number|string|module:echarts/data/Graph.Node} n1
+ * @param {number|string|module:echarts/data/Graph.Node} n2
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @returns {string} key
+ */
+
+
+var getKeyOfEdges = function (n1, n2, seriesModel) {
+  var source = [n1.id, n1.dataIndex].join('.');
+  var target = [n2.id, n2.dataIndex].join('.');
+  return [seriesModel.uid, source, target].join(KEY_DELIMITER);
+};
+/**
+ * get opposite key
+ * @param {string} key
+ * @returns {string}
+ */
+
+
+var getOppositeKey = function (key) {
+  var keys = key.split(KEY_DELIMITER);
+  return [keys[0], keys[2], keys[1]].join(KEY_DELIMITER);
+};
+/**
+ * get edgeMap with key
+ * @param edge
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ */
+
+
+var getEdgeFromMap = function (edge, seriesModel) {
+  var key = getKeyOfEdges(edge.node1, edge.node2, seriesModel);
+  return seriesModel.__edgeMap[key];
+};
+/**
+ * calculate all cases total length
+ * @param edge
+ * @param seriesModel
+ * @returns {number}
+ */
+
+
+var getTotalLengthBetweenNodes = function (edge, seriesModel) {
+  var len = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node1, edge.node2, seriesModel), seriesModel);
+  var lenV = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node2, edge.node1, seriesModel), seriesModel);
+  return len + lenV;
+};
+/**
+ *
+ * @param key
+ */
+
+
+var getEdgeMapLengthWithKey = function (key, seriesModel) {
+  var edgeMap = seriesModel.__edgeMap;
+  return edgeMap[key] ? edgeMap[key].length : 0;
+};
+/**
+ * Count the number of edges between the same two points, used to obtain the curvature table and the parity of the edge
+ * @see /graph/GraphSeries.js@getInitialData
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ */
+
+
+export function initCurvenessList(seriesModel) {
+  if (!getAutoCurvenessParams(seriesModel)) {
+    return;
+  }
+
+  seriesModel.__curvenessList = [];
+  seriesModel.__edgeMap = {}; // calc the array of curveness List
+
+  createCurveness(seriesModel);
+}
+/**
+ * set edgeMap with key
+ * @param {number|string|module:echarts/data/Graph.Node} n1
+ * @param {number|string|module:echarts/data/Graph.Node} n2
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param {number} index
+ */
+
+export function createEdgeMapForCurveness(n1, n2, seriesModel, index) {
+  if (!getAutoCurvenessParams(seriesModel)) {
+    return;
+  }
+
+  var key = getKeyOfEdges(n1, n2, seriesModel);
+  var edgeMap = seriesModel.__edgeMap;
+  var oppositeEdges = edgeMap[getOppositeKey(key)]; // set direction
+
+  if (edgeMap[key] && !oppositeEdges) {
+    edgeMap[key].isForward = true;
+  } else if (oppositeEdges && edgeMap[key]) {
+    oppositeEdges.isForward = true;
+    edgeMap[key].isForward = false;
+  }
+
+  edgeMap[key] = edgeMap[key] || [];
+  edgeMap[key].push(index);
+}
+/**
+ * get curvature for edge
+ * @param edge
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param index
+ */
+
+export function getCurvenessForEdge(edge, seriesModel, index, needReverse) {
+  var autoCurvenessParams = getAutoCurvenessParams(seriesModel);
+  var isArrayParam = zrUtil.isArray(autoCurvenessParams);
+
+  if (!autoCurvenessParams) {
+    return null;
+  }
+
+  var edgeArray = getEdgeFromMap(edge, seriesModel);
+
+  if (!edgeArray) {
+    return null;
+  }
+
+  var edgeIndex = -1;
+
+  for (var i = 0; i < edgeArray.length; i++) {
+    if (edgeArray[i] === index) {
+      edgeIndex = i;
+      break;
+    }
+  } // if totalLen is Longer createCurveness
+
+
+  var totalLen = getTotalLengthBetweenNodes(edge, seriesModel);
+  createCurveness(seriesModel, totalLen);
+  edge.lineStyle = edge.lineStyle || {}; // if is opposite edge, must set curvenss to opposite number
+
+  var curKey = getKeyOfEdges(edge.node1, edge.node2, seriesModel);
+  var curvenessList = seriesModel.__curvenessList; // if pass array no need parity
+
+  var parityCorrection = isArrayParam ? 0 : totalLen % 2 ? 0 : 1;
+
+  if (!edgeArray.isForward) {
+    // the opposite edge show outside
+    var oppositeKey = getOppositeKey(curKey);
+    var len = getEdgeMapLengthWithKey(oppositeKey, seriesModel);
+    var resValue = curvenessList[edgeIndex + len + parityCorrection]; // isNeedReverse, simple, force type need reverse the curveness in the junction of the forword and the opposite
+
+    if (needReverse) {
+      // set as array may make the parity handle with the len of opposite
+      if (isArrayParam) {
+        if (autoCurvenessParams && autoCurvenessParams[0] === 0) {
+          return (len + parityCorrection) % 2 ? resValue : -resValue;
+        } else {
+          return ((len % 2 ? 0 : 1) + parityCorrection) % 2 ? resValue : -resValue;
+        }
+      } else {
+        return (len + parityCorrection) % 2 ? resValue : -resValue;
+      }
+    } else {
+      return curvenessList[edgeIndex + len + parityCorrection];
+    }
+  } else {
+    return curvenessList[parityCorrection + edgeIndex];
+  }
+}
\ No newline at end of file
diff --git a/en/builder/src/echarts/chart/lines/LinesSeries.js b/en/builder/src/echarts/chart/lines/LinesSeries.js
index 4622ae7..7d8e209 100644
--- a/en/builder/src/echarts/chart/lines/LinesSeries.js
+++ b/en/builder/src/echarts/chart/lines/LinesSeries.js
@@ -72,8 +72,6 @@ var LinesSeries = SeriesModel.extend({
     LinesSeries.superApply(this, 'init', arguments);
   },
   mergeOption: function (option) {
-    // The input data may be null/undefined.
-    option.data = option.data || [];
     compatEc2(option);
 
     if (option.data) {
diff --git a/en/builder/src/echarts/chart/map/MapSeries.js b/en/builder/src/echarts/chart/map/MapSeries.js
index 6bbe187..e3012c8 100644
--- a/en/builder/src/echarts/chart/map/MapSeries.js
+++ b/en/builder/src/echarts/chart/map/MapSeries.js
@@ -118,7 +118,7 @@ var MapSeries = SeriesModel.extend({
    *
    * @param {number} dataIndex
    */
-  formatTooltip: function (dataIndex) {
+  formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
     // FIXME orignalData and data is a bit confusing
     var data = this.getData();
     var formattedValue = addCommas(this.getRawValue(dataIndex));
@@ -135,7 +135,8 @@ var MapSeries = SeriesModel.extend({
       }
     }
 
-    return seriesNames.join(', ') + '<br />' + encodeHTML(name + ' : ' + formattedValue);
+    var newLine = renderMode === 'html' ? '<br/>' : '\n';
+    return seriesNames.join(', ') + newLine + encodeHTML(name + ' : ' + formattedValue);
   },
 
   /**
diff --git a/en/builder/src/echarts/chart/radar/RadarSeries.js b/en/builder/src/echarts/chart/radar/RadarSeries.js
index 9b76c7b..55c4ce1 100644
--- a/en/builder/src/echarts/chart/radar/RadarSeries.js
+++ b/en/builder/src/echarts/chart/radar/RadarSeries.js
@@ -37,15 +37,16 @@ var RadarSeries = SeriesModel.extend({
       generateCoordCount: Infinity
     });
   },
-  formatTooltip: function (dataIndex) {
+  formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
     var data = this.getData();
     var coordSys = this.coordinateSystem;
     var indicatorAxes = coordSys.getIndicatorAxes();
     var name = this.getData().getName(dataIndex);
-    return encodeHTML(name === '' ? this.name : name) + '<br/>' + zrUtil.map(indicatorAxes, function (axis, idx) {
+    var newLine = renderMode === 'html' ? '<br/>' : '\n';
+    return encodeHTML(name === '' ? this.name : name) + newLine + zrUtil.map(indicatorAxes, function (axis, idx) {
       var val = data.get(data.mapDimension(axis.dim), dataIndex);
       return encodeHTML(axis.name + ' : ' + val);
-    }).join('<br />');
+    }).join(newLine);
   },
 
   /**
diff --git a/en/builder/src/echarts/chart/radar/RadarView.js b/en/builder/src/echarts/chart/radar/RadarView.js
index 9c02b66..8f9eaf3 100644
--- a/en/builder/src/echarts/chart/radar/RadarView.js
+++ b/en/builder/src/echarts/chart/radar/RadarView.js
@@ -47,12 +47,14 @@ export default echarts.extendChartView({
 
       var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
       var symbolPath = symbolUtil.createSymbol(symbolType, -1, -1, 2, 2, color);
+      var symbolRotate = data.getItemVisual(idx, 'symbolRotate') || 0;
       symbolPath.attr({
         style: {
           strokeNoScale: true
         },
         z2: 100,
-        scale: [symbolSize[0] / 2, symbolSize[1] / 2]
+        scale: [symbolSize[0] / 2, symbolSize[1] / 2],
+        rotation: symbolRotate * Math.PI / 180 || 0
       });
       return symbolPath;
     }
diff --git a/en/builder/src/echarts/chart/sunburst/SunburstPiece.js b/en/builder/src/echarts/chart/sunburst/SunburstPiece.js
index d5b0258..7e12404 100644
--- a/en/builder/src/echarts/chart/sunburst/SunburstPiece.js
+++ b/en/builder/src/echarts/chart/sunburst/SunburstPiece.js
@@ -166,7 +166,10 @@ SunburstPieceProto._updateLabel = function (seriesModel, visualColor, state) {
   var normalModel = itemModel.getModel('label');
   var labelModel = state === 'normal' || state === 'emphasis' ? normalModel : itemModel.getModel(state + '.label');
   var labelHoverModel = itemModel.getModel('emphasis.label');
-  var text = zrUtil.retrieve(seriesModel.getFormattedLabel(this.node.dataIndex, state, null, null, 'label'), this.node.name);
+  var labelFormatter = labelModel.get('formatter'); // Use normal formatter if no state formatter is defined
+
+  var labelState = labelFormatter ? state : 'normal';
+  var text = zrUtil.retrieve(seriesModel.getFormattedLabel(this.node.dataIndex, labelState, null, null, 'label'), this.node.name);
 
   if (getLabelAttr('show') === false) {
     text = '';
diff --git a/en/builder/src/echarts/chart/sunburst/SunburstSeries.js b/en/builder/src/echarts/chart/sunburst/SunburstSeries.js
index aa601db..75daab5 100644
--- a/en/builder/src/echarts/chart/sunburst/SunburstSeries.js
+++ b/en/builder/src/echarts/chart/sunburst/SunburstSeries.js
@@ -19,6 +19,7 @@
 import * as zrUtil from 'zrender/src/core/util';
 import SeriesModel from '../../model/Series';
 import Tree from '../../data/Tree';
+import Model from '../../model/Model';
 import { wrapTreePathInfo } from '../helper/treeHelper';
 export default SeriesModel.extend({
   type: 'series.sunburst',
@@ -34,14 +35,24 @@ export default SeriesModel.extend({
       children: option.data
     };
     completeTreeValue(root);
-    var levels = option.levels || []; // levels = option.levels = setDefault(levels, ecModel);
-
-    var treeOption = {};
-    treeOption.levels = levels; // Make sure always a new tree is created when setOption,
+    var levelModels = zrUtil.map(option.levels || [], function (levelDefine) {
+      return new Model(levelDefine, this, ecModel);
+    }, this); // Make sure always a new tree is created when setOption,
     // in TreemapView, we check whether oldTree === newTree
     // to choose mappings approach among old shapes and new shapes.
 
-    return Tree.createTree(root, this, treeOption).data;
+    var tree = Tree.createTree(root, this, beforeLink);
+
+    function beforeLink(nodeData) {
+      nodeData.wrapMethod('getItemModel', function (model, idx) {
+        var node = tree.getNodeByDataIndex(idx);
+        var levelModel = levelModels[node.depth];
+        levelModel && (model.parentModel = levelModel);
+        return model;
+      });
+    }
+
+    return tree.data;
   },
   optionUpdated: function () {
     this.resetViewRoot();
diff --git a/en/builder/src/echarts/chart/themeRiver/ThemeRiverSeries.js b/en/builder/src/echarts/chart/themeRiver/ThemeRiverSeries.js
index e56ff67..b4aeb07 100644
--- a/en/builder/src/echarts/chart/themeRiver/ThemeRiverSeries.js
+++ b/en/builder/src/echarts/chart/themeRiver/ThemeRiverSeries.js
@@ -54,9 +54,22 @@ var ThemeRiverSeries = SeriesModel.extend({
    * @return {Array}
    */
   fixData: function (data) {
-    var rawDataLength = data.length; // grouped data by name
+    var rawDataLength = data.length;
+    /**
+     * Make sure every layer data get the same keys.
+     * The value index tells which layer has visited.
+     * {
+     *  2014/01/01: -1
+     * }
+     */
+
+    var timeValueKeys = {}; // grouped data by name
 
     var groupResult = groupData(data, function (item) {
+      if (!timeValueKeys.hasOwnProperty(item[0])) {
+        timeValueKeys[item[0]] = -1;
+      }
+
       return item[2];
     });
     var layData = [];
@@ -67,40 +80,18 @@ var ThemeRiverSeries = SeriesModel.extend({
       });
     });
     var layerNum = layData.length;
-    var largestLayer = -1;
-    var index = -1;
-
-    for (var i = 0; i < layerNum; ++i) {
-      var len = layData[i].dataList.length;
-
-      if (len > largestLayer) {
-        largestLayer = len;
-        index = i;
-      }
-    }
 
     for (var k = 0; k < layerNum; ++k) {
-      if (k === index) {
-        continue;
-      }
-
       var name = layData[k].name;
 
-      for (var j = 0; j < largestLayer; ++j) {
-        var timeValue = layData[index].dataList[j][0];
-        var length = layData[k].dataList.length;
-        var keyIndex = -1;
-
-        for (var l = 0; l < length; ++l) {
-          var value = layData[k].dataList[l][0];
-
-          if (value === timeValue) {
-            keyIndex = l;
-            break;
-          }
-        }
+      for (var j = 0; j < layData[k].dataList.length; ++j) {
+        var timeValue = layData[k].dataList[j][0];
+        timeValueKeys[timeValue] = k;
+      }
 
-        if (keyIndex === -1) {
+      for (var timeValue in timeValueKeys) {
+        if (timeValueKeys.hasOwnProperty(timeValue) && timeValueKeys[timeValue] !== k) {
+          timeValueKeys[timeValue] = k;
           data[rawDataLength] = [];
           data[rawDataLength][0] = timeValue;
           data[rawDataLength][1] = 0;
diff --git a/en/builder/src/echarts/chart/tree/TreeSeries.js b/en/builder/src/echarts/chart/tree/TreeSeries.js
index 6be8bed..5534548 100644
--- a/en/builder/src/echarts/chart/tree/TreeSeries.js
+++ b/en/builder/src/echarts/chart/tree/TreeSeries.js
@@ -40,7 +40,7 @@ export default SeriesModel.extend({
     };
     var leaves = option.leaves || {};
     var leavesModel = new Model(leaves, this, this.ecModel);
-    var tree = Tree.createTree(root, this, {}, beforeLink);
+    var tree = Tree.createTree(root, this, beforeLink);
 
     function beforeLink(nodeData) {
       nodeData.wrapMethod('getItemModel', function (model, idx) {
diff --git a/en/builder/src/echarts/chart/tree/TreeView.js b/en/builder/src/echarts/chart/tree/TreeView.js
index 8664b9a..15486b0 100644
--- a/en/builder/src/echarts/chart/tree/TreeView.js
+++ b/en/builder/src/echarts/chart/tree/TreeView.js
@@ -426,9 +426,9 @@ function drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sou
 
       graphic.updateProps(edge, {
         shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
-        style: {
+        style: zrUtil.defaults({
           opacity: 1
-        }
+        }, seriesScope.lineStyle)
       }, seriesModel);
     }
   } else if (edgeShape === 'polyline') {
@@ -462,9 +462,9 @@ function drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sou
             parentPoint: [targetLayout.x, targetLayout.y],
             childPoints: childPoints
           },
-          style: {
+          style: zrUtil.defaults({
             opacity: 1
-          }
+          }, seriesScope.lineStyle)
         }, seriesModel);
       }
     } else {}
diff --git a/en/builder/src/echarts/chart/treemap/TreemapSeries.js b/en/builder/src/echarts/chart/treemap/TreemapSeries.js
index f1317aa..251d50c 100644
--- a/en/builder/src/echarts/chart/treemap/TreemapSeries.js
+++ b/en/builder/src/echarts/chart/treemap/TreemapSeries.js
@@ -195,21 +195,30 @@ export default SeriesModel.extend({
       children: option.data
     };
     completeTreeValue(root);
-    var levels = option.levels || [];
+    var levels = option.levels || []; // Used in "visual priority" in `treemapVisual.js`.
+    // This way is a little tricky, must satisfy the precondition:
+    //   1. There is no `treeNode.getModel('itemStyle.xxx')` used.
+    //   2. The `Model.prototype.getModel()` will not use any clone-like way.
+
+    var designatedVisualItemStyle = this.designatedVisualItemStyle = {};
+    var designatedVisualModel = new Model({
+      itemStyle: designatedVisualItemStyle
+    }, this, ecModel);
     levels = option.levels = setDefault(levels, ecModel);
     var levelModels = zrUtil.map(levels || [], function (levelDefine) {
-      return new Model(levelDefine, this, ecModel);
+      return new Model(levelDefine, designatedVisualModel, ecModel);
     }, this); // Make sure always a new tree is created when setOption,
     // in TreemapView, we check whether oldTree === newTree
     // to choose mappings approach among old shapes and new shapes.
 
-    var tree = Tree.createTree(root, this, null, beforeLink);
+    var tree = Tree.createTree(root, this, beforeLink);
 
     function beforeLink(nodeData) {
       nodeData.wrapMethod('getItemModel', function (model, idx) {
         var node = tree.getNodeByDataIndex(idx);
-        var levelModel = levelModels[node.depth];
-        levelModel && (model.parentModel = levelModel);
+        var levelModel = levelModels[node.depth]; // If no levelModel, we also need `designatedVisualModel`.
+
+        model.parentModel = levelModel || designatedVisualModel;
         return model;
       });
     }
diff --git a/en/builder/src/echarts/chart/treemap/treemapLayout.js b/en/builder/src/echarts/chart/treemap/treemapLayout.js
index 92ab6f1..9ce8424 100644
--- a/en/builder/src/echarts/chart/treemap/treemapLayout.js
+++ b/en/builder/src/echarts/chart/treemap/treemapLayout.js
@@ -417,7 +417,7 @@ function position(row, rowFixedLength, rect, halfGapWidth, flush) {
 
   rect[xy[idx1WhenH]] += rowOtherLength;
   rect[wh[idx1WhenH]] -= rowOtherLength;
-} // Return [containerWidth, containerHeight] as defualt.
+} // Return [containerWidth, containerHeight] as default.
 
 
 function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) {
diff --git a/en/builder/src/echarts/chart/treemap/treemapVisual.js b/en/builder/src/echarts/chart/treemap/treemapVisual.js
index 083573b..99d5b71 100644
--- a/en/builder/src/echarts/chart/treemap/treemapVisual.js
+++ b/en/builder/src/echarts/chart/treemap/treemapVisual.js
@@ -26,21 +26,17 @@ export default {
   reset: function (seriesModel, ecModel, api, payload) {
     var tree = seriesModel.getData().tree;
     var root = tree.root;
-    var seriesItemStyleModel = seriesModel.getModel(ITEM_STYLE_NORMAL);
 
     if (root.isRemoved()) {
       return;
     }
 
-    var levelItemStyles = zrUtil.map(tree.levelModels, function (levelModel) {
-      return levelModel ? levelModel.get(ITEM_STYLE_NORMAL) : null;
-    });
     travelTree(root, // Visual should calculate from tree root but not view root.
-    {}, levelItemStyles, seriesItemStyleModel, seriesModel.getViewRoot().getAncestors(), seriesModel);
+    {}, seriesModel.getViewRoot().getAncestors(), seriesModel);
   }
 };
 
-function travelTree(node, designatedVisual, levelItemStyles, seriesItemStyleModel, viewRootAncestors, seriesModel) {
+function travelTree(node, designatedVisual, viewRootAncestors, seriesModel) {
   var nodeModel = node.getModel();
   var nodeLayout = node.getLayout(); // Optimize
 
@@ -49,8 +45,7 @@ function travelTree(node, designatedVisual, levelItemStyles, seriesItemStyleMode
   }
 
   var nodeItemStyleModel = node.getModel(ITEM_STYLE_NORMAL);
-  var levelItemStyle = levelItemStyles[node.depth];
-  var visuals = buildVisuals(nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel); // calculate border color
+  var visuals = buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel); // calculate border color
 
   var borderColor = nodeItemStyleModel.get('borderColor');
   var borderColorSaturation = nodeItemStyleModel.get('borderColorSaturation');
@@ -76,21 +71,20 @@ function travelTree(node, designatedVisual, levelItemStyles, seriesItemStyleMode
       // If higher than viewRoot, only ancestors of viewRoot is needed to visit.
       if (child.depth >= viewRootAncestors.length || child === viewRootAncestors[child.depth]) {
         var childVisual = mapVisual(nodeModel, visuals, child, index, mapping, seriesModel);
-        travelTree(child, childVisual, levelItemStyles, seriesItemStyleModel, viewRootAncestors, seriesModel);
+        travelTree(child, childVisual, viewRootAncestors, seriesModel);
       }
     });
   }
 }
 
-function buildVisuals(nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel) {
+function buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel) {
   var visuals = zrUtil.extend({}, designatedVisual);
+  var designatedVisualItemStyle = seriesModel.designatedVisualItemStyle;
   zrUtil.each(['color', 'colorAlpha', 'colorSaturation'], function (visualName) {
     // Priority: thisNode > thisLevel > parentNodeDesignated > seriesModel
-    var val = nodeItemStyleModel.get(visualName, true); // Ignore parent
-
-    val == null && levelItemStyle && (val = levelItemStyle[visualName]);
-    val == null && (val = designatedVisual[visualName]);
-    val == null && (val = seriesItemStyleModel.get(visualName));
+    designatedVisualItemStyle[visualName] = designatedVisual[visualName];
+    var val = nodeItemStyleModel.get(visualName);
+    designatedVisualItemStyle[visualName] = null;
     val != null && (visuals[visualName] = val);
   });
   return visuals;
diff --git a/en/builder/src/echarts/component/axisPointer/axisTrigger.js b/en/builder/src/echarts/component/axisPointer/axisTrigger.js
index 1ffc5c5..95d009b 100644
--- a/en/builder/src/echarts/component/axisPointer/axisTrigger.js
+++ b/en/builder/src/echarts/component/axisPointer/axisTrigger.js
@@ -153,7 +153,7 @@ function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) {
   var payloadInfo = buildPayloadsBySeries(newValue, axisInfo);
   var payloadBatch = payloadInfo.payloadBatch;
   var snapToValue = payloadInfo.snapToValue; // Fill content of event obj for echarts.connect.
-  // By defualt use the first involved series data as a sample to connect.
+  // By default use the first involved series data as a sample to connect.
 
   if (payloadBatch[0] && outputFinder.seriesIndex == null) {
     zrUtil.extend(outputFinder, payloadBatch[0]);
diff --git a/en/builder/src/echarts/component/legend/ScrollableLegendView.js b/en/builder/src/echarts/component/legend/ScrollableLegendView.js
index dc00046..bbfe7e5 100644
--- a/en/builder/src/echarts/component/legend/ScrollableLegendView.js
+++ b/en/builder/src/echarts/component/legend/ScrollableLegendView.js
@@ -404,7 +404,7 @@ var ScrollableLegendView = LegendView.extend({
     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
+      // we use defaultIndex. But the index on the legend model and
       // action payload is still illegal. That case will not be
       // changed until some scenario requires.
 
diff --git a/en/builder/src/echarts/component/marker/MarkAreaView.js b/en/builder/src/echarts/component/marker/MarkAreaView.js
index 3a9e9d2..8b2147a 100644
--- a/en/builder/src/echarts/component/marker/MarkAreaView.js
+++ b/en/builder/src/echarts/component/marker/MarkAreaView.js
@@ -186,32 +186,70 @@ MarkerView.extend({
 
     areaData.each(function (idx) {
       // Layout
-      areaData.setItemLayout(idx, zrUtil.map(dimPermutations, function (dim) {
+      var points = zrUtil.map(dimPermutations, function (dim) {
         return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
-      })); // Visual
+      }); // If none of the area is inside coordSys, allClipped is set to be true
+      // in layout so that label will not be displayed. See #12591
+
+      var allClipped = true;
+      zrUtil.each(dimPermutations, function (dim) {
+        if (!allClipped) {
+          return;
+        }
+
+        var xValue = areaData.get(dim[0], idx);
+        var yValue = areaData.get(dim[1], idx); // If is infinity, the axis should be considered not clipped
+
+        if ((isInifinity(xValue) || coordSys.getAxis('x').containData(xValue)) && (isInifinity(yValue) || coordSys.getAxis('y').containData(yValue))) {
+          allClipped = false;
+        }
+      });
+      areaData.setItemLayout(idx, {
+        points: points,
+        allClipped: allClipped
+      }); // Visual
 
       areaData.setItemVisual(idx, {
         color: seriesData.getVisual('color')
       });
     });
     areaData.diff(polygonGroup.__data).add(function (idx) {
-      var polygon = new graphic.Polygon({
-        shape: {
-          points: areaData.getItemLayout(idx)
-        }
-      });
-      areaData.setItemGraphicEl(idx, polygon);
-      polygonGroup.group.add(polygon);
+      var layout = areaData.getItemLayout(idx);
+
+      if (!layout.allClipped) {
+        var polygon = new graphic.Polygon({
+          shape: {
+            points: layout.points
+          }
+        });
+        areaData.setItemGraphicEl(idx, polygon);
+        polygonGroup.group.add(polygon);
+      }
     }).update(function (newIdx, oldIdx) {
       var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx);
 
-      graphic.updateProps(polygon, {
-        shape: {
-          points: areaData.getItemLayout(newIdx)
+      var layout = areaData.getItemLayout(newIdx);
+
+      if (!layout.allClipped) {
+        if (polygon) {
+          graphic.updateProps(polygon, {
+            shape: {
+              points: layout.points
+            }
+          }, maModel, newIdx);
+        } else {
+          polygon = new graphic.Polygon({
+            shape: {
+              points: layout.points
+            }
+          });
         }
-      }, maModel, newIdx);
-      polygonGroup.group.add(polygon);
-      areaData.setItemGraphicEl(newIdx, polygon);
+
+        areaData.setItemGraphicEl(newIdx, polygon);
+        polygonGroup.group.add(polygon);
+      } else if (polygon) {
+        polygonGroup.group.remove(polygon);
+      }
     }).remove(function (idx) {
       var polygon = polygonGroup.__data.getItemGraphicEl(idx);
 
diff --git a/en/builder/src/echarts/component/marker/MarkLineView.js b/en/builder/src/echarts/component/marker/MarkLineView.js
index 9962bf9..2147d17 100644
--- a/en/builder/src/echarts/component/marker/MarkLineView.js
+++ b/en/builder/src/echarts/component/marker/MarkLineView.js
@@ -250,8 +250,10 @@ export default MarkerView.extend({
       });
       lineData.setItemLayout(idx, [fromData.getItemLayout(idx), toData.getItemLayout(idx)]);
       lineData.setItemVisual(idx, {
+        'fromSymbolRotate': fromData.getItemVisual(idx, 'symbolRotate'),
         'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'),
         'fromSymbol': fromData.getItemVisual(idx, 'symbol'),
+        'toSymbolRotate': toData.getItemVisual(idx, 'symbolRotate'),
         'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'),
         'toSymbol': toData.getItemVisual(idx, 'symbol')
       });
@@ -269,6 +271,7 @@ export default MarkerView.extend({
       var itemModel = data.getItemModel(idx);
       updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api);
       data.setItemVisual(idx, {
+        symbolRotate: itemModel.get('symbolRotate'),
         symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
         symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
         color: itemModel.get('itemStyle.color') || seriesData.getVisual('color')
diff --git a/en/builder/src/echarts/component/marker/MarkPointView.js b/en/builder/src/echarts/component/marker/MarkPointView.js
index 8e7c18b..44414be 100644
--- a/en/builder/src/echarts/component/marker/MarkPointView.js
+++ b/en/builder/src/echarts/component/marker/MarkPointView.js
@@ -91,10 +91,12 @@ export default MarkerView.extend({
       var itemModel = mpData.getItemModel(idx);
       var symbol = itemModel.getShallow('symbol');
       var symbolSize = itemModel.getShallow('symbolSize');
+      var symbolRotate = itemModel.getShallow('symbolRotate');
       var isFnSymbol = zrUtil.isFunction(symbol);
       var isFnSymbolSize = zrUtil.isFunction(symbolSize);
+      var isFnSymbolRotate = zrUtil.isFunction(symbolRotate);
 
-      if (isFnSymbol || isFnSymbolSize) {
+      if (isFnSymbol || isFnSymbolSize || isFnSymbolRotate) {
         var rawIdx = mpModel.getRawValue(idx);
         var dataParams = mpModel.getDataParams(idx);
 
@@ -106,11 +108,16 @@ export default MarkerView.extend({
           // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据?
           symbolSize = symbolSize(rawIdx, dataParams);
         }
+
+        if (isFnSymbolRotate) {
+          symbolRotate = symbolRotate(rawIdx, dataParams);
+        }
       }
 
       mpData.setItemVisual(idx, {
         symbol: symbol,
         symbolSize: symbolSize,
+        symbolRotate: symbolRotate,
         color: itemModel.get('itemStyle.color') || seriesData.getVisual('color')
       });
     }); // TODO Text are wrong
diff --git a/en/builder/src/echarts/component/marker/MarkerModel.js b/en/builder/src/echarts/component/marker/MarkerModel.js
index c104533..73dbb49 100644
--- a/en/builder/src/echarts/component/marker/MarkerModel.js
+++ b/en/builder/src/echarts/component/marker/MarkerModel.js
@@ -107,15 +107,16 @@ var MarkerModel = echarts.extendComponentModel({
       }, this);
     }
   },
-  formatTooltip: function (dataIndex) {
+  formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
     var data = this.getData();
     var value = this.getRawValue(dataIndex);
     var formattedValue = zrUtil.isArray(value) ? zrUtil.map(value, addCommas).join(', ') : addCommas(value);
     var name = data.getName(dataIndex);
     var html = encodeHTML(this.name);
+    var newLine = renderMode === 'html' ? '<br/>' : '\n';
 
     if (value != null || name) {
-      html += '<br />';
+      html += newLine;
     }
 
     if (name) {
diff --git a/en/builder/src/echarts/component/timeline/SliderTimelineView.js b/en/builder/src/echarts/component/timeline/SliderTimelineView.js
index e891586..5c3eb2e 100644
--- a/en/builder/src/echarts/component/timeline/SliderTimelineView.js
+++ b/en/builder/src/echarts/component/timeline/SliderTimelineView.js
@@ -535,7 +535,13 @@ function getViewRect(model, api) {
 }
 
 function makeIcon(timelineModel, objPath, rect, opts) {
-  var icon = graphic.makePath(timelineModel.get(objPath).replace(/^path:\/\//, ''), zrUtil.clone(opts || {}), new BoundingRect(rect[0], rect[1], rect[2], rect[3]), 'center');
+  var style = opts.style;
+  var icon = graphic.createIcon(timelineModel.get(objPath), opts || {}, new BoundingRect(rect[0], rect[1], rect[2], rect[3])); // TODO createIcon won't use style in opt.
+
+  if (style) {
+    icon.setStyle(style);
+  }
+
   return icon;
 }
 /**
diff --git a/en/builder/src/echarts/component/title.js b/en/builder/src/echarts/component/title.js
index 63596d9..1e5c97a 100644
--- a/en/builder/src/echarts/component/title.js
+++ b/en/builder/src/echarts/component/title.js
@@ -131,7 +131,7 @@ echarts.extendComponentView({
 
     if (sublink) {
       subTextEl.on('click', function () {
-        windowOpen(link, '_' + titleModel.get('subtarget'));
+        windowOpen(sublink, '_' + titleModel.get('subtarget'));
       });
     }
 
diff --git a/en/builder/src/echarts/component/toolbox/feature/DataView.js b/en/builder/src/echarts/component/toolbox/feature/DataView.js
index 7e4923a..36c0d83 100644
--- a/en/builder/src/echarts/component/toolbox/feature/DataView.js
+++ b/en/builder/src/echarts/component/toolbox/feature/DataView.js
@@ -91,7 +91,8 @@ function assembleSeriesWithCategoryAxis(series) {
     }));
     var columns = [categoryAxis.model.getCategories()];
     zrUtil.each(group.series, function (series) {
-      columns.push(series.getRawData().mapArray(valueAxisDim, function (val) {
+      var rawData = series.getRawData();
+      columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim), function (val) {
         return val;
       }));
     }); // Assemble table content
@@ -217,7 +218,15 @@ function parseListContents(str) {
   var data = [];
 
   for (var i = 0; i < lines.length; i++) {
-    var items = trim(lines[i]).split(itemSplitRegex);
+    // if line is empty, ignore it.
+    // there is a case that a user forgot to delete `\n`.
+    var line = trim(lines[i]);
+
+    if (!line) {
+      continue;
+    }
+
+    var items = line.split(itemSplitRegex);
     var name = '';
     var value;
     var hasName = false;
@@ -424,14 +433,20 @@ function tryMergeDataOption(newData, originalData) {
     var original = originalData && originalData[idx];
 
     if (zrUtil.isObject(original) && !zrUtil.isArray(original)) {
-      if (zrUtil.isObject(newVal) && !zrUtil.isArray(newVal)) {
-        newVal = newVal.value;
-      } // Original data has option
+      var newValIsObject = zrUtil.isObject(newVal) && !zrUtil.isArray(newVal);
 
+      if (!newValIsObject) {
+        newVal = {
+          value: newVal
+        };
+      } // original data has name but new data has no name
 
-      return zrUtil.defaults({
-        value: newVal
-      }, original);
+
+      var shouldDeleteName = original.name != null && newVal.name == null; // Original data has option
+
+      newVal = zrUtil.defaults(newVal, original);
+      shouldDeleteName && delete newVal.name;
+      return newVal;
     } else {
       return newVal;
     }
diff --git a/en/builder/src/echarts/component/toolbox/feature/DataZoom.js b/en/builder/src/echarts/component/toolbox/feature/DataZoom.js
index 65abfa5..e40b1b3 100644
--- a/en/builder/src/echarts/component/toolbox/feature/DataZoom.js
+++ b/en/builder/src/echarts/component/toolbox/feature/DataZoom.js
@@ -54,7 +54,11 @@ DataZoom.defaultOption = {
     back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
   },
   // `zoom`, `back`
-  title: zrUtil.clone(dataZoomLang.title)
+  title: zrUtil.clone(dataZoomLang.title),
+  brushStyle: {
+    borderWidth: 0,
+    color: 'rgba(0,0,0,0.2)'
+  }
 };
 var proto = DataZoom.prototype;
 
@@ -214,11 +218,7 @@ function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
     return targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared ? 'lineX' : !targetInfo.xAxisDeclared && targetInfo.yAxisDeclared ? 'lineY' : 'rect';
   })).enableBrush(zoomActive ? {
     brushType: 'auto',
-    brushStyle: {
-      // FIXME user customized?
-      lineWidth: 0,
-      fill: 'rgba(0,0,0,0.2)'
-    }
+    brushStyle: featureModel.getModel('brushStyle').getItemStyle()
   } : false);
 }
 
diff --git a/en/builder/src/echarts/component/toolbox/feature/SaveAsImage.js b/en/builder/src/echarts/component/toolbox/feature/SaveAsImage.js
index 5d90fac..5c79e2c 100644
--- a/en/builder/src/echarts/component/toolbox/feature/SaveAsImage.js
+++ b/en/builder/src/echarts/component/toolbox/feature/SaveAsImage.js
@@ -62,7 +62,8 @@ proto.onclick = function (ecModel, api) {
     $a.target = '_blank';
     $a.href = url;
     var evt = new MouseEvent('click', {
-      view: window,
+      // some micro front-end framework, window maybe is a Proxy
+      view: document.defaultView,
       bubbles: true,
       cancelable: false
     });
diff --git a/en/builder/src/echarts/component/tooltip/TooltipContent.js b/en/builder/src/echarts/component/tooltip/TooltipContent.js
index 4a6b6e1..283d086 100644
--- a/en/builder/src/echarts/component/tooltip/TooltipContent.js
+++ b/en/builder/src/echarts/component/tooltip/TooltipContent.js
@@ -52,7 +52,18 @@ function assembleFont(textStyleModel) {
   var color = textStyleModel.getTextColor();
   color && cssText.push('color:' + color);
   cssText.push('font:' + textStyleModel.getFont());
-  fontSize && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
+  var lineHeight = textStyleModel.get('lineHeight');
+
+  if (lineHeight == null) {
+    lineHeight = Math.round(fontSize * 3 / 2);
+  }
+
+  fontSize && cssText.push('line-height:' + lineHeight + 'px');
+  var shadowColor = textStyleModel.get('textShadowColor');
+  var shadowBlur = textStyleModel.get('textShadowBlur') || 0;
+  var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0;
+  var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0;
+  shadowBlur && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px ' + shadowBlur + 'px ' + shadowColor);
   each(['decoration', 'align'], function (name) {
     var val = textStyleModel.get(name);
     val && cssText.push('text-' + name + ':' + val);
@@ -126,6 +137,10 @@ function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
       out[1] += viewportRootOffset.offsetTop;
     }
   }
+
+  out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+
+  out[3] = out[1] / zr.getHeight(); // The ratio of top to height
 }
 /**
  * @alias module:echarts/component/tooltip/TooltipContent
@@ -150,7 +165,8 @@ function TooltipContent(container, api, opt) {
   this.el = el;
   var zr = this._zr = api.getZr();
   var appendToBody = this._appendToBody = opt && opt.appendToBody;
-  this._styleCoord = [0, 0];
+  this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
+
   makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
 
   if (appendToBody) {
@@ -221,7 +237,7 @@ TooltipContent.prototype = {
   /**
    * Update when tooltip is rendered
    */
-  update: function () {
+  update: function (tooltipModel) {
     // FIXME
     // Move this logic to ec main?
     var container = this._container;
@@ -230,10 +246,28 @@ TooltipContent.prototype = {
 
     if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
       domStyle.position = 'relative';
-    } // Hide the tooltip
+    }
+
+    var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+    alwaysShowContent && this._moveTooltipIfResized(); // Hide the tooltip
     // PENDING
     // this.hide();
+  },
+
+  /**
+   * when `alwaysShowContent` is true,
+   * we should move the tooltip after chart resized
+   */
+  _moveTooltipIfResized: function () {
+    var ratioX = this._styleCoord[2]; // The ratio of left to width
+
+    var ratioY = this._styleCoord[3]; // The ratio of top to height
+
+    var realX = ratioX * this._zr.getWidth();
+
+    var realY = ratioY * this._zr.getHeight();
 
+    this.moveTo(realX, realY);
   },
   show: function (tooltipModel) {
     clearTimeout(this._hideTimeout);
@@ -243,10 +277,10 @@ TooltipContent.prototype = {
     // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
     // we should set initial value to `left` and `top`.
     + ';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
+    el.style.display = el.innerHTML ? 'block' : 'none'; // If mouse occasionally move over the tooltip, a mouseout event will be
+    // triggered by canvas, and cause some unexpectable result like dragging
     // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
-    // it. Although it is not suppored by IE8~IE10, fortunately it is a rare
+    // it. Although it is not supported by IE8~IE10, fortunately it is a rare
     // scenario.
 
     el.style.pointerEvents = this._enterable ? 'auto' : 'none';
@@ -276,7 +310,7 @@ TooltipContent.prototype = {
   hideLater: function (time) {
     if (this._show && !(this._inContent && this._enterable)) {
       if (time) {
-        this._hideDelay = time; // Set show false to avoid invoke hideLater mutiple times
+        this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times
 
         this._show = false;
         this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time);
diff --git a/en/builder/src/echarts/component/tooltip/TooltipRichContent.js b/en/builder/src/echarts/component/tooltip/TooltipRichContent.js
index 54c1d95..603ce30 100644
--- a/en/builder/src/echarts/component/tooltip/TooltipRichContent.js
+++ b/en/builder/src/echarts/component/tooltip/TooltipRichContent.js
@@ -19,13 +19,26 @@
 import * as zrUtil from 'zrender/src/core/util'; // import Group from 'zrender/src/container/Group';
 
 import Text from 'zrender/src/graphic/Text';
+import * as graphicUtil from '../../util/graphic';
+
+function makeStyleCoord(out, zr, zrX, zrY) {
+  out[0] = zrX;
+  out[1] = zrY;
+  out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+
+  out[3] = out[1] / zr.getHeight(); // The ratio of top to height
+}
 /**
  * @alias module:echarts/component/tooltip/TooltipRichContent
  * @constructor
  */
 
+
 function TooltipRichContent(api) {
-  this._zr = api.getZr();
+  var zr = this._zr = api.getZr();
+  this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
+
+  makeStyleCoord(this._styleCoord, zr, api.getWidth() / 2, api.getHeight() / 2);
   this._show = false;
   /**
    * @private
@@ -46,7 +59,25 @@ TooltipRichContent.prototype = {
   /**
    * Update when tooltip is rendered
    */
-  update: function () {// noop
+  update: function (tooltipModel) {
+    var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+    alwaysShowContent && this._moveTooltipIfResized();
+  },
+
+  /**
+   * when `alwaysShowContent` is true,
+   * we should move the tooltip after chart resized
+   */
+  _moveTooltipIfResized: function () {
+    var ratioX = this._styleCoord[2]; // The ratio of left to width
+
+    var ratioY = this._styleCoord[3]; // The ratio of top to height
+
+    var realX = ratioX * this._zr.getWidth();
+
+    var realY = ratioY * this._zr.getHeight();
+
+    this.moveTo(realX, realY);
   },
   show: function (tooltipModel) {
     if (this._hideTimeout) {
@@ -101,16 +132,24 @@ TooltipRichContent.prototype = {
       startId = text.indexOf('{marker');
     }
 
+    var textStyleModel = tooltipModel.getModel('textStyle');
+    var fontSize = textStyleModel.get('fontSize');
+    var lineHeight = tooltipModel.get('textLineHeight');
+
+    if (lineHeight == null) {
+      lineHeight = Math.round(fontSize * 3 / 2);
+    }
+
     this.el = new Text({
-      style: {
+      style: graphicUtil.setTextStyle({}, textStyleModel, {
         rich: markers,
         text: content,
-        textLineHeight: 20,
         textBackgroundColor: tooltipModel.get('backgroundColor'),
         textBorderRadius: tooltipModel.get('borderRadius'),
         textFill: tooltipModel.get('textStyle.color'),
-        textPadding: tooltipModel.get('padding')
-      },
+        textPadding: tooltipModel.get('padding'),
+        textLineHeight: lineHeight
+      }),
       z: tooltipModel.get('z')
     });
 
@@ -145,7 +184,9 @@ TooltipRichContent.prototype = {
   },
   moveTo: function (x, y) {
     if (this.el) {
-      this.el.attr('position', [x, y]);
+      var styleCoord = this._styleCoord;
+      makeStyleCoord(styleCoord, this._zr, x, y);
+      this.el.attr('position', [styleCoord[0], styleCoord[1]]);
     }
   },
   hide: function () {
@@ -158,7 +199,7 @@ TooltipRichContent.prototype = {
   hideLater: function (time) {
     if (this._show && !(this._inContent && this._enterable)) {
       if (time) {
-        this._hideDelay = time; // Set show false to avoid invoke hideLater mutiple times
+        this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times
 
         this._show = false;
         this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time);
@@ -170,6 +211,13 @@ TooltipRichContent.prototype = {
   isShow: function () {
     return this._show;
   },
+  dispose: function () {
+    clearTimeout(this._hideTimeout);
+
+    if (this.el) {
+      this._zr.remove(this.el);
+    }
+  },
   getOuterSize: function () {
     var size = this.getSize();
     return {
diff --git a/en/builder/src/echarts/component/tooltip/TooltipView.js b/en/builder/src/echarts/component/tooltip/TooltipView.js
index 100bf3e..0c5d6d2 100644
--- a/en/builder/src/echarts/component/tooltip/TooltipView.js
+++ b/en/builder/src/echarts/component/tooltip/TooltipView.js
@@ -105,7 +105,7 @@ export default echarts.extendComponentView({
 
     this._alwaysShowContent = tooltipModel.get('alwaysShowContent');
     var tooltipContent = this._tooltipContent;
-    tooltipContent.update();
+    tooltipContent.update(tooltipModel);
     tooltipContent.setEnterable(tooltipModel.get('enterable'));
 
     this._initGlobalListener();
@@ -309,7 +309,7 @@ export default echarts.extendComponentView({
   _showOrMove: function (tooltipModel, cb) {
     // showDelay is used in this case: tooltip.enterable is set
     // as true. User intent to move mouse into tooltip and click
-    // something. `showDelay` makes it easyer to enter the content
+    // something. `showDelay` makes it easier to enter the content
     // but tooltip do not move immediately.
     var delay = tooltipModel.get('showDelay');
     cb = zrUtil.bind(cb, this);
@@ -375,7 +375,7 @@ export default echarts.extendComponentView({
           }
         }); // Default tooltip content
         // FIXME
-        // (1) shold be the first data which has name?
+        // (1) should be the first data which has name?
         // (2) themeRiver, firstDataIndex is array, and first line is unnecessary.
 
         var firstLine = valueLabel;
@@ -465,7 +465,7 @@ export default echarts.extendComponentView({
     var subTooltipModel = new Model(tooltipOpt, this._tooltipModel, this._ecModel);
     var defaultHtml = subTooltipModel.get('content');
     var asyncTicket = Math.random(); // Do not check whether `trigger` is 'none' here, because `trigger`
-    // only works on cooridinate system. In fact, we have not found case
+    // only works on coordinate system. In fact, we have not found case
     // that requires setting `trigger` nothing on component yet.
 
     this._showOrMove(subTooltipModel, function () {
diff --git a/en/builder/src/echarts/component/visualMap/VisualMapModel.js b/en/builder/src/echarts/component/visualMap/VisualMapModel.js
index c1a9e43..f2dc807 100644
--- a/en/builder/src/echarts/component/visualMap/VisualMapModel.js
+++ b/en/builder/src/echarts/component/visualMap/VisualMapModel.js
@@ -370,7 +370,7 @@ var VisualMapModel = echarts.extendComponentModel({
       // Originally we use visualMap.color as the default color, but setOption at
       // the second time the default color will be erased. So we change to use
       // constant DEFAULT_COLOR.
-      // If user do not want the defualt color, set inRange: {color: null}.
+      // If user do not want the default color, set inRange: {color: null}.
 
 
       base.inRange = base.inRange || {
diff --git a/en/builder/src/echarts/coord/axisDefault.js b/en/builder/src/echarts/coord/axisDefault.js
index b690a5c..8c4912d 100644
--- a/en/builder/src/echarts/coord/axisDefault.js
+++ b/en/builder/src/echarts/coord/axisDefault.js
@@ -27,7 +27,7 @@ var defaultOption = {
   name: '',
   // 'start' | 'middle' | 'end'
   nameLocation: 'end',
-  // By degree. By defualt auto rotate by nameLocation.
+  // By degree. By default auto rotate by nameLocation.
   nameRotate: null,
   nameTruncate: {
     maxWidth: null,
diff --git a/en/builder/src/echarts/coord/axisHelper.js b/en/builder/src/echarts/coord/axisHelper.js
index b76eeeb..bfb64f9 100644
--- a/en/builder/src/echarts/coord/axisHelper.js
+++ b/en/builder/src/echarts/coord/axisHelper.js
@@ -356,8 +356,8 @@ function rotateTextRect(textRect, rotate) {
   var boundingBox = textRect.plain();
   var beforeWidth = boundingBox.width;
   var beforeHeight = boundingBox.height;
-  var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
-  var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
+  var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
+  var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
   var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
   return rotatedRect;
 }
diff --git a/en/builder/src/echarts/coord/geo/GeoModel.js b/en/builder/src/echarts/coord/geo/GeoModel.js
index d4b8380..ad637ad 100644
--- a/en/builder/src/echarts/coord/geo/GeoModel.js
+++ b/en/builder/src/echarts/coord/geo/GeoModel.js
@@ -117,8 +117,9 @@ var GeoModel = ComponentModel.extend({
    * @return {string}
    */
   getFormattedLabel: function (name, status) {
+    status = status || 'normal';
     var regionModel = this.getRegionModel(name);
-    var formatter = regionModel.get('label' + (status === 'normal' ? '.' : status + '.') + 'formatter');
+    var formatter = regionModel.get((status === 'normal' ? '' : status + '.') + 'label.formatter');
     var params = {
       name: name
     };
diff --git a/en/builder/src/echarts/data/Graph.js b/en/builder/src/echarts/data/Graph.js
index 87ef723..e6ebc2e 100644
--- a/en/builder/src/echarts/data/Graph.js
+++ b/en/builder/src/echarts/data/Graph.js
@@ -164,12 +164,7 @@ graphProto.addEdge = function (n1, n2, dataIndex) {
     return;
   }
 
-  var key = n1.id + '-' + n2.id; // PENDING
-
-  if (edgesMap[key]) {
-    return;
-  }
-
+  var key = n1.id + '-' + n2.id;
   var edge = new Edge(n1, n2, dataIndex);
   edge.hostGraph = this;
 
diff --git a/en/builder/src/echarts/data/List.js b/en/builder/src/echarts/data/List.js
index 7778a5a..3e0a834 100644
--- a/en/builder/src/echarts/data/List.js
+++ b/en/builder/src/echarts/data/List.js
@@ -384,7 +384,7 @@ listProto.mapDimension = function (coordDim, idx) {
  * Initialize from data
  * @param {Array.<Object|number|Array>} data source or data or data provider.
  * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
- *        defualt label/tooltip.
+ *        default label/tooltip.
  *        A name can be specified in encode.itemName,
  *        or dataItem.name (only for series option data),
  *        or provided in nameList from outside.
diff --git a/en/builder/src/echarts/data/Tree.js b/en/builder/src/echarts/data/Tree.js
index 74ec726..b00de03 100644
--- a/en/builder/src/echarts/data/Tree.js
+++ b/en/builder/src/echarts/data/Tree.js
@@ -23,7 +23,6 @@
  * @module echarts/data/Tree
  */
 import * as zrUtil from 'zrender/src/core/util';
-import Model from '../model/Model';
 import linkList from './helper/linkList';
 import List from './List';
 import createDimensions from './helper/createDimensions';
@@ -256,20 +255,7 @@ TreeNode.prototype = {
 
     var hostTree = this.hostTree;
     var itemModel = hostTree.data.getItemModel(this.dataIndex);
-    var levelModel = this.getLevelModel(); // FIXME: refactor levelModel to "beforeLink", and remove levelModel here.
-
-    if (levelModel) {
-      return itemModel.getModel(path, levelModel.getModel(path));
-    } else {
-      return itemModel.getModel(path);
-    }
-  },
-
-  /**
-   * @return {module:echarts/model/Model}
-   */
-  getLevelModel: function () {
-    return (this.hostTree.levelModels || [])[this.depth];
+    return itemModel.getModel(path);
   },
 
   /**
@@ -342,10 +328,9 @@ TreeNode.prototype = {
  * @constructor
  * @alias module:echarts/data/Tree
  * @param {module:echarts/model/Model} hostModel
- * @param {Array.<Object>} levelOptions
  */
 
-function Tree(hostModel, levelOptions) {
+function Tree(hostModel) {
   /**
    * @type {module:echarts/data/Tree~TreeNode}
    * @readOnly
@@ -371,15 +356,6 @@ function Tree(hostModel, levelOptions) {
    */
 
   this.hostModel = hostModel;
-  /**
-   * @private
-   * @readOnly
-   * @type {Array.<module:echarts/model/Model}
-   */
-
-  this.levelModels = zrUtil.map(levelOptions || [], function (levelDefine) {
-    return new Model(levelDefine, hostModel, hostModel.ecModel);
-  });
 }
 
 Tree.prototype = {
@@ -466,13 +442,11 @@ Tree.prototype = {
  * @static
  * @param {Object} dataRoot Root node.
  * @param {module:echarts/model/Model} hostModel
- * @param {Object} treeOptions
- * @param {Array.<Object>} treeOptions.levels
  * @return module:echarts/data/Tree
  */
 
-Tree.createTree = function (dataRoot, hostModel, treeOptions, beforeLink) {
-  var tree = new Tree(hostModel, treeOptions && treeOptions.levels);
+Tree.createTree = function (dataRoot, hostModel, beforeLink) {
+  var tree = new Tree(hostModel);
   var listData = [];
   var dimMax = 1;
   buildHierarchy(dataRoot);
diff --git a/en/builder/src/echarts/echarts.js b/en/builder/src/echarts/echarts.js
index 8d0573b..f645d49 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.8.0';
+export var version = '4.9.0';
 export var dependencies = {
-  zrender: '4.3.1'
+  zrender: '4.3.2'
 };
 var TEST_FRAME_REMAIN_TIME = 1;
 var PRIORITY_PROCESSOR_FILTER = 1000;
diff --git a/en/builder/src/echarts/layout/barPolar.js b/en/builder/src/echarts/layout/barPolar.js
index 6ead4f3..a957551 100644
--- a/en/builder/src/echarts/layout/barPolar.js
+++ b/en/builder/src/echarts/layout/barPolar.js
@@ -65,7 +65,7 @@ function barLayoutPolar(seriesType, ecModel, api) {
     /*, baseDim*/
     );
     var clampLayout = baseAxis.dim !== 'radius' || !seriesModel.get('roundCap', true);
-    var valueAxisStart = valueAxis.getExtent()[0];
+    var valueAxisStart = valueAxis.dim === 'radius' ? valueAxis.dataToRadius(0) : valueAxis.dataToAngle(0);
 
     for (var idx = 0, len = data.count(); idx < len; idx++) {
       var value = data.get(valueDim, idx);
diff --git a/en/builder/src/echarts/processor/dataSample.js b/en/builder/src/echarts/processor/dataSample.js
index f42ad4f..473371d 100644
--- a/en/builder/src/echarts/processor/dataSample.js
+++ b/en/builder/src/echarts/processor/dataSample.js
@@ -86,7 +86,7 @@ export default function (seriesType) {
         var valueAxis = coordSys.getOtherAxis(baseAxis);
         var extent = baseAxis.getExtent(); // Coordinste system has been resized
 
-        var size = extent[1] - extent[0];
+        var size = Math.abs(extent[1] - extent[0]);
         var rate = Math.round(data.count() / size);
 
         if (rate > 1) {
diff --git a/en/builder/src/echarts/stream/Scheduler.js b/en/builder/src/echarts/stream/Scheduler.js
index 7a281f0..dd07f69 100644
--- a/en/builder/src/echarts/stream/Scheduler.js
+++ b/en/builder/src/echarts/stream/Scheduler.js
@@ -63,7 +63,7 @@ var proto = Scheduler.prototype;
  */
 
 proto.restoreData = function (ecModel, payload) {
-  // TODO: Only restroe needed series and components, but not all components.
+  // TODO: Only restore needed series and components, but not all components.
   // Currently `restoreData` of all of the series and component will be called.
   // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
   // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
diff --git a/en/builder/src/echarts/visual/VisualMapping.js b/en/builder/src/echarts/visual/VisualMapping.js
index 723e4c0..4c3731d 100644
--- a/en/builder/src/echarts/visual/VisualMapping.js
+++ b/en/builder/src/echarts/visual/VisualMapping.js
@@ -45,7 +45,7 @@ var CATEGORY_DEFAULT_VISUAL_INDEX = -1;
  *                                            visual data can be array or object
  *                                            (like: {cate1: '#222', none: '#fff'})
  *                                            or primary types (which represents
- *                                            defualt category visual), otherwise visual
+ *                                            default category visual), otherwise visual
  *                                            can be array or primary (which will be
  *                                            normalized to array).
  *
diff --git a/en/builder/src/zrender/animation/track.js b/en/builder/src/zrender/animation/track.js
index 9056389..ac7c2ba 100755
--- a/en/builder/src/zrender/animation/track.js
+++ b/en/builder/src/zrender/animation/track.js
@@ -186,10 +186,6 @@ export function createTrackClip(target, propName, keyframes, easing, delay, loop
           value = interpolateNumber(kfValues[frame], kfValues[frame + 1], w);
         }
 
-        if (target.aaaa != null) {
-          console.log(target.uuid, value, propName);
-        }
-
         setter(target, propName, value);
       }
     }
diff --git a/en/builder/src/zrender/svg/helper/GradientManager.js b/en/builder/src/zrender/svg/helper/GradientManager.js
index af03d8a..345a357 100644
--- a/en/builder/src/zrender/svg/helper/GradientManager.js
+++ b/en/builder/src/zrender/svg/helper/GradientManager.js
@@ -155,7 +155,7 @@ GradientManager.prototype.updateDom = function (gradient, dom) {
     stop.setAttribute('offset', colors[i].offset * 100 + '%');
     var color = colors[i].color;
 
-    if (color.indexOf('rgba' > -1)) {
+    if (color.indexOf('rgba') > -1) {
       // Fix Safari bug that stop-color not recognizing alpha #9014
       var opacity = colorTool.parse(color)[3];
       var hex = colorTool.toHex(color); // stop-color cannot be color, since:
diff --git a/en/builder/src/zrender/zrender.js b/en/builder/src/zrender/zrender.js
index a237ab5..2e9103f 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.3.1';
+export var version = '4.3.2';
 /**
  * Initializing a zrender instance
  * @param {HTMLElement} dom
diff --git a/en/changelog.html b/en/changelog.html
index 1f91095..7466cfb 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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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,54 @@
     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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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">2020-08-06</div>
+
+<ul>
+<li><p>[Feature] [graph] Support multiple edges to link nodes in graph. <a href="https://github.com/apache/incubator-echarts/pull/12590">#12590</a> (<a href="https://github.com/wf123537200">wf123537200</a>)</p>
+</li>
+<li><p>[Feature] [funnel] Add <code>orient</code> option in funnel. Support horizontal layout. <a href="https://github.com/apache/incubator-echarts/pull/12754">#12754</a> (<a href="https://github.com/regrex">regrex</a>)</p>
+</li>
+<li><p>[Enhancement] [tooltip] Add text shadow options. <a href="https://github.com/apache/incubator-echarts/pull/12664">#12664</a> (<a href="https://github.com/Ovilia">Ovilia</a>)</p>
+</li>
+<li><p>[Enhancement] [toolbox] Add <code>brushStyle</code> option to configuration style of brush rect in the dataZoom feature. <a href="https://github.com/apache/incubator-echarts/pull/12550">#12550</a> (<a href="https://github.com/zhiyuc123">zhiyuc123</a>)</p>
+</li>
+<li><p>[Fix] [themeRiver] Optimize data process in themeRiver. <a href="https://github.com/apache/incubator-echarts/pull/12022">#12022</a> (<a href="https://github.com/Zaynex">Zaynex</a>)</p>
+</li>
+<li><p>[Fix] [toolbox] Fix pie series render incorrectly after editing its data in the dataView feature. <a href="https://github.com/apache/incubator-echarts/pull/12561">#12561</a> (<a href="https://github.com/plainheart">plainheart</a>)</p>
+</li>
+<li><p>[Fix] [toolbox] Fix dataView shows NaN when using dataset. <a href="https://github.com/apache/incubator-echarts/pull/11849">#11849</a> (<a href="https://github.com/susiwen8">susiwen8</a>)</p>
+</li>
+<li><p>[Fix] [toolbox] Fix saveAsImage may have error in some special environments. <a href="https://github.com/apache/incubator-echarts/pull/12643">#12643</a> (<a href="https://github.com/lzr900515">lzr900515</a>)</p>
+</li>
+<li><p>[Fix] [lines] Fix lines disappear if setOption again without data. <a href="https://github.com/apache/incubator-echarts/pull/12850">#12850</a> (<a href="https://github.com/plainheart">plainheart</a>)</p>
+</li>
+<li><p>[Fix] [sunburst] [treemap] Fix label formatter in <code>levels</code> not work bug. <a href="https://github.com/apache/incubator-echarts/pull/12742">#12742</a> (<a href="https://github.com/Ovilia">Ovilia</a>)</p>
+</li>
+<li><p>[Fix] [bmap] Fix bmap event <code>moveend</code> is always triggered when dragging or zoomend. <a href="https://github.com/apache/incubator-echarts/pull/12558">#12558</a> (<a href="https://github.com/plainheart">plainheart</a>)</p>
+</li>
+<li><p>[Fix] [grid] Fix wrong gap calculation when <code>containLabel</code>is set in grid. <a href="https://github.com/apache/incubator-echarts/issues/12259">#12259</a> (<a href="https://github.com/Ling310">Ling310</a>)</p>
+</li>
+<li><p>[Fix] [tooltip] Fix newline in tooltip of radar and map series when using <code>ricText</code> render mode. <a href="https://github.com/apache/incubator-echarts/pull/12664">#12664</a> (<a href="https://github.com/Ovilia">Ovilia</a>)</p>
+</li>
+<li><p>[Fix] [tooltip] Update tooltip position proportionally when chart resized. <a href="https://github.com/apache/incubator-echarts/pull/12834">#12834</a> (<a href="https://github.com/liulinboyi">liulinboyi</a>)</p>
+</li>
+<li><p>[Fix] [tooltip] Fix tooltip dispose in <code>richText</code> render mode. <a href="https://github.com/apache/incubator-echarts/pull/12608">#12608</a> (<a href="https://github.com/plainheart">plainheart</a>)</p>
+</li>
+<li><p>[Fix] [tree] Fix image symbol not display on first render. <a href="https://github.com/apache/incubator-echarts/pull/12367">#12367</a> (<a href="https://github.com/plainheart">plainheart</a>)</p>
+</li>
+<li><p>[Fix] [geo] Fix label formatter not work bug. <a href="https://github.com/apache/incubator-echarts/pull/12762">#12762</a> (<a href="https://github.com/plainheart">plainheart</a>)</p>
+</li>
+<li><p>[Fix] [bar] Fix error when switching <code>showBackground</code> from <code>false</code> to <code>true</code>. <a href="https://github.com/apache/incubator-echarts/pull/13085">#13085</a> (<a href="https://github.com/easonyq">easonyq</a>)</p>
+</li>
+<li><p>[Fix] [markArea] Fix label is not hidden when markArea is outside the grid. <a href="https://github.com/apache/incubator-echarts/pull/12669">#12669</a> (<a href="https://github.com/Ovilia">Ovilia</a>)</p>
+</li>
+<li><p>[Fix] [markLine] [markPoint] Fix <code>symbolRotate</code> not work bug. <a href="https://github.com/apache/incubator-echarts/pull/12737">#12737</a> <a href="https://github.com/apache/incubator-echarts/pull/12392">#12392</a> (<a href="https://github.com/plainheart">plainheart</a>)</p>
+</li>
+<li><p>[Fix] [polar] Fix bar layout on polar with nagive axis. <a href="https://github.com/apache/incubator-echarts/pull/12418">#12418</a> (<a href="https://github.com/gracelia">gracelia</a>)</p>
+</li>
+</ul>
+<h2 id="v4-8-0">v4.8.0</h2>
 <div class="time">2020-05-25</div>
 
 <ul>
@@ -1300,7 +1347,7 @@ Fix that the line label can not be returned to its original opacity after <code>
 <ul>
 <li>The new echarts</li>
 </ul>
-<footer class="inner-footer"><div class="container"><div class="row"><div class="col-md-8"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessaril [...]
+<footer class="inner-footer"><div class="container"><div class="row"><div class="col-md-8"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessaril [...]
 
 // Fix scroll position covered by nav
 window.addEventListener('hashchange', function() {
diff --git a/en/cheat-sheet.html b/en/cheat-sheet.html
index 4de9511..30d0ea7 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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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,8 +7,8 @@
     document.head.insertBefore(el, document.getElementById('font-hack'));
 }
 </script><title>Cheat Sheet - 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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
-</script><script src="https://cdn.jsdelivr.net/npm/echarts@4.8.0/dist/echarts.min.js"></script><script src="https://echarts.apache.org/en/js/cheat-sheet-en.js?_v_=1598523895644"></script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
+<!--[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 [...]
+</script><script src="https://cdn.jsdelivr.net/npm/echarts@4.8.0/dist/echarts.min.js"></script><script src="https://echarts.apache.org/en/js/cheat-sheet-en.js?_v_=1598903776431"></script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/coding-standard.html b/en/coding-standard.html
index ae1a703..c24b469 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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -574,7 +574,7 @@ var arr = new Array();
 <p><strong>[MUST]</strong> Do not use <code>for in</code> in array traverse.</p>
 <h3 id="others">Others</h3>
 <p><strong>[MUST]</strong> Do not use <code>eval</code> and <code>with</code>. <code>new Function</code> can be used.</p>
-<footer class="inner-footer"><div class="container"><div class="row"><div class="col-md-8"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessaril [...]
+<footer class="inner-footer"><div class="container"><div class="row"><div class="col-md-8"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessaril [...]
 
 var $list = $('#standard-nav');
 $('.page-detail h2, .page-detail h3, .page-detail h4')
diff --git a/en/committers.html b/en/committers.html
index fd41fb2..3ec3e05 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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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>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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/contributing.html b/en/contributing.html
index 08ef5db..5448929 100644
--- a/en/contributing.html
+++ b/en/contributing.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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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>Contributing - 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="https://echarts.apache.org/zh/images/forie.png?_v_=20200710_1" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="ECharts FAQ"></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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="clo [...]
+<!--[if (gt IE 8)|!(IE)]><body class="ECharts FAQ"></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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="clo [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/dependencies.html b/en/dependencies.html
index 42f0435..a105e09 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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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>Dependencies - 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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/dist/echarts-en.common.js b/en/dist/echarts-en.common.js
index 900be34..1c491ae 100644
--- a/en/dist/echarts-en.common.js
+++ b/en/dist/echarts-en.common.js
@@ -11595,7 +11595,7 @@ var instances$1 = {};    // ZRender实例map索引
 /**
  * @type {string}
  */
-var version$1 = '4.3.1';
+var version$1 = '4.3.2';
 
 /**
  * Initializing a zrender instance
@@ -26152,7 +26152,7 @@ var proto = Scheduler.prototype;
  * @param {Object} payload
  */
 proto.restoreData = function (ecModel, payload) {
-    // TODO: Only restroe needed series and components, but not all components.
+    // TODO: Only restore needed series and components, but not all components.
     // Currently `restoreData` of all of the series and component will be called.
     // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
     // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
@@ -27729,10 +27729,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.8.0';
+var version = '4.9.0';
 
 var dependencies = {
-    zrender: '4.3.1'
+    zrender: '4.3.2'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -30975,7 +30975,7 @@ listProto.mapDimension = function (coordDim, idx) {
  * Initialize from data
  * @param {Array.<Object|number|Array>} data source or data or data provider.
  * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
- *        defualt label/tooltip.
+ *        default label/tooltip.
  *        A name can be specified in encode.itemName,
  *        or dataItem.name (only for series option data),
  *        or provided in nameList from outside.
@@ -35567,8 +35567,8 @@ function rotateTextRect(textRect, rotate) {
     var boundingBox = textRect.plain();
     var beforeWidth = boundingBox.width;
     var beforeHeight = boundingBox.height;
-    var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
-    var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
+    var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
+    var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
     var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
 
     return rotatedRect;
@@ -37669,7 +37669,7 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     }
     else {
         symbolPath.setStyle({
-            opacity: null,
+            opacity: 1,
             shadowBlur: null,
             shadowOffsetX: null,
             shadowOffsetY: null,
@@ -39854,7 +39854,7 @@ var dataSample = function (seriesType) {
                 var valueAxis = coordSys.getOtherAxis(baseAxis);
                 var extent = baseAxis.getExtent();
                 // Coordinste system has been resized
-                var size = extent[1] - extent[0];
+                var size = Math.abs(extent[1] - extent[0]);
                 var rate = Math.round(data.count() / size);
                 if (rate > 1) {
                     var sampler;
@@ -40310,7 +40310,7 @@ var defaultOption = {
     name: '',
     // 'start' | 'middle' | 'end'
     nameLocation: 'end',
-    // By degree. By defualt auto rotate by nameLocation.
+    // By degree. By default auto rotate by nameLocation.
     nameRotate: null,
     nameTruncate: {
         maxWidth: null,
@@ -43553,20 +43553,25 @@ extendChartView({
         var bgEls = [];
         var oldBgEls = this._backgroundEls || [];
 
+        var createBackground = function (dataIndex) {
+            var bgLayout = getLayout[coord.type](data, dataIndex);
+            var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
+            bgEl.useStyle(backgroundModel.getBarItemStyle());
+            // Only cartesian2d support borderRadius.
+            if (coord.type === 'cartesian2d') {
+                bgEl.setShape('r', barBorderRadius);
+            }
+            bgEls[dataIndex] = bgEl;
+            return bgEl;
+        };
+
         data.diff(oldData)
             .add(function (dataIndex) {
                 var itemModel = data.getItemModel(dataIndex);
                 var layout = getLayout[coord.type](data, dataIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgLayout = getLayout[coord.type](data, dataIndex);
-                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
-                    }
-                    bgEls[dataIndex] = bgEl;
+                    createBackground(dataIndex);
                 }
 
                 // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
@@ -43600,13 +43605,19 @@ extendChartView({
                 var layout = getLayout[coord.type](data, newIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgEl = oldBgEls[oldIndex];
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
+                    var bgEl;
+                    if (oldBgEls.length === 0) {
+                        bgEl = createBackground(oldIndex);
+                    }
+                    else {
+                        bgEl = oldBgEls[oldIndex];
+                        bgEl.useStyle(backgroundModel.getBarItemStyle());
+                        // Only cartesian2d support borderRadius.
+                        if (coord.type === 'cartesian2d') {
+                            bgEl.setShape('r', barBorderRadius);
+                        }
+                        bgEls[newIndex] = bgEl;
                     }
-                    bgEls[newIndex] = bgEl;
 
                     var bgLayout = getLayout[coord.type](data, newIndex);
                     var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
@@ -43766,8 +43777,31 @@ var clip = {
         return clipped;
     },
 
-    polar: function (coordSysClipArea) {
-        return false;
+    polar: function (coordSysClipArea, layout) {
+        var signR = layout.r0 <= layout.r ? 1 : -1;
+        // Make sure r is larger than r0
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        var r = mathMin$4(layout.r, coordSysClipArea.r);
+        var r0 = mathMax$4(layout.r0, coordSysClipArea.r0);
+
+        layout.r = r;
+        layout.r0 = r0;
+
+        var clipped = r - r0 < 0;
+
+        // Reverse back
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        return clipped;
     }
 };
 
@@ -47110,7 +47144,7 @@ function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) {
     var snapToValue = payloadInfo.snapToValue;
 
     // Fill content of event obj for echarts.connect.
-    // By defualt use the first involved series data as a sample to connect.
+    // By default use the first involved series data as a sample to connect.
     if (payloadBatch[0] && outputFinder.seriesIndex == null) {
         extend(outputFinder, payloadBatch[0]);
     }
@@ -48788,8 +48822,21 @@ function assembleFont(textStyleModel) {
 
     cssText.push('font:' + textStyleModel.getFont());
 
+    var lineHeight = textStyleModel.get('lineHeight');
+    if (lineHeight == null) {
+        lineHeight = Math.round(fontSize * 3 / 2);
+    }
+
     fontSize
-        && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
+        && cssText.push('line-height:' + lineHeight + 'px');
+
+    var shadowColor = textStyleModel.get('textShadowColor');
+    var shadowBlur = textStyleModel.get('textShadowBlur') || 0;
+    var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0;
+    var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0;
+    shadowBlur
+        && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px '
+            + shadowBlur + 'px ' + shadowColor);
 
     each$10(['decoration', 'align'], function (name) {
         var val = textStyleModel.get(name);
@@ -48873,6 +48920,8 @@ function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
             out[1] += viewportRootOffset.offsetTop;
         }
     }
+    out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+    out[3] = out[1] / zr.getHeight(); // The ratio of top to height
 }
 
 /**
@@ -48897,7 +48946,7 @@ function TooltipContent(container, api, opt) {
     var zr = this._zr = api.getZr();
     var appendToBody = this._appendToBody = opt && opt.appendToBody;
 
-    this._styleCoord = [0, 0];
+    this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
 
     makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
 
@@ -48968,7 +49017,7 @@ TooltipContent.prototype = {
     /**
      * Update when tooltip is rendered
      */
-    update: function () {
+    update: function (tooltipModel) {
         // FIXME
         // Move this logic to ec main?
         var container = this._container;
@@ -48978,11 +49027,25 @@ TooltipContent.prototype = {
         if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
             domStyle.position = 'relative';
         }
+        var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+        alwaysShowContent && this._moveTooltipIfResized();
         // Hide the tooltip
         // PENDING
         // this.hide();
     },
 
+    /**
+     * when `alwaysShowContent` is true,
+     * we should move the tooltip after chart resized
+     */
+    _moveTooltipIfResized: function () {
+        var ratioX = this._styleCoord[2]; // The ratio of left to width
+        var ratioY = this._styleCoord[3]; // The ratio of top to height
+        var realX = ratioX * this._zr.getWidth();
+        var realY = ratioY * this._zr.getHeight();
+        this.moveTo(realX, realY);
+    },
+
     show: function (tooltipModel) {
         clearTimeout(this._hideTimeout);
         var el = this.el;
@@ -48997,10 +49060,10 @@ TooltipContent.prototype = {
 
         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
+        // If mouse occasionally move over the tooltip, a mouseout event will be
+        // triggered by canvas, and cause some unexpectable result like dragging
         // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
-        // it. Although it is not suppored by IE8~IE10, fortunately it is a rare
+        // it. Although it is not supported by IE8~IE10, fortunately it is a rare
         // scenario.
         el.style.pointerEvents = this._enterable ? 'auto' : 'none';
 
@@ -49038,7 +49101,7 @@ TooltipContent.prototype = {
         if (this._show && !(this._inContent && this._enterable)) {
             if (time) {
                 this._hideDelay = time;
-                // Set show false to avoid invoke hideLater mutiple times
+                // Set show false to avoid invoke hideLater multiple times
                 this._show = false;
                 this._hideTimeout = setTimeout(bind(this.hide, this), time);
             }
@@ -49095,13 +49158,24 @@ TooltipContent.prototype = {
 */
 
 // import Group from 'zrender/src/container/Group';
+function makeStyleCoord$1(out, zr, zrX, zrY) {
+    out[0] = zrX;
+    out[1] = zrY;
+    out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+    out[3] = out[1] / zr.getHeight(); // The ratio of top to height
+}
+
 /**
  * @alias module:echarts/component/tooltip/TooltipRichContent
  * @constructor
  */
 function TooltipRichContent(api) {
 
-    this._zr = api.getZr();
+    var zr = this._zr = api.getZr();
+
+    this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
+
+    makeStyleCoord$1(this._styleCoord, zr, api.getWidth() / 2, api.getHeight() / 2);
 
     this._show = false;
 
@@ -49124,8 +49198,21 @@ TooltipRichContent.prototype = {
     /**
      * Update when tooltip is rendered
      */
-    update: function () {
-        // noop
+    update: function (tooltipModel) {
+        var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+        alwaysShowContent && this._moveTooltipIfResized();
+    },
+
+    /**
+     * when `alwaysShowContent` is true,
+     * we should move the tooltip after chart resized
+     */
+    _moveTooltipIfResized: function () {
+        var ratioX = this._styleCoord[2]; // The ratio of left to width
+        var ratioY = this._styleCoord[3]; // The ratio of top to height
+        var realX = ratioX * this._zr.getWidth();
+        var realY = ratioY * this._zr.getHeight();
+        this.moveTo(realX, realY);
     },
 
     show: function (tooltipModel) {
@@ -49180,16 +49267,23 @@ TooltipRichContent.prototype = {
             startId = text.indexOf('{marker');
         }
 
+        var textStyleModel = tooltipModel.getModel('textStyle');
+        var fontSize = textStyleModel.get('fontSize');
+        var lineHeight = tooltipModel.get('textLineHeight');
+        if (lineHeight == null) {
+            lineHeight = Math.round(fontSize * 3 / 2);
+        }
+
         this.el = new Text({
-            style: {
+            style: setTextStyle({}, textStyleModel, {
                 rich: markers,
                 text: content,
-                textLineHeight: 20,
                 textBackgroundColor: tooltipModel.get('backgroundColor'),
                 textBorderRadius: tooltipModel.get('borderRadius'),
                 textFill: tooltipModel.get('textStyle.color'),
-                textPadding: tooltipModel.get('padding')
-            },
+                textPadding: tooltipModel.get('padding'),
+                textLineHeight: lineHeight
+            }),
             z: tooltipModel.get('z')
         });
         this._zr.add(this.el);
@@ -49224,7 +49318,9 @@ TooltipRichContent.prototype = {
 
     moveTo: function (x, y) {
         if (this.el) {
-            this.el.attr('position', [x, y]);
+            var styleCoord = this._styleCoord;
+            makeStyleCoord$1(styleCoord, this._zr, x, y);
+            this.el.attr('position', [styleCoord[0], styleCoord[1]]);
         }
     },
 
@@ -49239,7 +49335,7 @@ TooltipRichContent.prototype = {
         if (this._show && !(this._inContent && this._enterable)) {
             if (time) {
                 this._hideDelay = time;
-                // Set show false to avoid invoke hideLater mutiple times
+                // Set show false to avoid invoke hideLater multiple times
                 this._show = false;
                 this._hideTimeout = setTimeout(bind(this.hide, this), time);
             }
@@ -49253,6 +49349,14 @@ TooltipRichContent.prototype = {
         return this._show;
     },
 
+    dispose: function () {
+        clearTimeout(this._hideTimeout);
+
+        if (this.el) {
+            this._zr.remove(this.el);
+        }
+    },
+
     getOuterSize: function () {
         var size = this.getSize();
         return {
@@ -49357,7 +49461,7 @@ extendComponentView({
         this._alwaysShowContent = tooltipModel.get('alwaysShowContent');
 
         var tooltipContent = this._tooltipContent;
-        tooltipContent.update();
+        tooltipContent.update(tooltipModel);
         tooltipContent.setEnterable(tooltipModel.get('enterable'));
 
         this._initGlobalListener();
@@ -49587,7 +49691,7 @@ extendComponentView({
     _showOrMove: function (tooltipModel, cb) {
         // showDelay is used in this case: tooltip.enterable is set
         // as true. User intent to move mouse into tooltip and click
-        // something. `showDelay` makes it easyer to enter the content
+        // something. `showDelay` makes it easier to enter the content
         // but tooltip do not move immediately.
         var delay = tooltipModel.get('showDelay');
         cb = bind(cb, this);
@@ -49672,7 +49776,7 @@ extendComponentView({
 
                 // Default tooltip content
                 // FIXME
-                // (1) shold be the first data which has name?
+                // (1) should be the first data which has name?
                 // (2) themeRiver, firstDataIndex is array, and first line is unnecessary.
                 var firstLine = valueLabel;
                 if (renderMode !== 'html') {
@@ -49788,7 +49892,7 @@ extendComponentView({
         var asyncTicket = Math.random();
 
         // Do not check whether `trigger` is 'none' here, because `trigger`
-        // only works on cooridinate system. In fact, we have not found case
+        // only works on coordinate system. In fact, we have not found case
         // that requires setting `trigger` nothing on component yet.
 
         this._showOrMove(subTooltipModel, function () {
@@ -51834,7 +51938,7 @@ var ScrollableLegendView = LegendView.extend({
             var legendDataIdx = child.__legendDataIndex;
             // FIXME
             // If the given targetDataIndex (from model) is illegal,
-            // we use defualtIndex. But the index on the legend model and
+            // we use defaultIndex. 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) {
@@ -52076,7 +52180,7 @@ extendComponentView({
         }
         if (sublink) {
             subTextEl.on('click', function () {
-                windowOpen(link, '_' + titleModel.get('subtarget'));
+                windowOpen(sublink, '_' + titleModel.get('subtarget'));
             });
         }
 
@@ -52277,15 +52381,16 @@ var MarkerModel = extendComponentModel({
         }
     },
 
-    formatTooltip: function (dataIndex) {
+    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
         var data = this.getData();
         var value = this.getRawValue(dataIndex);
         var formattedValue = isArray(value)
             ? map(value, addCommas$1).join(', ') : addCommas$1(value);
         var name = data.getName(dataIndex);
         var html = encodeHTML$1(this.name);
+        var newLine = renderMode === 'html' ? '<br/>' : '\n';
         if (value != null || name) {
-            html += '<br />';
+            html += newLine;
         }
         if (name) {
             html += encodeHTML$1(name);
@@ -52750,10 +52855,12 @@ MarkerView.extend({
             var itemModel = mpData.getItemModel(idx);
             var symbol = itemModel.getShallow('symbol');
             var symbolSize = itemModel.getShallow('symbolSize');
+            var symbolRotate = itemModel.getShallow('symbolRotate');
             var isFnSymbol = isFunction$1(symbol);
             var isFnSymbolSize = isFunction$1(symbolSize);
+            var isFnSymbolRotate = isFunction$1(symbolRotate);
 
-            if (isFnSymbol || isFnSymbolSize) {
+            if (isFnSymbol || isFnSymbolSize || isFnSymbolRotate) {
                 var rawIdx = mpModel.getRawValue(idx);
                 var dataParams = mpModel.getDataParams(idx);
                 if (isFnSymbol) {
@@ -52763,11 +52870,15 @@ MarkerView.extend({
                     // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据?
                     symbolSize = symbolSize(rawIdx, dataParams);
                 }
+                if (isFnSymbolRotate) {
+                    symbolRotate = symbolRotate(rawIdx, dataParams);
+                }
             }
 
             mpData.setItemVisual(idx, {
                 symbol: symbol,
                 symbolSize: symbolSize,
+                symbolRotate: symbolRotate,
                 color: itemModel.get('itemStyle.color')
                     || seriesData.getVisual('color')
             });
@@ -53019,22 +53130,29 @@ function makeSymbolTypeKey(symbolCategory) {
  * @inner
  */
 function createSymbol$1(name, lineData, idx) {
-    var color = lineData.getItemVisual(idx, 'color');
     var symbolType = lineData.getItemVisual(idx, name);
-    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
 
     if (!symbolType || symbolType === 'none') {
         return;
     }
 
+    var color = lineData.getItemVisual(idx, 'color');
+    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
+    var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate');
+
     if (!isArray(symbolSize)) {
         symbolSize = [symbolSize, symbolSize];
     }
+
     var symbolPath = createSymbol(
         symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2,
         symbolSize[0], symbolSize[1], color
     );
 
+    // rotate by default if symbolRotate is not specified or NaN
+    symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate)
+        ? void 0
+        : +symbolRotate * Math.PI / 180 || 0;
     symbolPath.name = name;
 
     return symbolPath;
@@ -53102,18 +53220,38 @@ function updateSymbolAndLabelBeforeLineUpdate() {
 
     if (symbolFrom) {
         symbolFrom.attr('position', fromPos);
-        var tangent = line.tangentAt(0);
-        symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
-            tangent[1], tangent[0]
-        ));
+        // Fix #12388
+        // when symbol is set to be 'arrow' in markLine,
+        // symbolRotate value will be ignored, and compulsively use tangent angle.
+        // rotate by default if symbol rotation is not specified
+        var specifiedRotation = symbolFrom.__specifiedRotation;
+        if (specifiedRotation == null) {
+            var tangent = line.tangentAt(0);
+            symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
+                tangent[1], tangent[0]
+            ));
+        }
+        else {
+            symbolFrom.attr('rotation', specifiedRotation);
+        }
         symbolFrom.attr('scale', [invScale * percent, invScale * percent]);
     }
     if (symbolTo) {
         symbolTo.attr('position', toPos);
-        var tangent = line.tangentAt(1);
-        symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
-            tangent[1], tangent[0]
-        ));
+        // Fix #12388
+        // when symbol is set to be 'arrow' in markLine,
+        // symbolRotate value will be ignored, and compulsively use tangent angle.
+        // rotate by default if symbol rotation is not specified
+        var specifiedRotation = symbolTo.__specifiedRotation;
+        if (specifiedRotation == null) {
+            var tangent = line.tangentAt(1);
+            symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
+                tangent[1], tangent[0]
+            ));
+        }
+        else {
+            symbolTo.attr('rotation', specifiedRotation);
+        }
         symbolTo.attr('scale', [invScale * percent, invScale * percent]);
     }
 
@@ -53909,8 +54047,10 @@ MarkerView.extend({
             ]);
 
             lineData.setItemVisual(idx, {
+                'fromSymbolRotate': fromData.getItemVisual(idx, 'symbolRotate'),
                 'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'),
                 'fromSymbol': fromData.getItemVisual(idx, 'symbol'),
+                'toSymbolRotate': toData.getItemVisual(idx, 'symbolRotate'),
                 'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'),
                 'toSymbol': toData.getItemVisual(idx, 'symbol')
             });
@@ -53932,8 +54072,8 @@ MarkerView.extend({
             updateSingleMarkerEndLayout(
                 data, idx, isFrom, seriesModel, api
             );
-
             data.setItemVisual(idx, {
+                symbolRotate: itemModel.get('symbolRotate'),
                 symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
                 symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
                 color: itemModel.get('itemStyle.color') || seriesData.getVisual('color')
@@ -54292,9 +54432,29 @@ MarkerView.extend({
         // Update visual and layout of line
         areaData.each(function (idx) {
             // Layout
-            areaData.setItemLayout(idx, map(dimPermutations, function (dim) {
+            var points = map(dimPermutations, function (dim) {
                 return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
-            }));
+            });
+            // If none of the area is inside coordSys, allClipped is set to be true
+            // in layout so that label will not be displayed. See #12591
+            var allClipped = true;
+            each$1(dimPermutations, function (dim) {
+                if (!allClipped) {
+                    return;
+                }
+                var xValue = areaData.get(dim[0], idx);
+                var yValue = areaData.get(dim[1], idx);
+                // If is infinity, the axis should be considered not clipped
+                if ((isInifinity$1(xValue) || coordSys.getAxis('x').containData(xValue))
+                    && (isInifinity$1(yValue) || coordSys.getAxis('y').containData(yValue))
+                ) {
+                    allClipped = false;
+                }
+            });
+            areaData.setItemLayout(idx, {
+                points: points,
+                allClipped: allClipped
+            });
 
             // Visual
             areaData.setItemVisual(idx, {
@@ -54305,23 +54465,41 @@ MarkerView.extend({
 
         areaData.diff(polygonGroup.__data)
             .add(function (idx) {
-                var polygon = new Polygon({
-                    shape: {
-                        points: areaData.getItemLayout(idx)
-                    }
-                });
-                areaData.setItemGraphicEl(idx, polygon);
-                polygonGroup.group.add(polygon);
+                var layout = areaData.getItemLayout(idx);
+                if (!layout.allClipped) {
+                    var polygon = new Polygon({
+                        shape: {
+                            points: layout.points
+                        }
+                    });
+                    areaData.setItemGraphicEl(idx, polygon);
+                    polygonGroup.group.add(polygon);
+                }
             })
             .update(function (newIdx, oldIdx) {
                 var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx);
-                updateProps(polygon, {
-                    shape: {
-                        points: areaData.getItemLayout(newIdx)
+                var layout = areaData.getItemLayout(newIdx);
+                if (!layout.allClipped) {
+                    if (polygon) {
+                        updateProps(polygon, {
+                            shape: {
+                                points: layout.points
+                            }
+                        }, maModel, newIdx);
                     }
-                }, maModel, newIdx);
-                polygonGroup.group.add(polygon);
-                areaData.setItemGraphicEl(newIdx, polygon);
+                    else {
+                        polygon = new Polygon({
+                            shape: {
+                                points: layout.points
+                            }
+                        });
+                    }
+                    areaData.setItemGraphicEl(newIdx, polygon);
+                    polygonGroup.group.add(polygon);
+                }
+                else if (polygon) {
+                    polygonGroup.group.remove(polygon);
+                }
             })
             .remove(function (idx) {
                 var polygon = polygonGroup.__data.getItemGraphicEl(idx);
@@ -58370,7 +58548,8 @@ proto$2.onclick = function (ecModel, api) {
         $a.target = '_blank';
         $a.href = url;
         var evt = new MouseEvent('click', {
-            view: window,
+            // some micro front-end framework, window maybe is a Proxy
+            view: document.defaultView,
             bubbles: true,
             cancelable: false
         });
@@ -58685,7 +58864,8 @@ function assembleSeriesWithCategoryAxis(series) {
         }));
         var columns = [categoryAxis.model.getCategories()];
         each$1(group.series, function (series) {
-            columns.push(series.getRawData().mapArray(valueAxisDim, function (val) {
+            var rawData = series.getRawData();
+            columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim), function (val) {
                 return val;
             }));
         });
@@ -58803,7 +58983,13 @@ function parseListContents(str) {
 
     var data = [];
     for (var i = 0; i < lines.length; i++) {
-        var items = trim$1(lines[i]).split(itemSplitRegex);
+        // if line is empty, ignore it.
+        // there is a case that a user forgot to delete `\n`.
+        var line = trim$1(lines[i]);
+        if (!line) {
+            continue;
+        }
+        var items = line.split(itemSplitRegex);
         var name = '';
         var value;
         var hasName = false;
@@ -59018,13 +59204,18 @@ function tryMergeDataOption(newData, originalData) {
     return map(newData, function (newVal, idx) {
         var original = originalData && originalData[idx];
         if (isObject$1(original) && !isArray(original)) {
-            if (isObject$1(newVal) && !isArray(newVal)) {
-                newVal = newVal.value;
+            var newValIsObject = isObject$1(newVal) && !isArray(newVal);
+            if (!newValIsObject) {
+                newVal = {
+                    value: newVal
+                };
             }
+            // original data has name but new data has no name
+            var shouldDeleteName = original.name != null && newVal.name == null;
             // Original data has option
-            return defaults({
-                value: newVal
-            }, original);
+            newVal = defaults(newVal, original);
+            shouldDeleteName && (delete newVal.name);
+            return newVal;
         }
         else {
             return newVal;
@@ -60855,7 +61046,11 @@ DataZoom.defaultOption = {
         back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
     },
     // `zoom`, `back`
-    title: clone(dataZoomLang.title)
+    title: clone(dataZoomLang.title),
+    brushStyle: {
+        borderWidth: 0,
+        color: 'rgba(0,0,0,0.2)'
+    }
 };
 
 var proto$4 = DataZoom.prototype;
@@ -61030,11 +61225,7 @@ function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
             zoomActive
             ? {
                 brushType: 'auto',
-                brushStyle: {
-                    // FIXME user customized?
-                    lineWidth: 0,
-                    fill: 'rgba(0,0,0,0.2)'
-                }
+                brushStyle: featureModel.getModel('brushStyle').getItemStyle()
             }
             : false
         );
@@ -63616,7 +63807,7 @@ GradientManager.prototype.updateDom = function (gradient, dom) {
         stop.setAttribute('offset', colors[i].offset * 100 + '%');
 
         var color = colors[i].color;
-        if (color.indexOf('rgba' > -1)) {
+        if (color.indexOf('rgba') > -1) {
             // Fix Safari bug that stop-color not recognizing alpha #9014
             var opacity = parse(color)[3];
             var hex = toHex(color);
diff --git a/en/dist/echarts-en.common.min.js b/en/dist/echarts-en.common.min.js
index 0e025de..62cdf1c 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,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.js b/en/dist/echarts-en.js
index 69dc8fc..2e4223f 100644
--- a/en/dist/echarts-en.js
+++ b/en/dist/echarts-en.js
@@ -11595,7 +11595,7 @@ var instances$1 = {};    // ZRender实例map索引
 /**
  * @type {string}
  */
-var version$1 = '4.3.1';
+var version$1 = '4.3.2';
 
 /**
  * Initializing a zrender instance
@@ -26231,7 +26231,7 @@ var proto = Scheduler.prototype;
  * @param {Object} payload
  */
 proto.restoreData = function (ecModel, payload) {
-    // TODO: Only restroe needed series and components, but not all components.
+    // TODO: Only restore needed series and components, but not all components.
     // Currently `restoreData` of all of the series and component will be called.
     // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
     // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
@@ -27812,10 +27812,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.8.0';
+var version = '4.9.0';
 
 var dependencies = {
-    zrender: '4.3.1'
+    zrender: '4.3.2'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -31058,7 +31058,7 @@ listProto.mapDimension = function (coordDim, idx) {
  * Initialize from data
  * @param {Array.<Object|number|Array>} data source or data or data provider.
  * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
- *        defualt label/tooltip.
+ *        default label/tooltip.
  *        A name can be specified in encode.itemName,
  *        or dataItem.name (only for series option data),
  *        or provided in nameList from outside.
@@ -35677,8 +35677,8 @@ function rotateTextRect(textRect, rotate) {
     var boundingBox = textRect.plain();
     var beforeWidth = boundingBox.width;
     var beforeHeight = boundingBox.height;
-    var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
-    var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
+    var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
+    var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
     var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
 
     return rotatedRect;
@@ -37779,7 +37779,7 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     }
     else {
         symbolPath.setStyle({
-            opacity: null,
+            opacity: 1,
             shadowBlur: null,
             shadowOffsetX: null,
             shadowOffsetY: null,
@@ -39964,7 +39964,7 @@ var dataSample = function (seriesType) {
                 var valueAxis = coordSys.getOtherAxis(baseAxis);
                 var extent = baseAxis.getExtent();
                 // Coordinste system has been resized
-                var size = extent[1] - extent[0];
+                var size = Math.abs(extent[1] - extent[0]);
                 var rate = Math.round(data.count() / size);
                 if (rate > 1) {
                     var sampler;
@@ -40420,7 +40420,7 @@ var defaultOption = {
     name: '',
     // 'start' | 'middle' | 'end'
     nameLocation: 'end',
-    // By degree. By defualt auto rotate by nameLocation.
+    // By degree. By default auto rotate by nameLocation.
     nameRotate: null,
     nameTruncate: {
         maxWidth: null,
@@ -43663,20 +43663,25 @@ extendChartView({
         var bgEls = [];
         var oldBgEls = this._backgroundEls || [];
 
+        var createBackground = function (dataIndex) {
+            var bgLayout = getLayout[coord.type](data, dataIndex);
+            var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
+            bgEl.useStyle(backgroundModel.getBarItemStyle());
+            // Only cartesian2d support borderRadius.
+            if (coord.type === 'cartesian2d') {
+                bgEl.setShape('r', barBorderRadius);
+            }
+            bgEls[dataIndex] = bgEl;
+            return bgEl;
+        };
+
         data.diff(oldData)
             .add(function (dataIndex) {
                 var itemModel = data.getItemModel(dataIndex);
                 var layout = getLayout[coord.type](data, dataIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgLayout = getLayout[coord.type](data, dataIndex);
-                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
-                    }
-                    bgEls[dataIndex] = bgEl;
+                    createBackground(dataIndex);
                 }
 
                 // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
@@ -43710,13 +43715,19 @@ extendChartView({
                 var layout = getLayout[coord.type](data, newIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgEl = oldBgEls[oldIndex];
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
+                    var bgEl;
+                    if (oldBgEls.length === 0) {
+                        bgEl = createBackground(oldIndex);
+                    }
+                    else {
+                        bgEl = oldBgEls[oldIndex];
+                        bgEl.useStyle(backgroundModel.getBarItemStyle());
+                        // Only cartesian2d support borderRadius.
+                        if (coord.type === 'cartesian2d') {
+                            bgEl.setShape('r', barBorderRadius);
+                        }
+                        bgEls[newIndex] = bgEl;
                     }
-                    bgEls[newIndex] = bgEl;
 
                     var bgLayout = getLayout[coord.type](data, newIndex);
                     var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
@@ -43876,8 +43887,31 @@ var clip = {
         return clipped;
     },
 
-    polar: function (coordSysClipArea) {
-        return false;
+    polar: function (coordSysClipArea, layout) {
+        var signR = layout.r0 <= layout.r ? 1 : -1;
+        // Make sure r is larger than r0
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        var r = mathMin$4(layout.r, coordSysClipArea.r);
+        var r0 = mathMax$4(layout.r0, coordSysClipArea.r0);
+
+        layout.r = r;
+        layout.r0 = r0;
+
+        var clipped = r - r0 < 0;
+
+        // Reverse back
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        return clipped;
     }
 };
 
@@ -47113,16 +47147,17 @@ var RadarSeries = SeriesModel.extend({
         });
     },
 
-    formatTooltip: function (dataIndex) {
+    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
         var data = this.getData();
         var coordSys = this.coordinateSystem;
         var indicatorAxes = coordSys.getIndicatorAxes();
         var name = this.getData().getName(dataIndex);
-        return encodeHTML(name === '' ? this.name : name) + '<br/>'
+        var newLine = renderMode === 'html' ? '<br/>' : '\n';
+        return encodeHTML(name === '' ? this.name : name) + newLine
             + map(indicatorAxes, function (axis, idx) {
                 var val = data.get(data.mapDimension(axis.dim), dataIndex);
                 return encodeHTML(axis.name + ' : ' + val);
-            }).join('<br />');
+            }).join(newLine);
     },
 
     /**
@@ -47218,12 +47253,14 @@ extendChartView({
             var symbolPath = createSymbol(
                 symbolType, -1, -1, 2, 2, color
             );
+            var symbolRotate = data.getItemVisual(idx, 'symbolRotate') || 0;
             symbolPath.attr({
                 style: {
                     strokeNoScale: true
                 },
                 z2: 100,
-                scale: [symbolSize[0] / 2, symbolSize[1] / 2]
+                scale: [symbolSize[0] / 2, symbolSize[1] / 2],
+                rotation: symbolRotate * Math.PI / 180 || 0
             });
             return symbolPath;
         }
@@ -48189,7 +48226,7 @@ var MapSeries = SeriesModel.extend({
      *
      * @param {number} dataIndex
      */
-    formatTooltip: function (dataIndex) {
+    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
         // FIXME orignalData and data is a bit confusing
         var data = this.getData();
         var formattedValue = addCommas(this.getRawValue(dataIndex));
@@ -48207,7 +48244,8 @@ var MapSeries = SeriesModel.extend({
             }
         }
 
-        return seriesNames.join(', ') + '<br />'
+        var newLine = renderMode === 'html' ? '<br/>' : '\n';
+        return seriesNames.join(', ') + newLine
             + encodeHTML(name + ' : ' + formattedValue);
     },
 
@@ -50997,22 +51035,7 @@ TreeNode.prototype = {
         }
         var hostTree = this.hostTree;
         var itemModel = hostTree.data.getItemModel(this.dataIndex);
-        var levelModel = this.getLevelModel();
-
-        // FIXME: refactor levelModel to "beforeLink", and remove levelModel here.
-        if (levelModel) {
-            return itemModel.getModel(path, levelModel.getModel(path));
-        }
-        else {
-            return itemModel.getModel(path);
-        }
-    },
-
-    /**
-     * @return {module:echarts/model/Model}
-     */
-    getLevelModel: function () {
-        return (this.hostTree.levelModels || [])[this.depth];
+        return itemModel.getModel(path);
     },
 
     /**
@@ -51084,9 +51107,8 @@ TreeNode.prototype = {
  * @constructor
  * @alias module:echarts/data/Tree
  * @param {module:echarts/model/Model} hostModel
- * @param {Array.<Object>} levelOptions
  */
-function Tree(hostModel, levelOptions) {
+function Tree(hostModel) {
     /**
      * @type {module:echarts/data/Tree~TreeNode}
      * @readOnly
@@ -51113,15 +51135,6 @@ function Tree(hostModel, levelOptions) {
      */
     this.hostModel = hostModel;
 
-    /**
-     * @private
-     * @readOnly
-     * @type {Array.<module:echarts/model/Model}
-     */
-    this.levelModels = map(levelOptions || [], function (levelDefine) {
-        return new Model(levelDefine, hostModel, hostModel.ecModel);
-    });
-
 }
 
 Tree.prototype = {
@@ -51211,13 +51224,11 @@ Tree.prototype = {
  * @static
  * @param {Object} dataRoot Root node.
  * @param {module:echarts/model/Model} hostModel
- * @param {Object} treeOptions
- * @param {Array.<Object>} treeOptions.levels
  * @return module:echarts/data/Tree
  */
-Tree.createTree = function (dataRoot, hostModel, treeOptions, beforeLink) {
+Tree.createTree = function (dataRoot, hostModel, beforeLink) {
 
-    var tree = new Tree(hostModel, treeOptions && treeOptions.levels);
+    var tree = new Tree(hostModel);
     var listData = [];
     var dimMax = 1;
 
@@ -51325,7 +51336,7 @@ SeriesModel.extend({
         var leaves = option.leaves || {};
         var leavesModel = new Model(leaves, this, this.ecModel);
 
-        var tree = Tree.createTree(root, this, {}, beforeLink);
+        var tree = Tree.createTree(root, this, beforeLink);
 
         function beforeLink(nodeData) {
             nodeData.wrapMethod('getItemModel', function (model, idx) {
@@ -52264,7 +52275,7 @@ function drawEdge(
 
             updateProps(edge, {
                 shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
-                style: {opacity: 1}
+                style: defaults({opacity: 1}, seriesScope.lineStyle)
             }, seriesModel);
         }
     }
@@ -52294,7 +52305,7 @@ function drawEdge(
                         parentPoint: [targetLayout.x, targetLayout.y],
                         childPoints: childPoints
                     },
-                    style: {opacity: 1}
+                    style: defaults({opacity: 1}, seriesScope.lineStyle)
                 }, seriesModel);
             }
         }
@@ -52943,21 +52954,29 @@ SeriesModel.extend({
 
         var levels = option.levels || [];
 
+        // Used in "visual priority" in `treemapVisual.js`.
+        // This way is a little tricky, must satisfy the precondition:
+        //   1. There is no `treeNode.getModel('itemStyle.xxx')` used.
+        //   2. The `Model.prototype.getModel()` will not use any clone-like way.
+        var designatedVisualItemStyle = this.designatedVisualItemStyle = {};
+        var designatedVisualModel = new Model({itemStyle: designatedVisualItemStyle}, this, ecModel);
+
         levels = option.levels = setDefault(levels, ecModel);
         var levelModels = map(levels || [], function (levelDefine) {
-            return new Model(levelDefine, this, ecModel);
+            return new Model(levelDefine, designatedVisualModel, ecModel);
         }, this);
 
         // Make sure always a new tree is created when setOption,
         // in TreemapView, we check whether oldTree === newTree
         // to choose mappings approach among old shapes and new shapes.
-        var tree = Tree.createTree(root, this, null, beforeLink);
+        var tree = Tree.createTree(root, this, beforeLink);
 
         function beforeLink(nodeData) {
             nodeData.wrapMethod('getItemModel', function (model, idx) {
                 var node = tree.getNodeByDataIndex(idx);
                 var levelModel = levelModels[node.depth];
-                levelModel && (model.parentModel = levelModel);
+                // If no levelModel, we also need `designatedVisualModel`.
+                model.parentModel = levelModel || designatedVisualModel;
                 return model;
             });
         }
@@ -54506,7 +54525,7 @@ var CATEGORY_DEFAULT_VISUAL_INDEX = -1;
  *                                            visual data can be array or object
  *                                            (like: {cate1: '#222', none: '#fff'})
  *                                            or primary types (which represents
- *                                            defualt category visual), otherwise visual
+ *                                            default category visual), otherwise visual
  *                                            can be array or primary (which will be
  *                                            normalized to array).
  *
@@ -55124,21 +55143,14 @@ var treemapVisual = {
     reset: function (seriesModel, ecModel, api, payload) {
         var tree = seriesModel.getData().tree;
         var root = tree.root;
-        var seriesItemStyleModel = seriesModel.getModel(ITEM_STYLE_NORMAL);
 
         if (root.isRemoved()) {
             return;
         }
 
-        var levelItemStyles = map(tree.levelModels, function (levelModel) {
-            return levelModel ? levelModel.get(ITEM_STYLE_NORMAL) : null;
-        });
-
         travelTree(
             root, // Visual should calculate from tree root but not view root.
             {},
-            levelItemStyles,
-            seriesItemStyleModel,
             seriesModel.getViewRoot().getAncestors(),
             seriesModel
         );
@@ -55146,8 +55158,7 @@ var treemapVisual = {
 };
 
 function travelTree(
-    node, designatedVisual, levelItemStyles, seriesItemStyleModel,
-    viewRootAncestors, seriesModel
+    node, designatedVisual, viewRootAncestors, seriesModel
 ) {
     var nodeModel = node.getModel();
     var nodeLayout = node.getLayout();
@@ -55158,10 +55169,7 @@ function travelTree(
     }
 
     var nodeItemStyleModel = node.getModel(ITEM_STYLE_NORMAL);
-    var levelItemStyle = levelItemStyles[node.depth];
-    var visuals = buildVisuals(
-        nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel
-    );
+    var visuals = buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel);
 
     // calculate border color
     var borderColor = nodeItemStyleModel.get('borderColor');
@@ -55194,27 +55202,21 @@ function travelTree(
                 var childVisual = mapVisual$1(
                     nodeModel, visuals, child, index, mapping, seriesModel
                 );
-                travelTree(
-                    child, childVisual, levelItemStyles, seriesItemStyleModel,
-                    viewRootAncestors, seriesModel
-                );
+                travelTree(child, childVisual, viewRootAncestors, seriesModel);
             }
         });
     }
 }
 
-function buildVisuals(
-    nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel
-) {
+function buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel) {
     var visuals = extend({}, designatedVisual);
+    var designatedVisualItemStyle = seriesModel.designatedVisualItemStyle;
 
     each$1(['color', 'colorAlpha', 'colorSaturation'], function (visualName) {
         // Priority: thisNode > thisLevel > parentNodeDesignated > seriesModel
-        var val = nodeItemStyleModel.get(visualName, true); // Ignore parent
-        val == null && levelItemStyle && (val = levelItemStyle[visualName]);
-        val == null && (val = designatedVisual[visualName]);
-        val == null && (val = seriesItemStyleModel.get(visualName));
-
+        designatedVisualItemStyle[visualName] = designatedVisual[visualName];
+        var val = nodeItemStyleModel.get(visualName);
+        designatedVisualItemStyle[visualName] = null;
         val != null && (visuals[visualName] = val);
     });
 
@@ -55802,7 +55804,7 @@ function position(row, rowFixedLength, rect, halfGapWidth, flush) {
     rect[wh[idx1WhenH]] -= rowOtherLength;
 }
 
-// Return [containerWidth, containerHeight] as defualt.
+// Return [containerWidth, containerHeight] as default.
 function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) {
     // If targetInfo.node exists, we zoom to the node,
     // so estimate whold width and heigth by target node.
@@ -56108,11 +56110,6 @@ graphProto.addEdge = function (n1, n2, dataIndex) {
     }
 
     var key = n1.id + '-' + n2.id;
-    // PENDING
-    if (edgesMap[key]) {
-        return;
-    }
-
     var edge = new Edge(n1, n2, dataIndex);
     edge.hostGraph = this;
 
@@ -56512,10 +56509,12 @@ var createGraphFromNodeEdge = function (nodes, edges, seriesModel, directed, bef
     var linkNameList = [];
     var validEdges = [];
     var linkCount = 0;
+
     for (var i = 0; i < edges.length; i++) {
         var link = edges[i];
         var source = link.source;
         var target = link.target;
+
         // addEdge may fail when source or target not exists
         if (graph.addEdge(source, target, linkCount)) {
             validEdges.push(link);
@@ -56562,7 +56561,6 @@ var createGraphFromNodeEdge = function (nodes, edges, seriesModel, directed, bef
 
     // Update dataIndex of nodes and edges because invalid edge may be removed
     graph.update();
-
     return graph;
 };
 
@@ -56585,6 +56583,234 @@ var createGraphFromNodeEdge = function (nodes, edges, seriesModel, directed, bef
 * under the License.
 */
 
+var KEY_DELIMITER = '-->';
+/**
+ * params handler
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @returns {*}
+ */
+var getAutoCurvenessParams = function (seriesModel) {
+    return seriesModel.get('autoCurveness') || null;
+};
+
+/**
+ * Generate a list of edge curvatures, 20 is the default
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param {number} appendLength
+ * @return  20 => [0, -0.2, 0.2, -0.4, 0.4, -0.6, 0.6, -0.8, 0.8, -1, 1, -1.2, 1.2, -1.4, 1.4, -1.6, 1.6, -1.8, 1.8, -2]
+ */
+var createCurveness = function (seriesModel, appendLength) {
+    var autoCurvenessParmas = getAutoCurvenessParams(seriesModel);
+    var length = 20;
+    var curvenessList = [];
+
+    // handler the function set
+    if (typeof autoCurvenessParmas === 'number') {
+        length = autoCurvenessParmas;
+    }
+    else if (isArray(autoCurvenessParmas)) {
+        seriesModel.__curvenessList = autoCurvenessParmas;
+        return;
+    }
+
+    // append length
+    if (appendLength > length) {
+        length = appendLength;
+    }
+
+    // make sure the length is even
+    var len = length % 2 ? length + 2 : length + 3;
+    curvenessList = [];
+
+    for (var i = 0; i < len; i++) {
+        curvenessList.push((i % 2 ? i + 1 : i) / 10 * (i % 2 ? -1 : 1));
+    }
+    seriesModel.__curvenessList = curvenessList;
+};
+
+/**
+ * Create different cache key data in the positive and negative directions, in order to set the curvature later
+ * @param {number|string|module:echarts/data/Graph.Node} n1
+ * @param {number|string|module:echarts/data/Graph.Node} n2
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @returns {string} key
+ */
+var getKeyOfEdges = function (n1, n2, seriesModel) {
+    var source = [n1.id, n1.dataIndex].join('.');
+    var target = [n2.id, n2.dataIndex].join('.');
+    return [seriesModel.uid, source, target].join(KEY_DELIMITER);
+};
+
+/**
+ * get opposite key
+ * @param {string} key
+ * @returns {string}
+ */
+var getOppositeKey = function (key) {
+    var keys = key.split(KEY_DELIMITER);
+    return [keys[0], keys[2], keys[1]].join(KEY_DELIMITER);
+};
+
+/**
+ * get edgeMap with key
+ * @param edge
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ */
+var getEdgeFromMap = function (edge, seriesModel) {
+    var key = getKeyOfEdges(edge.node1, edge.node2, seriesModel);
+    return seriesModel.__edgeMap[key];
+};
+
+/**
+ * calculate all cases total length
+ * @param edge
+ * @param seriesModel
+ * @returns {number}
+ */
+var getTotalLengthBetweenNodes = function (edge, seriesModel) {
+    var len = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node1, edge.node2, seriesModel), seriesModel);
+    var lenV = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node2, edge.node1, seriesModel), seriesModel);
+
+    return len + lenV;
+};
+
+/**
+ *
+ * @param key
+ */
+var getEdgeMapLengthWithKey = function (key, seriesModel) {
+    var edgeMap = seriesModel.__edgeMap;
+    return edgeMap[key] ? edgeMap[key].length : 0;
+};
+
+/**
+ * Count the number of edges between the same two points, used to obtain the curvature table and the parity of the edge
+ * @see /graph/GraphSeries.js@getInitialData
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ */
+function initCurvenessList(seriesModel) {
+    if (!getAutoCurvenessParams(seriesModel)) {
+        return;
+    }
+
+    seriesModel.__curvenessList = [];
+    seriesModel.__edgeMap = {};
+    // calc the array of curveness List
+    createCurveness(seriesModel);
+}
+
+/**
+ * set edgeMap with key
+ * @param {number|string|module:echarts/data/Graph.Node} n1
+ * @param {number|string|module:echarts/data/Graph.Node} n2
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param {number} index
+ */
+function createEdgeMapForCurveness(n1, n2, seriesModel, index) {
+    if (!getAutoCurvenessParams(seriesModel)) {
+        return;
+    }
+
+    var key = getKeyOfEdges(n1, n2, seriesModel);
+    var edgeMap = seriesModel.__edgeMap;
+    var oppositeEdges = edgeMap[getOppositeKey(key)];
+    // set direction
+    if (edgeMap[key] && !oppositeEdges) {
+        edgeMap[key].isForward = true;
+    }
+    else if (oppositeEdges && edgeMap[key]) {
+        oppositeEdges.isForward = true;
+        edgeMap[key].isForward = false;
+    }
+
+    edgeMap[key] = edgeMap[key] || [];
+    edgeMap[key].push(index);
+}
+
+/**
+ * get curvature for edge
+ * @param edge
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param index
+ */
+function getCurvenessForEdge(edge, seriesModel, index, needReverse) {
+    var autoCurvenessParams = getAutoCurvenessParams(seriesModel);
+    var isArrayParam = isArray(autoCurvenessParams);
+    if (!autoCurvenessParams) {
+        return null;
+    }
+
+    var edgeArray = getEdgeFromMap(edge, seriesModel);
+    if (!edgeArray) {
+        return null;
+    }
+
+    var edgeIndex = -1;
+    for (var i = 0; i < edgeArray.length; i++) {
+        if (edgeArray[i] === index) {
+            edgeIndex = i;
+            break;
+        }
+    }
+    // if totalLen is Longer createCurveness
+    var totalLen = getTotalLengthBetweenNodes(edge, seriesModel);
+    createCurveness(seriesModel, totalLen);
+
+    edge.lineStyle = edge.lineStyle || {};
+    // if is opposite edge, must set curvenss to opposite number
+    var curKey = getKeyOfEdges(edge.node1, edge.node2, seriesModel);
+    var curvenessList = seriesModel.__curvenessList;
+    // if pass array no need parity
+    var parityCorrection = isArrayParam ? 0 : totalLen % 2 ? 0 : 1;
+
+    if (!edgeArray.isForward) {
+        // the opposite edge show outside
+        var oppositeKey = getOppositeKey(curKey);
+        var len = getEdgeMapLengthWithKey(oppositeKey, seriesModel);
+        var resValue = curvenessList[edgeIndex + len + parityCorrection];
+        // isNeedReverse, simple, force type need reverse the curveness in the junction of the forword and the opposite
+        if (needReverse) {
+            // set as array may make the parity handle with the len of opposite
+            if (isArrayParam) {
+                if (autoCurvenessParams && autoCurvenessParams[0] === 0) {
+                    return (len + parityCorrection) % 2 ? resValue : -resValue;
+                }
+                else {
+                    return ((len % 2 ? 0 : 1) + parityCorrection) % 2 ? resValue : -resValue;
+                }
+            }
+            else {
+                return (len + parityCorrection) % 2 ? resValue : -resValue;
+            }
+        }
+        else {
+            return curvenessList[edgeIndex + len + parityCorrection];
+        }
+    }
+    else {
+        return curvenessList[parityCorrection + edgeIndex];
+    }
+}
+
+/*
+* 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 GraphSeries = extendSeriesModel({
 
     type: 'series.graph',
@@ -56625,7 +56851,13 @@ var GraphSeries = extendSeriesModel({
         var self = this;
 
         if (nodes && edges) {
-            return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data;
+            // auto curveness
+            initCurvenessList(this);
+            var graph = createGraphFromNodeEdge(nodes, edges, this, true, beforeLink);
+            each$1(graph.edges, function (edge) {
+                createEdgeMapForCurveness(edge.node1, edge.node2, this, edge.dataIndex);
+            }, this);
+            return graph.data;
         }
 
         function beforeLink(nodeData, edgeData) {
@@ -56837,7 +57069,6 @@ var GraphSeries = extendSeriesModel({
         lineStyle: {
             color: '#aaa',
             width: 1,
-            curveness: 0,
             opacity: 0.5
         },
         emphasis: {
@@ -56952,22 +57183,29 @@ function makeSymbolTypeKey(symbolCategory) {
  * @inner
  */
 function createSymbol$1(name, lineData, idx) {
-    var color = lineData.getItemVisual(idx, 'color');
     var symbolType = lineData.getItemVisual(idx, name);
-    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
 
     if (!symbolType || symbolType === 'none') {
         return;
     }
 
+    var color = lineData.getItemVisual(idx, 'color');
+    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
+    var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate');
+
     if (!isArray(symbolSize)) {
         symbolSize = [symbolSize, symbolSize];
     }
+
     var symbolPath = createSymbol(
         symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2,
         symbolSize[0], symbolSize[1], color
     );
 
+    // rotate by default if symbolRotate is not specified or NaN
+    symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate)
+        ? void 0
+        : +symbolRotate * Math.PI / 180 || 0;
     symbolPath.name = name;
 
     return symbolPath;
@@ -57035,18 +57273,38 @@ function updateSymbolAndLabelBeforeLineUpdate() {
 
     if (symbolFrom) {
         symbolFrom.attr('position', fromPos);
-        var tangent = line.tangentAt(0);
-        symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
-            tangent[1], tangent[0]
-        ));
+        // Fix #12388
+        // when symbol is set to be 'arrow' in markLine,
+        // symbolRotate value will be ignored, and compulsively use tangent angle.
+        // rotate by default if symbol rotation is not specified
+        var specifiedRotation = symbolFrom.__specifiedRotation;
+        if (specifiedRotation == null) {
+            var tangent = line.tangentAt(0);
+            symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
+                tangent[1], tangent[0]
+            ));
+        }
+        else {
+            symbolFrom.attr('rotation', specifiedRotation);
+        }
         symbolFrom.attr('scale', [invScale * percent, invScale * percent]);
     }
     if (symbolTo) {
         symbolTo.attr('position', toPos);
-        var tangent = line.tangentAt(1);
-        symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
-            tangent[1], tangent[0]
-        ));
+        // Fix #12388
+        // when symbol is set to be 'arrow' in markLine,
+        // symbolRotate value will be ignored, and compulsively use tangent angle.
+        // rotate by default if symbol rotation is not specified
+        var specifiedRotation = symbolTo.__specifiedRotation;
+        if (specifiedRotation == null) {
+            var tangent = line.tangentAt(1);
+            symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
+                tangent[1], tangent[0]
+            ));
+        }
+        else {
+            symbolTo.attr('rotation', specifiedRotation);
+        }
         symbolTo.attr('scale', [invScale * percent, invScale * percent]);
     }
 
@@ -58484,12 +58742,16 @@ function simpleLayout$1(seriesModel) {
         node.setLayout([+model.get('x'), +model.get('y')]);
     });
 
-    simpleLayoutEdge(graph);
+    simpleLayoutEdge(graph, seriesModel);
 }
 
-function simpleLayoutEdge(graph) {
-    graph.eachEdge(function (edge) {
-        var curveness = edge.getModel().get('lineStyle.curveness') || 0;
+function simpleLayoutEdge(graph, seriesModel) {
+    graph.eachEdge(function (edge, index) {
+        var curveness = retrieve3(
+            edge.getModel().get('lineStyle.curveness'),
+            -getCurvenessForEdge(edge, seriesModel, index, true),
+            0
+        );
         var p1 = clone$1(edge.node1.getLayout());
         var p2 = clone$1(edge.node2.getLayout());
         var points = [p1, p2];
@@ -58553,7 +58815,7 @@ var simpleLayout = function (ecModel, api) {
                 }
             }
 
-            simpleLayoutEdge(data.graph);
+            simpleLayoutEdge(data.graph, seriesModel);
         }
         else if (!layout || layout === 'none') {
             simpleLayout$1(seriesModel);
@@ -58633,8 +58895,12 @@ function circularLayout$1(seriesModel, basedOn) {
 
     _layoutNodesBasedOn[basedOn](seriesModel, coordSys, graph, nodeData, r, cx, cy, count);
 
-    graph.eachEdge(function (edge) {
-        var curveness = edge.getModel().get('lineStyle.curveness') || 0;
+    graph.eachEdge(function (edge, index) {
+        var curveness = retrieve3(
+            edge.getModel().get('lineStyle.curveness'),
+            getCurvenessForEdge(edge, seriesModel, index),
+            0
+        );
         var p1 = clone$1(edge.node1.getLayout());
         var p2 = clone$1(edge.node2.getLayout());
         var cp1;
@@ -58978,11 +59244,16 @@ var forceLayout = function (ecModel) {
                     d = (edgeLength[0] + edgeLength[1]) / 2;
                 }
                 var edgeModel = edge.getModel();
+                var curveness = retrieve3(
+                    edgeModel.get('lineStyle.curveness'),
+                    -getCurvenessForEdge(edge, graphSeries, idx, true),
+                    0
+                );
                 return {
                     n1: nodes[edge.node1.dataIndex],
                     n2: nodes[edge.node2.dataIndex],
                     d: d,
-                    curveness: edgeModel.get('lineStyle.curveness') || 0,
+                    curveness: curveness,
                     ignoreForceLayout: edgeModel.get('ignoreForceLayout')
                 };
             });
@@ -59881,6 +60152,7 @@ var FunnelSeries = extendSeriesModel({
         minSize: '0%',
         maxSize: '100%',
         sort: 'descending', // 'ascending', 'descending'
+        orient: 'vertical',
         gap: 0,
         funnelAlign: 'center',
         label: {
@@ -60184,6 +60456,7 @@ function labelLayout$1(data) {
         var itemModel = data.getItemModel(idx);
         var labelModel = itemModel.getModel('label');
         var labelPosition = labelModel.get('position');
+        var orient = itemModel.get('orient');
 
         var labelLineModel = itemModel.getModel('labelLine');
 
@@ -60223,7 +60496,18 @@ function labelLayout$1(data) {
             var x1;
             var y1;
             var x2;
+            var y2;
             var labelLineLen = labelLineModel.get('length');
+            if (__DEV__) {
+                if (orient === 'vertical' && ['top', 'bottom'].indexOf(labelPosition) > -1) {
+                    labelPosition = 'left';
+                    console.warn('Position error: Funnel chart on vertical orient dose not support top and bottom.');
+                }
+                if (orient === 'horizontal' && ['left', 'right'].indexOf(labelPosition) > -1) {
+                    labelPosition = 'bottom';
+                    console.warn('Position error: Funnel chart on horizontal orient dose not support left and right.');
+                }
+            }
             if (labelPosition === 'left') {
                 // Left side
                 x1 = (points[3][0] + points[0][0]) / 2;
@@ -60240,50 +60524,106 @@ function labelLayout$1(data) {
                 textX = x2 + 5;
                 textAlign = 'left';
             }
+            else if (labelPosition === 'top') {
+                // Top side
+                x1 = (points[3][0] + points[0][0]) / 2;
+                y1 = (points[3][1] + points[0][1]) / 2;
+                y2 = y1 - labelLineLen;
+                textY = y2 - 5;
+                textAlign = 'center';
+            }
+            else if (labelPosition === 'bottom') {
+                // Bottom side
+                x1 = (points[1][0] + points[2][0]) / 2;
+                y1 = (points[1][1] + points[2][1]) / 2;
+                y2 = y1 + labelLineLen;
+                textY = y2 + 5;
+                textAlign = 'center';
+            }
             else if (labelPosition === 'rightTop') {
                 // RightTop side
-                x1 = points[1][0];
-                y1 = points[1][1];
-                x2 = x1 + labelLineLen;
-                textX = x2 + 5;
-                textAlign = 'top';
+                x1 = orient === 'horizontal' ? points[3][0] : points[1][0];
+                y1 = orient === 'horizontal' ? points[3][1] : points[1][1];
+                if (orient === 'horizontal') {
+                    y2 = y1 - labelLineLen;
+                    textY = y2 - 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 + labelLineLen;
+                    textX = x2 + 5;
+                    textAlign = 'top';
+                }
             }
             else if (labelPosition === 'rightBottom') {
                 // RightBottom side
                 x1 = points[2][0];
                 y1 = points[2][1];
-                x2 = x1 + labelLineLen;
-                textX = x2 + 5;
-                textAlign = 'bottom';
+                if (orient === 'horizontal') {
+                    y2 = y1 + labelLineLen;
+                    textY = y2 + 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 + labelLineLen;
+                    textX = x2 + 5;
+                    textAlign = 'bottom';
+                }
             }
             else if (labelPosition === 'leftTop') {
                 // LeftTop side
                 x1 = points[0][0];
-                y1 = points[1][1];
-                x2 = x1 - labelLineLen;
-                textX = x2 - 5;
-                textAlign = 'right';
+                y1 = orient === 'horizontal' ? points[0][1] : points[1][1];
+                if (orient === 'horizontal') {
+                    y2 = y1 - labelLineLen;
+                    textY = y2 - 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 - labelLineLen;
+                    textX = x2 - 5;
+                    textAlign = 'right';
+                }
             }
             else if (labelPosition === 'leftBottom') {
                 // LeftBottom side
-                x1 = points[3][0];
-                y1 = points[2][1];
-                x2 = x1 - labelLineLen;
-                textX = x2 - 5;
-                textAlign = 'right';
+                x1 = orient === 'horizontal' ? points[1][0] : points[3][0];
+                y1 = orient === 'horizontal' ? points[1][1] : points[2][1];
+                if (orient === 'horizontal') {
+                    y2 = y1 + labelLineLen;
+                    textY = y2 + 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 - labelLineLen;
+                    textX = x2 - 5;
+                    textAlign = 'right';
+                }
             }
             else {
-                // Right side
+                // Right side or Bottom side
                 x1 = (points[1][0] + points[2][0]) / 2;
                 y1 = (points[1][1] + points[2][1]) / 2;
-                x2 = x1 + labelLineLen;
-                textX = x2 + 5;
-                textAlign = 'left';
+                if (orient === 'horizontal') {
+                    y2 = y1 + labelLineLen;
+                    textY = y2 + 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 + labelLineLen;
+                    textX = x2 + 5;
+                    textAlign = 'left';
+                }
+            }
+            if (orient === 'horizontal') {
+                x2 = x1;
+                textX = x2;
+            }
+            else {
+                y2 = y1;
+                textY = y2;
             }
-            var y2 = y1;
-
             linePoints = [[x1, y1], [x2, y2]];
-            textY = y2;
         }
 
         layout.label = {
@@ -60304,11 +60644,19 @@ var funnelLayout = function (ecModel, api, payload) {
         var sort = seriesModel.get('sort');
         var viewRect = getViewRect$3(seriesModel, api);
         var indices = getSortedIndices(data, sort);
+        var orient = seriesModel.get('orient');
+        var viewWidth = viewRect.width;
+        var viewHeight = viewRect.height;
+        var x = viewRect.x;
+        var y = viewRect.y;
 
-        var sizeExtent = [
-            parsePercent$1(seriesModel.get('minSize'), viewRect.width),
-            parsePercent$1(seriesModel.get('maxSize'), viewRect.width)
-        ];
+        var sizeExtent = orient === 'horizontal' ? [
+            parsePercent$1(seriesModel.get('minSize'), viewHeight),
+            parsePercent$1(seriesModel.get('maxSize'), viewHeight)
+        ] : [
+                parsePercent$1(seriesModel.get('minSize'), viewWidth),
+                parsePercent$1(seriesModel.get('maxSize'), viewWidth)
+            ];
         var dataExtent = data.getDataExtent(valueDim);
         var min = seriesModel.get('min');
         var max = seriesModel.get('max');
@@ -60321,64 +60669,113 @@ var funnelLayout = function (ecModel, api, payload) {
 
         var funnelAlign = seriesModel.get('funnelAlign');
         var gap = seriesModel.get('gap');
-        var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count();
-
-        var y = viewRect.y;
+        var viewSize = orient === 'horizontal' ? viewWidth : viewHeight;
+        var itemSize = (viewSize - gap * (data.count() - 1)) / data.count();
 
-        var getLinePoints = function (idx, offY) {
+        var getLinePoints = function (idx, offset) {
             // End point index is data.count() and we assign it 0
+            if (orient === 'horizontal') {
+                var val = data.get(valueDim, idx) || 0;
+                var itemHeight = linearMap(val, [min, max], sizeExtent, true);
+                var y0;
+                switch (funnelAlign) {
+                    case 'top':
+                        y0 = y;
+                        break;
+                    case 'center':
+                        y0 = y + (viewHeight - itemHeight) / 2;
+                        break;
+                    case 'bottom':
+                        y0 = y + (viewHeight - itemHeight);
+                        break;
+                }
+
+                return [
+                    [offset, y0],
+                    [offset, y0 + itemHeight]
+                ];
+            }
             var val = data.get(valueDim, idx) || 0;
             var itemWidth = linearMap(val, [min, max], sizeExtent, true);
             var x0;
             switch (funnelAlign) {
                 case 'left':
-                    x0 = viewRect.x;
+                    x0 = x;
                     break;
                 case 'center':
-                    x0 = viewRect.x + (viewRect.width - itemWidth) / 2;
+                    x0 = x + (viewWidth - itemWidth) / 2;
                     break;
                 case 'right':
-                    x0 = viewRect.x + viewRect.width - itemWidth;
+                    x0 = x + viewWidth - itemWidth;
                     break;
             }
             return [
-                [x0, offY],
-                [x0 + itemWidth, offY]
+                [x0, offset],
+                [x0 + itemWidth, offset]
             ];
         };
 
         if (sort === 'ascending') {
             // From bottom to top
-            itemHeight = -itemHeight;
+            itemSize = -itemSize;
             gap = -gap;
-            y += viewRect.height;
+            if (orient === 'horizontal') {
+                x += viewWidth;
+            }
+            else {
+                y += viewHeight;
+            }
             indices = indices.reverse();
         }
 
         for (var i = 0; i < indices.length; i++) {
             var idx = indices[i];
             var nextIdx = indices[i + 1];
-
             var itemModel = data.getItemModel(idx);
-            var height = itemModel.get('itemStyle.height');
-            if (height == null) {
-                height = itemHeight;
+
+            if (orient === 'horizontal') {
+                var width = itemModel.get('itemStyle.width');
+                if (width == null) {
+                    width = itemSize;
+                }
+                else {
+                    width = parsePercent$1(width, viewWidth);
+                    if (sort === 'ascending') {
+                        width = -width;
+                    }
+                }
+
+                var start = getLinePoints(idx, x);
+                var end = getLinePoints(nextIdx, x + width);
+
+                x += width + gap;
+
+                data.setItemLayout(idx, {
+                    points: start.concat(end.slice().reverse())
+                });
             }
             else {
-                height = parsePercent$1(height, viewRect.height);
-                if (sort === 'ascending') {
-                    height = -height;
+                var height = itemModel.get('itemStyle.height');
+                if (height == null) {
+                    height = itemSize;
+                }
+                else {
+                    height = parsePercent$1(height, viewHeight);
+                    if (sort === 'ascending') {
+                        height = -height;
+                    }
                 }
-            }
 
-            var start = getLinePoints(idx, y);
-            var end = getLinePoints(nextIdx, y + height);
+                var start = orient === 'horizontal' ? getLinePoints(idx, x) : getLinePoints(idx, y);
+                var end = orient === 'horizontal'
+                    ? getLinePoints(nextIdx, x + width) : getLinePoints(nextIdx, y + height);
 
-            y += height + gap;
+                y += height + gap;
 
-            data.setItemLayout(idx, {
-                points: start.concat(end.slice().reverse())
-            });
+                data.setItemLayout(idx, {
+                    points: start.concat(end.slice().reverse())
+                });
+            }
         }
 
         labelLayout$1(data);
@@ -66689,8 +67086,6 @@ var LinesSeries = SeriesModel.extend({
     },
 
     mergeOption: function (option) {
-        // The input data may be null/undefined.
-        option.data = option.data || [];
 
         compatEc2(option);
 
@@ -68582,7 +68977,7 @@ var PictorialBarSeries = BaseBarSeries.extend({
         symbolPosition: null, // 'start' or 'end' or 'center', null means auto.
         symbolOffset: null,
         symbolMargin: null,   // start margin and end margin. Can be a number or a percent string.
-                                // Auto margin by defualt.
+                                // Auto margin by default.
         symbolRepeat: false,  // false/null/undefined, means no repeat.
                                 // Can be true, means auto calculate repeat times and cut by data.
                                 // Can be a number, specifies repeat times, and do not cut by data.
@@ -70418,7 +70813,7 @@ function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) {
     var snapToValue = payloadInfo.snapToValue;
 
     // Fill content of event obj for echarts.connect.
-    // By defualt use the first involved series data as a sample to connect.
+    // By default use the first involved series data as a sample to connect.
     if (payloadBatch[0] && outputFinder.seriesIndex == null) {
         extend(outputFinder, payloadBatch[0]);
     }
@@ -72136,52 +72531,46 @@ var ThemeRiverSeries = SeriesModel.extend({
      */
     fixData: function (data) {
         var rawDataLength = data.length;
+        /**
+         * Make sure every layer data get the same keys.
+         * The value index tells which layer has visited.
+         * {
+         *  2014/01/01: -1
+         * }
+         */
+        var timeValueKeys = {};
 
         // grouped data by name
         var groupResult = groupData(data, function (item) {
+            if (!timeValueKeys.hasOwnProperty(item[0])) {
+                timeValueKeys[item[0]] = -1;
+            }
             return item[2];
         });
         var layData = [];
         groupResult.buckets.each(function (items, key) {
             layData.push({name: key, dataList: items});
         });
-
         var layerNum = layData.length;
-        var largestLayer = -1;
-        var index = -1;
-        for (var i = 0; i < layerNum; ++i) {
-            var len = layData[i].dataList.length;
-            if (len > largestLayer) {
-                largestLayer = len;
-                index = i;
-            }
-        }
 
         for (var k = 0; k < layerNum; ++k) {
-            if (k === index) {
-                continue;
-            }
             var name = layData[k].name;
-            for (var j = 0; j < largestLayer; ++j) {
-                var timeValue = layData[index].dataList[j][0];
-                var length = layData[k].dataList.length;
-                var keyIndex = -1;
-                for (var l = 0; l < length; ++l) {
-                    var value = layData[k].dataList[l][0];
-                    if (value === timeValue) {
-                        keyIndex = l;
-                        break;
-                    }
-                }
-                if (keyIndex === -1) {
+            for (var j = 0; j < layData[k].dataList.length; ++j) {
+                var timeValue = layData[k].dataList[j][0];
+                timeValueKeys[timeValue] = k;
+            }
+
+            for (var timeValue in timeValueKeys) {
+                if (timeValueKeys.hasOwnProperty(timeValue) && timeValueKeys[timeValue] !== k) {
+                    timeValueKeys[timeValue] = k;
                     data[rawDataLength] = [];
                     data[rawDataLength][0] = timeValue;
                     data[rawDataLength][1] = 0;
                     data[rawDataLength][2] = name;
                     rawDataLength++;
-
                 }
             }
+
         }
         return data;
     },
@@ -72800,18 +73189,25 @@ SeriesModel.extend({
 
         completeTreeValue$1(root);
 
-        var levels = option.levels || [];
-
-        // levels = option.levels = setDefault(levels, ecModel);
-
-        var treeOption = {};
-
-        treeOption.levels = levels;
+        var levelModels = map(option.levels || [], function (levelDefine) {
+            return new Model(levelDefine, this, ecModel);
+        }, this);
 
         // Make sure always a new tree is created when setOption,
         // in TreemapView, we check whether oldTree === newTree
         // to choose mappings approach among old shapes and new shapes.
-        return Tree.createTree(root, this, treeOption).data;
+        var tree = Tree.createTree(root, this, beforeLink);
+
+        function beforeLink(nodeData) {
+            nodeData.wrapMethod('getItemModel', function (model, idx) {
+                var node = tree.getNodeByDataIndex(idx);
+                var levelModel = levelModels[node.depth];
+                levelModel && (model.parentModel = levelModel);
+                return model;
+            });
+        }
+
+        return tree.data;
     },
 
     optionUpdated: function () {
@@ -73181,9 +73577,13 @@ SunburstPieceProto._updateLabel = function (seriesModel, visualColor, state) {
         : itemModel.getModel(state + '.label');
     var labelHoverModel = itemModel.getModel('emphasis.label');
 
+    var labelFormatter = labelModel.get('formatter');
+    // Use normal formatter if no state formatter is defined
+    var labelState = labelFormatter ? state : 'normal';
+
     var text = retrieve(
         seriesModel.getFormattedLabel(
-            this.node.dataIndex, state, null, null, 'label'
+            this.node.dataIndex, labelState, null, null, 'label'
         ),
         this.node.name
     );
@@ -75112,8 +75512,9 @@ function barLayoutPolar(seriesType, ecModel, api) {
         var clampLayout = baseAxis.dim !== 'radius'
             || !seriesModel.get('roundCap', true);
 
-        var valueAxisStart = valueAxis.getExtent()[0];
-
+        var valueAxisStart = valueAxis.dim === 'radius'
+            ? valueAxis.dataToRadius(0)
+            : valueAxis.dataToAngle(0);
         for (var idx = 0, len = data.count(); idx < len; idx++) {
             var value = data.get(valueDim, idx);
             var baseValue = data.get(baseDim, idx);
@@ -75125,6 +75526,7 @@ function barLayoutPolar(seriesType, ecModel, api) {
             // stackResultDimension directly.
             // Only ordinal axis can be stacked.
             if (stacked) {
+
                 if (!lastStackCoords[stackId][baseValue]) {
                     lastStackCoords[stackId][baseValue] = {
                         p: valueAxisStart, // Positive stack
@@ -77014,12 +77416,9 @@ var GeoModel = ComponentModel.extend({
      * @return {string}
      */
     getFormattedLabel: function (name, status) {
+        status = status || 'normal';
         var regionModel = this.getRegionModel(name);
-        var formatter = regionModel.get(
-            'label'
-            + (status === 'normal' ? '.' : status + '.')
-            + 'formatter'
-        );
+        var formatter = regionModel.get((status === 'normal' ? '' : status + '.') + 'label.formatter');
         var params = {
             name: name
         };
@@ -79426,7 +79825,8 @@ proto$2.onclick = function (ecModel, api) {
         $a.target = '_blank';
         $a.href = url;
         var evt = new MouseEvent('click', {
-            view: window,
+            // some micro front-end framework, window maybe is a Proxy
+            view: document.defaultView,
             bubbles: true,
             cancelable: false
         });
@@ -79741,7 +80141,8 @@ function assembleSeriesWithCategoryAxis(series) {
         }));
         var columns = [categoryAxis.model.getCategories()];
         each$1(group.series, function (series) {
-            columns.push(series.getRawData().mapArray(valueAxisDim, function (val) {
+            var rawData = series.getRawData();
+            columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim), function (val) {
                 return val;
             }));
         });
@@ -79859,7 +80260,13 @@ function parseListContents(str) {
 
     var data = [];
     for (var i = 0; i < lines.length; i++) {
-        var items = trim$1(lines[i]).split(itemSplitRegex);
+        // if line is empty, ignore it.
+        // there is a case that a user forgot to delete `\n`.
+        var line = trim$1(lines[i]);
+        if (!line) {
+            continue;
+        }
+        var items = line.split(itemSplitRegex);
         var name = '';
         var value;
         var hasName = false;
@@ -80074,13 +80481,18 @@ function tryMergeDataOption(newData, originalData) {
     return map(newData, function (newVal, idx) {
         var original = originalData && originalData[idx];
         if (isObject$1(original) && !isArray(original)) {
-            if (isObject$1(newVal) && !isArray(newVal)) {
-                newVal = newVal.value;
+            var newValIsObject = isObject$1(newVal) && !isArray(newVal);
+            if (!newValIsObject) {
+                newVal = {
+                    value: newVal
+                };
             }
+            // original data has name but new data has no name
+            var shouldDeleteName = original.name != null && newVal.name == null;
             // Original data has option
-            return defaults({
-                value: newVal
-            }, original);
+            newVal = defaults(newVal, original);
+            shouldDeleteName && (delete newVal.name);
+            return newVal;
         }
         else {
             return newVal;
@@ -82367,7 +82779,11 @@ DataZoom.defaultOption = {
         back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
     },
     // `zoom`, `back`
-    title: clone(dataZoomLang.title)
+    title: clone(dataZoomLang.title),
+    brushStyle: {
+        borderWidth: 0,
+        color: 'rgba(0,0,0,0.2)'
+    }
 };
 
 var proto$4 = DataZoom.prototype;
@@ -82542,11 +82958,7 @@ function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
             zoomActive
             ? {
                 brushType: 'auto',
-                brushStyle: {
-                    // FIXME user customized?
-                    lineWidth: 0,
-                    fill: 'rgba(0,0,0,0.2)'
-                }
+                brushStyle: featureModel.getModel('brushStyle').getItemStyle()
             }
             : false
         );
@@ -82884,8 +83296,21 @@ function assembleFont(textStyleModel) {
 
     cssText.push('font:' + textStyleModel.getFont());
 
+    var lineHeight = textStyleModel.get('lineHeight');
+    if (lineHeight == null) {
+        lineHeight = Math.round(fontSize * 3 / 2);
+    }
+
     fontSize
-        && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
+        && cssText.push('line-height:' + lineHeight + 'px');
+
+    var shadowColor = textStyleModel.get('textShadowColor');
+    var shadowBlur = textStyleModel.get('textShadowBlur') || 0;
+    var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0;
+    var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0;
+    shadowBlur
+        && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px '
+            + shadowBlur + 'px ' + shadowColor);
 
     each$22(['decoration', 'align'], function (name) {
         var val = textStyleModel.get(name);
@@ -82969,6 +83394,8 @@ function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
             out[1] += viewportRootOffset.offsetTop;
         }
     }
+    out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+    out[3] = out[1] / zr.getHeight(); // The ratio of top to height
 }
 
 /**
@@ -82993,7 +83420,7 @@ function TooltipContent(container, api, opt) {
     var zr = this._zr = api.getZr();
     var appendToBody = this._appendToBody = opt && opt.appendToBody;
 
-    this._styleCoord = [0, 0];
+    this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
 
     makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
 
@@ -83064,7 +83491,7 @@ TooltipContent.prototype = {
     /**
      * Update when tooltip is rendered
      */
-    update: function () {
+    update: function (tooltipModel) {
         // FIXME
         // Move this logic to ec main?
         var container = this._container;
@@ -83074,11 +83501,25 @@ TooltipContent.prototype = {
         if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
             domStyle.position = 'relative';
         }
+        var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+        alwaysShowContent && this._moveTooltipIfResized();
         // Hide the tooltip
         // PENDING
         // this.hide();
     },
 
+    /**
+     * when `alwaysShowContent` is true,
+     * we should move the tooltip after chart resized
+     */
+    _moveTooltipIfResized: function () {
+        var ratioX = this._styleCoord[2]; // The ratio of left to width
+        var ratioY = this._styleCoord[3]; // The ratio of top to height
+        var realX = ratioX * this._zr.getWidth();
+        var realY = ratioY * this._zr.getHeight();
+        this.moveTo(realX, realY);
+    },
+
     show: function (tooltipModel) {
         clearTimeout(this._hideTimeout);
         var el = this.el;
@@ -83093,10 +83534,10 @@ TooltipContent.prototype = {
 
         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
+        // If mouse occasionally move over the tooltip, a mouseout event will be
+        // triggered by canvas, and cause some unexpectable result like dragging
         // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
-        // it. Although it is not suppored by IE8~IE10, fortunately it is a rare
+        // it. Although it is not supported by IE8~IE10, fortunately it is a rare
         // scenario.
         el.style.pointerEvents = this._enterable ? 'auto' : 'none';
 
@@ -83134,7 +83575,7 @@ TooltipContent.prototype = {
         if (this._show && !(this._inContent && this._enterable)) {
             if (time) {
                 this._hideDelay = time;
-                // Set show false to avoid invoke hideLater mutiple times
+                // Set show false to avoid invoke hideLater multiple times
                 this._show = false;
                 this._hideTimeout = setTimeout(bind(this.hide, this), time);
             }
@@ -83191,13 +83632,24 @@ TooltipContent.prototype = {
 */
 
 // import Group from 'zrender/src/container/Group';
+function makeStyleCoord$1(out, zr, zrX, zrY) {
+    out[0] = zrX;
+    out[1] = zrY;
+    out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+    out[3] = out[1] / zr.getHeight(); // The ratio of top to height
+}
+
 /**
  * @alias module:echarts/component/tooltip/TooltipRichContent
  * @constructor
  */
 function TooltipRichContent(api) {
 
-    this._zr = api.getZr();
+    var zr = this._zr = api.getZr();
+
+    this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
+
+    makeStyleCoord$1(this._styleCoord, zr, api.getWidth() / 2, api.getHeight() / 2);
 
     this._show = false;
 
@@ -83220,8 +83672,21 @@ TooltipRichContent.prototype = {
     /**
      * Update when tooltip is rendered
      */
-    update: function () {
-        // noop
+    update: function (tooltipModel) {
+        var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+        alwaysShowContent && this._moveTooltipIfResized();
+    },
+
+    /**
+     * when `alwaysShowContent` is true,
+     * we should move the tooltip after chart resized
+     */
+    _moveTooltipIfResized: function () {
+        var ratioX = this._styleCoord[2]; // The ratio of left to width
+        var ratioY = this._styleCoord[3]; // The ratio of top to height
+        var realX = ratioX * this._zr.getWidth();
+        var realY = ratioY * this._zr.getHeight();
+        this.moveTo(realX, realY);
     },
 
     show: function (tooltipModel) {
@@ -83276,16 +83741,23 @@ TooltipRichContent.prototype = {
             startId = text.indexOf('{marker');
         }
 
+        var textStyleModel = tooltipModel.getModel('textStyle');
+        var fontSize = textStyleModel.get('fontSize');
+        var lineHeight = tooltipModel.get('textLineHeight');
+        if (lineHeight == null) {
+            lineHeight = Math.round(fontSize * 3 / 2);
+        }
+
         this.el = new Text({
-            style: {
+            style: setTextStyle({}, textStyleModel, {
                 rich: markers,
                 text: content,
-                textLineHeight: 20,
                 textBackgroundColor: tooltipModel.get('backgroundColor'),
                 textBorderRadius: tooltipModel.get('borderRadius'),
                 textFill: tooltipModel.get('textStyle.color'),
-                textPadding: tooltipModel.get('padding')
-            },
+                textPadding: tooltipModel.get('padding'),
+                textLineHeight: lineHeight
+            }),
             z: tooltipModel.get('z')
         });
         this._zr.add(this.el);
@@ -83320,7 +83792,9 @@ TooltipRichContent.prototype = {
 
     moveTo: function (x, y) {
         if (this.el) {
-            this.el.attr('position', [x, y]);
+            var styleCoord = this._styleCoord;
+            makeStyleCoord$1(styleCoord, this._zr, x, y);
+            this.el.attr('position', [styleCoord[0], styleCoord[1]]);
         }
     },
 
@@ -83335,7 +83809,7 @@ TooltipRichContent.prototype = {
         if (this._show && !(this._inContent && this._enterable)) {
             if (time) {
                 this._hideDelay = time;
-                // Set show false to avoid invoke hideLater mutiple times
+                // Set show false to avoid invoke hideLater multiple times
                 this._show = false;
                 this._hideTimeout = setTimeout(bind(this.hide, this), time);
             }
@@ -83349,6 +83823,14 @@ TooltipRichContent.prototype = {
         return this._show;
     },
 
+    dispose: function () {
+        clearTimeout(this._hideTimeout);
+
+        if (this.el) {
+            this._zr.remove(this.el);
+        }
+    },
+
     getOuterSize: function () {
         var size = this.getSize();
         return {
@@ -83453,7 +83935,7 @@ extendComponentView({
         this._alwaysShowContent = tooltipModel.get('alwaysShowContent');
 
         var tooltipContent = this._tooltipContent;
-        tooltipContent.update();
+        tooltipContent.update(tooltipModel);
         tooltipContent.setEnterable(tooltipModel.get('enterable'));
 
         this._initGlobalListener();
@@ -83683,7 +84165,7 @@ extendComponentView({
     _showOrMove: function (tooltipModel, cb) {
         // showDelay is used in this case: tooltip.enterable is set
         // as true. User intent to move mouse into tooltip and click
-        // something. `showDelay` makes it easyer to enter the content
+        // something. `showDelay` makes it easier to enter the content
         // but tooltip do not move immediately.
         var delay = tooltipModel.get('showDelay');
         cb = bind(cb, this);
@@ -83768,7 +84250,7 @@ extendComponentView({
 
                 // Default tooltip content
                 // FIXME
-                // (1) shold be the first data which has name?
+                // (1) should be the first data which has name?
                 // (2) themeRiver, firstDataIndex is array, and first line is unnecessary.
                 var firstLine = valueLabel;
                 if (renderMode !== 'html') {
@@ -83884,7 +84366,7 @@ extendComponentView({
         var asyncTicket = Math.random();
 
         // Do not check whether `trigger` is 'none' here, because `trigger`
-        // only works on cooridinate system. In fact, we have not found case
+        // only works on coordinate system. In fact, we have not found case
         // that requires setting `trigger` nothing on component yet.
 
         this._showOrMove(subTooltipModel, function () {
@@ -85625,7 +86107,7 @@ extendComponentView({
         }
         if (sublink) {
             subTextEl.on('click', function () {
-                windowOpen(link, '_' + titleModel.get('subtarget'));
+                windowOpen(sublink, '_' + titleModel.get('subtarget'));
             });
         }
 
@@ -86903,13 +87385,16 @@ function getViewRect$5(model, api) {
 }
 
 function makeIcon(timelineModel, objPath, rect, opts) {
-    var icon = makePath(
-        timelineModel.get(objPath).replace(/^path:\/\//, ''),
-        clone(opts || {}),
-        new BoundingRect(rect[0], rect[1], rect[2], rect[3]),
-        'center'
+    var style = opts.style;
+    var icon = createIcon(
+        timelineModel.get(objPath),
+        opts || {},
+        new BoundingRect(rect[0], rect[1], rect[2], rect[3])
     );
-
+    // TODO createIcon won't use style in opt.
+    if (style) {
+        icon.setStyle(style);
+    }
     return icon;
 }
 
@@ -87135,15 +87620,16 @@ var MarkerModel = extendComponentModel({
         }
     },
 
-    formatTooltip: function (dataIndex) {
+    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
         var data = this.getData();
         var value = this.getRawValue(dataIndex);
         var formattedValue = isArray(value)
             ? map(value, addCommas$1).join(', ') : addCommas$1(value);
         var name = data.getName(dataIndex);
         var html = encodeHTML$1(this.name);
+        var newLine = renderMode === 'html' ? '<br/>' : '\n';
         if (value != null || name) {
-            html += '<br />';
+            html += newLine;
         }
         if (name) {
             html += encodeHTML$1(name);
@@ -87608,10 +88094,12 @@ MarkerView.extend({
             var itemModel = mpData.getItemModel(idx);
             var symbol = itemModel.getShallow('symbol');
             var symbolSize = itemModel.getShallow('symbolSize');
+            var symbolRotate = itemModel.getShallow('symbolRotate');
             var isFnSymbol = isFunction$1(symbol);
             var isFnSymbolSize = isFunction$1(symbolSize);
+            var isFnSymbolRotate = isFunction$1(symbolRotate);
 
-            if (isFnSymbol || isFnSymbolSize) {
+            if (isFnSymbol || isFnSymbolSize || isFnSymbolRotate) {
                 var rawIdx = mpModel.getRawValue(idx);
                 var dataParams = mpModel.getDataParams(idx);
                 if (isFnSymbol) {
@@ -87621,11 +88109,15 @@ MarkerView.extend({
                     // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据?
                     symbolSize = symbolSize(rawIdx, dataParams);
                 }
+                if (isFnSymbolRotate) {
+                    symbolRotate = symbolRotate(rawIdx, dataParams);
+                }
             }
 
             mpData.setItemVisual(idx, {
                 symbol: symbol,
                 symbolSize: symbolSize,
+                symbolRotate: symbolRotate,
                 color: itemModel.get('itemStyle.color')
                     || seriesData.getVisual('color')
             });
@@ -88061,8 +88553,10 @@ MarkerView.extend({
             ]);
 
             lineData.setItemVisual(idx, {
+                'fromSymbolRotate': fromData.getItemVisual(idx, 'symbolRotate'),
                 'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'),
                 'fromSymbol': fromData.getItemVisual(idx, 'symbol'),
+                'toSymbolRotate': toData.getItemVisual(idx, 'symbolRotate'),
                 'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'),
                 'toSymbol': toData.getItemVisual(idx, 'symbol')
             });
@@ -88084,8 +88578,8 @@ MarkerView.extend({
             updateSingleMarkerEndLayout(
                 data, idx, isFrom, seriesModel, api
             );
-
             data.setItemVisual(idx, {
+                symbolRotate: itemModel.get('symbolRotate'),
                 symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
                 symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
                 color: itemModel.get('itemStyle.color') || seriesData.getVisual('color')
@@ -88444,9 +88938,29 @@ MarkerView.extend({
         // Update visual and layout of line
         areaData.each(function (idx) {
             // Layout
-            areaData.setItemLayout(idx, map(dimPermutations, function (dim) {
+            var points = map(dimPermutations, function (dim) {
                 return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
-            }));
+            });
+            // If none of the area is inside coordSys, allClipped is set to be true
+            // in layout so that label will not be displayed. See #12591
+            var allClipped = true;
+            each$1(dimPermutations, function (dim) {
+                if (!allClipped) {
+                    return;
+                }
+                var xValue = areaData.get(dim[0], idx);
+                var yValue = areaData.get(dim[1], idx);
+                // If is infinity, the axis should be considered not clipped
+                if ((isInifinity$1(xValue) || coordSys.getAxis('x').containData(xValue))
+                    && (isInifinity$1(yValue) || coordSys.getAxis('y').containData(yValue))
+                ) {
+                    allClipped = false;
+                }
+            });
+            areaData.setItemLayout(idx, {
+                points: points,
+                allClipped: allClipped
+            });
 
             // Visual
             areaData.setItemVisual(idx, {
@@ -88457,23 +88971,41 @@ MarkerView.extend({
 
         areaData.diff(polygonGroup.__data)
             .add(function (idx) {
-                var polygon = new Polygon({
-                    shape: {
-                        points: areaData.getItemLayout(idx)
-                    }
-                });
-                areaData.setItemGraphicEl(idx, polygon);
-                polygonGroup.group.add(polygon);
+                var layout = areaData.getItemLayout(idx);
+                if (!layout.allClipped) {
+                    var polygon = new Polygon({
+                        shape: {
+                            points: layout.points
+                        }
+                    });
+                    areaData.setItemGraphicEl(idx, polygon);
+                    polygonGroup.group.add(polygon);
+                }
             })
             .update(function (newIdx, oldIdx) {
                 var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx);
-                updateProps(polygon, {
-                    shape: {
-                        points: areaData.getItemLayout(newIdx)
+                var layout = areaData.getItemLayout(newIdx);
+                if (!layout.allClipped) {
+                    if (polygon) {
+                        updateProps(polygon, {
+                            shape: {
+                                points: layout.points
+                            }
+                        }, maModel, newIdx);
+                    }
+                    else {
+                        polygon = new Polygon({
+                            shape: {
+                                points: layout.points
+                            }
+                        });
                     }
-                }, maModel, newIdx);
-                polygonGroup.group.add(polygon);
-                areaData.setItemGraphicEl(newIdx, polygon);
+                    areaData.setItemGraphicEl(newIdx, polygon);
+                    polygonGroup.group.add(polygon);
+                }
+                else if (polygon) {
+                    polygonGroup.group.remove(polygon);
+                }
             })
             .remove(function (idx) {
                 var polygon = polygonGroup.__data.getItemGraphicEl(idx);
@@ -90218,7 +90750,7 @@ var ScrollableLegendView = LegendView.extend({
             var legendDataIdx = child.__legendDataIndex;
             // FIXME
             // If the given targetDataIndex (from model) is illegal,
-            // we use defualtIndex. But the index on the legend model and
+            // we use defaultIndex. 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) {
@@ -92435,7 +92967,7 @@ var VisualMapModel = extendComponentModel({
             // Originally we use visualMap.color as the default color, but setOption at
             // the second time the default color will be erased. So we change to use
             // constant DEFAULT_COLOR.
-            // If user do not want the defualt color, set inRange: {color: null}.
+            // If user do not want the default color, set inRange: {color: null}.
             base.inRange = base.inRange || {color: ecModel.get('gradientColor')};
 
             // If using shortcut like: {inRange: 'symbol'}, complete default value.
@@ -97234,7 +97766,7 @@ GradientManager.prototype.updateDom = function (gradient, dom) {
         stop.setAttribute('offset', colors[i].offset * 100 + '%');
 
         var color = colors[i].color;
-        if (color.indexOf('rgba' > -1)) {
+        if (color.indexOf('rgba') > -1) {
             // Fix Safari bug that stop-color not recognizing alpha #9014
             var opacity = parse(color)[3];
             var hex = toHex(color);
diff --git a/en/dist/echarts-en.js.map b/en/dist/echarts-en.js.map
index 85f8c54..54c9f32 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/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
+{"version":3,"file":"echarts-en.js","sources":["../src/config.js","../node_modules/zrender/src/core/guid.js","../node_modules/zrender/src/core/env.js","../node_modules/zrender/src/core/util.js","../node_modules/zrender/src/core/vector.js","../node_modules/zrender/src/mixin/Draggable.js","../node_modules/zrender/src/mixin/Eventful.js","../node_modules/zrender/src/core/fourPointsTransform.js","../node_modules/zrender/src/core/dom.js","../node_modules/zrender/src/core/event.js","../node_mod [...]
\ No newline at end of file
diff --git a/en/dist/echarts-en.min.js b/en/dist/echarts-en.min.js
index 9129d3e..c7022fc 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 960a3a5..85d515f 100644
--- a/en/dist/echarts-en.simple.js
+++ b/en/dist/echarts-en.simple.js
@@ -11289,7 +11289,7 @@ var painterCtors = {
 /**
  * @type {string}
  */
-var version$1 = '4.3.1';
+var version$1 = '4.3.2';
 
 /**
  * Initializing a zrender instance
@@ -25578,7 +25578,7 @@ var proto = Scheduler.prototype;
  * @param {Object} payload
  */
 proto.restoreData = function (ecModel, payload) {
-    // TODO: Only restroe needed series and components, but not all components.
+    // TODO: Only restore needed series and components, but not all components.
     // Currently `restoreData` of all of the series and component will be called.
     // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
     // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
@@ -27155,10 +27155,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.8.0';
+var version = '4.9.0';
 
 var dependencies = {
-    zrender: '4.3.1'
+    zrender: '4.3.2'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -30401,7 +30401,7 @@ listProto.mapDimension = function (coordDim, idx) {
  * Initialize from data
  * @param {Array.<Object|number|Array>} data source or data or data provider.
  * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
- *        defualt label/tooltip.
+ *        default label/tooltip.
  *        A name can be specified in encode.itemName,
  *        or dataItem.name (only for series option data),
  *        or provided in nameList from outside.
@@ -33594,7 +33594,7 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     }
     else {
         symbolPath.setStyle({
-            opacity: null,
+            opacity: 1,
             shadowBlur: null,
             shadowOffsetX: null,
             shadowOffsetY: null,
@@ -35779,7 +35779,7 @@ var dataSample = function (seriesType) {
                 var valueAxis = coordSys.getOtherAxis(baseAxis);
                 var extent = baseAxis.getExtent();
                 // Coordinste system has been resized
-                var size = extent[1] - extent[0];
+                var size = Math.abs(extent[1] - extent[0]);
                 var rate = Math.round(data.count() / size);
                 if (rate > 1) {
                     var sampler;
@@ -37945,8 +37945,8 @@ function rotateTextRect(textRect, rotate) {
     var boundingBox = textRect.plain();
     var beforeWidth = boundingBox.width;
     var beforeHeight = boundingBox.height;
-    var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
-    var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
+    var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
+    var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
     var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
 
     return rotatedRect;
@@ -39141,7 +39141,7 @@ var defaultOption = {
     name: '',
     // 'start' | 'middle' | 'end'
     nameLocation: 'end',
-    // By degree. By defualt auto rotate by nameLocation.
+    // By degree. By default auto rotate by nameLocation.
     nameRotate: null,
     nameTruncate: {
         maxWidth: null,
@@ -42231,20 +42231,25 @@ extendChartView({
         var bgEls = [];
         var oldBgEls = this._backgroundEls || [];
 
+        var createBackground = function (dataIndex) {
+            var bgLayout = getLayout[coord.type](data, dataIndex);
+            var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
+            bgEl.useStyle(backgroundModel.getBarItemStyle());
+            // Only cartesian2d support borderRadius.
+            if (coord.type === 'cartesian2d') {
+                bgEl.setShape('r', barBorderRadius);
+            }
+            bgEls[dataIndex] = bgEl;
+            return bgEl;
+        };
+
         data.diff(oldData)
             .add(function (dataIndex) {
                 var itemModel = data.getItemModel(dataIndex);
                 var layout = getLayout[coord.type](data, dataIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgLayout = getLayout[coord.type](data, dataIndex);
-                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
-                    }
-                    bgEls[dataIndex] = bgEl;
+                    createBackground(dataIndex);
                 }
 
                 // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
@@ -42278,13 +42283,19 @@ extendChartView({
                 var layout = getLayout[coord.type](data, newIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgEl = oldBgEls[oldIndex];
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
+                    var bgEl;
+                    if (oldBgEls.length === 0) {
+                        bgEl = createBackground(oldIndex);
+                    }
+                    else {
+                        bgEl = oldBgEls[oldIndex];
+                        bgEl.useStyle(backgroundModel.getBarItemStyle());
+                        // Only cartesian2d support borderRadius.
+                        if (coord.type === 'cartesian2d') {
+                            bgEl.setShape('r', barBorderRadius);
+                        }
+                        bgEls[newIndex] = bgEl;
                     }
-                    bgEls[newIndex] = bgEl;
 
                     var bgLayout = getLayout[coord.type](data, newIndex);
                     var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
@@ -42444,8 +42455,31 @@ var clip = {
         return clipped;
     },
 
-    polar: function (coordSysClipArea) {
-        return false;
+    polar: function (coordSysClipArea, layout) {
+        var signR = layout.r0 <= layout.r ? 1 : -1;
+        // Make sure r is larger than r0
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        var r = mathMin$4(layout.r, coordSysClipArea.r);
+        var r0 = mathMax$4(layout.r0, coordSysClipArea.r0);
+
+        layout.r = r;
+        layout.r0 = r0;
+
+        var clipped = r - r0 < 0;
+
+        // Reverse back
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        return clipped;
     }
 };
 
diff --git a/en/dist/echarts-en.simple.min.js b/en/dist/echarts-en.simple.min.js
index 0bdc6f3..7a54c7a 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 1b2ee0f..52127c4 100644
--- a/en/dist/echarts.common.js
+++ b/en/dist/echarts.common.js
@@ -11595,7 +11595,7 @@ var instances$1 = {};    // ZRender实例map索引
 /**
  * @type {string}
  */
-var version$1 = '4.3.1';
+var version$1 = '4.3.2';
 
 /**
  * Initializing a zrender instance
@@ -26152,7 +26152,7 @@ var proto = Scheduler.prototype;
  * @param {Object} payload
  */
 proto.restoreData = function (ecModel, payload) {
-    // TODO: Only restroe needed series and components, but not all components.
+    // TODO: Only restore needed series and components, but not all components.
     // Currently `restoreData` of all of the series and component will be called.
     // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
     // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
@@ -27729,10 +27729,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.8.0';
+var version = '4.9.0';
 
 var dependencies = {
-    zrender: '4.3.1'
+    zrender: '4.3.2'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -30975,7 +30975,7 @@ listProto.mapDimension = function (coordDim, idx) {
  * Initialize from data
  * @param {Array.<Object|number|Array>} data source or data or data provider.
  * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
- *        defualt label/tooltip.
+ *        default label/tooltip.
  *        A name can be specified in encode.itemName,
  *        or dataItem.name (only for series option data),
  *        or provided in nameList from outside.
@@ -35567,8 +35567,8 @@ function rotateTextRect(textRect, rotate) {
     var boundingBox = textRect.plain();
     var beforeWidth = boundingBox.width;
     var beforeHeight = boundingBox.height;
-    var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
-    var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
+    var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
+    var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
     var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
 
     return rotatedRect;
@@ -37669,7 +37669,7 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     }
     else {
         symbolPath.setStyle({
-            opacity: null,
+            opacity: 1,
             shadowBlur: null,
             shadowOffsetX: null,
             shadowOffsetY: null,
@@ -39854,7 +39854,7 @@ var dataSample = function (seriesType) {
                 var valueAxis = coordSys.getOtherAxis(baseAxis);
                 var extent = baseAxis.getExtent();
                 // Coordinste system has been resized
-                var size = extent[1] - extent[0];
+                var size = Math.abs(extent[1] - extent[0]);
                 var rate = Math.round(data.count() / size);
                 if (rate > 1) {
                     var sampler;
@@ -40310,7 +40310,7 @@ var defaultOption = {
     name: '',
     // 'start' | 'middle' | 'end'
     nameLocation: 'end',
-    // By degree. By defualt auto rotate by nameLocation.
+    // By degree. By default auto rotate by nameLocation.
     nameRotate: null,
     nameTruncate: {
         maxWidth: null,
@@ -43553,20 +43553,25 @@ extendChartView({
         var bgEls = [];
         var oldBgEls = this._backgroundEls || [];
 
+        var createBackground = function (dataIndex) {
+            var bgLayout = getLayout[coord.type](data, dataIndex);
+            var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
+            bgEl.useStyle(backgroundModel.getBarItemStyle());
+            // Only cartesian2d support borderRadius.
+            if (coord.type === 'cartesian2d') {
+                bgEl.setShape('r', barBorderRadius);
+            }
+            bgEls[dataIndex] = bgEl;
+            return bgEl;
+        };
+
         data.diff(oldData)
             .add(function (dataIndex) {
                 var itemModel = data.getItemModel(dataIndex);
                 var layout = getLayout[coord.type](data, dataIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgLayout = getLayout[coord.type](data, dataIndex);
-                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
-                    }
-                    bgEls[dataIndex] = bgEl;
+                    createBackground(dataIndex);
                 }
 
                 // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
@@ -43600,13 +43605,19 @@ extendChartView({
                 var layout = getLayout[coord.type](data, newIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgEl = oldBgEls[oldIndex];
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
+                    var bgEl;
+                    if (oldBgEls.length === 0) {
+                        bgEl = createBackground(oldIndex);
+                    }
+                    else {
+                        bgEl = oldBgEls[oldIndex];
+                        bgEl.useStyle(backgroundModel.getBarItemStyle());
+                        // Only cartesian2d support borderRadius.
+                        if (coord.type === 'cartesian2d') {
+                            bgEl.setShape('r', barBorderRadius);
+                        }
+                        bgEls[newIndex] = bgEl;
                     }
-                    bgEls[newIndex] = bgEl;
 
                     var bgLayout = getLayout[coord.type](data, newIndex);
                     var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
@@ -43766,8 +43777,31 @@ var clip = {
         return clipped;
     },
 
-    polar: function (coordSysClipArea) {
-        return false;
+    polar: function (coordSysClipArea, layout) {
+        var signR = layout.r0 <= layout.r ? 1 : -1;
+        // Make sure r is larger than r0
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        var r = mathMin$4(layout.r, coordSysClipArea.r);
+        var r0 = mathMax$4(layout.r0, coordSysClipArea.r0);
+
+        layout.r = r;
+        layout.r0 = r0;
+
+        var clipped = r - r0 < 0;
+
+        // Reverse back
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        return clipped;
     }
 };
 
@@ -47110,7 +47144,7 @@ function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) {
     var snapToValue = payloadInfo.snapToValue;
 
     // Fill content of event obj for echarts.connect.
-    // By defualt use the first involved series data as a sample to connect.
+    // By default use the first involved series data as a sample to connect.
     if (payloadBatch[0] && outputFinder.seriesIndex == null) {
         extend(outputFinder, payloadBatch[0]);
     }
@@ -48788,8 +48822,21 @@ function assembleFont(textStyleModel) {
 
     cssText.push('font:' + textStyleModel.getFont());
 
+    var lineHeight = textStyleModel.get('lineHeight');
+    if (lineHeight == null) {
+        lineHeight = Math.round(fontSize * 3 / 2);
+    }
+
     fontSize
-        && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
+        && cssText.push('line-height:' + lineHeight + 'px');
+
+    var shadowColor = textStyleModel.get('textShadowColor');
+    var shadowBlur = textStyleModel.get('textShadowBlur') || 0;
+    var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0;
+    var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0;
+    shadowBlur
+        && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px '
+            + shadowBlur + 'px ' + shadowColor);
 
     each$10(['decoration', 'align'], function (name) {
         var val = textStyleModel.get(name);
@@ -48873,6 +48920,8 @@ function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
             out[1] += viewportRootOffset.offsetTop;
         }
     }
+    out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+    out[3] = out[1] / zr.getHeight(); // The ratio of top to height
 }
 
 /**
@@ -48897,7 +48946,7 @@ function TooltipContent(container, api, opt) {
     var zr = this._zr = api.getZr();
     var appendToBody = this._appendToBody = opt && opt.appendToBody;
 
-    this._styleCoord = [0, 0];
+    this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
 
     makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
 
@@ -48968,7 +49017,7 @@ TooltipContent.prototype = {
     /**
      * Update when tooltip is rendered
      */
-    update: function () {
+    update: function (tooltipModel) {
         // FIXME
         // Move this logic to ec main?
         var container = this._container;
@@ -48978,11 +49027,25 @@ TooltipContent.prototype = {
         if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
             domStyle.position = 'relative';
         }
+        var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+        alwaysShowContent && this._moveTooltipIfResized();
         // Hide the tooltip
         // PENDING
         // this.hide();
     },
 
+    /**
+     * when `alwaysShowContent` is true,
+     * we should move the tooltip after chart resized
+     */
+    _moveTooltipIfResized: function () {
+        var ratioX = this._styleCoord[2]; // The ratio of left to width
+        var ratioY = this._styleCoord[3]; // The ratio of top to height
+        var realX = ratioX * this._zr.getWidth();
+        var realY = ratioY * this._zr.getHeight();
+        this.moveTo(realX, realY);
+    },
+
     show: function (tooltipModel) {
         clearTimeout(this._hideTimeout);
         var el = this.el;
@@ -48997,10 +49060,10 @@ TooltipContent.prototype = {
 
         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
+        // If mouse occasionally move over the tooltip, a mouseout event will be
+        // triggered by canvas, and cause some unexpectable result like dragging
         // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
-        // it. Although it is not suppored by IE8~IE10, fortunately it is a rare
+        // it. Although it is not supported by IE8~IE10, fortunately it is a rare
         // scenario.
         el.style.pointerEvents = this._enterable ? 'auto' : 'none';
 
@@ -49038,7 +49101,7 @@ TooltipContent.prototype = {
         if (this._show && !(this._inContent && this._enterable)) {
             if (time) {
                 this._hideDelay = time;
-                // Set show false to avoid invoke hideLater mutiple times
+                // Set show false to avoid invoke hideLater multiple times
                 this._show = false;
                 this._hideTimeout = setTimeout(bind(this.hide, this), time);
             }
@@ -49095,13 +49158,24 @@ TooltipContent.prototype = {
 */
 
 // import Group from 'zrender/src/container/Group';
+function makeStyleCoord$1(out, zr, zrX, zrY) {
+    out[0] = zrX;
+    out[1] = zrY;
+    out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+    out[3] = out[1] / zr.getHeight(); // The ratio of top to height
+}
+
 /**
  * @alias module:echarts/component/tooltip/TooltipRichContent
  * @constructor
  */
 function TooltipRichContent(api) {
 
-    this._zr = api.getZr();
+    var zr = this._zr = api.getZr();
+
+    this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
+
+    makeStyleCoord$1(this._styleCoord, zr, api.getWidth() / 2, api.getHeight() / 2);
 
     this._show = false;
 
@@ -49124,8 +49198,21 @@ TooltipRichContent.prototype = {
     /**
      * Update when tooltip is rendered
      */
-    update: function () {
-        // noop
+    update: function (tooltipModel) {
+        var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+        alwaysShowContent && this._moveTooltipIfResized();
+    },
+
+    /**
+     * when `alwaysShowContent` is true,
+     * we should move the tooltip after chart resized
+     */
+    _moveTooltipIfResized: function () {
+        var ratioX = this._styleCoord[2]; // The ratio of left to width
+        var ratioY = this._styleCoord[3]; // The ratio of top to height
+        var realX = ratioX * this._zr.getWidth();
+        var realY = ratioY * this._zr.getHeight();
+        this.moveTo(realX, realY);
     },
 
     show: function (tooltipModel) {
@@ -49180,16 +49267,23 @@ TooltipRichContent.prototype = {
             startId = text.indexOf('{marker');
         }
 
+        var textStyleModel = tooltipModel.getModel('textStyle');
+        var fontSize = textStyleModel.get('fontSize');
+        var lineHeight = tooltipModel.get('textLineHeight');
+        if (lineHeight == null) {
+            lineHeight = Math.round(fontSize * 3 / 2);
+        }
+
         this.el = new Text({
-            style: {
+            style: setTextStyle({}, textStyleModel, {
                 rich: markers,
                 text: content,
-                textLineHeight: 20,
                 textBackgroundColor: tooltipModel.get('backgroundColor'),
                 textBorderRadius: tooltipModel.get('borderRadius'),
                 textFill: tooltipModel.get('textStyle.color'),
-                textPadding: tooltipModel.get('padding')
-            },
+                textPadding: tooltipModel.get('padding'),
+                textLineHeight: lineHeight
+            }),
             z: tooltipModel.get('z')
         });
         this._zr.add(this.el);
@@ -49224,7 +49318,9 @@ TooltipRichContent.prototype = {
 
     moveTo: function (x, y) {
         if (this.el) {
-            this.el.attr('position', [x, y]);
+            var styleCoord = this._styleCoord;
+            makeStyleCoord$1(styleCoord, this._zr, x, y);
+            this.el.attr('position', [styleCoord[0], styleCoord[1]]);
         }
     },
 
@@ -49239,7 +49335,7 @@ TooltipRichContent.prototype = {
         if (this._show && !(this._inContent && this._enterable)) {
             if (time) {
                 this._hideDelay = time;
-                // Set show false to avoid invoke hideLater mutiple times
+                // Set show false to avoid invoke hideLater multiple times
                 this._show = false;
                 this._hideTimeout = setTimeout(bind(this.hide, this), time);
             }
@@ -49253,6 +49349,14 @@ TooltipRichContent.prototype = {
         return this._show;
     },
 
+    dispose: function () {
+        clearTimeout(this._hideTimeout);
+
+        if (this.el) {
+            this._zr.remove(this.el);
+        }
+    },
+
     getOuterSize: function () {
         var size = this.getSize();
         return {
@@ -49357,7 +49461,7 @@ extendComponentView({
         this._alwaysShowContent = tooltipModel.get('alwaysShowContent');
 
         var tooltipContent = this._tooltipContent;
-        tooltipContent.update();
+        tooltipContent.update(tooltipModel);
         tooltipContent.setEnterable(tooltipModel.get('enterable'));
 
         this._initGlobalListener();
@@ -49587,7 +49691,7 @@ extendComponentView({
     _showOrMove: function (tooltipModel, cb) {
         // showDelay is used in this case: tooltip.enterable is set
         // as true. User intent to move mouse into tooltip and click
-        // something. `showDelay` makes it easyer to enter the content
+        // something. `showDelay` makes it easier to enter the content
         // but tooltip do not move immediately.
         var delay = tooltipModel.get('showDelay');
         cb = bind(cb, this);
@@ -49672,7 +49776,7 @@ extendComponentView({
 
                 // Default tooltip content
                 // FIXME
-                // (1) shold be the first data which has name?
+                // (1) should be the first data which has name?
                 // (2) themeRiver, firstDataIndex is array, and first line is unnecessary.
                 var firstLine = valueLabel;
                 if (renderMode !== 'html') {
@@ -49788,7 +49892,7 @@ extendComponentView({
         var asyncTicket = Math.random();
 
         // Do not check whether `trigger` is 'none' here, because `trigger`
-        // only works on cooridinate system. In fact, we have not found case
+        // only works on coordinate system. In fact, we have not found case
         // that requires setting `trigger` nothing on component yet.
 
         this._showOrMove(subTooltipModel, function () {
@@ -51834,7 +51938,7 @@ var ScrollableLegendView = LegendView.extend({
             var legendDataIdx = child.__legendDataIndex;
             // FIXME
             // If the given targetDataIndex (from model) is illegal,
-            // we use defualtIndex. But the index on the legend model and
+            // we use defaultIndex. 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) {
@@ -52076,7 +52180,7 @@ extendComponentView({
         }
         if (sublink) {
             subTextEl.on('click', function () {
-                windowOpen(link, '_' + titleModel.get('subtarget'));
+                windowOpen(sublink, '_' + titleModel.get('subtarget'));
             });
         }
 
@@ -52277,15 +52381,16 @@ var MarkerModel = extendComponentModel({
         }
     },
 
-    formatTooltip: function (dataIndex) {
+    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
         var data = this.getData();
         var value = this.getRawValue(dataIndex);
         var formattedValue = isArray(value)
             ? map(value, addCommas$1).join(', ') : addCommas$1(value);
         var name = data.getName(dataIndex);
         var html = encodeHTML$1(this.name);
+        var newLine = renderMode === 'html' ? '<br/>' : '\n';
         if (value != null || name) {
-            html += '<br />';
+            html += newLine;
         }
         if (name) {
             html += encodeHTML$1(name);
@@ -52750,10 +52855,12 @@ MarkerView.extend({
             var itemModel = mpData.getItemModel(idx);
             var symbol = itemModel.getShallow('symbol');
             var symbolSize = itemModel.getShallow('symbolSize');
+            var symbolRotate = itemModel.getShallow('symbolRotate');
             var isFnSymbol = isFunction$1(symbol);
             var isFnSymbolSize = isFunction$1(symbolSize);
+            var isFnSymbolRotate = isFunction$1(symbolRotate);
 
-            if (isFnSymbol || isFnSymbolSize) {
+            if (isFnSymbol || isFnSymbolSize || isFnSymbolRotate) {
                 var rawIdx = mpModel.getRawValue(idx);
                 var dataParams = mpModel.getDataParams(idx);
                 if (isFnSymbol) {
@@ -52763,11 +52870,15 @@ MarkerView.extend({
                     // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据?
                     symbolSize = symbolSize(rawIdx, dataParams);
                 }
+                if (isFnSymbolRotate) {
+                    symbolRotate = symbolRotate(rawIdx, dataParams);
+                }
             }
 
             mpData.setItemVisual(idx, {
                 symbol: symbol,
                 symbolSize: symbolSize,
+                symbolRotate: symbolRotate,
                 color: itemModel.get('itemStyle.color')
                     || seriesData.getVisual('color')
             });
@@ -53019,22 +53130,29 @@ function makeSymbolTypeKey(symbolCategory) {
  * @inner
  */
 function createSymbol$1(name, lineData, idx) {
-    var color = lineData.getItemVisual(idx, 'color');
     var symbolType = lineData.getItemVisual(idx, name);
-    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
 
     if (!symbolType || symbolType === 'none') {
         return;
     }
 
+    var color = lineData.getItemVisual(idx, 'color');
+    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
+    var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate');
+
     if (!isArray(symbolSize)) {
         symbolSize = [symbolSize, symbolSize];
     }
+
     var symbolPath = createSymbol(
         symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2,
         symbolSize[0], symbolSize[1], color
     );
 
+    // rotate by default if symbolRotate is not specified or NaN
+    symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate)
+        ? void 0
+        : +symbolRotate * Math.PI / 180 || 0;
     symbolPath.name = name;
 
     return symbolPath;
@@ -53102,18 +53220,38 @@ function updateSymbolAndLabelBeforeLineUpdate() {
 
     if (symbolFrom) {
         symbolFrom.attr('position', fromPos);
-        var tangent = line.tangentAt(0);
-        symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
-            tangent[1], tangent[0]
-        ));
+        // Fix #12388
+        // when symbol is set to be 'arrow' in markLine,
+        // symbolRotate value will be ignored, and compulsively use tangent angle.
+        // rotate by default if symbol rotation is not specified
+        var specifiedRotation = symbolFrom.__specifiedRotation;
+        if (specifiedRotation == null) {
+            var tangent = line.tangentAt(0);
+            symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
+                tangent[1], tangent[0]
+            ));
+        }
+        else {
+            symbolFrom.attr('rotation', specifiedRotation);
+        }
         symbolFrom.attr('scale', [invScale * percent, invScale * percent]);
     }
     if (symbolTo) {
         symbolTo.attr('position', toPos);
-        var tangent = line.tangentAt(1);
-        symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
-            tangent[1], tangent[0]
-        ));
+        // Fix #12388
+        // when symbol is set to be 'arrow' in markLine,
+        // symbolRotate value will be ignored, and compulsively use tangent angle.
+        // rotate by default if symbol rotation is not specified
+        var specifiedRotation = symbolTo.__specifiedRotation;
+        if (specifiedRotation == null) {
+            var tangent = line.tangentAt(1);
+            symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
+                tangent[1], tangent[0]
+            ));
+        }
+        else {
+            symbolTo.attr('rotation', specifiedRotation);
+        }
         symbolTo.attr('scale', [invScale * percent, invScale * percent]);
     }
 
@@ -53909,8 +54047,10 @@ MarkerView.extend({
             ]);
 
             lineData.setItemVisual(idx, {
+                'fromSymbolRotate': fromData.getItemVisual(idx, 'symbolRotate'),
                 'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'),
                 'fromSymbol': fromData.getItemVisual(idx, 'symbol'),
+                'toSymbolRotate': toData.getItemVisual(idx, 'symbolRotate'),
                 'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'),
                 'toSymbol': toData.getItemVisual(idx, 'symbol')
             });
@@ -53932,8 +54072,8 @@ MarkerView.extend({
             updateSingleMarkerEndLayout(
                 data, idx, isFrom, seriesModel, api
             );
-
             data.setItemVisual(idx, {
+                symbolRotate: itemModel.get('symbolRotate'),
                 symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
                 symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
                 color: itemModel.get('itemStyle.color') || seriesData.getVisual('color')
@@ -54292,9 +54432,29 @@ MarkerView.extend({
         // Update visual and layout of line
         areaData.each(function (idx) {
             // Layout
-            areaData.setItemLayout(idx, map(dimPermutations, function (dim) {
+            var points = map(dimPermutations, function (dim) {
                 return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
-            }));
+            });
+            // If none of the area is inside coordSys, allClipped is set to be true
+            // in layout so that label will not be displayed. See #12591
+            var allClipped = true;
+            each$1(dimPermutations, function (dim) {
+                if (!allClipped) {
+                    return;
+                }
+                var xValue = areaData.get(dim[0], idx);
+                var yValue = areaData.get(dim[1], idx);
+                // If is infinity, the axis should be considered not clipped
+                if ((isInifinity$1(xValue) || coordSys.getAxis('x').containData(xValue))
+                    && (isInifinity$1(yValue) || coordSys.getAxis('y').containData(yValue))
+                ) {
+                    allClipped = false;
+                }
+            });
+            areaData.setItemLayout(idx, {
+                points: points,
+                allClipped: allClipped
+            });
 
             // Visual
             areaData.setItemVisual(idx, {
@@ -54305,23 +54465,41 @@ MarkerView.extend({
 
         areaData.diff(polygonGroup.__data)
             .add(function (idx) {
-                var polygon = new Polygon({
-                    shape: {
-                        points: areaData.getItemLayout(idx)
-                    }
-                });
-                areaData.setItemGraphicEl(idx, polygon);
-                polygonGroup.group.add(polygon);
+                var layout = areaData.getItemLayout(idx);
+                if (!layout.allClipped) {
+                    var polygon = new Polygon({
+                        shape: {
+                            points: layout.points
+                        }
+                    });
+                    areaData.setItemGraphicEl(idx, polygon);
+                    polygonGroup.group.add(polygon);
+                }
             })
             .update(function (newIdx, oldIdx) {
                 var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx);
-                updateProps(polygon, {
-                    shape: {
-                        points: areaData.getItemLayout(newIdx)
+                var layout = areaData.getItemLayout(newIdx);
+                if (!layout.allClipped) {
+                    if (polygon) {
+                        updateProps(polygon, {
+                            shape: {
+                                points: layout.points
+                            }
+                        }, maModel, newIdx);
                     }
-                }, maModel, newIdx);
-                polygonGroup.group.add(polygon);
-                areaData.setItemGraphicEl(newIdx, polygon);
+                    else {
+                        polygon = new Polygon({
+                            shape: {
+                                points: layout.points
+                            }
+                        });
+                    }
+                    areaData.setItemGraphicEl(newIdx, polygon);
+                    polygonGroup.group.add(polygon);
+                }
+                else if (polygon) {
+                    polygonGroup.group.remove(polygon);
+                }
             })
             .remove(function (idx) {
                 var polygon = polygonGroup.__data.getItemGraphicEl(idx);
@@ -58370,7 +58548,8 @@ proto$2.onclick = function (ecModel, api) {
         $a.target = '_blank';
         $a.href = url;
         var evt = new MouseEvent('click', {
-            view: window,
+            // some micro front-end framework, window maybe is a Proxy
+            view: document.defaultView,
             bubbles: true,
             cancelable: false
         });
@@ -58685,7 +58864,8 @@ function assembleSeriesWithCategoryAxis(series) {
         }));
         var columns = [categoryAxis.model.getCategories()];
         each$1(group.series, function (series) {
-            columns.push(series.getRawData().mapArray(valueAxisDim, function (val) {
+            var rawData = series.getRawData();
+            columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim), function (val) {
                 return val;
             }));
         });
@@ -58803,7 +58983,13 @@ function parseListContents(str) {
 
     var data = [];
     for (var i = 0; i < lines.length; i++) {
-        var items = trim$1(lines[i]).split(itemSplitRegex);
+        // if line is empty, ignore it.
+        // there is a case that a user forgot to delete `\n`.
+        var line = trim$1(lines[i]);
+        if (!line) {
+            continue;
+        }
+        var items = line.split(itemSplitRegex);
         var name = '';
         var value;
         var hasName = false;
@@ -59018,13 +59204,18 @@ function tryMergeDataOption(newData, originalData) {
     return map(newData, function (newVal, idx) {
         var original = originalData && originalData[idx];
         if (isObject$1(original) && !isArray(original)) {
-            if (isObject$1(newVal) && !isArray(newVal)) {
-                newVal = newVal.value;
+            var newValIsObject = isObject$1(newVal) && !isArray(newVal);
+            if (!newValIsObject) {
+                newVal = {
+                    value: newVal
+                };
             }
+            // original data has name but new data has no name
+            var shouldDeleteName = original.name != null && newVal.name == null;
             // Original data has option
-            return defaults({
-                value: newVal
-            }, original);
+            newVal = defaults(newVal, original);
+            shouldDeleteName && (delete newVal.name);
+            return newVal;
         }
         else {
             return newVal;
@@ -60855,7 +61046,11 @@ DataZoom.defaultOption = {
         back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
     },
     // `zoom`, `back`
-    title: clone(dataZoomLang.title)
+    title: clone(dataZoomLang.title),
+    brushStyle: {
+        borderWidth: 0,
+        color: 'rgba(0,0,0,0.2)'
+    }
 };
 
 var proto$4 = DataZoom.prototype;
@@ -61030,11 +61225,7 @@ function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
             zoomActive
             ? {
                 brushType: 'auto',
-                brushStyle: {
-                    // FIXME user customized?
-                    lineWidth: 0,
-                    fill: 'rgba(0,0,0,0.2)'
-                }
+                brushStyle: featureModel.getModel('brushStyle').getItemStyle()
             }
             : false
         );
@@ -63616,7 +63807,7 @@ GradientManager.prototype.updateDom = function (gradient, dom) {
         stop.setAttribute('offset', colors[i].offset * 100 + '%');
 
         var color = colors[i].color;
-        if (color.indexOf('rgba' > -1)) {
+        if (color.indexOf('rgba') > -1) {
             // Fix Safari bug that stop-color not recognizing alpha #9014
             var opacity = parse(color)[3];
             var hex = toHex(color);
diff --git a/en/dist/echarts.common.min.js b/en/dist/echarts.common.min.js
index 54d93ec..137a43c 100644
--- a/en/dist/echarts.common.min.js
+++ b/en/dist/echarts.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,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.js b/en/dist/echarts.js
index dd55582..5c36a4c 100644
--- a/en/dist/echarts.js
+++ b/en/dist/echarts.js
@@ -11595,7 +11595,7 @@ var instances$1 = {};    // ZRender实例map索引
 /**
  * @type {string}
  */
-var version$1 = '4.3.1';
+var version$1 = '4.3.2';
 
 /**
  * Initializing a zrender instance
@@ -26231,7 +26231,7 @@ var proto = Scheduler.prototype;
  * @param {Object} payload
  */
 proto.restoreData = function (ecModel, payload) {
-    // TODO: Only restroe needed series and components, but not all components.
+    // TODO: Only restore needed series and components, but not all components.
     // Currently `restoreData` of all of the series and component will be called.
     // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
     // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
@@ -27812,10 +27812,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.8.0';
+var version = '4.9.0';
 
 var dependencies = {
-    zrender: '4.3.1'
+    zrender: '4.3.2'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -31058,7 +31058,7 @@ listProto.mapDimension = function (coordDim, idx) {
  * Initialize from data
  * @param {Array.<Object|number|Array>} data source or data or data provider.
  * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
- *        defualt label/tooltip.
+ *        default label/tooltip.
  *        A name can be specified in encode.itemName,
  *        or dataItem.name (only for series option data),
  *        or provided in nameList from outside.
@@ -35677,8 +35677,8 @@ function rotateTextRect(textRect, rotate) {
     var boundingBox = textRect.plain();
     var beforeWidth = boundingBox.width;
     var beforeHeight = boundingBox.height;
-    var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
-    var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
+    var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
+    var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
     var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
 
     return rotatedRect;
@@ -37779,7 +37779,7 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     }
     else {
         symbolPath.setStyle({
-            opacity: null,
+            opacity: 1,
             shadowBlur: null,
             shadowOffsetX: null,
             shadowOffsetY: null,
@@ -39964,7 +39964,7 @@ var dataSample = function (seriesType) {
                 var valueAxis = coordSys.getOtherAxis(baseAxis);
                 var extent = baseAxis.getExtent();
                 // Coordinste system has been resized
-                var size = extent[1] - extent[0];
+                var size = Math.abs(extent[1] - extent[0]);
                 var rate = Math.round(data.count() / size);
                 if (rate > 1) {
                     var sampler;
@@ -40420,7 +40420,7 @@ var defaultOption = {
     name: '',
     // 'start' | 'middle' | 'end'
     nameLocation: 'end',
-    // By degree. By defualt auto rotate by nameLocation.
+    // By degree. By default auto rotate by nameLocation.
     nameRotate: null,
     nameTruncate: {
         maxWidth: null,
@@ -43663,20 +43663,25 @@ extendChartView({
         var bgEls = [];
         var oldBgEls = this._backgroundEls || [];
 
+        var createBackground = function (dataIndex) {
+            var bgLayout = getLayout[coord.type](data, dataIndex);
+            var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
+            bgEl.useStyle(backgroundModel.getBarItemStyle());
+            // Only cartesian2d support borderRadius.
+            if (coord.type === 'cartesian2d') {
+                bgEl.setShape('r', barBorderRadius);
+            }
+            bgEls[dataIndex] = bgEl;
+            return bgEl;
+        };
+
         data.diff(oldData)
             .add(function (dataIndex) {
                 var itemModel = data.getItemModel(dataIndex);
                 var layout = getLayout[coord.type](data, dataIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgLayout = getLayout[coord.type](data, dataIndex);
-                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
-                    }
-                    bgEls[dataIndex] = bgEl;
+                    createBackground(dataIndex);
                 }
 
                 // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
@@ -43710,13 +43715,19 @@ extendChartView({
                 var layout = getLayout[coord.type](data, newIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgEl = oldBgEls[oldIndex];
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
+                    var bgEl;
+                    if (oldBgEls.length === 0) {
+                        bgEl = createBackground(oldIndex);
+                    }
+                    else {
+                        bgEl = oldBgEls[oldIndex];
+                        bgEl.useStyle(backgroundModel.getBarItemStyle());
+                        // Only cartesian2d support borderRadius.
+                        if (coord.type === 'cartesian2d') {
+                            bgEl.setShape('r', barBorderRadius);
+                        }
+                        bgEls[newIndex] = bgEl;
                     }
-                    bgEls[newIndex] = bgEl;
 
                     var bgLayout = getLayout[coord.type](data, newIndex);
                     var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
@@ -43876,8 +43887,31 @@ var clip = {
         return clipped;
     },
 
-    polar: function (coordSysClipArea) {
-        return false;
+    polar: function (coordSysClipArea, layout) {
+        var signR = layout.r0 <= layout.r ? 1 : -1;
+        // Make sure r is larger than r0
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        var r = mathMin$4(layout.r, coordSysClipArea.r);
+        var r0 = mathMax$4(layout.r0, coordSysClipArea.r0);
+
+        layout.r = r;
+        layout.r0 = r0;
+
+        var clipped = r - r0 < 0;
+
+        // Reverse back
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        return clipped;
     }
 };
 
@@ -47113,16 +47147,17 @@ var RadarSeries = SeriesModel.extend({
         });
     },
 
-    formatTooltip: function (dataIndex) {
+    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
         var data = this.getData();
         var coordSys = this.coordinateSystem;
         var indicatorAxes = coordSys.getIndicatorAxes();
         var name = this.getData().getName(dataIndex);
-        return encodeHTML(name === '' ? this.name : name) + '<br/>'
+        var newLine = renderMode === 'html' ? '<br/>' : '\n';
+        return encodeHTML(name === '' ? this.name : name) + newLine
             + map(indicatorAxes, function (axis, idx) {
                 var val = data.get(data.mapDimension(axis.dim), dataIndex);
                 return encodeHTML(axis.name + ' : ' + val);
-            }).join('<br />');
+            }).join(newLine);
     },
 
     /**
@@ -47218,12 +47253,14 @@ extendChartView({
             var symbolPath = createSymbol(
                 symbolType, -1, -1, 2, 2, color
             );
+            var symbolRotate = data.getItemVisual(idx, 'symbolRotate') || 0;
             symbolPath.attr({
                 style: {
                     strokeNoScale: true
                 },
                 z2: 100,
-                scale: [symbolSize[0] / 2, symbolSize[1] / 2]
+                scale: [symbolSize[0] / 2, symbolSize[1] / 2],
+                rotation: symbolRotate * Math.PI / 180 || 0
             });
             return symbolPath;
         }
@@ -48189,7 +48226,7 @@ var MapSeries = SeriesModel.extend({
      *
      * @param {number} dataIndex
      */
-    formatTooltip: function (dataIndex) {
+    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
         // FIXME orignalData and data is a bit confusing
         var data = this.getData();
         var formattedValue = addCommas(this.getRawValue(dataIndex));
@@ -48207,7 +48244,8 @@ var MapSeries = SeriesModel.extend({
             }
         }
 
-        return seriesNames.join(', ') + '<br />'
+        var newLine = renderMode === 'html' ? '<br/>' : '\n';
+        return seriesNames.join(', ') + newLine
             + encodeHTML(name + ' : ' + formattedValue);
     },
 
@@ -50997,22 +51035,7 @@ TreeNode.prototype = {
         }
         var hostTree = this.hostTree;
         var itemModel = hostTree.data.getItemModel(this.dataIndex);
-        var levelModel = this.getLevelModel();
-
-        // FIXME: refactor levelModel to "beforeLink", and remove levelModel here.
-        if (levelModel) {
-            return itemModel.getModel(path, levelModel.getModel(path));
-        }
-        else {
-            return itemModel.getModel(path);
-        }
-    },
-
-    /**
-     * @return {module:echarts/model/Model}
-     */
-    getLevelModel: function () {
-        return (this.hostTree.levelModels || [])[this.depth];
+        return itemModel.getModel(path);
     },
 
     /**
@@ -51084,9 +51107,8 @@ TreeNode.prototype = {
  * @constructor
  * @alias module:echarts/data/Tree
  * @param {module:echarts/model/Model} hostModel
- * @param {Array.<Object>} levelOptions
  */
-function Tree(hostModel, levelOptions) {
+function Tree(hostModel) {
     /**
      * @type {module:echarts/data/Tree~TreeNode}
      * @readOnly
@@ -51113,15 +51135,6 @@ function Tree(hostModel, levelOptions) {
      */
     this.hostModel = hostModel;
 
-    /**
-     * @private
-     * @readOnly
-     * @type {Array.<module:echarts/model/Model}
-     */
-    this.levelModels = map(levelOptions || [], function (levelDefine) {
-        return new Model(levelDefine, hostModel, hostModel.ecModel);
-    });
-
 }
 
 Tree.prototype = {
@@ -51211,13 +51224,11 @@ Tree.prototype = {
  * @static
  * @param {Object} dataRoot Root node.
  * @param {module:echarts/model/Model} hostModel
- * @param {Object} treeOptions
- * @param {Array.<Object>} treeOptions.levels
  * @return module:echarts/data/Tree
  */
-Tree.createTree = function (dataRoot, hostModel, treeOptions, beforeLink) {
+Tree.createTree = function (dataRoot, hostModel, beforeLink) {
 
-    var tree = new Tree(hostModel, treeOptions && treeOptions.levels);
+    var tree = new Tree(hostModel);
     var listData = [];
     var dimMax = 1;
 
@@ -51325,7 +51336,7 @@ SeriesModel.extend({
         var leaves = option.leaves || {};
         var leavesModel = new Model(leaves, this, this.ecModel);
 
-        var tree = Tree.createTree(root, this, {}, beforeLink);
+        var tree = Tree.createTree(root, this, beforeLink);
 
         function beforeLink(nodeData) {
             nodeData.wrapMethod('getItemModel', function (model, idx) {
@@ -52264,7 +52275,7 @@ function drawEdge(
 
             updateProps(edge, {
                 shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
-                style: {opacity: 1}
+                style: defaults({opacity: 1}, seriesScope.lineStyle)
             }, seriesModel);
         }
     }
@@ -52294,7 +52305,7 @@ function drawEdge(
                         parentPoint: [targetLayout.x, targetLayout.y],
                         childPoints: childPoints
                     },
-                    style: {opacity: 1}
+                    style: defaults({opacity: 1}, seriesScope.lineStyle)
                 }, seriesModel);
             }
         }
@@ -52943,21 +52954,29 @@ SeriesModel.extend({
 
         var levels = option.levels || [];
 
+        // Used in "visual priority" in `treemapVisual.js`.
+        // This way is a little tricky, must satisfy the precondition:
+        //   1. There is no `treeNode.getModel('itemStyle.xxx')` used.
+        //   2. The `Model.prototype.getModel()` will not use any clone-like way.
+        var designatedVisualItemStyle = this.designatedVisualItemStyle = {};
+        var designatedVisualModel = new Model({itemStyle: designatedVisualItemStyle}, this, ecModel);
+
         levels = option.levels = setDefault(levels, ecModel);
         var levelModels = map(levels || [], function (levelDefine) {
-            return new Model(levelDefine, this, ecModel);
+            return new Model(levelDefine, designatedVisualModel, ecModel);
         }, this);
 
         // Make sure always a new tree is created when setOption,
         // in TreemapView, we check whether oldTree === newTree
         // to choose mappings approach among old shapes and new shapes.
-        var tree = Tree.createTree(root, this, null, beforeLink);
+        var tree = Tree.createTree(root, this, beforeLink);
 
         function beforeLink(nodeData) {
             nodeData.wrapMethod('getItemModel', function (model, idx) {
                 var node = tree.getNodeByDataIndex(idx);
                 var levelModel = levelModels[node.depth];
-                levelModel && (model.parentModel = levelModel);
+                // If no levelModel, we also need `designatedVisualModel`.
+                model.parentModel = levelModel || designatedVisualModel;
                 return model;
             });
         }
@@ -54506,7 +54525,7 @@ var CATEGORY_DEFAULT_VISUAL_INDEX = -1;
  *                                            visual data can be array or object
  *                                            (like: {cate1: '#222', none: '#fff'})
  *                                            or primary types (which represents
- *                                            defualt category visual), otherwise visual
+ *                                            default category visual), otherwise visual
  *                                            can be array or primary (which will be
  *                                            normalized to array).
  *
@@ -55124,21 +55143,14 @@ var treemapVisual = {
     reset: function (seriesModel, ecModel, api, payload) {
         var tree = seriesModel.getData().tree;
         var root = tree.root;
-        var seriesItemStyleModel = seriesModel.getModel(ITEM_STYLE_NORMAL);
 
         if (root.isRemoved()) {
             return;
         }
 
-        var levelItemStyles = map(tree.levelModels, function (levelModel) {
-            return levelModel ? levelModel.get(ITEM_STYLE_NORMAL) : null;
-        });
-
         travelTree(
             root, // Visual should calculate from tree root but not view root.
             {},
-            levelItemStyles,
-            seriesItemStyleModel,
             seriesModel.getViewRoot().getAncestors(),
             seriesModel
         );
@@ -55146,8 +55158,7 @@ var treemapVisual = {
 };
 
 function travelTree(
-    node, designatedVisual, levelItemStyles, seriesItemStyleModel,
-    viewRootAncestors, seriesModel
+    node, designatedVisual, viewRootAncestors, seriesModel
 ) {
     var nodeModel = node.getModel();
     var nodeLayout = node.getLayout();
@@ -55158,10 +55169,7 @@ function travelTree(
     }
 
     var nodeItemStyleModel = node.getModel(ITEM_STYLE_NORMAL);
-    var levelItemStyle = levelItemStyles[node.depth];
-    var visuals = buildVisuals(
-        nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel
-    );
+    var visuals = buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel);
 
     // calculate border color
     var borderColor = nodeItemStyleModel.get('borderColor');
@@ -55194,27 +55202,21 @@ function travelTree(
                 var childVisual = mapVisual$1(
                     nodeModel, visuals, child, index, mapping, seriesModel
                 );
-                travelTree(
-                    child, childVisual, levelItemStyles, seriesItemStyleModel,
-                    viewRootAncestors, seriesModel
-                );
+                travelTree(child, childVisual, viewRootAncestors, seriesModel);
             }
         });
     }
 }
 
-function buildVisuals(
-    nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel
-) {
+function buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel) {
     var visuals = extend({}, designatedVisual);
+    var designatedVisualItemStyle = seriesModel.designatedVisualItemStyle;
 
     each$1(['color', 'colorAlpha', 'colorSaturation'], function (visualName) {
         // Priority: thisNode > thisLevel > parentNodeDesignated > seriesModel
-        var val = nodeItemStyleModel.get(visualName, true); // Ignore parent
-        val == null && levelItemStyle && (val = levelItemStyle[visualName]);
-        val == null && (val = designatedVisual[visualName]);
-        val == null && (val = seriesItemStyleModel.get(visualName));
-
+        designatedVisualItemStyle[visualName] = designatedVisual[visualName];
+        var val = nodeItemStyleModel.get(visualName);
+        designatedVisualItemStyle[visualName] = null;
         val != null && (visuals[visualName] = val);
     });
 
@@ -55802,7 +55804,7 @@ function position(row, rowFixedLength, rect, halfGapWidth, flush) {
     rect[wh[idx1WhenH]] -= rowOtherLength;
 }
 
-// Return [containerWidth, containerHeight] as defualt.
+// Return [containerWidth, containerHeight] as default.
 function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) {
     // If targetInfo.node exists, we zoom to the node,
     // so estimate whold width and heigth by target node.
@@ -56108,11 +56110,6 @@ graphProto.addEdge = function (n1, n2, dataIndex) {
     }
 
     var key = n1.id + '-' + n2.id;
-    // PENDING
-    if (edgesMap[key]) {
-        return;
-    }
-
     var edge = new Edge(n1, n2, dataIndex);
     edge.hostGraph = this;
 
@@ -56512,10 +56509,12 @@ var createGraphFromNodeEdge = function (nodes, edges, seriesModel, directed, bef
     var linkNameList = [];
     var validEdges = [];
     var linkCount = 0;
+
     for (var i = 0; i < edges.length; i++) {
         var link = edges[i];
         var source = link.source;
         var target = link.target;
+
         // addEdge may fail when source or target not exists
         if (graph.addEdge(source, target, linkCount)) {
             validEdges.push(link);
@@ -56562,7 +56561,6 @@ var createGraphFromNodeEdge = function (nodes, edges, seriesModel, directed, bef
 
     // Update dataIndex of nodes and edges because invalid edge may be removed
     graph.update();
-
     return graph;
 };
 
@@ -56585,6 +56583,234 @@ var createGraphFromNodeEdge = function (nodes, edges, seriesModel, directed, bef
 * under the License.
 */
 
+var KEY_DELIMITER = '-->';
+/**
+ * params handler
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @returns {*}
+ */
+var getAutoCurvenessParams = function (seriesModel) {
+    return seriesModel.get('autoCurveness') || null;
+};
+
+/**
+ * Generate a list of edge curvatures, 20 is the default
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param {number} appendLength
+ * @return  20 => [0, -0.2, 0.2, -0.4, 0.4, -0.6, 0.6, -0.8, 0.8, -1, 1, -1.2, 1.2, -1.4, 1.4, -1.6, 1.6, -1.8, 1.8, -2]
+ */
+var createCurveness = function (seriesModel, appendLength) {
+    var autoCurvenessParmas = getAutoCurvenessParams(seriesModel);
+    var length = 20;
+    var curvenessList = [];
+
+    // handler the function set
+    if (typeof autoCurvenessParmas === 'number') {
+        length = autoCurvenessParmas;
+    }
+    else if (isArray(autoCurvenessParmas)) {
+        seriesModel.__curvenessList = autoCurvenessParmas;
+        return;
+    }
+
+    // append length
+    if (appendLength > length) {
+        length = appendLength;
+    }
+
+    // make sure the length is even
+    var len = length % 2 ? length + 2 : length + 3;
+    curvenessList = [];
+
+    for (var i = 0; i < len; i++) {
+        curvenessList.push((i % 2 ? i + 1 : i) / 10 * (i % 2 ? -1 : 1));
+    }
+    seriesModel.__curvenessList = curvenessList;
+};
+
+/**
+ * Create different cache key data in the positive and negative directions, in order to set the curvature later
+ * @param {number|string|module:echarts/data/Graph.Node} n1
+ * @param {number|string|module:echarts/data/Graph.Node} n2
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @returns {string} key
+ */
+var getKeyOfEdges = function (n1, n2, seriesModel) {
+    var source = [n1.id, n1.dataIndex].join('.');
+    var target = [n2.id, n2.dataIndex].join('.');
+    return [seriesModel.uid, source, target].join(KEY_DELIMITER);
+};
+
+/**
+ * get opposite key
+ * @param {string} key
+ * @returns {string}
+ */
+var getOppositeKey = function (key) {
+    var keys = key.split(KEY_DELIMITER);
+    return [keys[0], keys[2], keys[1]].join(KEY_DELIMITER);
+};
+
+/**
+ * get edgeMap with key
+ * @param edge
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ */
+var getEdgeFromMap = function (edge, seriesModel) {
+    var key = getKeyOfEdges(edge.node1, edge.node2, seriesModel);
+    return seriesModel.__edgeMap[key];
+};
+
+/**
+ * calculate all cases total length
+ * @param edge
+ * @param seriesModel
+ * @returns {number}
+ */
+var getTotalLengthBetweenNodes = function (edge, seriesModel) {
+    var len = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node1, edge.node2, seriesModel), seriesModel);
+    var lenV = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node2, edge.node1, seriesModel), seriesModel);
+
+    return len + lenV;
+};
+
+/**
+ *
+ * @param key
+ */
+var getEdgeMapLengthWithKey = function (key, seriesModel) {
+    var edgeMap = seriesModel.__edgeMap;
+    return edgeMap[key] ? edgeMap[key].length : 0;
+};
+
+/**
+ * Count the number of edges between the same two points, used to obtain the curvature table and the parity of the edge
+ * @see /graph/GraphSeries.js@getInitialData
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ */
+function initCurvenessList(seriesModel) {
+    if (!getAutoCurvenessParams(seriesModel)) {
+        return;
+    }
+
+    seriesModel.__curvenessList = [];
+    seriesModel.__edgeMap = {};
+    // calc the array of curveness List
+    createCurveness(seriesModel);
+}
+
+/**
+ * set edgeMap with key
+ * @param {number|string|module:echarts/data/Graph.Node} n1
+ * @param {number|string|module:echarts/data/Graph.Node} n2
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param {number} index
+ */
+function createEdgeMapForCurveness(n1, n2, seriesModel, index) {
+    if (!getAutoCurvenessParams(seriesModel)) {
+        return;
+    }
+
+    var key = getKeyOfEdges(n1, n2, seriesModel);
+    var edgeMap = seriesModel.__edgeMap;
+    var oppositeEdges = edgeMap[getOppositeKey(key)];
+    // set direction
+    if (edgeMap[key] && !oppositeEdges) {
+        edgeMap[key].isForward = true;
+    }
+    else if (oppositeEdges && edgeMap[key]) {
+        oppositeEdges.isForward = true;
+        edgeMap[key].isForward = false;
+    }
+
+    edgeMap[key] = edgeMap[key] || [];
+    edgeMap[key].push(index);
+}
+
+/**
+ * get curvature for edge
+ * @param edge
+ * @param {module:echarts/model/SeriesModel} seriesModel
+ * @param index
+ */
+function getCurvenessForEdge(edge, seriesModel, index, needReverse) {
+    var autoCurvenessParams = getAutoCurvenessParams(seriesModel);
+    var isArrayParam = isArray(autoCurvenessParams);
+    if (!autoCurvenessParams) {
+        return null;
+    }
+
+    var edgeArray = getEdgeFromMap(edge, seriesModel);
+    if (!edgeArray) {
+        return null;
+    }
+
+    var edgeIndex = -1;
+    for (var i = 0; i < edgeArray.length; i++) {
+        if (edgeArray[i] === index) {
+            edgeIndex = i;
+            break;
+        }
+    }
+    // if totalLen is Longer createCurveness
+    var totalLen = getTotalLengthBetweenNodes(edge, seriesModel);
+    createCurveness(seriesModel, totalLen);
+
+    edge.lineStyle = edge.lineStyle || {};
+    // if is opposite edge, must set curvenss to opposite number
+    var curKey = getKeyOfEdges(edge.node1, edge.node2, seriesModel);
+    var curvenessList = seriesModel.__curvenessList;
+    // if pass array no need parity
+    var parityCorrection = isArrayParam ? 0 : totalLen % 2 ? 0 : 1;
+
+    if (!edgeArray.isForward) {
+        // the opposite edge show outside
+        var oppositeKey = getOppositeKey(curKey);
+        var len = getEdgeMapLengthWithKey(oppositeKey, seriesModel);
+        var resValue = curvenessList[edgeIndex + len + parityCorrection];
+        // isNeedReverse, simple, force type need reverse the curveness in the junction of the forword and the opposite
+        if (needReverse) {
+            // set as array may make the parity handle with the len of opposite
+            if (isArrayParam) {
+                if (autoCurvenessParams && autoCurvenessParams[0] === 0) {
+                    return (len + parityCorrection) % 2 ? resValue : -resValue;
+                }
+                else {
+                    return ((len % 2 ? 0 : 1) + parityCorrection) % 2 ? resValue : -resValue;
+                }
+            }
+            else {
+                return (len + parityCorrection) % 2 ? resValue : -resValue;
+            }
+        }
+        else {
+            return curvenessList[edgeIndex + len + parityCorrection];
+        }
+    }
+    else {
+        return curvenessList[parityCorrection + edgeIndex];
+    }
+}
+
+/*
+* 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 GraphSeries = extendSeriesModel({
 
     type: 'series.graph',
@@ -56625,7 +56851,13 @@ var GraphSeries = extendSeriesModel({
         var self = this;
 
         if (nodes && edges) {
-            return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data;
+            // auto curveness
+            initCurvenessList(this);
+            var graph = createGraphFromNodeEdge(nodes, edges, this, true, beforeLink);
+            each$1(graph.edges, function (edge) {
+                createEdgeMapForCurveness(edge.node1, edge.node2, this, edge.dataIndex);
+            }, this);
+            return graph.data;
         }
 
         function beforeLink(nodeData, edgeData) {
@@ -56837,7 +57069,6 @@ var GraphSeries = extendSeriesModel({
         lineStyle: {
             color: '#aaa',
             width: 1,
-            curveness: 0,
             opacity: 0.5
         },
         emphasis: {
@@ -56952,22 +57183,29 @@ function makeSymbolTypeKey(symbolCategory) {
  * @inner
  */
 function createSymbol$1(name, lineData, idx) {
-    var color = lineData.getItemVisual(idx, 'color');
     var symbolType = lineData.getItemVisual(idx, name);
-    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
 
     if (!symbolType || symbolType === 'none') {
         return;
     }
 
+    var color = lineData.getItemVisual(idx, 'color');
+    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
+    var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate');
+
     if (!isArray(symbolSize)) {
         symbolSize = [symbolSize, symbolSize];
     }
+
     var symbolPath = createSymbol(
         symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2,
         symbolSize[0], symbolSize[1], color
     );
 
+    // rotate by default if symbolRotate is not specified or NaN
+    symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate)
+        ? void 0
+        : +symbolRotate * Math.PI / 180 || 0;
     symbolPath.name = name;
 
     return symbolPath;
@@ -57035,18 +57273,38 @@ function updateSymbolAndLabelBeforeLineUpdate() {
 
     if (symbolFrom) {
         symbolFrom.attr('position', fromPos);
-        var tangent = line.tangentAt(0);
-        symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
-            tangent[1], tangent[0]
-        ));
+        // Fix #12388
+        // when symbol is set to be 'arrow' in markLine,
+        // symbolRotate value will be ignored, and compulsively use tangent angle.
+        // rotate by default if symbol rotation is not specified
+        var specifiedRotation = symbolFrom.__specifiedRotation;
+        if (specifiedRotation == null) {
+            var tangent = line.tangentAt(0);
+            symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
+                tangent[1], tangent[0]
+            ));
+        }
+        else {
+            symbolFrom.attr('rotation', specifiedRotation);
+        }
         symbolFrom.attr('scale', [invScale * percent, invScale * percent]);
     }
     if (symbolTo) {
         symbolTo.attr('position', toPos);
-        var tangent = line.tangentAt(1);
-        symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
-            tangent[1], tangent[0]
-        ));
+        // Fix #12388
+        // when symbol is set to be 'arrow' in markLine,
+        // symbolRotate value will be ignored, and compulsively use tangent angle.
+        // rotate by default if symbol rotation is not specified
+        var specifiedRotation = symbolTo.__specifiedRotation;
+        if (specifiedRotation == null) {
+            var tangent = line.tangentAt(1);
+            symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
+                tangent[1], tangent[0]
+            ));
+        }
+        else {
+            symbolTo.attr('rotation', specifiedRotation);
+        }
         symbolTo.attr('scale', [invScale * percent, invScale * percent]);
     }
 
@@ -58484,12 +58742,16 @@ function simpleLayout$1(seriesModel) {
         node.setLayout([+model.get('x'), +model.get('y')]);
     });
 
-    simpleLayoutEdge(graph);
+    simpleLayoutEdge(graph, seriesModel);
 }
 
-function simpleLayoutEdge(graph) {
-    graph.eachEdge(function (edge) {
-        var curveness = edge.getModel().get('lineStyle.curveness') || 0;
+function simpleLayoutEdge(graph, seriesModel) {
+    graph.eachEdge(function (edge, index) {
+        var curveness = retrieve3(
+            edge.getModel().get('lineStyle.curveness'),
+            -getCurvenessForEdge(edge, seriesModel, index, true),
+            0
+        );
         var p1 = clone$1(edge.node1.getLayout());
         var p2 = clone$1(edge.node2.getLayout());
         var points = [p1, p2];
@@ -58553,7 +58815,7 @@ var simpleLayout = function (ecModel, api) {
                 }
             }
 
-            simpleLayoutEdge(data.graph);
+            simpleLayoutEdge(data.graph, seriesModel);
         }
         else if (!layout || layout === 'none') {
             simpleLayout$1(seriesModel);
@@ -58633,8 +58895,12 @@ function circularLayout$1(seriesModel, basedOn) {
 
     _layoutNodesBasedOn[basedOn](seriesModel, coordSys, graph, nodeData, r, cx, cy, count);
 
-    graph.eachEdge(function (edge) {
-        var curveness = edge.getModel().get('lineStyle.curveness') || 0;
+    graph.eachEdge(function (edge, index) {
+        var curveness = retrieve3(
+            edge.getModel().get('lineStyle.curveness'),
+            getCurvenessForEdge(edge, seriesModel, index),
+            0
+        );
         var p1 = clone$1(edge.node1.getLayout());
         var p2 = clone$1(edge.node2.getLayout());
         var cp1;
@@ -58978,11 +59244,16 @@ var forceLayout = function (ecModel) {
                     d = (edgeLength[0] + edgeLength[1]) / 2;
                 }
                 var edgeModel = edge.getModel();
+                var curveness = retrieve3(
+                    edgeModel.get('lineStyle.curveness'),
+                    -getCurvenessForEdge(edge, graphSeries, idx, true),
+                    0
+                );
                 return {
                     n1: nodes[edge.node1.dataIndex],
                     n2: nodes[edge.node2.dataIndex],
                     d: d,
-                    curveness: edgeModel.get('lineStyle.curveness') || 0,
+                    curveness: curveness,
                     ignoreForceLayout: edgeModel.get('ignoreForceLayout')
                 };
             });
@@ -59881,6 +60152,7 @@ var FunnelSeries = extendSeriesModel({
         minSize: '0%',
         maxSize: '100%',
         sort: 'descending', // 'ascending', 'descending'
+        orient: 'vertical',
         gap: 0,
         funnelAlign: 'center',
         label: {
@@ -60184,6 +60456,7 @@ function labelLayout$1(data) {
         var itemModel = data.getItemModel(idx);
         var labelModel = itemModel.getModel('label');
         var labelPosition = labelModel.get('position');
+        var orient = itemModel.get('orient');
 
         var labelLineModel = itemModel.getModel('labelLine');
 
@@ -60223,7 +60496,18 @@ function labelLayout$1(data) {
             var x1;
             var y1;
             var x2;
+            var y2;
             var labelLineLen = labelLineModel.get('length');
+            if (__DEV__) {
+                if (orient === 'vertical' && ['top', 'bottom'].indexOf(labelPosition) > -1) {
+                    labelPosition = 'left';
+                    console.warn('Position error: Funnel chart on vertical orient dose not support top and bottom.');
+                }
+                if (orient === 'horizontal' && ['left', 'right'].indexOf(labelPosition) > -1) {
+                    labelPosition = 'bottom';
+                    console.warn('Position error: Funnel chart on horizontal orient dose not support left and right.');
+                }
+            }
             if (labelPosition === 'left') {
                 // Left side
                 x1 = (points[3][0] + points[0][0]) / 2;
@@ -60240,50 +60524,106 @@ function labelLayout$1(data) {
                 textX = x2 + 5;
                 textAlign = 'left';
             }
+            else if (labelPosition === 'top') {
+                // Top side
+                x1 = (points[3][0] + points[0][0]) / 2;
+                y1 = (points[3][1] + points[0][1]) / 2;
+                y2 = y1 - labelLineLen;
+                textY = y2 - 5;
+                textAlign = 'center';
+            }
+            else if (labelPosition === 'bottom') {
+                // Bottom side
+                x1 = (points[1][0] + points[2][0]) / 2;
+                y1 = (points[1][1] + points[2][1]) / 2;
+                y2 = y1 + labelLineLen;
+                textY = y2 + 5;
+                textAlign = 'center';
+            }
             else if (labelPosition === 'rightTop') {
                 // RightTop side
-                x1 = points[1][0];
-                y1 = points[1][1];
-                x2 = x1 + labelLineLen;
-                textX = x2 + 5;
-                textAlign = 'top';
+                x1 = orient === 'horizontal' ? points[3][0] : points[1][0];
+                y1 = orient === 'horizontal' ? points[3][1] : points[1][1];
+                if (orient === 'horizontal') {
+                    y2 = y1 - labelLineLen;
+                    textY = y2 - 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 + labelLineLen;
+                    textX = x2 + 5;
+                    textAlign = 'top';
+                }
             }
             else if (labelPosition === 'rightBottom') {
                 // RightBottom side
                 x1 = points[2][0];
                 y1 = points[2][1];
-                x2 = x1 + labelLineLen;
-                textX = x2 + 5;
-                textAlign = 'bottom';
+                if (orient === 'horizontal') {
+                    y2 = y1 + labelLineLen;
+                    textY = y2 + 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 + labelLineLen;
+                    textX = x2 + 5;
+                    textAlign = 'bottom';
+                }
             }
             else if (labelPosition === 'leftTop') {
                 // LeftTop side
                 x1 = points[0][0];
-                y1 = points[1][1];
-                x2 = x1 - labelLineLen;
-                textX = x2 - 5;
-                textAlign = 'right';
+                y1 = orient === 'horizontal' ? points[0][1] : points[1][1];
+                if (orient === 'horizontal') {
+                    y2 = y1 - labelLineLen;
+                    textY = y2 - 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 - labelLineLen;
+                    textX = x2 - 5;
+                    textAlign = 'right';
+                }
             }
             else if (labelPosition === 'leftBottom') {
                 // LeftBottom side
-                x1 = points[3][0];
-                y1 = points[2][1];
-                x2 = x1 - labelLineLen;
-                textX = x2 - 5;
-                textAlign = 'right';
+                x1 = orient === 'horizontal' ? points[1][0] : points[3][0];
+                y1 = orient === 'horizontal' ? points[1][1] : points[2][1];
+                if (orient === 'horizontal') {
+                    y2 = y1 + labelLineLen;
+                    textY = y2 + 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 - labelLineLen;
+                    textX = x2 - 5;
+                    textAlign = 'right';
+                }
             }
             else {
-                // Right side
+                // Right side or Bottom side
                 x1 = (points[1][0] + points[2][0]) / 2;
                 y1 = (points[1][1] + points[2][1]) / 2;
-                x2 = x1 + labelLineLen;
-                textX = x2 + 5;
-                textAlign = 'left';
+                if (orient === 'horizontal') {
+                    y2 = y1 + labelLineLen;
+                    textY = y2 + 5;
+                    textAlign = 'center';
+                }
+                else {
+                    x2 = x1 + labelLineLen;
+                    textX = x2 + 5;
+                    textAlign = 'left';
+                }
+            }
+            if (orient === 'horizontal') {
+                x2 = x1;
+                textX = x2;
+            }
+            else {
+                y2 = y1;
+                textY = y2;
             }
-            var y2 = y1;
-
             linePoints = [[x1, y1], [x2, y2]];
-            textY = y2;
         }
 
         layout.label = {
@@ -60304,11 +60644,19 @@ var funnelLayout = function (ecModel, api, payload) {
         var sort = seriesModel.get('sort');
         var viewRect = getViewRect$3(seriesModel, api);
         var indices = getSortedIndices(data, sort);
+        var orient = seriesModel.get('orient');
+        var viewWidth = viewRect.width;
+        var viewHeight = viewRect.height;
+        var x = viewRect.x;
+        var y = viewRect.y;
 
-        var sizeExtent = [
-            parsePercent$1(seriesModel.get('minSize'), viewRect.width),
-            parsePercent$1(seriesModel.get('maxSize'), viewRect.width)
-        ];
+        var sizeExtent = orient === 'horizontal' ? [
+            parsePercent$1(seriesModel.get('minSize'), viewHeight),
+            parsePercent$1(seriesModel.get('maxSize'), viewHeight)
+        ] : [
+                parsePercent$1(seriesModel.get('minSize'), viewWidth),
+                parsePercent$1(seriesModel.get('maxSize'), viewWidth)
+            ];
         var dataExtent = data.getDataExtent(valueDim);
         var min = seriesModel.get('min');
         var max = seriesModel.get('max');
@@ -60321,64 +60669,113 @@ var funnelLayout = function (ecModel, api, payload) {
 
         var funnelAlign = seriesModel.get('funnelAlign');
         var gap = seriesModel.get('gap');
-        var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count();
-
-        var y = viewRect.y;
+        var viewSize = orient === 'horizontal' ? viewWidth : viewHeight;
+        var itemSize = (viewSize - gap * (data.count() - 1)) / data.count();
 
-        var getLinePoints = function (idx, offY) {
+        var getLinePoints = function (idx, offset) {
             // End point index is data.count() and we assign it 0
+            if (orient === 'horizontal') {
+                var val = data.get(valueDim, idx) || 0;
+                var itemHeight = linearMap(val, [min, max], sizeExtent, true);
+                var y0;
+                switch (funnelAlign) {
+                    case 'top':
+                        y0 = y;
+                        break;
+                    case 'center':
+                        y0 = y + (viewHeight - itemHeight) / 2;
+                        break;
+                    case 'bottom':
+                        y0 = y + (viewHeight - itemHeight);
+                        break;
+                }
+
+                return [
+                    [offset, y0],
+                    [offset, y0 + itemHeight]
+                ];
+            }
             var val = data.get(valueDim, idx) || 0;
             var itemWidth = linearMap(val, [min, max], sizeExtent, true);
             var x0;
             switch (funnelAlign) {
                 case 'left':
-                    x0 = viewRect.x;
+                    x0 = x;
                     break;
                 case 'center':
-                    x0 = viewRect.x + (viewRect.width - itemWidth) / 2;
+                    x0 = x + (viewWidth - itemWidth) / 2;
                     break;
                 case 'right':
-                    x0 = viewRect.x + viewRect.width - itemWidth;
+                    x0 = x + viewWidth - itemWidth;
                     break;
             }
             return [
-                [x0, offY],
-                [x0 + itemWidth, offY]
+                [x0, offset],
+                [x0 + itemWidth, offset]
             ];
         };
 
         if (sort === 'ascending') {
             // From bottom to top
-            itemHeight = -itemHeight;
+            itemSize = -itemSize;
             gap = -gap;
-            y += viewRect.height;
+            if (orient === 'horizontal') {
+                x += viewWidth;
+            }
+            else {
+                y += viewHeight;
+            }
             indices = indices.reverse();
         }
 
         for (var i = 0; i < indices.length; i++) {
             var idx = indices[i];
             var nextIdx = indices[i + 1];
-
             var itemModel = data.getItemModel(idx);
-            var height = itemModel.get('itemStyle.height');
-            if (height == null) {
-                height = itemHeight;
+
+            if (orient === 'horizontal') {
+                var width = itemModel.get('itemStyle.width');
+                if (width == null) {
+                    width = itemSize;
+                }
+                else {
+                    width = parsePercent$1(width, viewWidth);
+                    if (sort === 'ascending') {
+                        width = -width;
+                    }
+                }
+
+                var start = getLinePoints(idx, x);
+                var end = getLinePoints(nextIdx, x + width);
+
+                x += width + gap;
+
+                data.setItemLayout(idx, {
+                    points: start.concat(end.slice().reverse())
+                });
             }
             else {
-                height = parsePercent$1(height, viewRect.height);
-                if (sort === 'ascending') {
-                    height = -height;
+                var height = itemModel.get('itemStyle.height');
+                if (height == null) {
+                    height = itemSize;
+                }
+                else {
+                    height = parsePercent$1(height, viewHeight);
+                    if (sort === 'ascending') {
+                        height = -height;
+                    }
                 }
-            }
 
-            var start = getLinePoints(idx, y);
-            var end = getLinePoints(nextIdx, y + height);
+                var start = orient === 'horizontal' ? getLinePoints(idx, x) : getLinePoints(idx, y);
+                var end = orient === 'horizontal'
+                    ? getLinePoints(nextIdx, x + width) : getLinePoints(nextIdx, y + height);
 
-            y += height + gap;
+                y += height + gap;
 
-            data.setItemLayout(idx, {
-                points: start.concat(end.slice().reverse())
-            });
+                data.setItemLayout(idx, {
+                    points: start.concat(end.slice().reverse())
+                });
+            }
         }
 
         labelLayout$1(data);
@@ -66689,8 +67086,6 @@ var LinesSeries = SeriesModel.extend({
     },
 
     mergeOption: function (option) {
-        // The input data may be null/undefined.
-        option.data = option.data || [];
 
         compatEc2(option);
 
@@ -68582,7 +68977,7 @@ var PictorialBarSeries = BaseBarSeries.extend({
         symbolPosition: null, // 'start' or 'end' or 'center', null means auto.
         symbolOffset: null,
         symbolMargin: null,   // start margin and end margin. Can be a number or a percent string.
-                                // Auto margin by defualt.
+                                // Auto margin by default.
         symbolRepeat: false,  // false/null/undefined, means no repeat.
                                 // Can be true, means auto calculate repeat times and cut by data.
                                 // Can be a number, specifies repeat times, and do not cut by data.
@@ -70418,7 +70813,7 @@ function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) {
     var snapToValue = payloadInfo.snapToValue;
 
     // Fill content of event obj for echarts.connect.
-    // By defualt use the first involved series data as a sample to connect.
+    // By default use the first involved series data as a sample to connect.
     if (payloadBatch[0] && outputFinder.seriesIndex == null) {
         extend(outputFinder, payloadBatch[0]);
     }
@@ -72136,52 +72531,46 @@ var ThemeRiverSeries = SeriesModel.extend({
      */
     fixData: function (data) {
         var rawDataLength = data.length;
+        /**
+         * Make sure every layer data get the same keys.
+         * The value index tells which layer has visited.
+         * {
+         *  2014/01/01: -1
+         * }
+         */
+        var timeValueKeys = {};
 
         // grouped data by name
         var groupResult = groupData(data, function (item) {
+            if (!timeValueKeys.hasOwnProperty(item[0])) {
+                timeValueKeys[item[0]] = -1;
+            }
             return item[2];
         });
         var layData = [];
         groupResult.buckets.each(function (items, key) {
             layData.push({name: key, dataList: items});
         });
-
         var layerNum = layData.length;
-        var largestLayer = -1;
-        var index = -1;
-        for (var i = 0; i < layerNum; ++i) {
-            var len = layData[i].dataList.length;
-            if (len > largestLayer) {
-                largestLayer = len;
-                index = i;
-            }
-        }
 
         for (var k = 0; k < layerNum; ++k) {
-            if (k === index) {
-                continue;
-            }
             var name = layData[k].name;
-            for (var j = 0; j < largestLayer; ++j) {
-                var timeValue = layData[index].dataList[j][0];
-                var length = layData[k].dataList.length;
-                var keyIndex = -1;
-                for (var l = 0; l < length; ++l) {
-                    var value = layData[k].dataList[l][0];
-                    if (value === timeValue) {
-                        keyIndex = l;
-                        break;
-                    }
-                }
-                if (keyIndex === -1) {
+            for (var j = 0; j < layData[k].dataList.length; ++j) {
+                var timeValue = layData[k].dataList[j][0];
+                timeValueKeys[timeValue] = k;
+            }
+
+            for (var timeValue in timeValueKeys) {
+                if (timeValueKeys.hasOwnProperty(timeValue) && timeValueKeys[timeValue] !== k) {
+                    timeValueKeys[timeValue] = k;
                     data[rawDataLength] = [];
                     data[rawDataLength][0] = timeValue;
                     data[rawDataLength][1] = 0;
                     data[rawDataLength][2] = name;
                     rawDataLength++;
-
                 }
             }
+
         }
         return data;
     },
@@ -72800,18 +73189,25 @@ SeriesModel.extend({
 
         completeTreeValue$1(root);
 
-        var levels = option.levels || [];
-
-        // levels = option.levels = setDefault(levels, ecModel);
-
-        var treeOption = {};
-
-        treeOption.levels = levels;
+        var levelModels = map(option.levels || [], function (levelDefine) {
+            return new Model(levelDefine, this, ecModel);
+        }, this);
 
         // Make sure always a new tree is created when setOption,
         // in TreemapView, we check whether oldTree === newTree
         // to choose mappings approach among old shapes and new shapes.
-        return Tree.createTree(root, this, treeOption).data;
+        var tree = Tree.createTree(root, this, beforeLink);
+
+        function beforeLink(nodeData) {
+            nodeData.wrapMethod('getItemModel', function (model, idx) {
+                var node = tree.getNodeByDataIndex(idx);
+                var levelModel = levelModels[node.depth];
+                levelModel && (model.parentModel = levelModel);
+                return model;
+            });
+        }
+
+        return tree.data;
     },
 
     optionUpdated: function () {
@@ -73181,9 +73577,13 @@ SunburstPieceProto._updateLabel = function (seriesModel, visualColor, state) {
         : itemModel.getModel(state + '.label');
     var labelHoverModel = itemModel.getModel('emphasis.label');
 
+    var labelFormatter = labelModel.get('formatter');
+    // Use normal formatter if no state formatter is defined
+    var labelState = labelFormatter ? state : 'normal';
+
     var text = retrieve(
         seriesModel.getFormattedLabel(
-            this.node.dataIndex, state, null, null, 'label'
+            this.node.dataIndex, labelState, null, null, 'label'
         ),
         this.node.name
     );
@@ -75112,8 +75512,9 @@ function barLayoutPolar(seriesType, ecModel, api) {
         var clampLayout = baseAxis.dim !== 'radius'
             || !seriesModel.get('roundCap', true);
 
-        var valueAxisStart = valueAxis.getExtent()[0];
-
+        var valueAxisStart = valueAxis.dim === 'radius'
+            ? valueAxis.dataToRadius(0)
+            : valueAxis.dataToAngle(0);
         for (var idx = 0, len = data.count(); idx < len; idx++) {
             var value = data.get(valueDim, idx);
             var baseValue = data.get(baseDim, idx);
@@ -75125,6 +75526,7 @@ function barLayoutPolar(seriesType, ecModel, api) {
             // stackResultDimension directly.
             // Only ordinal axis can be stacked.
             if (stacked) {
+
                 if (!lastStackCoords[stackId][baseValue]) {
                     lastStackCoords[stackId][baseValue] = {
                         p: valueAxisStart, // Positive stack
@@ -77014,12 +77416,9 @@ var GeoModel = ComponentModel.extend({
      * @return {string}
      */
     getFormattedLabel: function (name, status) {
+        status = status || 'normal';
         var regionModel = this.getRegionModel(name);
-        var formatter = regionModel.get(
-            'label'
-            + (status === 'normal' ? '.' : status + '.')
-            + 'formatter'
-        );
+        var formatter = regionModel.get((status === 'normal' ? '' : status + '.') + 'label.formatter');
         var params = {
             name: name
         };
@@ -79426,7 +79825,8 @@ proto$2.onclick = function (ecModel, api) {
         $a.target = '_blank';
         $a.href = url;
         var evt = new MouseEvent('click', {
-            view: window,
+            // some micro front-end framework, window maybe is a Proxy
+            view: document.defaultView,
             bubbles: true,
             cancelable: false
         });
@@ -79741,7 +80141,8 @@ function assembleSeriesWithCategoryAxis(series) {
         }));
         var columns = [categoryAxis.model.getCategories()];
         each$1(group.series, function (series) {
-            columns.push(series.getRawData().mapArray(valueAxisDim, function (val) {
+            var rawData = series.getRawData();
+            columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim), function (val) {
                 return val;
             }));
         });
@@ -79859,7 +80260,13 @@ function parseListContents(str) {
 
     var data = [];
     for (var i = 0; i < lines.length; i++) {
-        var items = trim$1(lines[i]).split(itemSplitRegex);
+        // if line is empty, ignore it.
+        // there is a case that a user forgot to delete `\n`.
+        var line = trim$1(lines[i]);
+        if (!line) {
+            continue;
+        }
+        var items = line.split(itemSplitRegex);
         var name = '';
         var value;
         var hasName = false;
@@ -80074,13 +80481,18 @@ function tryMergeDataOption(newData, originalData) {
     return map(newData, function (newVal, idx) {
         var original = originalData && originalData[idx];
         if (isObject$1(original) && !isArray(original)) {
-            if (isObject$1(newVal) && !isArray(newVal)) {
-                newVal = newVal.value;
+            var newValIsObject = isObject$1(newVal) && !isArray(newVal);
+            if (!newValIsObject) {
+                newVal = {
+                    value: newVal
+                };
             }
+            // original data has name but new data has no name
+            var shouldDeleteName = original.name != null && newVal.name == null;
             // Original data has option
-            return defaults({
-                value: newVal
-            }, original);
+            newVal = defaults(newVal, original);
+            shouldDeleteName && (delete newVal.name);
+            return newVal;
         }
         else {
             return newVal;
@@ -82367,7 +82779,11 @@ DataZoom.defaultOption = {
         back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
     },
     // `zoom`, `back`
-    title: clone(dataZoomLang.title)
+    title: clone(dataZoomLang.title),
+    brushStyle: {
+        borderWidth: 0,
+        color: 'rgba(0,0,0,0.2)'
+    }
 };
 
 var proto$4 = DataZoom.prototype;
@@ -82542,11 +82958,7 @@ function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
             zoomActive
             ? {
                 brushType: 'auto',
-                brushStyle: {
-                    // FIXME user customized?
-                    lineWidth: 0,
-                    fill: 'rgba(0,0,0,0.2)'
-                }
+                brushStyle: featureModel.getModel('brushStyle').getItemStyle()
             }
             : false
         );
@@ -82884,8 +83296,21 @@ function assembleFont(textStyleModel) {
 
     cssText.push('font:' + textStyleModel.getFont());
 
+    var lineHeight = textStyleModel.get('lineHeight');
+    if (lineHeight == null) {
+        lineHeight = Math.round(fontSize * 3 / 2);
+    }
+
     fontSize
-        && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
+        && cssText.push('line-height:' + lineHeight + 'px');
+
+    var shadowColor = textStyleModel.get('textShadowColor');
+    var shadowBlur = textStyleModel.get('textShadowBlur') || 0;
+    var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0;
+    var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0;
+    shadowBlur
+        && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px '
+            + shadowBlur + 'px ' + shadowColor);
 
     each$22(['decoration', 'align'], function (name) {
         var val = textStyleModel.get(name);
@@ -82969,6 +83394,8 @@ function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
             out[1] += viewportRootOffset.offsetTop;
         }
     }
+    out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+    out[3] = out[1] / zr.getHeight(); // The ratio of top to height
 }
 
 /**
@@ -82993,7 +83420,7 @@ function TooltipContent(container, api, opt) {
     var zr = this._zr = api.getZr();
     var appendToBody = this._appendToBody = opt && opt.appendToBody;
 
-    this._styleCoord = [0, 0];
+    this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
 
     makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
 
@@ -83064,7 +83491,7 @@ TooltipContent.prototype = {
     /**
      * Update when tooltip is rendered
      */
-    update: function () {
+    update: function (tooltipModel) {
         // FIXME
         // Move this logic to ec main?
         var container = this._container;
@@ -83074,11 +83501,25 @@ TooltipContent.prototype = {
         if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
             domStyle.position = 'relative';
         }
+        var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+        alwaysShowContent && this._moveTooltipIfResized();
         // Hide the tooltip
         // PENDING
         // this.hide();
     },
 
+    /**
+     * when `alwaysShowContent` is true,
+     * we should move the tooltip after chart resized
+     */
+    _moveTooltipIfResized: function () {
+        var ratioX = this._styleCoord[2]; // The ratio of left to width
+        var ratioY = this._styleCoord[3]; // The ratio of top to height
+        var realX = ratioX * this._zr.getWidth();
+        var realY = ratioY * this._zr.getHeight();
+        this.moveTo(realX, realY);
+    },
+
     show: function (tooltipModel) {
         clearTimeout(this._hideTimeout);
         var el = this.el;
@@ -83093,10 +83534,10 @@ TooltipContent.prototype = {
 
         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
+        // If mouse occasionally move over the tooltip, a mouseout event will be
+        // triggered by canvas, and cause some unexpectable result like dragging
         // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
-        // it. Although it is not suppored by IE8~IE10, fortunately it is a rare
+        // it. Although it is not supported by IE8~IE10, fortunately it is a rare
         // scenario.
         el.style.pointerEvents = this._enterable ? 'auto' : 'none';
 
@@ -83134,7 +83575,7 @@ TooltipContent.prototype = {
         if (this._show && !(this._inContent && this._enterable)) {
             if (time) {
                 this._hideDelay = time;
-                // Set show false to avoid invoke hideLater mutiple times
+                // Set show false to avoid invoke hideLater multiple times
                 this._show = false;
                 this._hideTimeout = setTimeout(bind(this.hide, this), time);
             }
@@ -83191,13 +83632,24 @@ TooltipContent.prototype = {
 */
 
 // import Group from 'zrender/src/container/Group';
+function makeStyleCoord$1(out, zr, zrX, zrY) {
+    out[0] = zrX;
+    out[1] = zrY;
+    out[2] = out[0] / zr.getWidth(); // The ratio of left to width
+    out[3] = out[1] / zr.getHeight(); // The ratio of top to height
+}
+
 /**
  * @alias module:echarts/component/tooltip/TooltipRichContent
  * @constructor
  */
 function TooltipRichContent(api) {
 
-    this._zr = api.getZr();
+    var zr = this._zr = api.getZr();
+
+    this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
+
+    makeStyleCoord$1(this._styleCoord, zr, api.getWidth() / 2, api.getHeight() / 2);
 
     this._show = false;
 
@@ -83220,8 +83672,21 @@ TooltipRichContent.prototype = {
     /**
      * Update when tooltip is rendered
      */
-    update: function () {
-        // noop
+    update: function (tooltipModel) {
+        var alwaysShowContent = tooltipModel.get('alwaysShowContent');
+        alwaysShowContent && this._moveTooltipIfResized();
+    },
+
+    /**
+     * when `alwaysShowContent` is true,
+     * we should move the tooltip after chart resized
+     */
+    _moveTooltipIfResized: function () {
+        var ratioX = this._styleCoord[2]; // The ratio of left to width
+        var ratioY = this._styleCoord[3]; // The ratio of top to height
+        var realX = ratioX * this._zr.getWidth();
+        var realY = ratioY * this._zr.getHeight();
+        this.moveTo(realX, realY);
     },
 
     show: function (tooltipModel) {
@@ -83276,16 +83741,23 @@ TooltipRichContent.prototype = {
             startId = text.indexOf('{marker');
         }
 
+        var textStyleModel = tooltipModel.getModel('textStyle');
+        var fontSize = textStyleModel.get('fontSize');
+        var lineHeight = tooltipModel.get('textLineHeight');
+        if (lineHeight == null) {
+            lineHeight = Math.round(fontSize * 3 / 2);
+        }
+
         this.el = new Text({
-            style: {
+            style: setTextStyle({}, textStyleModel, {
                 rich: markers,
                 text: content,
-                textLineHeight: 20,
                 textBackgroundColor: tooltipModel.get('backgroundColor'),
                 textBorderRadius: tooltipModel.get('borderRadius'),
                 textFill: tooltipModel.get('textStyle.color'),
-                textPadding: tooltipModel.get('padding')
-            },
+                textPadding: tooltipModel.get('padding'),
+                textLineHeight: lineHeight
+            }),
             z: tooltipModel.get('z')
         });
         this._zr.add(this.el);
@@ -83320,7 +83792,9 @@ TooltipRichContent.prototype = {
 
     moveTo: function (x, y) {
         if (this.el) {
-            this.el.attr('position', [x, y]);
+            var styleCoord = this._styleCoord;
+            makeStyleCoord$1(styleCoord, this._zr, x, y);
+            this.el.attr('position', [styleCoord[0], styleCoord[1]]);
         }
     },
 
@@ -83335,7 +83809,7 @@ TooltipRichContent.prototype = {
         if (this._show && !(this._inContent && this._enterable)) {
             if (time) {
                 this._hideDelay = time;
-                // Set show false to avoid invoke hideLater mutiple times
+                // Set show false to avoid invoke hideLater multiple times
                 this._show = false;
                 this._hideTimeout = setTimeout(bind(this.hide, this), time);
             }
@@ -83349,6 +83823,14 @@ TooltipRichContent.prototype = {
         return this._show;
     },
 
+    dispose: function () {
+        clearTimeout(this._hideTimeout);
+
+        if (this.el) {
+            this._zr.remove(this.el);
+        }
+    },
+
     getOuterSize: function () {
         var size = this.getSize();
         return {
@@ -83453,7 +83935,7 @@ extendComponentView({
         this._alwaysShowContent = tooltipModel.get('alwaysShowContent');
 
         var tooltipContent = this._tooltipContent;
-        tooltipContent.update();
+        tooltipContent.update(tooltipModel);
         tooltipContent.setEnterable(tooltipModel.get('enterable'));
 
         this._initGlobalListener();
@@ -83683,7 +84165,7 @@ extendComponentView({
     _showOrMove: function (tooltipModel, cb) {
         // showDelay is used in this case: tooltip.enterable is set
         // as true. User intent to move mouse into tooltip and click
-        // something. `showDelay` makes it easyer to enter the content
+        // something. `showDelay` makes it easier to enter the content
         // but tooltip do not move immediately.
         var delay = tooltipModel.get('showDelay');
         cb = bind(cb, this);
@@ -83768,7 +84250,7 @@ extendComponentView({
 
                 // Default tooltip content
                 // FIXME
-                // (1) shold be the first data which has name?
+                // (1) should be the first data which has name?
                 // (2) themeRiver, firstDataIndex is array, and first line is unnecessary.
                 var firstLine = valueLabel;
                 if (renderMode !== 'html') {
@@ -83884,7 +84366,7 @@ extendComponentView({
         var asyncTicket = Math.random();
 
         // Do not check whether `trigger` is 'none' here, because `trigger`
-        // only works on cooridinate system. In fact, we have not found case
+        // only works on coordinate system. In fact, we have not found case
         // that requires setting `trigger` nothing on component yet.
 
         this._showOrMove(subTooltipModel, function () {
@@ -85625,7 +86107,7 @@ extendComponentView({
         }
         if (sublink) {
             subTextEl.on('click', function () {
-                windowOpen(link, '_' + titleModel.get('subtarget'));
+                windowOpen(sublink, '_' + titleModel.get('subtarget'));
             });
         }
 
@@ -86903,13 +87385,16 @@ function getViewRect$5(model, api) {
 }
 
 function makeIcon(timelineModel, objPath, rect, opts) {
-    var icon = makePath(
-        timelineModel.get(objPath).replace(/^path:\/\//, ''),
-        clone(opts || {}),
-        new BoundingRect(rect[0], rect[1], rect[2], rect[3]),
-        'center'
+    var style = opts.style;
+    var icon = createIcon(
+        timelineModel.get(objPath),
+        opts || {},
+        new BoundingRect(rect[0], rect[1], rect[2], rect[3])
     );
-
+    // TODO createIcon won't use style in opt.
+    if (style) {
+        icon.setStyle(style);
+    }
     return icon;
 }
 
@@ -87135,15 +87620,16 @@ var MarkerModel = extendComponentModel({
         }
     },
 
-    formatTooltip: function (dataIndex) {
+    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {
         var data = this.getData();
         var value = this.getRawValue(dataIndex);
         var formattedValue = isArray(value)
             ? map(value, addCommas$1).join(', ') : addCommas$1(value);
         var name = data.getName(dataIndex);
         var html = encodeHTML$1(this.name);
+        var newLine = renderMode === 'html' ? '<br/>' : '\n';
         if (value != null || name) {
-            html += '<br />';
+            html += newLine;
         }
         if (name) {
             html += encodeHTML$1(name);
@@ -87608,10 +88094,12 @@ MarkerView.extend({
             var itemModel = mpData.getItemModel(idx);
             var symbol = itemModel.getShallow('symbol');
             var symbolSize = itemModel.getShallow('symbolSize');
+            var symbolRotate = itemModel.getShallow('symbolRotate');
             var isFnSymbol = isFunction$1(symbol);
             var isFnSymbolSize = isFunction$1(symbolSize);
+            var isFnSymbolRotate = isFunction$1(symbolRotate);
 
-            if (isFnSymbol || isFnSymbolSize) {
+            if (isFnSymbol || isFnSymbolSize || isFnSymbolRotate) {
                 var rawIdx = mpModel.getRawValue(idx);
                 var dataParams = mpModel.getDataParams(idx);
                 if (isFnSymbol) {
@@ -87621,11 +88109,15 @@ MarkerView.extend({
                     // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据?
                     symbolSize = symbolSize(rawIdx, dataParams);
                 }
+                if (isFnSymbolRotate) {
+                    symbolRotate = symbolRotate(rawIdx, dataParams);
+                }
             }
 
             mpData.setItemVisual(idx, {
                 symbol: symbol,
                 symbolSize: symbolSize,
+                symbolRotate: symbolRotate,
                 color: itemModel.get('itemStyle.color')
                     || seriesData.getVisual('color')
             });
@@ -88061,8 +88553,10 @@ MarkerView.extend({
             ]);
 
             lineData.setItemVisual(idx, {
+                'fromSymbolRotate': fromData.getItemVisual(idx, 'symbolRotate'),
                 'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'),
                 'fromSymbol': fromData.getItemVisual(idx, 'symbol'),
+                'toSymbolRotate': toData.getItemVisual(idx, 'symbolRotate'),
                 'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'),
                 'toSymbol': toData.getItemVisual(idx, 'symbol')
             });
@@ -88084,8 +88578,8 @@ MarkerView.extend({
             updateSingleMarkerEndLayout(
                 data, idx, isFrom, seriesModel, api
             );
-
             data.setItemVisual(idx, {
+                symbolRotate: itemModel.get('symbolRotate'),
                 symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
                 symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
                 color: itemModel.get('itemStyle.color') || seriesData.getVisual('color')
@@ -88444,9 +88938,29 @@ MarkerView.extend({
         // Update visual and layout of line
         areaData.each(function (idx) {
             // Layout
-            areaData.setItemLayout(idx, map(dimPermutations, function (dim) {
+            var points = map(dimPermutations, function (dim) {
                 return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
-            }));
+            });
+            // If none of the area is inside coordSys, allClipped is set to be true
+            // in layout so that label will not be displayed. See #12591
+            var allClipped = true;
+            each$1(dimPermutations, function (dim) {
+                if (!allClipped) {
+                    return;
+                }
+                var xValue = areaData.get(dim[0], idx);
+                var yValue = areaData.get(dim[1], idx);
+                // If is infinity, the axis should be considered not clipped
+                if ((isInifinity$1(xValue) || coordSys.getAxis('x').containData(xValue))
+                    && (isInifinity$1(yValue) || coordSys.getAxis('y').containData(yValue))
+                ) {
+                    allClipped = false;
+                }
+            });
+            areaData.setItemLayout(idx, {
+                points: points,
+                allClipped: allClipped
+            });
 
             // Visual
             areaData.setItemVisual(idx, {
@@ -88457,23 +88971,41 @@ MarkerView.extend({
 
         areaData.diff(polygonGroup.__data)
             .add(function (idx) {
-                var polygon = new Polygon({
-                    shape: {
-                        points: areaData.getItemLayout(idx)
-                    }
-                });
-                areaData.setItemGraphicEl(idx, polygon);
-                polygonGroup.group.add(polygon);
+                var layout = areaData.getItemLayout(idx);
+                if (!layout.allClipped) {
+                    var polygon = new Polygon({
+                        shape: {
+                            points: layout.points
+                        }
+                    });
+                    areaData.setItemGraphicEl(idx, polygon);
+                    polygonGroup.group.add(polygon);
+                }
             })
             .update(function (newIdx, oldIdx) {
                 var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx);
-                updateProps(polygon, {
-                    shape: {
-                        points: areaData.getItemLayout(newIdx)
+                var layout = areaData.getItemLayout(newIdx);
+                if (!layout.allClipped) {
+                    if (polygon) {
+                        updateProps(polygon, {
+                            shape: {
+                                points: layout.points
+                            }
+                        }, maModel, newIdx);
+                    }
+                    else {
+                        polygon = new Polygon({
+                            shape: {
+                                points: layout.points
+                            }
+                        });
                     }
-                }, maModel, newIdx);
-                polygonGroup.group.add(polygon);
-                areaData.setItemGraphicEl(newIdx, polygon);
+                    areaData.setItemGraphicEl(newIdx, polygon);
+                    polygonGroup.group.add(polygon);
+                }
+                else if (polygon) {
+                    polygonGroup.group.remove(polygon);
+                }
             })
             .remove(function (idx) {
                 var polygon = polygonGroup.__data.getItemGraphicEl(idx);
@@ -90218,7 +90750,7 @@ var ScrollableLegendView = LegendView.extend({
             var legendDataIdx = child.__legendDataIndex;
             // FIXME
             // If the given targetDataIndex (from model) is illegal,
-            // we use defualtIndex. But the index on the legend model and
+            // we use defaultIndex. 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) {
@@ -92435,7 +92967,7 @@ var VisualMapModel = extendComponentModel({
             // Originally we use visualMap.color as the default color, but setOption at
             // the second time the default color will be erased. So we change to use
             // constant DEFAULT_COLOR.
-            // If user do not want the defualt color, set inRange: {color: null}.
+            // If user do not want the default color, set inRange: {color: null}.
             base.inRange = base.inRange || {color: ecModel.get('gradientColor')};
 
             // If using shortcut like: {inRange: 'symbol'}, complete default value.
@@ -97234,7 +97766,7 @@ GradientManager.prototype.updateDom = function (gradient, dom) {
         stop.setAttribute('offset', colors[i].offset * 100 + '%');
 
         var color = colors[i].color;
-        if (color.indexOf('rgba' > -1)) {
+        if (color.indexOf('rgba') > -1) {
             // Fix Safari bug that stop-color not recognizing alpha #9014
             var opacity = parse(color)[3];
             var hex = toHex(color);
diff --git a/en/dist/echarts.js.map b/en/dist/echarts.js.map
index 479d634..e10fee3 100644
--- a/en/dist/echarts.js.map
+++ b/en/dist/echarts.js.map
@@ -1 +1 @@
-{"version":3,"file":"echarts.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.js", [...]
\ No newline at end of file
+{"version":3,"file":"echarts.js","sources":["../src/config.js","../node_modules/zrender/src/core/guid.js","../node_modules/zrender/src/core/env.js","../node_modules/zrender/src/core/util.js","../node_modules/zrender/src/core/vector.js","../node_modules/zrender/src/mixin/Draggable.js","../node_modules/zrender/src/mixin/Eventful.js","../node_modules/zrender/src/core/fourPointsTransform.js","../node_modules/zrender/src/core/dom.js","../node_modules/zrender/src/core/event.js","../node_module [...]
\ No newline at end of file
diff --git a/en/dist/echarts.min.js b/en/dist/echarts.min.js
index dc78df6..4b25b97 100644
--- a/en/dist/echarts.min.js
+++ b/en/dist/echarts.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.simple.js b/en/dist/echarts.simple.js
index 4bb3088..cf88f37 100644
--- a/en/dist/echarts.simple.js
+++ b/en/dist/echarts.simple.js
@@ -11289,7 +11289,7 @@ var painterCtors = {
 /**
  * @type {string}
  */
-var version$1 = '4.3.1';
+var version$1 = '4.3.2';
 
 /**
  * Initializing a zrender instance
@@ -25578,7 +25578,7 @@ var proto = Scheduler.prototype;
  * @param {Object} payload
  */
 proto.restoreData = function (ecModel, payload) {
-    // TODO: Only restroe needed series and components, but not all components.
+    // TODO: Only restore needed series and components, but not all components.
     // Currently `restoreData` of all of the series and component will be called.
     // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
     // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
@@ -27155,10 +27155,10 @@ var isFunction = isFunction$1;
 var isObject = isObject$1;
 var parseClassType = ComponentModel.parseClassType;
 
-var version = '4.8.0';
+var version = '4.9.0';
 
 var dependencies = {
-    zrender: '4.3.1'
+    zrender: '4.3.2'
 };
 
 var TEST_FRAME_REMAIN_TIME = 1;
@@ -30401,7 +30401,7 @@ listProto.mapDimension = function (coordDim, idx) {
  * Initialize from data
  * @param {Array.<Object|number|Array>} data source or data or data provider.
  * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
- *        defualt label/tooltip.
+ *        default label/tooltip.
  *        A name can be specified in encode.itemName,
  *        or dataItem.name (only for series option data),
  *        or provided in nameList from outside.
@@ -33594,7 +33594,7 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     }
     else {
         symbolPath.setStyle({
-            opacity: null,
+            opacity: 1,
             shadowBlur: null,
             shadowOffsetX: null,
             shadowOffsetY: null,
@@ -35779,7 +35779,7 @@ var dataSample = function (seriesType) {
                 var valueAxis = coordSys.getOtherAxis(baseAxis);
                 var extent = baseAxis.getExtent();
                 // Coordinste system has been resized
-                var size = extent[1] - extent[0];
+                var size = Math.abs(extent[1] - extent[0]);
                 var rate = Math.round(data.count() / size);
                 if (rate > 1) {
                     var sampler;
@@ -37945,8 +37945,8 @@ function rotateTextRect(textRect, rotate) {
     var boundingBox = textRect.plain();
     var beforeWidth = boundingBox.width;
     var beforeHeight = boundingBox.height;
-    var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
-    var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
+    var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
+    var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
     var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
 
     return rotatedRect;
@@ -39141,7 +39141,7 @@ var defaultOption = {
     name: '',
     // 'start' | 'middle' | 'end'
     nameLocation: 'end',
-    // By degree. By defualt auto rotate by nameLocation.
+    // By degree. By default auto rotate by nameLocation.
     nameRotate: null,
     nameTruncate: {
         maxWidth: null,
@@ -42231,20 +42231,25 @@ extendChartView({
         var bgEls = [];
         var oldBgEls = this._backgroundEls || [];
 
+        var createBackground = function (dataIndex) {
+            var bgLayout = getLayout[coord.type](data, dataIndex);
+            var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
+            bgEl.useStyle(backgroundModel.getBarItemStyle());
+            // Only cartesian2d support borderRadius.
+            if (coord.type === 'cartesian2d') {
+                bgEl.setShape('r', barBorderRadius);
+            }
+            bgEls[dataIndex] = bgEl;
+            return bgEl;
+        };
+
         data.diff(oldData)
             .add(function (dataIndex) {
                 var itemModel = data.getItemModel(dataIndex);
                 var layout = getLayout[coord.type](data, dataIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgLayout = getLayout[coord.type](data, dataIndex);
-                    var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
-                    }
-                    bgEls[dataIndex] = bgEl;
+                    createBackground(dataIndex);
                 }
 
                 // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
@@ -42278,13 +42283,19 @@ extendChartView({
                 var layout = getLayout[coord.type](data, newIndex, itemModel);
 
                 if (drawBackground) {
-                    var bgEl = oldBgEls[oldIndex];
-                    bgEl.useStyle(backgroundModel.getBarItemStyle());
-                    // Only cartesian2d support borderRadius.
-                    if (coord.type === 'cartesian2d') {
-                        bgEl.setShape('r', barBorderRadius);
+                    var bgEl;
+                    if (oldBgEls.length === 0) {
+                        bgEl = createBackground(oldIndex);
+                    }
+                    else {
+                        bgEl = oldBgEls[oldIndex];
+                        bgEl.useStyle(backgroundModel.getBarItemStyle());
+                        // Only cartesian2d support borderRadius.
+                        if (coord.type === 'cartesian2d') {
+                            bgEl.setShape('r', barBorderRadius);
+                        }
+                        bgEls[newIndex] = bgEl;
                     }
-                    bgEls[newIndex] = bgEl;
 
                     var bgLayout = getLayout[coord.type](data, newIndex);
                     var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
@@ -42444,8 +42455,31 @@ var clip = {
         return clipped;
     },
 
-    polar: function (coordSysClipArea) {
-        return false;
+    polar: function (coordSysClipArea, layout) {
+        var signR = layout.r0 <= layout.r ? 1 : -1;
+        // Make sure r is larger than r0
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        var r = mathMin$4(layout.r, coordSysClipArea.r);
+        var r0 = mathMax$4(layout.r0, coordSysClipArea.r0);
+
+        layout.r = r;
+        layout.r0 = r0;
+
+        var clipped = r - r0 < 0;
+
+        // Reverse back
+        if (signR < 0) {
+            var r = layout.r;
+            layout.r = layout.r0;
+            layout.r0 = r;
+        }
+
+        return clipped;
     }
 };
 
diff --git a/en/dist/echarts.simple.min.js b/en/dist/echarts.simple.min.js
index 7e2efe8..a3fd2d6 100644
--- a/en/dist/echarts.simple.min.js
+++ b/en/dist/echarts.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/extension/bmap.js b/en/dist/extension/bmap.js
index e3bd8a2..03970fe 100644
--- a/en/dist/extension/bmap.js
+++ b/en/dist/extension/bmap.js
@@ -179,7 +179,12 @@ BMapCoordSys.create = function (ecModel, api) {
             // Not support IE8
             bmapRoot.classList.add('ec-extension-bmap');
             root.appendChild(bmapRoot);
-            var bmap = bmapModel.__bmap = new BMap.Map(bmapRoot);
+
+            // initialize bmap
+            var mapOptions = bmapModel.get('mapOptions') || {};
+            // Not support `mapType`, use `bmap.setMapType(MapType)` instead.
+            delete mapOptions.mapType;
+            var bmap = bmapModel.__bmap = new BMap.Map(bmapRoot, mapOptions);
 
             var overlay = new Overlay(viewportRoot);
             bmap.addOverlay(overlay);
@@ -196,8 +201,13 @@ BMapCoordSys.create = function (ecModel, api) {
         var center = bmapModel.get('center');
         var zoom = bmapModel.get('zoom');
         if (center && zoom) {
-            var pt = new BMap.Point(center[0], center[1]);
-            bmap.centerAndZoom(pt, zoom);
+            var bmapCenter = bmap.getCenter();
+            var bmapZoom = bmap.getZoom();
+            var centerOrZoomChanged = bmapModel.centerOrZoomChanged([bmapCenter.lng, bmapCenter.lat], bmapZoom);
+            if (centerOrZoomChanged) {
+                var pt = new BMap.Point(center[0], center[1]);
+                bmap.centerAndZoom(pt, zoom);
+            }
         }
 
         bmapCoordSys = new BMapCoordSys(bmap, api);
@@ -262,348 +272,19 @@ echarts.extendComponentModel({
 
         zoom: 5,
 
+        // 2.0 http://lbsyun.baidu.com/custom/index.htm
         mapStyle: {},
 
+        // 3.0 http://lbsyun.baidu.com/index.php?title=open/custom
         mapStyleV2: {},
 
+        // See https://lbsyun.baidu.com/cms/jsapi/reference/jsapi_reference.html#a0b1
+        mapOptions: {},
+
         roam: false
     }
 });
 
-/**
- * @module zrender/core/util
- */
-
-// 用于处理merge时无法遍历Date等对象的问题
-var BUILTIN_OBJECT = {
-    '[object Function]': 1,
-    '[object RegExp]': 1,
-    '[object Date]': 1,
-    '[object Error]': 1,
-    '[object CanvasGradient]': 1,
-    '[object CanvasPattern]': 1,
-    // For node-canvas
-    '[object Image]': 1,
-    '[object Canvas]': 1
-};
-
-var TYPED_ARRAY = {
-    '[object Int8Array]': 1,
-    '[object Uint8Array]': 1,
-    '[object Uint8ClampedArray]': 1,
-    '[object Int16Array]': 1,
-    '[object Uint16Array]': 1,
-    '[object Int32Array]': 1,
-    '[object Uint32Array]': 1,
-    '[object Float32Array]': 1,
-    '[object Float64Array]': 1
-};
-
-var objToString = Object.prototype.toString;
-
-
-
-/**
- * Those data types can be cloned:
- *     Plain object, Array, TypedArray, number, string, null, undefined.
- * Those data types will be assgined using the orginal data:
- *     BUILTIN_OBJECT
- * Instance of user defined class will be cloned to a plain object, without
- * properties in prototype.
- * Other data types is not supported (not sure what will happen).
- *
- * Caution: do not support clone Date, for performance consideration.
- * (There might be a large number of date in `series.data`).
- * So date should not be modified in and out of echarts.
- *
- * @param {*} source
- * @return {*} new
- */
-function clone(source) {
-    if (source == null || typeof source !== 'object') {
-        return source;
-    }
-
-    var result = source;
-    var typeStr = objToString.call(source);
-
-    if (typeStr === '[object Array]') {
-        if (!isPrimitive(source)) {
-            result = [];
-            for (var i = 0, len = source.length; i < len; i++) {
-                result[i] = clone(source[i]);
-            }
-        }
-    }
-    else if (TYPED_ARRAY[typeStr]) {
-        if (!isPrimitive(source)) {
-            var Ctor = source.constructor;
-            if (source.constructor.from) {
-                result = Ctor.from(source);
-            }
-            else {
-                result = new Ctor(source.length);
-                for (var i = 0, len = source.length; i < len; i++) {
-                    result[i] = clone(source[i]);
-                }
-            }
-        }
-    }
-    else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
-        result = {};
-        for (var key in source) {
-            if (source.hasOwnProperty(key)) {
-                result[key] = clone(source[key]);
-            }
-        }
-    }
-
-    return result;
-}
-
-/**
- * @memberOf module:zrender/core/util
- * @param {*} target
- * @param {*} source
- * @param {boolean} [overwrite=false]
- */
-
-
-/**
- * @param {Array} targetAndSources The first item is target, and the rests are source.
- * @param {boolean} [overwrite=false]
- * @return {*} target
- */
-
-
-/**
- * @param {*} target
- * @param {*} source
- * @memberOf module:zrender/core/util
- */
-
-
-/**
- * @param {*} target
- * @param {*} source
- * @param {boolean} [overlay=false]
- * @memberOf module:zrender/core/util
- */
-
-
-
-
-
-
-/**
- * 查询数组中元素的index
- * @memberOf module:zrender/core/util
- */
-
-
-/**
- * 构造类继承关系
- *
- * @memberOf module:zrender/core/util
- * @param {Function} clazz 源类
- * @param {Function} baseClazz 基类
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {Object|Function} target
- * @param {Object|Function} sorce
- * @param {boolean} overlay
- */
-
-
-/**
- * Consider typed array.
- * @param {Array|TypedArray} data
- */
-
-
-/**
- * 数组或对象遍历
- * @memberOf module:zrender/core/util
- * @param {Object|Array} obj
- * @param {Function} cb
- * @param {*} [context]
- */
-
-
-/**
- * 数组映射
- * @memberOf module:zrender/core/util
- * @param {Array} obj
- * @param {Function} cb
- * @param {*} [context]
- * @return {Array}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {Array} obj
- * @param {Function} cb
- * @param {Object} [memo]
- * @param {*} [context]
- * @return {Array}
- */
-
-
-/**
- * 数组过滤
- * @memberOf module:zrender/core/util
- * @param {Array} obj
- * @param {Function} cb
- * @param {*} [context]
- * @return {Array}
- */
-
-
-/**
- * 数组项查找
- * @memberOf module:zrender/core/util
- * @param {Array} obj
- * @param {Function} cb
- * @param {*} [context]
- * @return {*}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {Function} func
- * @param {*} context
- * @return {Function}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {Function} func
- * @return {Function}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {*} value
- * @return {boolean}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {*} value
- * @return {boolean}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {*} value
- * @return {boolean}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {*} value
- * @return {boolean}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {*} value
- * @return {boolean}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {*} value
- * @return {boolean}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {*} value
- * @return {boolean}
- */
-function isDom(value) {
-    return typeof value === 'object'
-        && typeof value.nodeType === 'number'
-        && typeof value.ownerDocument === 'object';
-}
-
-/**
- * Whether is exactly NaN. Notice isNaN('a') returns true.
- * @param {*} value
- * @return {boolean}
- */
-
-
-/**
- * If value1 is not null, then return value1, otherwise judget rest of values.
- * Low performance.
- * @memberOf module:zrender/core/util
- * @return {*} Final value
- */
-
-
-
-
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {Array} arr
- * @param {number} startIndex
- * @param {number} endIndex
- * @return {Array}
- */
-
-
-/**
- * Normalize css liked array configuration
- * e.g.
- *  3 => [3, 3, 3, 3]
- *  [4, 2] => [4, 2, 4, 2]
- *  [4, 3, 2] => [4, 3, 2, 3]
- * @param {number|Array.<number>} val
- * @return {Array.<number>}
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {boolean} condition
- * @param {string} message
- */
-
-
-/**
- * @memberOf module:zrender/core/util
- * @param {string} str string to be trimed
- * @return {string} trimed string
- */
-
-
-var primitiveKey = '__ec_primitive__';
-/**
- * Set an object as primitive to be ignored traversing children in clone or merge
- */
-
-
-function isPrimitive(obj) {
-    return obj[primitiveKey];
-}
-
 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
@@ -623,6 +304,15 @@ function isPrimitive(obj) {
 * under the License.
 */
 
+function isEmptyObject(obj) {
+    for (var key in obj) {
+        if (obj.hasOwnProperty(key)) {
+            return false;
+        }
+    }
+    return true;
+}
+
 echarts.extendComponentView({
     type: 'bmap',
 
@@ -662,12 +352,10 @@ echarts.extendComponentView({
         }
 
         bmap.removeEventListener('moving', this._oldMoveHandler);
-        // FIXME
-        // Moveend may be triggered by centerAndZoom method when creating coordSys next time
-        // bmap.removeEventListener('moveend', this._oldMoveHandler);
+        bmap.removeEventListener('moveend', this._oldMoveHandler);
         bmap.removeEventListener('zoomend', this._oldZoomEndHandler);
         bmap.addEventListener('moving', moveHandler);
-        // bmap.addEventListener('moveend', moveHandler);
+        bmap.addEventListener('moveend', moveHandler);
         bmap.addEventListener('zoomend', zoomEndHandler);
 
         this._oldMoveHandler = moveHandler;
@@ -699,8 +387,8 @@ echarts.extendComponentView({
         var mapStyleStr = JSON.stringify(newMapStyle);
         if (JSON.stringify(originalStyle) !== mapStyleStr) {
             // FIXME May have blank tile when dragging if setMapStyle
-            if (Object.keys(newMapStyle).length) {
-                bmap.setMapStyle(clone(newMapStyle));
+            if (!isEmptyObject(newMapStyle2)) {
+                bmap.setMapStyle(echarts.util.clone(newMapStyle));
             }
             bMapModel.__mapStyle = JSON.parse(mapStyleStr);
         }
@@ -713,8 +401,8 @@ echarts.extendComponentView({
         var mapStyleStr2 = JSON.stringify(newMapStyle2);
         if (JSON.stringify(originalStyle2) !== mapStyleStr2) {
             // FIXME May have blank tile when dragging if setMapStyle
-            if (Object.keys(newMapStyle2).length) {
-                bmap.setMapStyleV2(clone(newMapStyle2));
+            if (!isEmptyObject(newMapStyle2)) {
+                bmap.setMapStyleV2(echarts.util.clone(newMapStyle2));
             }
             bMapModel.__mapStyle2 = JSON.parse(mapStyleStr2);
         }
diff --git a/en/dist/extension/bmap.js.map b/en/dist/extension/bmap.js.map
index 21dbc5e..07404b1 100644
--- a/en/dist/extension/bmap.js.map
+++ b/en/dist/extension/bmap.js.map
@@ -1 +1 @@
-{"version":3,"file":"bmap.js","sources":["../../extension-src/bmap/BMapCoordSys.js","../../extension-src/bmap/BMapModel.js","../../../zrender/src/core/util.js","../../extension-src/bmap/BMapView.js","../../extension-src/bmap/bmap.js"],"sourcesContent":["/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses  [...]
\ No newline at end of file
+{"version":3,"file":"bmap.js","sources":["../../extension-src/bmap/BMapCoordSys.js","../../extension-src/bmap/BMapModel.js","../../extension-src/bmap/BMapView.js","../../extension-src/bmap/bmap.js"],"sourcesContent":["/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache [...]
\ No newline at end of file
diff --git a/en/dist/extension/bmap.min.js b/en/dist/extension/bmap.min.js
index 00f6917..8a7a65c 100644
--- a/en/dist/extension/bmap.min.js
+++ b/en/dist/extension/bmap.min.js
@@ -19,4 +19,4 @@
 */
 
 
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("echarts")):"function"==typeof define&&define.amd?define(["exports","echarts"],e):e(t.bmap={},t.echarts)}(this,function(t,o){"use strict";function l(t,e){this._bmap=t,this.dimensions=["lng","lat"],this._mapOffset=[0,0],this._api=e,this._projection=new BMap.MercatorProjection}function n(i,a){return a=a||[0,0],o.util.map([0,1],function(t){var e=a[t],o=i[t]/2,n=[],r=[];return n[t]=e-o,r[t]=e+o,n[1-t]=r[1-t [...]
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("echarts")):"function"==typeof define&&define.amd?define(["exports","echarts"],t):t(e.bmap={},e.echarts)}(this,function(e,y){"use strict";function h(e,t){this._bmap=e,this.dimensions=["lng","lat"],this._mapOffset=[0,0],this._api=t,this._projection=new BMap.MercatorProjection}function o(a,r){return r=r||[0,0],y.util.map([0,1],function(e){var t=r[e],o=a[e]/2,n=[],i=[];return n[e]=t-o,i[e]=t+o,n[1-e]=i[1-e [...]
diff --git a/en/dist/extension/dataTool.js.map b/en/dist/extension/dataTool.js.map
index 416b0c1..0b565e9 100644
--- a/en/dist/extension/dataTool.js.map
+++ b/en/dist/extension/dataTool.js.map
@@ -1 +1 @@
-{"version":3,"file":"dataTool.js","sources":["../../../zrender/src/core/util.js","../../extension-src/dataTool/gexf.js","../../src/util/number.js","../../extension-src/dataTool/prepareBoxplotData.js","../../extension-src/dataTool/index.js"],"sourcesContent":["/**\n * @module zrender/core/util\n */\n\n// 用于处理merge时无法遍历Date等对象的问题\nvar BUILTIN_OBJECT = {\n    '[object Function]': 1,\n    '[object RegExp]': 1,\n    '[object Date]': 1,\n    '[object Error]': 1,\n    '[object CanvasGradient]': [...]
\ No newline at end of file
+{"version":3,"file":"dataTool.js","sources":["../../node_modules/zrender/src/core/util.js","../../extension-src/dataTool/gexf.js","../../src/util/number.js","../../extension-src/dataTool/prepareBoxplotData.js","../../extension-src/dataTool/index.js"],"sourcesContent":["/**\n * @module zrender/core/util\n */\n\n// 用于处理merge时无法遍历Date等对象的问题\nvar BUILTIN_OBJECT = {\n    '[object Function]': 1,\n    '[object RegExp]': 1,\n    '[object Date]': 1,\n    '[object Error]': 1,\n    '[object CanvasG [...]
\ No newline at end of file
diff --git a/en/documents/option-parts/option-outline.js b/en/documents/option-parts/option-outline.js
index 418f1d9..31f7db1 100644
--- a/en/documents/option-parts/option-outline.js
+++ b/en/documents/option-parts/option-outline.js
@@ -1 +1 @@
-window.__EC_DOC_option_outline = {"children":[{"type":"Object","isObject":true,"prop":"title","children":[{"type":"string","prop":"id"},{"default":true,"prop":"show"},{"default":"''","prop":"text"},{"default":"''","prop":"link"},{"default":"'blank'","prop":"target"},{"type":"Object","isObject":true,"prop":"textStyle","children":[{"type":"Color","default":"'#333'","prop":"color"},{"default":"'normal'","prop":"fontStyle"},{"type":["string","number"],"default":"normal","prop":"fontWeight"}, [...]
\ No newline at end of file
+window.__EC_DOC_option_outline = {"children":[{"type":"Object","isObject":true,"prop":"title","children":[{"type":"string","prop":"id"},{"default":true,"prop":"show"},{"default":"''","prop":"text"},{"default":"''","prop":"link"},{"default":"'blank'","prop":"target"},{"type":"Object","isObject":true,"prop":"textStyle","children":[{"type":"Color","default":"'#333'","prop":"color"},{"default":"'normal'","prop":"fontStyle"},{"type":["string","number"],"default":"normal","prop":"fontWeight"}, [...]
\ No newline at end of file
diff --git a/en/documents/option-parts/option-outline.json b/en/documents/option-parts/option-outline.json
index 3023e25..9686686 100644
--- a/en/documents/option-parts/option-outline.json
+++ b/en/documents/option-parts/option-outline.json
@@ -1 +1 @@
-{"children":[{"type":"Object","isObject":true,"prop":"title","children":[{"type":"string","prop":"id"},{"default":true,"prop":"show"},{"default":"''","prop":"text"},{"default":"''","prop":"link"},{"default":"'blank'","prop":"target"},{"type":"Object","isObject":true,"prop":"textStyle","children":[{"type":"Color","default":"'#333'","prop":"color"},{"default":"'normal'","prop":"fontStyle"},{"type":["string","number"],"default":"normal","prop":"fontWeight"},{"default":"'sans-serif'","prop": [...]
\ No newline at end of file
+{"children":[{"type":"Object","isObject":true,"prop":"title","children":[{"type":"string","prop":"id"},{"default":true,"prop":"show"},{"default":"''","prop":"text"},{"default":"''","prop":"link"},{"default":"'blank'","prop":"target"},{"type":"Object","isObject":true,"prop":"textStyle","children":[{"type":"Color","default":"'#333'","prop":"color"},{"default":"'normal'","prop":"fontStyle"},{"type":["string","number"],"default":"normal","prop":"fontWeight"},{"default":"'sans-serif'","prop": [...]
\ No newline at end of file
diff --git a/en/documents/option-parts/option.series-funnel.js b/en/documents/option-parts/option.series-funnel.js
index 47b58c3..03c8211 100644
--- a/en/documents/option-parts/option.series-funnel.js
+++ b/en/documents/option-parts/option.series-funnel.js
@@ -35,6 +35,13 @@ window.__EC_DOC_option_series_funnel = {
       "default": "100%"
     }
   },
+  "orient": {
+    "desc": "\n\n<p>Orient of funnel,Can be <code class=\"codespan\">&#39;vertical&#39;</code> or <code class=\"codespan\">&#39;horizontal&#39;</code>.</p>\n",
+    "uiControl": {
+      "type": "enum",
+      "options": "vertical,horizontal"
+    }
+  },
   "sort": {
     "desc": "<p>Data sorting, which can be whether <code class=\"codespan\">&#39;ascending&#39;</code>, <code class=\"codespan\">&#39;descending&#39;</code>, <code class=\"codespan\">&#39;none&#39;</code>(in data order) or a function, which is the same as <code class=\"codespan\">Array.prototype.sort(function (a, b) { ... })</code>;</p>\n",
     "uiControl": {
@@ -71,7 +78,7 @@ window.__EC_DOC_option_series_funnel = {
     "desc": "<p>Text label of funnel chart, to explain some data information about graphic item like value, name and so on. <code class=\"codespan\">label</code> is placed under <code class=\"codespan\">itemStyle</code> in ECharts 2.x. In ECharts 3, to make the configuration structure flatter, <code class=\"codespan\">label</code>is taken to be at the same level with <code class=\"codespan\">itemStyle</code>, and has <code class=\"codespan\">emphasis</code> as <code class=\"codespan\">it [...]
   },
   "label.position": {
-    "desc": "<p>Label position.</p>\n<p><strong>Options: </strong></p>\n<ul>\n<li><p><code class=\"codespan\">&#39;left&#39;</code></p>\n<p>  Left side of funnel chart. The corresponding trapezoid would be related to through <a href=\"#series-funnel.labelLine\">visual guide line</a>.</p>\n</li>\n<li><p><code class=\"codespan\">&#39;right&#39;</code></p>\n<p> Right side of funnel chart. The corresponding trapezoid would be related to through <a href=\"#series-funnel.labelLine\">visual gui [...]
+    "desc": "<p>Label position.</p>\n<p><strong>Options: </strong></p>\n<ul>\n<li><code class=\"codespan\">&#39;left&#39;</code>Left side of funnel chart. Available when <a href=\"#series-funnel.orient\">orient</a> is <code class=\"codespan\">&#39;vertical&#39;</code>.</li>\n<li><code class=\"codespan\">&#39;right&#39;</code> Right side of funnel chart. Available when <a href=\"#series-funnel.orient\">orient</a> is <code class=\"codespan\">&#39;horizontal&#39;</code>.</li>\n<li><code cla [...]
   },
   "label.formatter": {
     "desc": "<p>Data label formatter, which supports string template and callback function. In either form, <code class=\"codespan\">\\n</code> is supported to represent a new line.</p>\n<p><strong>String template</strong></p>\n<p>Model variation includes:</p>\n<ul>\n<li><code class=\"codespan\">{a}</code>: series name.</li>\n<li><code class=\"codespan\">{b}</code>: the name of a data item.</li>\n<li><code class=\"codespan\">{c}</code>: the value of a data item.</li>\n<li><code class=\"c [...]
@@ -1231,7 +1238,7 @@ window.__EC_DOC_option_series_funnel = {
     "desc": "<p>The label configuration of a single data item.</p>\n"
   },
   "data.label.position": {
-    "desc": "<p>Label position.</p>\n<p><strong>Options: </strong></p>\n<ul>\n<li><p><code class=\"codespan\">&#39;left&#39;</code></p>\n<p>  Left side of funnel chart. The corresponding trapezoid would be related to through <a href=\"#series-funnel.labelLine\">visual guide line</a>.</p>\n</li>\n<li><p><code class=\"codespan\">&#39;right&#39;</code></p>\n<p> Right side of funnel chart. The corresponding trapezoid would be related to through <a href=\"#series-funnel.labelLine\">visual gui [...]
+    "desc": "<p>Label position.</p>\n<p><strong>Options: </strong></p>\n<ul>\n<li><code class=\"codespan\">&#39;left&#39;</code>Left side of funnel chart. Available when <a href=\"#series-funnel.orient\">orient</a> is <code class=\"codespan\">&#39;vertical&#39;</code>.</li>\n<li><code class=\"codespan\">&#39;right&#39;</code> Right side of funnel chart. Available when <a href=\"#series-funnel.orient\">orient</a> is <code class=\"codespan\">&#39;horizontal&#39;</code>.</li>\n<li><code cla [...]
   },
   "data.label.color": {
     "desc": "<p> text color.</p>\n",
diff --git a/en/documents/option-parts/option.series-funnel.json b/en/documents/option-parts/option.series-funnel.json
index aeb8c67..4b136b8 100644
--- a/en/documents/option-parts/option.series-funnel.json
+++ b/en/documents/option-parts/option.series-funnel.json
@@ -35,6 +35,13 @@
       "default": "100%"
     }
   },
+  "orient": {
+    "desc": "\n\n<p>Orient of funnel,Can be <code class=\"codespan\">&#39;vertical&#39;</code> or <code class=\"codespan\">&#39;horizontal&#39;</code>.</p>\n",
+    "uiControl": {
+      "type": "enum",
+      "options": "vertical,horizontal"
+    }
+  },
   "sort": {
     "desc": "<p>Data sorting, which can be whether <code class=\"codespan\">&#39;ascending&#39;</code>, <code class=\"codespan\">&#39;descending&#39;</code>, <code class=\"codespan\">&#39;none&#39;</code>(in data order) or a function, which is the same as <code class=\"codespan\">Array.prototype.sort(function (a, b) { ... })</code>;</p>\n",
     "uiControl": {
@@ -71,7 +78,7 @@
     "desc": "<p>Text label of funnel chart, to explain some data information about graphic item like value, name and so on. <code class=\"codespan\">label</code> is placed under <code class=\"codespan\">itemStyle</code> in ECharts 2.x. In ECharts 3, to make the configuration structure flatter, <code class=\"codespan\">label</code>is taken to be at the same level with <code class=\"codespan\">itemStyle</code>, and has <code class=\"codespan\">emphasis</code> as <code class=\"codespan\">it [...]
   },
   "label.position": {
-    "desc": "<p>Label position.</p>\n<p><strong>Options: </strong></p>\n<ul>\n<li><p><code class=\"codespan\">&#39;left&#39;</code></p>\n<p>  Left side of funnel chart. The corresponding trapezoid would be related to through <a href=\"#series-funnel.labelLine\">visual guide line</a>.</p>\n</li>\n<li><p><code class=\"codespan\">&#39;right&#39;</code></p>\n<p> Right side of funnel chart. The corresponding trapezoid would be related to through <a href=\"#series-funnel.labelLine\">visual gui [...]
+    "desc": "<p>Label position.</p>\n<p><strong>Options: </strong></p>\n<ul>\n<li><code class=\"codespan\">&#39;left&#39;</code>Left side of funnel chart. Available when <a href=\"#series-funnel.orient\">orient</a> is <code class=\"codespan\">&#39;vertical&#39;</code>.</li>\n<li><code class=\"codespan\">&#39;right&#39;</code> Right side of funnel chart. Available when <a href=\"#series-funnel.orient\">orient</a> is <code class=\"codespan\">&#39;horizontal&#39;</code>.</li>\n<li><code cla [...]
   },
   "label.formatter": {
     "desc": "<p>Data label formatter, which supports string template and callback function. In either form, <code class=\"codespan\">\\n</code> is supported to represent a new line.</p>\n<p><strong>String template</strong></p>\n<p>Model variation includes:</p>\n<ul>\n<li><code class=\"codespan\">{a}</code>: series name.</li>\n<li><code class=\"codespan\">{b}</code>: the name of a data item.</li>\n<li><code class=\"codespan\">{c}</code>: the value of a data item.</li>\n<li><code class=\"c [...]
@@ -1231,7 +1238,7 @@
     "desc": "<p>The label configuration of a single data item.</p>\n"
   },
   "data.label.position": {
-    "desc": "<p>Label position.</p>\n<p><strong>Options: </strong></p>\n<ul>\n<li><p><code class=\"codespan\">&#39;left&#39;</code></p>\n<p>  Left side of funnel chart. The corresponding trapezoid would be related to through <a href=\"#series-funnel.labelLine\">visual guide line</a>.</p>\n</li>\n<li><p><code class=\"codespan\">&#39;right&#39;</code></p>\n<p> Right side of funnel chart. The corresponding trapezoid would be related to through <a href=\"#series-funnel.labelLine\">visual gui [...]
+    "desc": "<p>Label position.</p>\n<p><strong>Options: </strong></p>\n<ul>\n<li><code class=\"codespan\">&#39;left&#39;</code>Left side of funnel chart. Available when <a href=\"#series-funnel.orient\">orient</a> is <code class=\"codespan\">&#39;vertical&#39;</code>.</li>\n<li><code class=\"codespan\">&#39;right&#39;</code> Right side of funnel chart. Available when <a href=\"#series-funnel.orient\">orient</a> is <code class=\"codespan\">&#39;horizontal&#39;</code>.</li>\n<li><code cla [...]
   },
   "data.label.color": {
     "desc": "<p> text color.</p>\n",
diff --git a/en/documents/option-parts/option.series-graph.js b/en/documents/option-parts/option.series-graph.js
index d0da2e5..2ecf867 100644
--- a/en/documents/option-parts/option.series-graph.js
+++ b/en/documents/option-parts/option.series-graph.js
@@ -3033,6 +3033,9 @@ window.__EC_DOC_option_series_graph = {
       "step": "0.5"
     }
   },
+  "autoCurveness": {
+    "desc": "<p>For the situation where there are multiple links between nodes, the curveness of each link is automatically calculated.</p>\n<p>When set to <code class=\"codespan\">number</code>, it indicates the length of the edge curvenness array between two nodes, and the calculation result is given by the internal algorithm.</p>\n<p>When set to <code class=\"codespan\">Array</code>, it means that the curveness array is directly specified, and the multilateral curveness is directly se [...]
+  },
   "data": {
     "desc": "<p>Nodes list of graph.</p>\n<pre><code class=\"lang-js\">data: [{\n    name: &#39;1&#39;,\n    x: 10,\n    y: 10,\n    value: 10\n}, {\n    name: &#39;2&#39;,\n    x: 100,\n    y: 100,\n    value: 20,\n    symbolSize: 20,\n    itemStyle: {\n        color: &#39;red&#39;\n    }\n}]\n</code></pre>\n"
   },
diff --git a/en/documents/option-parts/option.series-graph.json b/en/documents/option-parts/option.series-graph.json
index 9b795c2..4ca466c 100644
--- a/en/documents/option-parts/option.series-graph.json
+++ b/en/documents/option-parts/option.series-graph.json
@@ -3033,6 +3033,9 @@
       "step": "0.5"
     }
   },
+  "autoCurveness": {
+    "desc": "<p>For the situation where there are multiple links between nodes, the curveness of each link is automatically calculated.</p>\n<p>When set to <code class=\"codespan\">number</code>, it indicates the length of the edge curvenness array between two nodes, and the calculation result is given by the internal algorithm.</p>\n<p>When set to <code class=\"codespan\">Array</code>, it means that the curveness array is directly specified, and the multilateral curveness is directly se [...]
+  },
   "data": {
     "desc": "<p>Nodes list of graph.</p>\n<pre><code class=\"lang-js\">data: [{\n    name: &#39;1&#39;,\n    x: 10,\n    y: 10,\n    value: 10\n}, {\n    name: &#39;2&#39;,\n    x: 100,\n    y: 100,\n    value: 20,\n    symbolSize: 20,\n    itemStyle: {\n        color: &#39;red&#39;\n    }\n}]\n</code></pre>\n"
   },
diff --git a/en/documents/option-parts/option.toolbox.js b/en/documents/option-parts/option.toolbox.js
index 27548b7..8364dda 100644
--- a/en/documents/option-parts/option.toolbox.js
+++ b/en/documents/option-parts/option.toolbox.js
@@ -921,6 +921,80 @@ window.__EC_DOC_option_toolbox = {
   "feature.dataZoom.yAxisIndex": {
     "desc": "<p>Defines which <a href=\"#yAxis\">yAxis</a> should be controlled. By default, it controls all y axes. If it is set to be <code class=\"codespan\">false</code>, then no y axis is controlled. If it is set to be then it controls axis with axisIndex of <code class=\"codespan\">3</code>. If it is set to be <code class=\"codespan\">[0, 3]</code>, it controls the x-axes with axisIndex of <code class=\"codespan\">0</code> and <code class=\"codespan\">3</code>.</p>\n"
   },
+  "feature.dataZoom.brushStyle": {
+    "desc": "<p>Style of brush rectangle.</p>\n"
+  },
+  "feature.dataZoom.brushStyle.color": {
+    "desc": "<p> color. </p>\n<blockquote>\n<p>Color can be represented in RGB, for example <code class=\"codespan\">&#39;rgb(128, 128, 128)&#39;</code>. RGBA can be used when you need alpha channel, for example <code class=\"codespan\">&#39;rgba(128, 128, 128, 0.5)&#39;</code>. You may also use hexadecimal format, for example <code class=\"codespan\">&#39;#ccc&#39;</code>. Gradient color and texture are also supported besides single colors.</p>\n<pre><code class=\"lang-js\">// Linear gr [...]
+    "uiControl": {
+      "type": "color"
+    }
+  },
+  "feature.dataZoom.brushStyle.borderColor": {
+    "desc": "<p> border color, whose format is similar to that of <code class=\"codespan\">color</code>.</p>\n",
+    "uiControl": {
+      "type": "color"
+    }
+  },
+  "feature.dataZoom.brushStyle.borderWidth": {
+    "desc": "<p> border width. No border when it is set to be 0.</p>\n",
+    "uiControl": {
+      "type": "number",
+      "value": "0",
+      "min": "0",
+      "step": "0.5"
+    }
+  },
+  "feature.dataZoom.brushStyle.borderType": {
+    "desc": "<p>Border type, which can be <code class=\"codespan\">&#39;solid&#39;</code>, <code class=\"codespan\">&#39;dashed&#39;</code>, or <code class=\"codespan\">&#39;dotted&#39;</code>. <code class=\"codespan\">&#39;solid&#39;</code> by default.</p>\n",
+    "uiControl": {
+      "type": "enum",
+      "default": "solid",
+      "options": "solid,dashed,dotted"
+    }
+  },
+  "feature.dataZoom.brushStyle.shadowBlur": {
+    "desc": "<p>Size of shadow blur. This attribute should be used along with <code class=\"codespan\">shadowColor</code>,<code class=\"codespan\">shadowOffsetX</code>, <code class=\"codespan\">shadowOffsetY</code> to set shadow to component.</p>\n<p>For example:</p>\n<pre><code class=\"lang-js\">{\n    shadowColor: &#39;rgba(0, 0, 0, 0.5)&#39;,\n    shadowBlur: 10\n}\n</code></pre>\n",
+    "uiControl": {
+      "type": "number",
+      "default": "",
+      "min": "0",
+      "step": "0.5"
+    }
+  },
+  "feature.dataZoom.brushStyle.shadowColor": {
+    "desc": "<p>Shadow color. Support same format as <code class=\"codespan\">color</code>.</p>\n",
+    "uiControl": {
+      "type": "color",
+      "default": ""
+    }
+  },
+  "feature.dataZoom.brushStyle.shadowOffsetX": {
+    "desc": "<p>Offset distance on the horizontal direction of shadow.</p>\n",
+    "uiControl": {
+      "type": "number",
+      "default": "0",
+      "step": "0.5"
+    }
+  },
+  "feature.dataZoom.brushStyle.shadowOffsetY": {
+    "desc": "<p>Offset distance on the vertical direction of shadow.</p>\n",
+    "uiControl": {
+      "type": "number",
+      "default": "0",
+      "step": "0.5"
+    }
+  },
+  "feature.dataZoom.brushStyle.opacity": {
+    "desc": "<p>Opacity of the component. Supports value from 0 to 1, and the component will not be drawn when set to 0.</p>\n",
+    "uiControl": {
+      "type": "number",
+      "default": "1",
+      "min": "0",
+      "max": "1",
+      "step": "0.01"
+    }
+  },
   "feature.magicType": {
     "desc": "<p>Magic type switching.\n<strong>示例: </strong></p>\n<pre><code class=\"lang-js\">feature: {\n    magicType: {\n        type: [&#39;line&#39;, &#39;bar&#39;, &#39;stack&#39;, &#39;tiled&#39;]\n    }\n}\n</code></pre>\n"
   },
diff --git a/en/documents/option-parts/option.toolbox.json b/en/documents/option-parts/option.toolbox.json
index 3393c40..2db60d7 100644
--- a/en/documents/option-parts/option.toolbox.json
+++ b/en/documents/option-parts/option.toolbox.json
@@ -921,6 +921,80 @@
   "feature.dataZoom.yAxisIndex": {
     "desc": "<p>Defines which <a href=\"#yAxis\">yAxis</a> should be controlled. By default, it controls all y axes. If it is set to be <code class=\"codespan\">false</code>, then no y axis is controlled. If it is set to be then it controls axis with axisIndex of <code class=\"codespan\">3</code>. If it is set to be <code class=\"codespan\">[0, 3]</code>, it controls the x-axes with axisIndex of <code class=\"codespan\">0</code> and <code class=\"codespan\">3</code>.</p>\n"
   },
+  "feature.dataZoom.brushStyle": {
+    "desc": "<p>Style of brush rectangle.</p>\n"
+  },
+  "feature.dataZoom.brushStyle.color": {
+    "desc": "<p> color. </p>\n<blockquote>\n<p>Color can be represented in RGB, for example <code class=\"codespan\">&#39;rgb(128, 128, 128)&#39;</code>. RGBA can be used when you need alpha channel, for example <code class=\"codespan\">&#39;rgba(128, 128, 128, 0.5)&#39;</code>. You may also use hexadecimal format, for example <code class=\"codespan\">&#39;#ccc&#39;</code>. Gradient color and texture are also supported besides single colors.</p>\n<pre><code class=\"lang-js\">// Linear gr [...]
+    "uiControl": {
+      "type": "color"
+    }
+  },
+  "feature.dataZoom.brushStyle.borderColor": {
+    "desc": "<p> border color, whose format is similar to that of <code class=\"codespan\">color</code>.</p>\n",
+    "uiControl": {
+      "type": "color"
+    }
+  },
+  "feature.dataZoom.brushStyle.borderWidth": {
+    "desc": "<p> border width. No border when it is set to be 0.</p>\n",
+    "uiControl": {
+      "type": "number",
+      "value": "0",
+      "min": "0",
+      "step": "0.5"
+    }
+  },
+  "feature.dataZoom.brushStyle.borderType": {
+    "desc": "<p>Border type, which can be <code class=\"codespan\">&#39;solid&#39;</code>, <code class=\"codespan\">&#39;dashed&#39;</code>, or <code class=\"codespan\">&#39;dotted&#39;</code>. <code class=\"codespan\">&#39;solid&#39;</code> by default.</p>\n",
+    "uiControl": {
+      "type": "enum",
+      "default": "solid",
+      "options": "solid,dashed,dotted"
+    }
+  },
+  "feature.dataZoom.brushStyle.shadowBlur": {
+    "desc": "<p>Size of shadow blur. This attribute should be used along with <code class=\"codespan\">shadowColor</code>,<code class=\"codespan\">shadowOffsetX</code>, <code class=\"codespan\">shadowOffsetY</code> to set shadow to component.</p>\n<p>For example:</p>\n<pre><code class=\"lang-js\">{\n    shadowColor: &#39;rgba(0, 0, 0, 0.5)&#39;,\n    shadowBlur: 10\n}\n</code></pre>\n",
+    "uiControl": {
+      "type": "number",
+      "default": "",
+      "min": "0",
+      "step": "0.5"
+    }
+  },
+  "feature.dataZoom.brushStyle.shadowColor": {
+    "desc": "<p>Shadow color. Support same format as <code class=\"codespan\">color</code>.</p>\n",
+    "uiControl": {
+      "type": "color",
+      "default": ""
+    }
+  },
+  "feature.dataZoom.brushStyle.shadowOffsetX": {
+    "desc": "<p>Offset distance on the horizontal direction of shadow.</p>\n",
+    "uiControl": {
+      "type": "number",
+      "default": "0",
+      "step": "0.5"
+    }
+  },
+  "feature.dataZoom.brushStyle.shadowOffsetY": {
+    "desc": "<p>Offset distance on the vertical direction of shadow.</p>\n",
+    "uiControl": {
+      "type": "number",
+      "default": "0",
+      "step": "0.5"
+    }
+  },
+  "feature.dataZoom.brushStyle.opacity": {
+    "desc": "<p>Opacity of the component. Supports value from 0 to 1, and the component will not be drawn when set to 0.</p>\n",
+    "uiControl": {
+      "type": "number",
+      "default": "1",
+      "min": "0",
+      "max": "1",
+      "step": "0.01"
+    }
+  },
   "feature.magicType": {
     "desc": "<p>Magic type switching.\n<strong>示例: </strong></p>\n<pre><code class=\"lang-js\">feature: {\n    magicType: {\n        type: [&#39;line&#39;, &#39;bar&#39;, &#39;stack&#39;, &#39;tiled&#39;]\n    }\n}\n</code></pre>\n"
   },
diff --git a/en/documents/option.json b/en/documents/option.json
index b8778c5..3c9c813 100644
--- a/en/documents/option.json
+++ b/en/documents/option.json
@@ -1 +1 @@
-{"$schema":"https://echarts.apache.org/doc/json-schem","option":{"type":"Object","properties":{"title":{"type":["Object"],"description":"<p>Title component, including main title and subtitle.</p>\n<p>In ECharts 2.x, a single instance of ECharts could contains one title component at most. However, in ECharts 3, there could be one or more than one title components. It is more useful when multiple diagrams in one instance all need titles.</p>\n<p><strong>Here are some instances of different [...]
\ No newline at end of file
+{"$schema":"https://echarts.apache.org/doc/json-schem","option":{"type":"Object","properties":{"title":{"type":["Object"],"description":"<p>Title component, including main title and subtitle.</p>\n<p>In ECharts 2.x, a single instance of ECharts could contains one title component at most. However, in ECharts 3, there could be one or more than one title components. It is more useful when multiple diagrams in one instance all need titles.</p>\n<p><strong>Here are some instances of different [...]
\ No newline at end of file
diff --git a/en/download-extension.html b/en/download-extension.html
index 61da81b..d21b2cd 100644
--- a/en/download-extension.html
+++ b/en/download-extension.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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>Download Extensions - 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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/download-map.html b/en/download-map.html
index 9bc504c..95680e6 100644
--- a/en/download-map.html
+++ b/en/download-map.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -8,7 +8,7 @@
 }
 </script><title>Download Maps - 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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
-</script><footer><div class="container"><div class="row"><div class="col-md-9"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflecti [...]
+</script><footer><div class="container"><div class="row"><div class="col-md-9"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflecti [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/download-theme.html b/en/download-theme.html
index 2ffcaa0..fbc8295 100644
--- a/en/download-theme.html
+++ b/en/download-theme.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -17,7 +17,7 @@ chart.setOption({
     ...
 });
 &lt;/script&gt;
-</pre></div></div></section><footer><div class="container"><div class="row"><div class="col-md-9"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not nec [...]
+</pre></div></div></section><footer><div class="container"><div class="row"><div class="col-md-9"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not nec [...]
 
 $('pre').addClass('prettyprint');
 prettyPrint();
diff --git a/en/download.html b/en/download.html
index d5bc921..20bcec9 100644
--- a/en/download.html
+++ b/en/download.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -16,7 +16,7 @@
     font-weight: normal;
 }
 */
-</style><nav class="navbar navbar-default navbar-fixed-top"><div class="container-fluid"><div class="navbar-header"><button type="button" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false" class="navbar-toggle collapsed"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="https://echarts.apache.org/en/index.html" class="navbar-brand"><img src="https://echarts.apa [...]
+</style><nav class="navbar navbar-default navbar-fixed-top"><div class="container-fluid"><div class="navbar-header"><button type="button" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false" class="navbar-toggle collapsed"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="https://echarts.apache.org/en/index.html" class="navbar-brand"><img src="https://echarts.apa [...]
 
 //- var list = [
 //-         {
diff --git a/en/faq.html b/en/faq.html
index d4e0325..b310718 100644
--- a/en/faq.html
+++ b/en/faq.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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,7 +9,7 @@
 </script><title>FAQ - 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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" alt="ie tip"></div></body><![endif]-->
 <!--[if (gt IE 8)|!(IE)]><body class="FAQ - Apache ECharts (incubating)"></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" tar [...]
    console.log(params);
-});</code></pre><p>Please refer to <a href="https://gallery.echartsjs.com/editor.html?c=xHyqn_rQ6g">this example</a>.</p><h3>How to make my custom map?</h3><p>The ECharts map is <a href="https://github.com/apache/incubator-echarts/blob/8eeb7e5abe207d0536c62ce1f4ddecc6adfdf85e/src/util/mapData/rawData/encode.js">additionally encoded</a> from original coordinates. You can use the <a href="https://github.com/giscafer/mapshaper-plus">mapshaper-plus tool</a> to upload a custom geojson file an [...]
+});</code></pre><p>Please refer to <a href="https://gallery.echartsjs.com/editor.html?c=xHyqn_rQ6g">this example</a>.</p><h3>How to make my custom map?</h3><p>The ECharts map is <a href="https://github.com/apache/incubator-echarts/blob/8eeb7e5abe207d0536c62ce1f4ddecc6adfdf85e/src/util/mapData/rawData/encode.js">additionally encoded</a> from original coordinates. You can use the <a href="https://github.com/giscafer/mapshaper-plus">mapshaper-plus tool</a> to upload a custom geojson file an [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/feature.html b/en/feature.html
index 620285a..df49e66 100644
--- a/en/feature.html
+++ b/en/feature.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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>Features - 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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/index.html b/en/index.html
index 3ecda78..715eb86 100644
--- a/en/index.html
+++ b/en/index.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -17,9 +17,9 @@
 
 </script><section id="feature-section"><div class="container"><div class="row features"><p>Apache ECharts (incubating)<sup>TM</sup> is an incubation project at <a target="_blank" href="https://www.apache.org/">The Apache Software Foundation</a> (ASF).</p></div><div class="row features"><div class="col-sm-4"><div class="feature-icon-panel"><svg width="36px" height="33px" viewbox="0 0 36 33" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class=" [...]
 <a class="github-button" href="https://github.com/apache/incubator-echarts" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star apache/incubator-echarts on GitHub">GitHub Stars</a></p></div></div><div id="feature-4" class="row feature-detail"><div class="col-sm-4 col"><h2>Brand-new v4.0</h2><p>Rendering ability for ten-million-level data</p><p>Supports both SVG and Canvas rendering</p><p>Seperates data and style configuring</p><p>Accessibility supports</p>< [...]
-</script></div></div></section><section id="publication"><div class="container"><div class="col-sm-8 col"><h2>ECharts: A Declarative Framework for Rapid Construction of Web-based Visualization</h2><p class="note"><i class="note-icon"><img classs="lazy" data-src="https://echarts.apache.org/en/images/note.svg?_v_=20200710_1" /></i> Please cite the following paper whenever you use ECharts in your R&D projects, products, research papers, technical reports, news reports, books, presentations, [...]
+</script></div></div></section><section id="publication"><div class="container"><div class="col-sm-8 col"><h2>ECharts: A Declarative Framework for Rapid Construction of Web-based Visualization</h2><p class="note"><i class="note-icon"><img classs="lazy" data-src="https://echarts.apache.org/en/images/note.svg?_v_=20200710_1" /></i> Please cite the following paper whenever you use ECharts in your R&D projects, products, research papers, technical reports, news reports, books, presentations, [...]
     elements_selector: ".lazy"
-};</script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@12.0.0/dist/lazyload.min.js"></script><script src="https://echarts.apache.org/en/js/index.js?_v_=1598523895644"></script><script async defer src="https://buttons.github.io/buttons.js"></script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
+};</script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@12.0.0/dist/lazyload.min.js"></script><script src="https://echarts.apache.org/en/js/index.js?_v_=1598903776431"></script><script async defer src="https://buttons.github.io/buttons.js"></script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/js/download.js b/en/js/download.js
index 6fc4cb6..f9486ab 100644
--- a/en/js/download.js
+++ b/en/js/download.js
@@ -1 +1 @@
-for(var param=[{publishedAt:"2020-05-25T00:00:00Z",prerelease:!1,name:"4.8.0"},{publishedAt:"2020-03-19T00:00:00Z",prerelease:!1,name:"4.7.0"},{publishedAt:"2019-12-30T00:00:00Z",prerelease:!1,name:"4.6.0"},{publishedAt:"2019-11-18T16:00:00Z",prerelease:!1,name:"4.5.0"},{publishedAt:"2019-10-15T01:12:00Z",prerelease:!1,name:"4.4.0"},{publishedAt:"2019-09-16T15:57:00Z",prerelease:!1,name:"4.3.0"},{publishedAt:"2019-03-21T10:27:59Z",prerelease:!1,name:"4.2.1"},{publishedAt:"2018-08-04T12:5 [...]
\ No newline at end of file
+for(var param=[{publishedAt:"2020-09-01T00:00:00Z",prerelease:!1,name:"4.9.0"},{publishedAt:"2020-05-25T00:00:00Z",prerelease:!1,name:"4.8.0"},{publishedAt:"2020-03-19T00:00:00Z",prerelease:!1,name:"4.7.0"},{publishedAt:"2019-12-30T00:00:00Z",prerelease:!1,name:"4.6.0"},{publishedAt:"2019-11-18T16:00:00Z",prerelease:!1,name:"4.5.0"},{publishedAt:"2019-10-15T01:12:00Z",prerelease:!1,name:"4.4.0"},{publishedAt:"2019-09-16T15:57:00Z",prerelease:!1,name:"4.3.0"},{publishedAt:"2019-03-21T10:2 [...]
\ No newline at end of file
diff --git a/en/maillist.html b/en/maillist.html
index c655944..40d28db 100644
--- a/en/maillist.html
+++ b/en/maillist.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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>Mailing List - 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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/option-gl.html b/en/option-gl.html
index 164af87..2ae1ad6 100644
--- a/en/option-gl.html
+++ b/en/option-gl.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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,8 +9,8 @@
 </script><title>Documentation - Apache ECharts(incubating)</title><style>html, body {
     /* position: sticky should not have overflow parents.*/
     overflow-x: hidden;
-}</style><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css"><link rel="stylesheet" href="https://echarts.apache.org/en/css/doc-bundle.css?_v_=1598523895644"><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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="https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css"><link rel="stylesheet" href="https://echarts.apache.org/en/css/doc-bundle.css?_v_=1598903776431"><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 </script><script type="text/javascript">window.globalArgsExtra = {
     baseUrl: 'documents/option-gl-parts',
     docType: 'option-gl',
@@ -19,7 +19,7 @@
 if (window.EC_WWW_CDN_PAY_ROOT) {
     window.globalArgsExtra.cdnRoot = window.EC_WWW_CDN_PAY_ROOT + '/en/' + window.globalArgsExtra.baseUrl
 }</script><script type="text/javascript">document.getElementById('nav-doc').className = 'active';
-window.globalArgsExtra.version = '1598523895644';
+window.globalArgsExtra.version = '1598903776431';
 echartsDoc.init('#ec-doc-main', window.globalArgsExtra);</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
diff --git a/en/option.html b/en/option.html
index a912378..3e4b7ec 100644
--- a/en/option.html
+++ b/en/option.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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,8 +9,8 @@
 </script><title>Documentation - Apache ECharts(incubating)</title><style>html, body {
     /* position: sticky should not have overflow parents.*/
     overflow-x: hidden;
-}</style><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css"><link rel="stylesheet" href="https://echarts.apache.org/en/css/doc-bundle.css?_v_=1598523895644"><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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="https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css"><link rel="stylesheet" href="https://echarts.apache.org/en/css/doc-bundle.css?_v_=1598903776431"><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 </script><script type="text/javascript">window.globalArgsExtra = {
     baseUrl: 'documents/option-parts',
     docType: 'option',
@@ -19,7 +19,7 @@
 if (window.EC_WWW_CDN_PAY_ROOT) {
     window.globalArgsExtra.cdnRoot = window.EC_WWW_CDN_PAY_ROOT + '/en/' + window.globalArgsExtra.baseUrl
 }</script><script type="text/javascript">document.getElementById('nav-doc').className = 'active';
-window.globalArgsExtra.version = '1598523895644';
+window.globalArgsExtra.version = '1598903776431';
 echartsDoc.init('#ec-doc-main', window.globalArgsExtra);</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
diff --git a/en/option3.html b/en/option3.html
index 2c3a0bd..fef3ab5 100644
--- a/en/option3.html
+++ b/en/option3.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="ECharts Configurations"></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 [...]
+<!--[if (gt IE 8)|!(IE)]><body class="ECharts Configurations"></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 [...]
 </script><footer><div class="container"><div class="row"><div class="col-md-9"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflecti [...]
 (function() {
 var hm = document.createElement("script");
diff --git a/en/resources.html b/en/resources.html
index e2188a8..29561a8 100644
--- a/en/resources.html
+++ b/en/resources.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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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>More Resources - 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="https://echarts.apache.org/zh/images/forie.png?_v_=20200710_1" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="More Resources"></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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class=" [...]
+<!--[if (gt IE 8)|!(IE)]><body class="More Resources"></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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class=" [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/security.html b/en/security.html
index 3a21bd7..c97634f 100644
--- a/en/security.html
+++ b/en/security.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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/zh/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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>Security - 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="https://echarts.apache.org/zh/images/forie.png?_v_=20200710_1" alt="ie tip"></div></body><![endif]-->
-<!--[if (gt IE 8)|!(IE)]><body class="Security"></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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close- [...]
+<!--[if (gt IE 8)|!(IE)]><body class="Security"></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 btn-main"><div>访问官网</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close- [...]
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/spreadsheet.html b/en/spreadsheet.html
index 81cae84..a9fc945 100644
--- a/en/spreadsheet.html
+++ b/en/spreadsheet.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -6,13 +6,13 @@
         + '@font-face {font-family:"noto-light";src:local("Microsoft Yahei");}';
     document.head.insertBefore(el, document.getElementById('font-hack'));
 }
-</script><title>Spreadsheet Tool - Apache ECharts (incubating)</title><link rel="stylesheet" type="text/css" href="https://echarts.apache.org/en/vendors/handsontable/0.26.1/dist/handsontable.full.min.css?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://echarts.apache.org/en/css/spreadsheet.css?_v_=1598523895644"><script src="vendors/esl.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[i [...]
-<!--[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 [...]
+</script><title>Spreadsheet Tool - Apache ECharts (incubating)</title><link rel="stylesheet" type="text/css" href="https://echarts.apache.org/en/vendors/handsontable/0.26.1/dist/handsontable.full.min.css?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://echarts.apache.org/en/css/spreadsheet.css?_v_=1598903776431"><script src="vendors/esl.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[i [...]
+<!--[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 [...]
 
 var vendorPath = '../vendors';
 
 define('globalArgs', extend({
-    version: '1598523895644',
+    version: '1598903776431',
     basePath: './'
 }, window.globalArgsExtra || {}));
 
@@ -31,7 +31,7 @@ require.config({
         numeral: vendorPath + '/numeral/1.4.7/numeral.min',
         immutable: vendorPath + '/immutable/3.7.4/dist/immutable'
     },
-    urlArgs: '_v_=1598523895644'
+    urlArgs: '_v_=1598903776431'
 });
 
 require(['spreadsheet/spreadsheet'], function (spreadsheet) {
diff --git a/en/theme-builder.html b/en/theme-builder.html
index e3bbff3..2e3ff3c 100644
--- a/en/theme-builder.html
+++ b/en/theme-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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) {
     var el = document.createElement('style');
     el.innerHTML = ''
@@ -526,7 +526,7 @@
 <script src="//cdn.jsdelivr.net/npm/file-saver@2.0.2/dist/FileSaver.min.js"></script>
 
 <script src="./theme-builder/app.min.js"></script>
-</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script><script type="text/javascript" src="https://echarts.apache.org/en/js/common.js?_v_=1598523895644"></script><script type="text/javascript">document.getElementById('nav-resources').className = 'active';</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
+</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script><script type="text/javascript" src="https://echarts.apache.org/en/js/common.js?_v_=1598903776431"></script><script type="text/javascript">document.getElementById('nav-resources').className = 'active';</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
 
diff --git a/en/tutorial.html b/en/tutorial.html
index f17a2d1..93e3a35 100644
--- a/en/tutorial.html
+++ b/en/tutorial.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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
+<!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="https://echarts.apache.org/en/images/favicon.png?_v_=20200710_1"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/boot [...]
 </script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pace-progressbar@1.0.2/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,8 +9,8 @@
 </script><title>Documentation - Apache ECharts(incubating)</title><style>html, body {
     /* position: sticky should not have overflow parents.*/
     overflow-x: hidden;
-}</style><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css"><link rel="stylesheet" href="https://echarts.apache.org/en/css/doc-bundle.css?_v_=1598523895644"><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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="https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css"><link rel="stylesheet" href="https://echarts.apache.org/en/css/doc-bundle.css?_v_=1598903776431"><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="https://echarts.apache.org/en/images/forie.png?_v_=20200710_1" 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 [...]
 </script><script type="text/javascript">window.globalArgsExtra = {
     baseUrl: 'documents/tutorial-parts',
     docType: 'tutorial',
@@ -19,7 +19,7 @@
 if (window.EC_WWW_CDN_PAY_ROOT) {
     window.globalArgsExtra.cdnRoot = window.EC_WWW_CDN_PAY_ROOT + '/en/' + window.globalArgsExtra.baseUrl
 }</script><script type="text/javascript">document.getElementById('nav-doc').className = 'active';
-window.globalArgsExtra.version = '1598523895644';
+window.globalArgsExtra.version = '1598903776431';
 echartsDoc.init('#ec-doc-main', window.globalArgsExtra);</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || [];
 (function() {
 var hm = document.createElement("script");
diff --git a/examples/data/thumb-dark/calendar-charts.jpg b/examples/data/thumb-dark/calendar-charts.jpg
index 65dae14..06f93cf 100644
Binary files a/examples/data/thumb-dark/calendar-charts.jpg and b/examples/data/thumb-dark/calendar-charts.jpg differ
diff --git a/examples/data/thumb-dark/calendar-effectscatter.jpg b/examples/data/thumb-dark/calendar-effectscatter.jpg
index b25031b..db2c668 100644
Binary files a/examples/data/thumb-dark/calendar-effectscatter.jpg and b/examples/data/thumb-dark/calendar-effectscatter.jpg differ
diff --git a/examples/data/thumb-dark/custom-profile.jpg b/examples/data/thumb-dark/custom-profile.jpg
index b30d277..1281fd4 100644
Binary files a/examples/data/thumb-dark/custom-profile.jpg and b/examples/data/thumb-dark/custom-profile.jpg differ
diff --git a/examples/data/thumb-dark/dynamic-data.jpg b/examples/data/thumb-dark/dynamic-data.jpg
index da05a42..6be0494 100644
Binary files a/examples/data/thumb-dark/dynamic-data.jpg and b/examples/data/thumb-dark/dynamic-data.jpg differ
diff --git a/examples/data/thumb-dark/effectScatter-bmap.jpg b/examples/data/thumb-dark/effectScatter-bmap.jpg
index ae8df14..6013849 100644
Binary files a/examples/data/thumb-dark/effectScatter-bmap.jpg and b/examples/data/thumb-dark/effectScatter-bmap.jpg differ
diff --git a/examples/data/thumb-dark/effectScatter-map.jpg b/examples/data/thumb-dark/effectScatter-map.jpg
index ecbc29c..8fb3687 100644
Binary files a/examples/data/thumb-dark/effectScatter-map.jpg and b/examples/data/thumb-dark/effectScatter-map.jpg differ
diff --git a/examples/data/thumb-dark/geo-lines.jpg b/examples/data/thumb-dark/geo-lines.jpg
index 058e7e6..5d067be 100644
Binary files a/examples/data/thumb-dark/geo-lines.jpg and b/examples/data/thumb-dark/geo-lines.jpg differ
diff --git a/examples/data/thumb-dark/graph-force.jpg b/examples/data/thumb-dark/graph-force.jpg
index f939464..1bede63 100644
Binary files a/examples/data/thumb-dark/graph-force.jpg and b/examples/data/thumb-dark/graph-force.jpg differ
diff --git a/examples/data/thumb-dark/graph-life-expectancy.jpg b/examples/data/thumb-dark/graph-life-expectancy.jpg
index ecfd7c8..2bb2187 100644
Binary files a/examples/data/thumb-dark/graph-life-expectancy.jpg and b/examples/data/thumb-dark/graph-life-expectancy.jpg differ
diff --git a/examples/data/thumb-dark/graph-webkit-dep.jpg b/examples/data/thumb-dark/graph-webkit-dep.jpg
index 68795d4..6317937 100644
Binary files a/examples/data/thumb-dark/graph-webkit-dep.jpg and b/examples/data/thumb-dark/graph-webkit-dep.jpg differ
diff --git a/examples/data/thumb-dark/graph.jpg b/examples/data/thumb-dark/graph.jpg
index e812c6b..025ce0d 100644
Binary files a/examples/data/thumb-dark/graph.jpg and b/examples/data/thumb-dark/graph.jpg differ
diff --git a/examples/data/thumb-dark/map-polygon.jpg b/examples/data/thumb-dark/map-polygon.jpg
index e884168..a6ae807 100644
Binary files a/examples/data/thumb-dark/map-polygon.jpg and b/examples/data/thumb-dark/map-polygon.jpg differ
diff --git a/examples/data/thumb-dark/mix-timeline-finance.jpg b/examples/data/thumb-dark/mix-timeline-finance.jpg
index 4800605..ffd0bc0 100644
Binary files a/examples/data/thumb-dark/mix-timeline-finance.jpg and b/examples/data/thumb-dark/mix-timeline-finance.jpg differ
diff --git a/examples/data/thumb-dark/pictorialBar-dotted.jpg b/examples/data/thumb-dark/pictorialBar-dotted.jpg
index 0477bbf..1a1d9e4 100644
Binary files a/examples/data/thumb-dark/pictorialBar-dotted.jpg and b/examples/data/thumb-dark/pictorialBar-dotted.jpg differ
diff --git a/examples/data/thumb-dark/scatter-clustering-process.jpg b/examples/data/thumb-dark/scatter-clustering-process.jpg
index 1b0202f..8b0879e 100644
Binary files a/examples/data/thumb-dark/scatter-clustering-process.jpg and b/examples/data/thumb-dark/scatter-clustering-process.jpg differ
diff --git a/examples/data/thumb-dark/scatter-effect.jpg b/examples/data/thumb-dark/scatter-effect.jpg
index 9a26876..bcfd0c7 100644
Binary files a/examples/data/thumb-dark/scatter-effect.jpg and b/examples/data/thumb-dark/scatter-effect.jpg differ
diff --git a/examples/data/thumb-dark/scatter-life-expectancy-timeline.jpg b/examples/data/thumb-dark/scatter-life-expectancy-timeline.jpg
index 846906e..78a5925 100644
Binary files a/examples/data/thumb-dark/scatter-life-expectancy-timeline.jpg and b/examples/data/thumb-dark/scatter-life-expectancy-timeline.jpg differ
diff --git a/examples/data/thumb-dark/scatter-nebula.jpg b/examples/data/thumb-dark/scatter-nebula.jpg
index dbe01ef..dec43bd 100644
Binary files a/examples/data/thumb-dark/scatter-nebula.jpg and b/examples/data/thumb-dark/scatter-nebula.jpg differ
diff --git a/examples/data/thumb-dark/scatter-nutrients-matrix.jpg b/examples/data/thumb-dark/scatter-nutrients-matrix.jpg
index de90af0..88ff8aa 100644
Binary files a/examples/data/thumb-dark/scatter-nutrients-matrix.jpg and b/examples/data/thumb-dark/scatter-nutrients-matrix.jpg differ
diff --git a/examples/data/thumb-dark/scatter-nutrients.jpg b/examples/data/thumb-dark/scatter-nutrients.jpg
index 0495f7c..143ab10 100644
Binary files a/examples/data/thumb-dark/scatter-nutrients.jpg and b/examples/data/thumb-dark/scatter-nutrients.jpg differ
diff --git a/examples/data/thumb-dark/scatter-weibo.jpg b/examples/data/thumb-dark/scatter-weibo.jpg
index 144403d..8f2107f 100644
Binary files a/examples/data/thumb-dark/scatter-weibo.jpg and b/examples/data/thumb-dark/scatter-weibo.jpg differ
diff --git a/examples/data/thumb-light/calendar-charts.jpg b/examples/data/thumb-light/calendar-charts.jpg
index c1edbea..27a6c19 100644
Binary files a/examples/data/thumb-light/calendar-charts.jpg and b/examples/data/thumb-light/calendar-charts.jpg differ
diff --git a/examples/data/thumb-light/calendar-effectscatter.jpg b/examples/data/thumb-light/calendar-effectscatter.jpg
index cd5b7c0..c6a88f1 100644
Binary files a/examples/data/thumb-light/calendar-effectscatter.jpg and b/examples/data/thumb-light/calendar-effectscatter.jpg differ
diff --git a/examples/data/thumb-light/confidence-band.jpg b/examples/data/thumb-light/confidence-band.jpg
index d6d05de..af74e1d 100644
Binary files a/examples/data/thumb-light/confidence-band.jpg and b/examples/data/thumb-light/confidence-band.jpg differ
diff --git a/examples/data/thumb-light/custom-profile.jpg b/examples/data/thumb-light/custom-profile.jpg
index 1f5608f..005dd7f 100644
Binary files a/examples/data/thumb-light/custom-profile.jpg and b/examples/data/thumb-light/custom-profile.jpg differ
diff --git a/examples/data/thumb-light/dynamic-data.jpg b/examples/data/thumb-light/dynamic-data.jpg
index 55cee84..69d857c 100644
Binary files a/examples/data/thumb-light/dynamic-data.jpg and b/examples/data/thumb-light/dynamic-data.jpg differ
diff --git a/examples/data/thumb-light/effectScatter-bmap.jpg b/examples/data/thumb-light/effectScatter-bmap.jpg
index f2bd21a..5b011b1 100644
Binary files a/examples/data/thumb-light/effectScatter-bmap.jpg and b/examples/data/thumb-light/effectScatter-bmap.jpg differ
diff --git a/examples/data/thumb-light/effectScatter-map.jpg b/examples/data/thumb-light/effectScatter-map.jpg
index de3c5f7..8c89f81 100644
Binary files a/examples/data/thumb-light/effectScatter-map.jpg and b/examples/data/thumb-light/effectScatter-map.jpg differ
diff --git a/examples/data/thumb-light/geo-lines.jpg b/examples/data/thumb-light/geo-lines.jpg
index 6d99268..bfa1057 100644
Binary files a/examples/data/thumb-light/geo-lines.jpg and b/examples/data/thumb-light/geo-lines.jpg differ
diff --git a/examples/data/thumb-light/graph-force.jpg b/examples/data/thumb-light/graph-force.jpg
index beda106..059bc72 100644
Binary files a/examples/data/thumb-light/graph-force.jpg and b/examples/data/thumb-light/graph-force.jpg differ
diff --git a/examples/data/thumb-light/graph-life-expectancy.jpg b/examples/data/thumb-light/graph-life-expectancy.jpg
index 2a1345f..31e3f95 100644
Binary files a/examples/data/thumb-light/graph-life-expectancy.jpg and b/examples/data/thumb-light/graph-life-expectancy.jpg differ
diff --git a/examples/data/thumb-light/graph-webkit-dep.jpg b/examples/data/thumb-light/graph-webkit-dep.jpg
index 7531840..7dd9ae4 100644
Binary files a/examples/data/thumb-light/graph-webkit-dep.jpg and b/examples/data/thumb-light/graph-webkit-dep.jpg differ
diff --git a/examples/data/thumb-light/graph.jpg b/examples/data/thumb-light/graph.jpg
index 9b21664..f36ed74 100644
Binary files a/examples/data/thumb-light/graph.jpg and b/examples/data/thumb-light/graph.jpg differ
diff --git a/examples/data/thumb-light/heatmap-bmap.jpg b/examples/data/thumb-light/heatmap-bmap.jpg
index 2d6ca9d..ad6a2d1 100644
Binary files a/examples/data/thumb-light/heatmap-bmap.jpg and b/examples/data/thumb-light/heatmap-bmap.jpg differ
diff --git a/examples/data/thumb-light/lines-bmap-bus.jpg b/examples/data/thumb-light/lines-bmap-bus.jpg
index dec84ee..ec9cd90 100644
Binary files a/examples/data/thumb-light/lines-bmap-bus.jpg and b/examples/data/thumb-light/lines-bmap-bus.jpg differ
diff --git a/examples/data/thumb-light/lines-bmap.jpg b/examples/data/thumb-light/lines-bmap.jpg
index 93bfa25..7d60aa9 100644
Binary files a/examples/data/thumb-light/lines-bmap.jpg and b/examples/data/thumb-light/lines-bmap.jpg differ
diff --git a/examples/data/thumb-light/map-bin.jpg b/examples/data/thumb-light/map-bin.jpg
index ec71ca2..ff07771 100644
Binary files a/examples/data/thumb-light/map-bin.jpg and b/examples/data/thumb-light/map-bin.jpg differ
diff --git a/examples/data/thumb-light/map-polygon.jpg b/examples/data/thumb-light/map-polygon.jpg
index f3131da..1f48514 100644
Binary files a/examples/data/thumb-light/map-polygon.jpg and b/examples/data/thumb-light/map-polygon.jpg differ
diff --git a/examples/data/thumb-light/mix-timeline-finance.jpg b/examples/data/thumb-light/mix-timeline-finance.jpg
index 691482a..d88f8d0 100644
Binary files a/examples/data/thumb-light/mix-timeline-finance.jpg and b/examples/data/thumb-light/mix-timeline-finance.jpg differ
diff --git a/examples/data/thumb-light/pictorialBar-dotted.jpg b/examples/data/thumb-light/pictorialBar-dotted.jpg
index 72d49be..df9e234 100644
Binary files a/examples/data/thumb-light/pictorialBar-dotted.jpg and b/examples/data/thumb-light/pictorialBar-dotted.jpg differ
diff --git a/examples/data/thumb-light/scatter-clustering-process.jpg b/examples/data/thumb-light/scatter-clustering-process.jpg
index 689ee94..cb06c79 100644
Binary files a/examples/data/thumb-light/scatter-clustering-process.jpg and b/examples/data/thumb-light/scatter-clustering-process.jpg differ
diff --git a/examples/data/thumb-light/scatter-effect.jpg b/examples/data/thumb-light/scatter-effect.jpg
index b06e084..539c27f 100644
Binary files a/examples/data/thumb-light/scatter-effect.jpg and b/examples/data/thumb-light/scatter-effect.jpg differ
diff --git a/examples/data/thumb-light/scatter-life-expectancy-timeline.jpg b/examples/data/thumb-light/scatter-life-expectancy-timeline.jpg
index b2e45df..2a6255f 100644
Binary files a/examples/data/thumb-light/scatter-life-expectancy-timeline.jpg and b/examples/data/thumb-light/scatter-life-expectancy-timeline.jpg differ
diff --git a/examples/data/thumb-light/scatter-nebula.jpg b/examples/data/thumb-light/scatter-nebula.jpg
index ea0d575..4269c16 100644
Binary files a/examples/data/thumb-light/scatter-nebula.jpg and b/examples/data/thumb-light/scatter-nebula.jpg differ
diff --git a/examples/data/thumb-light/scatter-nutrients-matrix.jpg b/examples/data/thumb-light/scatter-nutrients-matrix.jpg
index a8d679a..0e3ec49 100644
Binary files a/examples/data/thumb-light/scatter-nutrients-matrix.jpg and b/examples/data/thumb-light/scatter-nutrients-matrix.jpg differ
diff --git a/examples/data/thumb-light/scatter-nutrients.jpg b/examples/data/thumb-light/scatter-nutrients.jpg
index 66d74e7..3f5deed 100644
Binary files a/examples/data/thumb-light/scatter-nutrients.jpg and b/examples/data/thumb-light/scatter-nutrients.jpg differ
diff --git a/examples/data/thumb-light/scatter-weibo.jpg b/examples/data/thumb-light/scatter-weibo.jpg
index 207af4a..8f2107f 100644
Binary files a/examples/data/thumb-light/scatter-weibo.jpg and b/examples/data/thumb-light/scatter-weibo.jpg differ
diff --git a/examples/data/thumb/calendar-charts.jpg b/examples/data/thumb/calendar-charts.jpg
index a415392..b2e0d2e 100644
Binary files a/examples/data/thumb/calendar-charts.jpg and b/examples/data/thumb/calendar-charts.jpg differ
diff --git a/examples/data/thumb/calendar-effectscatter.jpg b/examples/data/thumb/calendar-effectscatter.jpg
index 956ad2b..e0d1bb1 100644
Binary files a/examples/data/thumb/calendar-effectscatter.jpg and b/examples/data/thumb/calendar-effectscatter.jpg differ
diff --git a/examples/data/thumb/custom-profile.jpg b/examples/data/thumb/custom-profile.jpg
index 0b4194a..66794c0 100644
Binary files a/examples/data/thumb/custom-profile.jpg and b/examples/data/thumb/custom-profile.jpg differ
diff --git a/examples/data/thumb/dynamic-data.jpg b/examples/data/thumb/dynamic-data.jpg
index a0bd68c..e50e740 100644
Binary files a/examples/data/thumb/dynamic-data.jpg and b/examples/data/thumb/dynamic-data.jpg differ
diff --git a/examples/data/thumb/effectScatter-bmap.jpg b/examples/data/thumb/effectScatter-bmap.jpg
index c8ed7b1..ab93866 100644
Binary files a/examples/data/thumb/effectScatter-bmap.jpg and b/examples/data/thumb/effectScatter-bmap.jpg differ
diff --git a/examples/data/thumb/effectScatter-map.jpg b/examples/data/thumb/effectScatter-map.jpg
index b7a9498..1759d38 100644
Binary files a/examples/data/thumb/effectScatter-map.jpg and b/examples/data/thumb/effectScatter-map.jpg differ
diff --git a/examples/data/thumb/geo-lines.jpg b/examples/data/thumb/geo-lines.jpg
index 8c4a8e1..595d253 100644
Binary files a/examples/data/thumb/geo-lines.jpg and b/examples/data/thumb/geo-lines.jpg differ
diff --git a/examples/data/thumb/graph-force.jpg b/examples/data/thumb/graph-force.jpg
index 5cb352f..338c048 100644
Binary files a/examples/data/thumb/graph-force.jpg and b/examples/data/thumb/graph-force.jpg differ
diff --git a/examples/data/thumb/graph-life-expectancy.jpg b/examples/data/thumb/graph-life-expectancy.jpg
index 01a3759..e0d427d 100644
Binary files a/examples/data/thumb/graph-life-expectancy.jpg and b/examples/data/thumb/graph-life-expectancy.jpg differ
diff --git a/examples/data/thumb/graph-webkit-dep.jpg b/examples/data/thumb/graph-webkit-dep.jpg
index 1c100ab..ec3367f 100644
Binary files a/examples/data/thumb/graph-webkit-dep.jpg and b/examples/data/thumb/graph-webkit-dep.jpg differ
diff --git a/examples/data/thumb/heatmap-bmap.jpg b/examples/data/thumb/heatmap-bmap.jpg
index 2d6ca9d..ad6a2d1 100644
... 12751 lines suppressed ...


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