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 2019/12/31 21:18:53 UTC

[incubator-echarts-website] branch asf-site updated: update to 4.6.0 and new doc website.

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 cffaec7  update to 4.6.0 and new doc website.
cffaec7 is described below

commit cffaec7f6d94f44b9e58ebd3a34798cdbcc2fa14
Author: 100pah <su...@gmail.com>
AuthorDate: Wed Jan 1 05:10:14 2020 +0800

    update to 4.6.0 and new doc website.
---
 builder/echarts.html                               |     2 +-
 .../src/echarts/action/createDataSelectAction.js   |     3 +-
 builder/src/echarts/chart/bar.js                   |     5 +-
 builder/src/echarts/chart/bar/BarSeries.js         |     8 +
 builder/src/echarts/chart/bar/BarView.js           |   190 +-
 builder/src/echarts/chart/bar/BaseBarSeries.js     |     6 +-
 .../echarts/chart/candlestick/CandlestickSeries.js |     1 +
 .../echarts/chart/candlestick/CandlestickView.js   |    40 +-
 .../echarts/chart/candlestick/candlestickLayout.js |     4 +-
 .../src/echarts/chart/chord/chordCircularLayout.js |     6 -
 builder/src/echarts/chart/custom.js                |    82 +-
 .../chart/effectScatter/EffectScatterSeries.js     |     4 +-
 builder/src/echarts/chart/funnel/FunnelSeries.js   |    14 +-
 builder/src/echarts/chart/funnel/FunnelView.js     |    21 +-
 builder/src/echarts/chart/funnel/funnelLayout.js   |    54 +-
 builder/src/echarts/chart/gauge/GaugeSeries.js     |     8 -
 builder/src/echarts/chart/gauge/GaugeView.js       |     3 +-
 builder/src/echarts/chart/graph.js                 |     2 +-
 builder/src/echarts/chart/graph/GraphSeries.js     |    14 +-
 builder/src/echarts/chart/graph/GraphView.js       |    90 +-
 builder/src/echarts/chart/graph/adjustEdge.js      |    12 +-
 builder/src/echarts/chart/graph/categoryVisual.js  |    17 +-
 builder/src/echarts/chart/graph/circularLayout.js  |     2 +-
 .../echarts/chart/graph/circularLayoutHelper.js    |    87 +-
 builder/src/echarts/chart/graph/forceHelper.js     |    10 +-
 builder/src/echarts/chart/graph/forceLayout.js     |     9 +-
 builder/src/echarts/chart/graph/graphHelper.js     |    42 +
 builder/src/echarts/chart/heatmap/HeatmapLayer.js  |     8 -
 builder/src/echarts/chart/heatmap/HeatmapView.js   |     8 +-
 builder/src/echarts/chart/helper/EffectSymbol.js   |     9 +-
 .../src/echarts/chart/helper/LargeSymbolDraw.js    |    27 +-
 builder/src/echarts/chart/helper/Line.js           |    15 +-
 builder/src/echarts/chart/helper/LinePath.js       |    13 +-
 builder/src/echarts/chart/helper/Symbol.js         |    64 +-
 .../chart/helper/createClipPathFromCoordSys.js     |    96 +
 .../echarts/chart/helper/createListFromArray.js    |    19 +-
 .../src/echarts/chart/helper/whiskerBoxCommon.js   |    35 +-
 builder/src/echarts/chart/line/LineSeries.js       |     6 +-
 builder/src/echarts/chart/line/LineView.js         |   165 +-
 builder/src/echarts/chart/lines/LinesSeries.js     |     3 +
 builder/src/echarts/chart/lines/LinesView.js       |     9 +
 builder/src/echarts/chart/map/MapSeries.js         |     6 +-
 builder/src/echarts/chart/pie/PieSeries.js         |    36 +-
 builder/src/echarts/chart/pie/PieView.js           |   148 +-
 builder/src/echarts/chart/pie/labelLayout.js       |   135 +-
 builder/src/echarts/chart/pie/pieLayout.js         |    26 +-
 builder/src/echarts/chart/radar/RadarSeries.js     |     5 +-
 builder/src/echarts/chart/radar/RadarView.js       |    16 +-
 builder/src/echarts/chart/radar/radarLayout.js     |    37 +-
 builder/src/echarts/chart/sankey/SankeySeries.js   |    55 +-
 builder/src/echarts/chart/sankey/SankeyView.js     |    51 +-
 builder/src/echarts/chart/sankey/sankeyAction.js   |     7 +-
 builder/src/echarts/chart/sankey/sankeyLayout.js   |   318 +-
 builder/src/echarts/chart/sankey/sankeyVisual.js   |    15 +-
 builder/src/echarts/chart/scatter/ScatterSeries.js |    11 +-
 builder/src/echarts/chart/scatter/ScatterView.js   |    17 +-
 .../src/echarts/chart/sunburst/SunburstPiece.js    |     2 +-
 .../src/echarts/chart/sunburst/sunburstLayout.js   |    18 +-
 .../echarts/chart/themeRiver/ThemeRiverSeries.js   |    13 +-
 .../src/echarts/chart/themeRiver/ThemeRiverView.js |     5 -
 .../echarts/chart/themeRiver/themeRiverLayout.js   |     5 -
 .../echarts/chart/themeRiver/themeRiverVisual.js   |     5 -
 builder/src/echarts/chart/tree/TreeSeries.js       |    23 +-
 builder/src/echarts/chart/tree/TreeView.js         |    29 +-
 builder/src/echarts/chart/tree/treeAction.js       |     5 -
 builder/src/echarts/chart/treemap/TreemapSeries.js |     2 +-
 .../src/echarts/component/axis/AngleAxisView.js    |   131 +-
 builder/src/echarts/component/axis/AxisBuilder.js  |   132 +-
 .../echarts/component/axis/CartesianAxisView.js    |    71 +-
 .../src/echarts/component/axis/RadiusAxisView.js   |    40 +-
 .../src/echarts/component/axis/SingleAxisView.js   |     5 +-
 .../component/axisPointer/BaseAxisPointer.js       |     2 +-
 .../component/axisPointer/CartesianAxisPointer.js  |    12 +-
 .../component/axisPointer/SingleAxisPointer.js     |    12 +-
 .../echarts/component/axisPointer/viewHelper.js    |     3 +
 builder/src/echarts/component/brush/BrushView.js   |     6 +
 builder/src/echarts/component/brush/brushAction.js |     5 +
 builder/src/echarts/component/brush/selector.js    |    50 +-
 builder/src/echarts/component/calendar.js          |     5 -
 builder/src/echarts/component/dataZoom.js          |    16 +-
 .../src/echarts/component/dataZoom/AxisProxy.js    |   100 +-
 .../echarts/component/dataZoom/DataZoomModel.js    |   117 +-
 .../echarts/component/dataZoom/InsideZoomView.js   |     2 +-
 .../echarts/component/dataZoom/SliderZoomView.js   |    19 +-
 .../component/dataZoom/dataZoomProcessor.js        |     4 +-
 builder/src/echarts/component/dataZoomInside.js    |     4 -
 builder/src/echarts/component/dataZoomSelect.js    |     3 +-
 builder/src/echarts/component/dataZoomSlider.js    |    25 +
 builder/src/echarts/component/graphic.js           |    55 +-
 .../echarts/component/helper/BrushController.js    |    68 +-
 builder/src/echarts/component/helper/MapDraw.js    |    57 +-
 builder/src/echarts/component/helper/sliderMove.js |    16 +-
 builder/src/echarts/component/legend.js            |     2 +-
 .../src/echarts/component/legend/LegendModel.js    |   107 +-
 builder/src/echarts/component/legend/LegendView.js |   183 +-
 .../component/legend/ScrollableLegendModel.js      |     9 -
 .../component/legend/ScrollableLegendView.js       |    71 +-
 .../src/echarts/component/legend/legendAction.js   |     8 +-
 .../src/echarts/component/marker/MarkLineView.js   |     9 +-
 .../src/echarts/component/marker/MarkPointView.js  |    22 +-
 .../src/echarts/component/marker/MarkerModel.js    |    16 +-
 builder/src/echarts/component/title.js             |    24 +-
 .../src/echarts/component/toolbox/ToolboxModel.js  |     9 +-
 .../src/echarts/component/toolbox/ToolboxView.js   |    45 +-
 .../echarts/component/toolbox/feature/DataView.js  |    17 +-
 .../echarts/component/toolbox/feature/DataZoom.js  |     3 +
 .../echarts/component/toolbox/feature/MagicType.js |    33 +-
 .../component/toolbox/feature/SaveAsImage.js       |    12 +-
 .../echarts/component/tooltip/TooltipContent.js    |    17 +-
 .../component/tooltip/TooltipContentManager.js     |   103 +
 .../component/tooltip/TooltipRichContent.js        |    11 +-
 .../src/echarts/component/tooltip/TooltipView.js   |     2 +-
 .../echarts/component/visualMap/ContinuousView.js  |     6 +-
 .../echarts/component/visualMap/PiecewiseModel.js  |     2 +-
 .../echarts/component/visualMap/PiecewiseView.js   |     2 +-
 builder/src/echarts/component/visualMap/helper.js  |    10 +-
 builder/src/echarts/coord/Axis.js                  |    57 +-
 builder/src/echarts/coord/axisDefault.js           |    23 +-
 builder/src/echarts/coord/axisTickLabelBuilder.js  |    12 +-
 builder/src/echarts/coord/cartesian/Cartesian2D.js |    17 +
 builder/src/echarts/coord/cartesian/Grid.js        |    14 +-
 builder/src/echarts/coord/geo/GeoModel.js          |     2 +-
 builder/src/echarts/coord/geo/geoJSONLoader.js     |     2 +-
 builder/src/echarts/coord/polar/Polar.js           |    33 +
 builder/src/echarts/coord/polar/polarCreator.js    |    13 +-
 builder/src/echarts/coord/radar/Radar.js           |     5 +-
 builder/src/echarts/coord/radar/RadarModel.js      |     5 +-
 builder/src/echarts/coord/single/AxisModel.js      |     4 +-
 builder/src/echarts/data/DataDiffer.js             |     6 +-
 builder/src/echarts/data/DataDimensionInfo.js      |   135 +
 builder/src/echarts/data/Graph.js                  |     9 +-
 builder/src/echarts/data/List.js                   |    98 +-
 builder/src/echarts/data/Tree.js                   |     3 +-
 .../src/echarts/data/helper/completeDimensions.js  |    77 +-
 .../src/echarts/data/helper/createDimensions.js    |     2 +
 builder/src/echarts/data/helper/dimensionHelper.js |    40 +-
 builder/src/echarts/data/helper/sourceHelper.js    |   324 +-
 builder/src/echarts/echarts.js                     |   142 +-
 builder/src/echarts/export.js                      |     2 +-
 builder/src/echarts/helper.js                      |     1 -
 builder/src/echarts/lang.js                        |    10 +
 builder/src/echarts/langEN.js                      |    42 +
 builder/src/echarts/langES.js                      |    67 +
 builder/src/echarts/langFI.js                      |    10 +
 builder/src/echarts/langTH.js                      |    10 +
 builder/src/echarts/layout/barGrid.js              |   184 +-
 builder/src/echarts/layout/barPolar.js             |    21 +-
 builder/src/echarts/model/Global.js                |     8 +-
 builder/src/echarts/model/OptionManager.js         |     2 +-
 builder/src/echarts/model/Series.js                |    11 +-
 builder/src/echarts/model/mixin/dataFormat.js      |     9 +-
 builder/src/echarts/model/mixin/lineStyle.js       |    14 +-
 builder/src/echarts/model/referHelper.js           |    50 +-
 builder/src/echarts/preprocessor/backwardCompat.js |    12 +-
 builder/src/echarts/processor/dataStack.js         |     2 +-
 builder/src/echarts/scale/Interval.js              |    89 +-
 builder/src/echarts/scale/Log.js                   |    11 +-
 builder/src/echarts/scale/helper.js                |    40 -
 builder/src/echarts/theme/dark.js                  |     3 +
 builder/src/echarts/util/KDTree.js                 |     7 -
 builder/src/echarts/util/graphic.js                |   500 +-
 builder/src/echarts/util/number.js                 |    37 +-
 builder/src/echarts/util/quickSelect.js            |     3 -
 builder/src/echarts/util/shape/sausage.js          |    68 +
 builder/src/echarts/util/symbol.js                 |    20 +-
 builder/src/echarts/view/Chart.js                  |    28 +-
 builder/src/echarts/visual/LegendVisualProvider.js |    54 +
 builder/src/echarts/visual/dataColor.js            |    22 +-
 builder/src/echarts/visual/seriesColor.js          |    29 +-
 builder/src/echarts/visual/symbol.js               |    28 +-
 builder/src/zrender/Handler.js                     |   120 +-
 builder/src/zrender/Layer.js                       |     6 +-
 builder/src/zrender/Painter.js                     |    34 +-
 builder/src/zrender/config.js                      |     7 +-
 builder/src/zrender/contain/text.js                |    51 +-
 builder/src/zrender/core/PathProxy.js              |    19 +-
 builder/src/zrender/core/env.js                    |    12 +-
 builder/src/zrender/core/event.js                  |   194 +-
 builder/src/zrender/core/fourPointsTransform.js    |    90 +
 builder/src/zrender/core/log.js                    |    16 +-
 builder/src/zrender/core/matrix.js                 |     2 +
 builder/src/zrender/core/timsort.js                |     4 +-
 builder/src/zrender/core/util.js                   |     8 +-
 builder/src/zrender/core/vector.js                 |     1 +
 builder/src/zrender/dom/HandlerProxy.js            |   495 +-
 builder/src/zrender/graphic/CompoundPath.js        |     2 +-
 builder/src/zrender/graphic/Displayable.js         |    53 +-
 builder/src/zrender/graphic/Path.js                |     6 +-
 builder/src/zrender/graphic/States.js              |     3 +
 builder/src/zrender/graphic/Style.js               |    31 +-
 builder/src/zrender/graphic/helper/text.js         |    25 +-
 builder/src/zrender/mixin/Animatable.js            |     4 +-
 builder/src/zrender/mixin/Draggable.js             |     7 +-
 builder/src/zrender/mixin/Eventful.js              |     6 +-
 builder/src/zrender/svg/Painter.js                 |    38 +-
 builder/src/zrender/svg/graphic.js                 |   324 +-
 builder/src/zrender/svg/helper/ClippathManager.js  |     4 +-
 builder/src/zrender/svg/helper/GradientManager.js  |     6 +-
 builder/src/zrender/svg/helper/ShadowManager.js    |    41 +-
 builder/src/zrender/vml/Painter.js                 |     4 +-
 builder/src/zrender/vml/graphic.js                 |    23 +-
 builder/src/zrender/zrender.js                     |    13 +-
 components/analytics.html                          |    11 +
 components/builder.html                            |    75 +
 components/download.html                           |    40 +
 components/footer.html                             |     1 +
 components/nav-mixin.html                          |     0
 components/nav.html                                |     1 +
 components/svg/community.html                      |     1 +
 components/svg/echarts-logo.html                   |     1 +
 components/svg/function.html                       |     1 +
 components/svg/heart.html                          |     1 +
 components/svg/more.html                           |     1 +
 dist/echarts-en.common.js                          |  7410 ++--
 dist/echarts-en.common.min.js                      |     2 +-
 dist/echarts-en.js                                 | 38009 ++++++++++---------
 dist/echarts-en.js.map                             |     2 +-
 dist/echarts-en.min.js                             |     2 +-
 dist/echarts-en.simple.js                          |  5220 ++-
 dist/echarts-en.simple.min.js                      |     2 +-
 dist/echarts.common.js                             |  7378 ++--
 dist/echarts.common.min.js                         |     2 +-
 dist/echarts.js                                    | 37977 +++++++++---------
 dist/echarts.js.map                                |     2 +-
 dist/echarts.min.js                                |     2 +-
 dist/echarts.simple.js                             |  5188 ++-
 dist/echarts.simple.min.js                         |     2 +-
 dist/extension/bmap.js                             |    17 +
 dist/extension/bmap.js.map                         |     2 +-
 dist/extension/bmap.min.js                         |     2 +-
 dist/extension/dataTool.js                         |   106 +-
 dist/extension/dataTool.js.map                     |     2 +-
 dist/extension/dataTool.min.js                     |     2 +-
 en/404.html                                        |     2 +-
 en/api.html                                        |    74 +-
 en/builder.html                                    |     8 +-
 en/changelog.html                                  |    51 +-
 en/cheat-sheet.html                                |     2 +-
 en/coding-standard.html                            |     2 +-
 en/committers.html                                 |     4 +-
 en/css/doc-bundle.css                              |  1009 +
 en/css/ecOption.css                                |   723 +-
 en/css/element-icons.ttf                           |   Bin 0 -> 55956 bytes
 en/css/element-icons.woff                          |   Bin 0 -> 28200 bytes
 en/css/main.css                                    |     2 +-
 en/dependencies.html                               |     2 +-
 en/download-extension.html                         |     2 +-
 en/download-map.html                               |     2 +-
 en/download-theme.html                             |     4 +-
 en/download.html                                   |     4 +-
 en/faq.html                                        |     2 +-
 en/feature.html                                    |     2 +-
 en/index.html                                      |     4 +-
 en/js/chart-list.js                                |     2 +-
 en/js/cheat-sheet-en.js                            |     2 +-
 en/js/cheat-sheet.js                               |     2 +-
 en/js/common.js                                    |     2 +-
 en/js/doc-bundle.js                                |    14 +
 en/js/docTool/main.js                              |     4 +-
 en/js/download.js                                  |     2 +-
 en/js/examples-nav.js                              |     2 +-
 en/js/index.js                                     |     2 +-
 en/maillist.html                                   |     2 +-
 en/option-gl.html                                  |    62 +-
 en/option.html                                     |    62 +-
 en/option3.html                                    |     2 +-
 en/tutorial.html                                   |    76 +-
 examples/data-gl/lines3d-flights-gl.js             |     2 -
 examples/data/area-rainfall.js                     |    50 +-
 examples/data/area-simple.js                       |     6 +-
 examples/data/area-stack.js                        |    52 +-
 examples/data/asset/data/aqi.csv                   |     2 +-
 examples/data/asset/data/gps/gps_0.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_1.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_10.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_100.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_101.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_102.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_103.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_104.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_105.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_106.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_107.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_108.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_109.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_11.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_110.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_111.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_112.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_113.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_114.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_115.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_116.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_117.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_118.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_119.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_12.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_120.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_121.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_122.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_123.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_124.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_125.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_126.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_127.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_128.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_129.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_13.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_130.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_131.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_132.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_133.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_134.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_135.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_136.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_137.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_138.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_139.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_14.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_140.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_141.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_142.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_143.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_144.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_145.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_146.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_147.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_148.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_149.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_15.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_150.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_151.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_152.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_153.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_154.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_155.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_156.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_157.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_158.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_159.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_16.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_160.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_161.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_162.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_163.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_164.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_165.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_166.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_167.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_168.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_169.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_17.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_170.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_171.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_172.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_173.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_174.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_175.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_176.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_177.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_178.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_179.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_18.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_180.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_181.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_182.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_183.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_184.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_185.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_186.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_187.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_188.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_189.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_19.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_190.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_191.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_192.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_193.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_194.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_195.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_196.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_197.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_198.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_199.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_2.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_20.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_200.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_201.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_202.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_203.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_204.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_205.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_206.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_207.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_208.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_209.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_21.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_210.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_211.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_212.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_213.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_214.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_215.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_216.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_217.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_218.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_219.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_22.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_220.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_221.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_222.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_223.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_224.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_225.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_226.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_227.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_228.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_229.bin           |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_23.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_24.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_25.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_26.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_27.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_28.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_29.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_3.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_30.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_31.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_32.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_33.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_34.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_35.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_36.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_37.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_38.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_39.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_4.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_40.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_41.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_42.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_43.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_44.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_45.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_46.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_47.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_48.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_49.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_5.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_50.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_51.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_52.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_53.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_54.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_55.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_56.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_57.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_58.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_59.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_6.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_60.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_61.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_62.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_63.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_64.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_65.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_66.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_67.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_68.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_69.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_7.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_70.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_71.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_72.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_73.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_74.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_75.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_76.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_77.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_78.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_79.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_8.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_80.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_81.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_82.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_83.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_84.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_85.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_86.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_87.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_88.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_89.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_9.bin             |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_90.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_91.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_92.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_93.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_94.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_95.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_96.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_97.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_98.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/gps_99.bin            |   Bin 400000 -> 400000 bytes
 examples/data/asset/data/gps/uniform.js            |    38 +
 examples/data/bar-animation-delay.js               |     4 +-
 examples/data/bar-brush.js                         |    18 +-
 examples/data/bar-gradient.js                      |    28 +-
 examples/data/bar-histogram.js                     |     8 +-
 examples/data/bar-label-rotation.js                |    25 +-
 examples/data/bar-negative.js                      |    60 +-
 examples/data/bar-negative2.js                     |    36 +-
 examples/data/bar-polar-real-estate.js             |    18 +-
 examples/data/bar-polar-stack-radial.js            |     5 +-
 examples/data/bar-polar-stack.js                   |     2 -
 examples/data/bar-rich-text.js                     |    72 +-
 examples/data/bar-stack.js                         |    88 +-
 examples/data/bar-tick-align.js                    |    26 +-
 examples/data/bar-waterfall.js                     |    34 +-
 examples/data/bar-waterfall2.js                    |    40 +-
 examples/data/bar-y-category-stack.js              |    44 +-
 examples/data/bar-y-category.js                    |     4 +-
 examples/data/bar1.js                              |    72 +-
 examples/data/boxplot-light-velocity2.js           |     2 +-
 examples/data/boxplot-multi.js                     |     6 +-
 examples/data/bubble-gradient.js                   |    54 +-
 examples/data/calendar-charts.js                   |     4 +-
 examples/data/calendar-effectscatter.js            |    46 +-
 examples/data/calendar-graph.js                    |    22 +-
 examples/data/calendar-heatmap.js                  |     4 +-
 examples/data/calendar-horizontal.js               |     3 +-
 examples/data/calendar-lunar.js                    |    36 +-
 examples/data/calendar-pie.js                      |    28 +-
 examples/data/calendar-vertical.js                 |     3 +-
 examples/data/candlestick-brush.js                 |    59 +-
 examples/data/candlestick-large.js                 |     5 +-
 examples/data/candlestick-sh-2015.js               |    28 +-
 examples/data/candlestick-sh.js                    |    40 +-
 examples/data/candlestick-touch.js                 |    34 +-
 examples/data/confidence-band.js                   |    21 +-
 examples/data/custom-bar-trend.js                  |     9 +-
 examples/data/custom-error-bar.js                  |     4 +-
 examples/data/custom-error-scatter.js              |     4 +-
 examples/data/custom-ohlc.js                       |     2 +-
 examples/data/custom-polar-heatmap.js              |    12 +-
 examples/data/custom-profile.js                    |     6 +-
 examples/data/custom-profit.js                     |    10 +-
 examples/data/custom-wind.js                       |     9 +-
 examples/data/cycle-plot.js                        |     1 -
 examples/data/dataset-encode0.js                   |     2 +-
 examples/data/doc-example/aria-pie.js              |     2 +-
 examples/data/doc-example/bar-large.js             |     1 -
 examples/data/doc-example/map-visualMap-pieces.js  |    45 +-
 examples/data/doc-example/mix-timeline-all.js      |     3 +-
 examples/data/doc-example/pie-highlight.js         |    28 +-
 examples/data/doc-example/pie-label-bleedMargin.js |    69 +
 .../doc-example/pie-label-distanceToLabelLine.js   |    69 +
 examples/data/doc-example/pie-label-margin.js      |    69 +
 .../doc-example/scatter-visualMap-categories.js    |     2 +-
 examples/data/dynamic-data.js                      |    14 +-
 examples/data/dynamic-data2.js                     |     2 +-
 examples/data/effectScatter-bmap.js                |    34 +-
 examples/data/effectScatter-map.js                 |    54 +-
 examples/data/funnel-align.js                      |    38 +-
 examples/data/funnel-customize.js                  |    46 +-
 examples/data/funnel-mutiple.js                    |    46 +-
 examples/data/funnel.js                            |     2 +-
 examples/data/gauge-car-dark.js                    |   232 +-
 examples/data/gauge-car.js                         |    42 +-
 examples/data/gauge.js                             |     6 +-
 examples/data/geo-lines.js                         |    44 +-
 examples/data/geo-map-scatter.js                   |    59 +-
 examples/data/graph-circular-layout.js             |    15 +-
 examples/data/graph-force.js                       |     6 +-
 examples/data/graph-force2.js                      |     2 -
 examples/data/graph-grid.js                        |     8 +-
 examples/data/graph-life-expectancy.js             |    98 +-
 examples/data/graph-npm.js                         |    16 +-
 examples/data/graph-simple.js                      |    36 +-
 examples/data/graph-webkit-dep.js                  |     8 +-
 examples/data/graph.js                             |    14 +-
 examples/data/grid-multiple.js                     |    40 +-
 examples/data/heatmap-bmap.js                      |    10 +-
 examples/data/heatmap-cartesian.js                 |    12 +-
 examples/data/heatmap-large-piecewise.js           |     6 +-
 examples/data/heatmap-large.js                     |     6 +-
 examples/data/heatmap-map.js                       |    16 +-
 examples/data/line-draggable.js                    |    48 +-
 examples/data/line-function.js                     |    81 +
 examples/data/line-graphic.js                      |    10 +-
 examples/data/line-log.js                          |     8 +-
 examples/data/line-marker.js                       |    24 +-
 examples/data/line-sections.js                     |     6 +-
 examples/data/line-stack.js                        |    34 +-
 examples/data/line-step.js                         |    20 +-
 examples/data/line-style.js                        |    16 +-
 examples/data/line-tooltip-touch.js                |    52 +-
 examples/data/line-y-category.js                   |    14 +-
 examples/data/lines-airline.js                     |    16 +-
 examples/data/lines-bmap-bus.js                    |    11 +-
 examples/data/lines-bmap-effect.js                 |    16 +-
 examples/data/lines-bmap.js                        |    10 +-
 examples/data/lines-ny.js                          |    10 +-
 examples/data/map-HK.js                            |    11 +-
 examples/data/map-bin.js                           |     4 +-
 examples/data/map-china-dataRange.js               |   151 +-
 examples/data/map-china.js                         |    13 +-
 examples/data/map-labels.js                        |   145 +-
 examples/data/map-locate.js                        |    14 +-
 examples/data/map-parallel-prices.js               |    47 +-
 examples/data/map-polygon.js                       |    37 +-
 examples/data/map-province.js                      |    22 +-
 examples/data/map-usa.js                           |     8 +-
 examples/data/map-world-dataRange.js               |    10 +-
 examples/data/map-world.js                         |    22 +-
 examples/data/meta/line-aqi.md                     |     2 +-
 examples/data/meta/line-draggable.md               |     2 +-
 examples/data/meta/line-easing.md                  |     4 +-
 examples/data/meta/line-function.md                |     5 +
 examples/data/meta/pie-alignTo.md                  |     5 +
 examples/data/meta/tree-polyline.md                |     5 +
 examples/data/mix-line-bar.js                      |    24 +-
 examples/data/mix-timeline-finance.js              |     9 +-
 examples/data/mix-zoom-on-value.js                 |    28 +-
 examples/data/multiple-x-axis.js                   |    14 +-
 examples/data/multiple-y-axis.js                   |    24 +-
 examples/data/parallel-aqi.js                      |     4 +-
 examples/data/parallel-nutrients.js                |     4 +-
 examples/data/pictorialBar-body-fill.js            |    16 +-
 examples/data/pictorialBar-dotted.js               |    40 +-
 examples/data/pictorialBar-hill.js                 |    26 +-
 examples/data/pictorialBar-spirit.js               |    42 +-
 examples/data/pictorialBar-vehicle.js              |     4 +-
 examples/data/pictorialBar-velocity.js             |    12 +-
 examples/data/pie-alignTo.js                       |    89 +
 examples/data/pie-custom.js                        |    52 +-
 examples/data/pie-doughnut.js                      |    24 +-
 examples/data/pie-legend.js                        |    18 +-
 examples/data/pie-nest.js                          |   128 +-
 examples/data/pie-pattern.js                       |    26 +-
 examples/data/pie-rich-text.js                     |   180 +-
 examples/data/pie-roseType.js                      |   101 +-
 examples/data/pie-simple.js                        |    30 +-
 examples/data/radar-aqi.js                         |    24 +-
 examples/data/radar-custom.js                      |    57 +-
 examples/data/radar-multiple.js                    |    25 +-
 examples/data/radar.js                             |    26 +-
 examples/data/radar2.js                            |    26 +-
 examples/data/sankey-energy.js                     |    12 +-
 examples/data/sankey-itemstyle.js                  |    24 +-
 examples/data/sankey-levels.js                     |     4 +-
 examples/data/sankey-nodeAlign-left.js             |     6 +-
 examples/data/sankey-nodeAlign-right.js            |     6 +-
 examples/data/sankey-simple.js                     |     2 +-
 examples/data/sankey-vertical.js                   |     6 +-
 examples/data/scatter-anscombe-quartet.js          |    16 +-
 examples/data/scatter-aqi-color.js                 |    24 +-
 examples/data/scatter-clustering-process.js        |    24 +-
 examples/data/scatter-exponential-regression.js    |    28 +-
 examples/data/scatter-large.js                     |     2 +-
 examples/data/scatter-life-expectancy-timeline.js  |    34 +-
 examples/data/scatter-linear-regression.js         |    28 +-
 examples/data/scatter-logarithmic-regression.js    |    70 +-
 examples/data/scatter-map.js                       |    34 +-
 examples/data/scatter-matrix.js                    |    10 +-
 examples/data/scatter-nebula.js                    |     2 +-
 examples/data/scatter-nutrients.js                 |    10 +-
 examples/data/scatter-painter-choice.js            |     6 +-
 examples/data/scatter-polynomial-regression.js     |    28 +-
 examples/data/scatter-single-axis.js               |     2 -
 examples/data/scatter-weibo.js                     |    40 +-
 examples/data/scatter-weight.js                    |    96 +-
 examples/data/scatter-world-population.js          |    24 +-
 examples/data/sunburst-book.js                     |     4 +-
 examples/data/themeRiver-basic.js                  |     4 +-
 examples/data/themeRiver-lastfm.js                 |     4 +-
 examples/data/thumb-dark/area-basic.jpg            |   Bin 11852 -> 11806 bytes
 examples/data/thumb-dark/area-rainfall.jpg         |   Bin 25563 -> 25429 bytes
 examples/data/thumb-dark/area-simple.jpg           |   Bin 20834 -> 22745 bytes
 examples/data/thumb-dark/area-stack.jpg            |   Bin 23016 -> 23524 bytes
 examples/data/thumb-dark/bar-animation-delay.jpg   |   Bin 26332 -> 26131 bytes
 examples/data/thumb-dark/bar-brush.jpg             |   Bin 15178 -> 15740 bytes
 examples/data/thumb-dark/bar-gradient.jpg          |   Bin 24803 -> 24692 bytes
 examples/data/thumb-dark/bar-histogram.jpg         |   Bin 19946 -> 19615 bytes
 examples/data/thumb-dark/bar-label-rotation.jpg    |   Bin 27624 -> 27070 bytes
 examples/data/thumb-dark/bar-large.jpg             |   Bin 23284 -> 22377 bytes
 examples/data/thumb-dark/bar-negative.jpg          |   Bin 26189 -> 26038 bytes
 examples/data/thumb-dark/bar-negative2.jpg         |   Bin 16494 -> 16477 bytes
 examples/data/thumb-dark/bar-polar-real-estate.jpg |   Bin 24140 -> 25031 bytes
 .../data/thumb-dark/bar-polar-stack-radial.jpg     |   Bin 19527 -> 19394 bytes
 examples/data/thumb-dark/bar-polar-stack.jpg       |   Bin 21158 -> 21050 bytes
 examples/data/thumb-dark/bar-rich-text.jpg         |   Bin 23817 -> 23723 bytes
 examples/data/thumb-dark/bar-simple.jpg            |   Bin 13835 -> 13822 bytes
 examples/data/thumb-dark/bar-stack.jpg             |   Bin 31437 -> 32731 bytes
 examples/data/thumb-dark/bar-tick-align.jpg        |   Bin 14779 -> 14587 bytes
 examples/data/thumb-dark/bar-waterfall.jpg         |   Bin 20879 -> 21926 bytes
 examples/data/thumb-dark/bar-waterfall2.jpg        |   Bin 22036 -> 23597 bytes
 examples/data/thumb-dark/bar-y-category-stack.jpg  |   Bin 27597 -> 27406 bytes
 examples/data/thumb-dark/bar-y-category.jpg        |   Bin 20294 -> 20126 bytes
 examples/data/thumb-dark/bar1.jpg                  |   Bin 26037 -> 25894 bytes
 .../data/thumb-dark/boxplot-light-velocity.jpg     |   Bin 19610 -> 19436 bytes
 .../data/thumb-dark/boxplot-light-velocity2.jpg    |   Bin 18860 -> 18619 bytes
 examples/data/thumb-dark/boxplot-multi.jpg         |   Bin 16292 -> 16219 bytes
 examples/data/thumb-dark/bubble-gradient.jpg       |   Bin 16265 -> 16212 bytes
 examples/data/thumb-dark/calendar-charts.jpg       |   Bin 19249 -> 19376 bytes
 .../data/thumb-dark/calendar-effectscatter.jpg     |   Bin 45475 -> 45016 bytes
 examples/data/thumb-dark/calendar-graph.jpg        |   Bin 18082 -> 17908 bytes
 examples/data/thumb-dark/calendar-heatmap.jpg      |   Bin 19934 -> 20038 bytes
 examples/data/thumb-dark/calendar-horizontal.jpg   |   Bin 40201 -> 39950 bytes
 examples/data/thumb-dark/calendar-lunar.jpg        |   Bin 19450 -> 19303 bytes
 examples/data/thumb-dark/calendar-pie.jpg          |   Bin 36900 -> 36971 bytes
 examples/data/thumb-dark/calendar-simple.jpg       |   Bin 16334 -> 16602 bytes
 examples/data/thumb-dark/calendar-vertical.jpg     |   Bin 31864 -> 31976 bytes
 examples/data/thumb-dark/candlestick-brush.jpg     |   Bin 18869 -> 18864 bytes
 examples/data/thumb-dark/candlestick-large.jpg     |   Bin 28110 -> 29106 bytes
 examples/data/thumb-dark/candlestick-sh-2015.jpg   |   Bin 17889 -> 18348 bytes
 examples/data/thumb-dark/candlestick-sh.jpg        |   Bin 33084 -> 32746 bytes
 examples/data/thumb-dark/candlestick-simple.jpg    |   Bin 13628 -> 13566 bytes
 examples/data/thumb-dark/candlestick-touch.jpg     |   Bin 22608 -> 23468 bytes
 examples/data/thumb-dark/confidence-band.jpg       |   Bin 13171 -> 13105 bytes
 examples/data/thumb-dark/custom-bar-trend.jpg      |   Bin 28098 -> 27240 bytes
 examples/data/thumb-dark/custom-calendar-icon.jpg  |   Bin 22744 -> 18947 bytes
 .../data/thumb-dark/custom-cartesian-polygon.jpg   |   Bin 19990 -> 21800 bytes
 examples/data/thumb-dark/custom-error-bar.jpg      |   Bin 23502 -> 25135 bytes
 examples/data/thumb-dark/custom-error-scatter.jpg  |   Bin 20954 -> 20920 bytes
 examples/data/thumb-dark/custom-gantt-flight.jpg   |   Bin 31449 -> 31534 bytes
 examples/data/thumb-dark/custom-hexbin.jpg         |   Bin 54317 -> 54253 bytes
 examples/data/thumb-dark/custom-polar-heatmap.jpg  |   Bin 22659 -> 22690 bytes
 examples/data/thumb-dark/custom-profile.jpg        |   Bin 20292 -> 19717 bytes
 examples/data/thumb-dark/custom-profit.jpg         |   Bin 16081 -> 16008 bytes
 examples/data/thumb-dark/custom-wind.jpg           |   Bin 53212 -> 53212 bytes
 examples/data/thumb-dark/cycle-plot.jpg            |   Bin 22869 -> 22824 bytes
 examples/data/thumb-dark/dataset-default.jpg       |   Bin 21209 -> 20637 bytes
 examples/data/thumb-dark/dataset-encode0.jpg       |   Bin 20311 -> 20229 bytes
 examples/data/thumb-dark/dataset-encode1.jpg       |   Bin 46555 -> 46544 bytes
 examples/data/thumb-dark/dataset-link.jpg          |   Bin 24283 -> 24346 bytes
 .../data/thumb-dark/dataset-series-layout-by.jpg   |   Bin 25779 -> 25625 bytes
 examples/data/thumb-dark/dataset-simple0.jpg       |   Bin 17429 -> 17397 bytes
 examples/data/thumb-dark/dataset-simple1.jpg       |   Bin 17429 -> 17397 bytes
 examples/data/thumb-dark/dynamic-data.jpg          |   Bin 24894 -> 24284 bytes
 examples/data/thumb-dark/dynamic-data2.jpg         |   Bin 12123 -> 12102 bytes
 examples/data/thumb-dark/effectScatter-bmap.jpg    |   Bin 14882 -> 14757 bytes
 examples/data/thumb-dark/effectScatter-map.jpg     |   Bin 18295 -> 18276 bytes
 examples/data/thumb-dark/funnel-align.jpg          |   Bin 25636 -> 25446 bytes
 examples/data/thumb-dark/funnel-customize.jpg      |   Bin 18258 -> 18148 bytes
 examples/data/thumb-dark/funnel-mutiple.jpg        |   Bin 25021 -> 24878 bytes
 examples/data/thumb-dark/funnel.jpg                |   Bin 14334 -> 14275 bytes
 examples/data/thumb-dark/gauge-car-dark.jpg        |   Bin 18111 -> 18142 bytes
 examples/data/thumb-dark/gauge-car.jpg             |   Bin 14628 -> 14634 bytes
 examples/data/thumb-dark/gauge.jpg                 |   Bin 10806 -> 10758 bytes
 examples/data/thumb-dark/geo-lines.jpg             |   Bin 14213 -> 13754 bytes
 examples/data/thumb-dark/geo-map-scatter.jpg       |   Bin 22973 -> 23543 bytes
 examples/data/thumb-dark/graph-circular-layout.jpg |   Bin 48650 -> 48683 bytes
 examples/data/thumb-dark/graph-force-dynamic.jpg   |   Bin 2798 -> 2828 bytes
 examples/data/thumb-dark/graph-force.jpg           |   Bin 24424 -> 24172 bytes
 examples/data/thumb-dark/graph-force2.jpg          |   Bin 17625 -> 17768 bytes
 examples/data/thumb-dark/graph-grid.jpg            |   Bin 19673 -> 16936 bytes
 examples/data/thumb-dark/graph-life-expectancy.jpg |   Bin 28593 -> 25305 bytes
 examples/data/thumb-dark/graph-npm.jpg             |   Bin 20572 -> 20651 bytes
 examples/data/thumb-dark/graph-simple.jpg          |   Bin 14086 -> 14039 bytes
 examples/data/thumb-dark/graph-webkit-dep.jpg      |   Bin 45331 -> 46107 bytes
 examples/data/thumb-dark/graph.jpg                 |   Bin 28016 -> 28114 bytes
 examples/data/thumb-dark/grid-multiple.jpg         |   Bin 31097 -> 31393 bytes
 examples/data/thumb-dark/heatmap-bmap.jpg          |   Bin 27124 -> 27103 bytes
 examples/data/thumb-dark/heatmap-cartesian.jpg     |   Bin 22304 -> 21992 bytes
 .../data/thumb-dark/heatmap-large-piecewise.jpg    |   Bin 48395 -> 40460 bytes
 examples/data/thumb-dark/heatmap-large.jpg         |   Bin 40255 -> 28648 bytes
 examples/data/thumb-dark/heatmap-map.jpg           |   Bin 14088 -> 13997 bytes
 examples/data/thumb-dark/line-aqi.jpg              |   Bin 30864 -> 30970 bytes
 examples/data/thumb-dark/line-draggable.jpg        |   Bin 21863 -> 21807 bytes
 examples/data/thumb-dark/line-easing.jpg           |   Bin 27852 -> 27819 bytes
 examples/data/thumb-dark/line-function.jpg         |   Bin 0 -> 36285 bytes
 examples/data/thumb-dark/line-gradient.jpg         |   Bin 21699 -> 22315 bytes
 examples/data/thumb-dark/line-graphic.jpg          |   Bin 26296 -> 25325 bytes
 .../line-in-cartesian-coordinate-system.jpg        |   Bin 15299 -> 15250 bytes
 examples/data/thumb-dark/line-log.jpg              |   Bin 21593 -> 35706 bytes
 examples/data/thumb-dark/line-marker.jpg           |   Bin 24174 -> 24050 bytes
 examples/data/thumb-dark/line-pen.jpg              |   Bin 18357 -> 17608 bytes
 examples/data/thumb-dark/line-polar.jpg            |   Bin 21778 -> 21643 bytes
 examples/data/thumb-dark/line-polar2.jpg           |   Bin 26440 -> 26303 bytes
 examples/data/thumb-dark/line-sections.jpg         |   Bin 17368 -> 17290 bytes
 examples/data/thumb-dark/line-simple.jpg           |   Bin 12765 -> 12736 bytes
 examples/data/thumb-dark/line-smooth.jpg           |   Bin 12775 -> 12740 bytes
 examples/data/thumb-dark/line-stack.jpg            |   Bin 24468 -> 25901 bytes
 examples/data/thumb-dark/line-step.jpg             |   Bin 19212 -> 19416 bytes
 examples/data/thumb-dark/line-style.jpg            |   Bin 13461 -> 13458 bytes
 examples/data/thumb-dark/line-tooltip-touch.jpg    |   Bin 15811 -> 15750 bytes
 examples/data/thumb-dark/line-y-category.jpg       |   Bin 18243 -> 17553 bytes
 examples/data/thumb-dark/lines-airline.jpg         |   Bin 31810 -> 31827 bytes
 examples/data/thumb-dark/lines-bmap-bus.jpg        |   Bin 24057 -> 24055 bytes
 examples/data/thumb-dark/lines-bmap-effect.jpg     |   Bin 2490 -> 135693 bytes
 examples/data/thumb-dark/lines-bmap.jpg            |   Bin 10136 -> 10131 bytes
 examples/data/thumb-dark/map-HK.jpg                |   Bin 28463 -> 28451 bytes
 examples/data/thumb-dark/map-bin.jpg               |   Bin 29946 -> 29967 bytes
 examples/data/thumb-dark/map-china-dataRange.jpg   |   Bin 27931 -> 27996 bytes
 examples/data/thumb-dark/map-china.jpg             |   Bin 23998 -> 23928 bytes
 examples/data/thumb-dark/map-labels.jpg            |   Bin 33119 -> 32746 bytes
 examples/data/thumb-dark/map-locate.jpg            |   Bin 23903 -> 23849 bytes
 examples/data/thumb-dark/map-parallel-prices.jpg   |   Bin 36832 -> 36598 bytes
 examples/data/thumb-dark/map-polygon.jpg           |   Bin 31340 -> 31242 bytes
 examples/data/thumb-dark/map-province.jpg          |   Bin 13103 -> 13113 bytes
 examples/data/thumb-dark/map-usa.jpg               |   Bin 17545 -> 17596 bytes
 examples/data/thumb-dark/map-world-dataRange.jpg   |   Bin 25331 -> 25250 bytes
 examples/data/thumb-dark/mix-line-bar.jpg          |   Bin 24418 -> 24232 bytes
 examples/data/thumb-dark/mix-timeline-finance.jpg  |   Bin 35412 -> 35329 bytes
 examples/data/thumb-dark/mix-zoom-on-value.jpg     |   Bin 28659 -> 28737 bytes
 examples/data/thumb-dark/multiple-x-axis.jpg       |   Bin 19051 -> 18931 bytes
 examples/data/thumb-dark/multiple-y-axis.jpg       |   Bin 25371 -> 25246 bytes
 examples/data/thumb-dark/parallel-aqi.jpg          |   Bin 39963 -> 39649 bytes
 examples/data/thumb-dark/parallel-nutrients.jpg    |   Bin 47015 -> 47250 bytes
 examples/data/thumb-dark/parallel-simple.jpg       |   Bin 12875 -> 12791 bytes
 .../data/thumb-dark/pictorialBar-body-fill.jpg     |   Bin 17627 -> 17612 bytes
 examples/data/thumb-dark/pictorialBar-dotted.jpg   |   Bin 24318 -> 24979 bytes
 examples/data/thumb-dark/pictorialBar-forest.jpg   |   Bin 5367 -> 5367 bytes
 examples/data/thumb-dark/pictorialBar-hill.jpg     |   Bin 28133 -> 28083 bytes
 examples/data/thumb-dark/pictorialBar-spirit.jpg   |   Bin 20039 -> 19949 bytes
 examples/data/thumb-dark/pictorialBar-vehicle.jpg  |   Bin 17525 -> 17587 bytes
 examples/data/thumb-dark/pictorialBar-velocity.jpg |   Bin 11002 -> 10957 bytes
 examples/data/thumb-dark/pie-alignTo.jpg           |   Bin 0 -> 15523 bytes
 examples/data/thumb-dark/pie-custom.jpg            |   Bin 7792 -> 7785 bytes
 examples/data/thumb-dark/pie-doughnut.jpg          |   Bin 12329 -> 12261 bytes
 examples/data/thumb-dark/pie-legend.jpg            |   Bin 21024 -> 19092 bytes
 examples/data/thumb-dark/pie-nest.jpg              |   Bin 25534 -> 25117 bytes
 examples/data/thumb-dark/pie-pattern.jpg           |   Bin 39837 -> 39635 bytes
 examples/data/thumb-dark/pie-rich-text.jpg         |   Bin 14697 -> 14597 bytes
 examples/data/thumb-dark/pie-roseType.jpg          |   Bin 17842 -> 17638 bytes
 examples/data/thumb-dark/pie-simple.jpg            |   Bin 15461 -> 15314 bytes
 examples/data/thumb-dark/radar-aqi.jpg             |   Bin 17681 -> 17576 bytes
 examples/data/thumb-dark/radar-custom.jpg          |   Bin 22978 -> 22825 bytes
 examples/data/thumb-dark/radar-multiple.jpg        |   Bin 25337 -> 23247 bytes
 examples/data/thumb-dark/radar.jpg                 |   Bin 23627 -> 23514 bytes
 examples/data/thumb-dark/radar2.jpg                |   Bin 24270 -> 24691 bytes
 examples/data/thumb-dark/sankey-energy.jpg         |   Bin 28167 -> 28461 bytes
 examples/data/thumb-dark/sankey-itemstyle.jpg      |   Bin 29408 -> 29334 bytes
 examples/data/thumb-dark/sankey-levels.jpg         |   Bin 30540 -> 30739 bytes
 examples/data/thumb-dark/sankey-nodeAlign-left.jpg |   Bin 24968 -> 25349 bytes
 .../data/thumb-dark/sankey-nodeAlign-right.jpg     |   Bin 24709 -> 25021 bytes
 examples/data/thumb-dark/sankey-simple.jpg         |   Bin 6363 -> 6370 bytes
 examples/data/thumb-dark/sankey-vertical.jpg       |   Bin 7570 -> 7570 bytes
 .../data/thumb-dark/scatter-anscombe-quartet.jpg   |   Bin 32838 -> 32679 bytes
 examples/data/thumb-dark/scatter-aqi-color.jpg     |   Bin 24430 -> 23760 bytes
 .../data/thumb-dark/scatter-clustering-process.jpg |   Bin 20707 -> 21266 bytes
 examples/data/thumb-dark/scatter-effect.jpg        |   Bin 22906 -> 22863 bytes
 .../thumb-dark/scatter-exponential-regression.jpg  |   Bin 31289 -> 31176 bytes
 examples/data/thumb-dark/scatter-large.jpg         |   Bin 22240 -> 22127 bytes
 .../scatter-life-expectancy-timeline.jpg           |   Bin 18007 -> 17866 bytes
 .../data/thumb-dark/scatter-linear-regression.jpg  |   Bin 21231 -> 21204 bytes
 .../thumb-dark/scatter-logarithmic-regression.jpg  |   Bin 23263 -> 23278 bytes
 examples/data/thumb-dark/scatter-map-brush.jpg     |   Bin 33269 -> 33119 bytes
 examples/data/thumb-dark/scatter-map.jpg           |   Bin 18468 -> 18472 bytes
 examples/data/thumb-dark/scatter-matrix.jpg        |   Bin 37635 -> 37526 bytes
 examples/data/thumb-dark/scatter-nebula.jpg        |   Bin 35417 -> 35325 bytes
 .../data/thumb-dark/scatter-nutrients-matrix.jpg   |   Bin 28123 -> 28147 bytes
 examples/data/thumb-dark/scatter-nutrients.jpg     |   Bin 10764 -> 10806 bytes
 .../data/thumb-dark/scatter-painter-choice.jpg     |   Bin 28170 -> 28351 bytes
 .../data/thumb-dark/scatter-polar-punchCard.jpg    |   Bin 22206 -> 22093 bytes
 .../thumb-dark/scatter-polynomial-regression.jpg   |   Bin 35755 -> 35523 bytes
 examples/data/thumb-dark/scatter-punchCard.jpg     |   Bin 24824 -> 24623 bytes
 examples/data/thumb-dark/scatter-simple.jpg        |   Bin 16351 -> 16319 bytes
 examples/data/thumb-dark/scatter-single-axis.jpg   |   Bin 29949 -> 29768 bytes
 examples/data/thumb-dark/scatter-stream-visual.jpg |   Bin 37332 -> 37344 bytes
 examples/data/thumb-dark/scatter-weibo.jpg         |   Bin 33748 -> 33773 bytes
 examples/data/thumb-dark/scatter-weight.jpg        |   Bin 33989 -> 33898 bytes
 .../data/thumb-dark/scatter-world-population.jpg   |   Bin 15630 -> 15647 bytes
 examples/data/thumb-dark/sunburst-book.jpg         |   Bin 37588 -> 36905 bytes
 examples/data/thumb-dark/sunburst-drink.jpg        |   Bin 56715 -> 56335 bytes
 examples/data/thumb-dark/sunburst-label-rotate.jpg |   Bin 19613 -> 19590 bytes
 examples/data/thumb-dark/sunburst-simple.jpg       |   Bin 15450 -> 15405 bytes
 examples/data/thumb-dark/sunburst-visualMap.jpg    |   Bin 18195 -> 18115 bytes
 examples/data/thumb-dark/themeRiver-basic.jpg      |   Bin 22609 -> 22636 bytes
 examples/data/thumb-dark/themeRiver-lastfm.jpg     |   Bin 25765 -> 25746 bytes
 examples/data/thumb-dark/tree-basic.jpg            |   Bin 25913 -> 26096 bytes
 examples/data/thumb-dark/tree-legend.jpg           |   Bin 26172 -> 26084 bytes
 .../data/thumb-dark/tree-orient-bottom-top.jpg     |   Bin 32519 -> 32550 bytes
 .../data/thumb-dark/tree-orient-right-left.jpg     |   Bin 28279 -> 28423 bytes
 examples/data/thumb-dark/tree-polyline.jpg         |   Bin 0 -> 34648 bytes
 examples/data/thumb-dark/tree-radial.jpg           |   Bin 36647 -> 36685 bytes
 examples/data/thumb-dark/tree-vertical.jpg         |   Bin 31059 -> 31023 bytes
 examples/data/thumb-dark/treemap-disk.jpg          |   Bin 28362 -> 28359 bytes
 examples/data/thumb-dark/treemap-drill-down.jpg    |   Bin 30647 -> 30632 bytes
 examples/data/thumb-dark/treemap-obama.jpg         |   Bin 31148 -> 31202 bytes
 examples/data/thumb-dark/treemap-show-parent.jpg   |   Bin 27779 -> 27816 bytes
 examples/data/thumb-dark/treemap-simple.jpg        |   Bin 8970 -> 9035 bytes
 examples/data/thumb-dark/treemap-visual.jpg        |   Bin 24809 -> 24828 bytes
 examples/data/thumb-dark/watermark.jpg             |   Bin 24087 -> 23442 bytes
 examples/data/thumb-dark/wind-barb.jpg             |   Bin 36911 -> 36967 bytes
 examples/data/thumb-light/area-basic.jpg           |   Bin 10276 -> 10265 bytes
 examples/data/thumb-light/area-rainfall.jpg        |   Bin 23479 -> 23413 bytes
 examples/data/thumb-light/area-simple.jpg          |   Bin 18827 -> 19869 bytes
 examples/data/thumb-light/area-stack.jpg           |   Bin 19956 -> 19813 bytes
 examples/data/thumb-light/bar-animation-delay.jpg  |   Bin 24047 -> 23936 bytes
 examples/data/thumb-light/bar-brush.jpg            |   Bin 20741 -> 20933 bytes
 examples/data/thumb-light/bar-gradient.jpg         |   Bin 25577 -> 25448 bytes
 examples/data/thumb-light/bar-histogram.jpg        |   Bin 15032 -> 14846 bytes
 examples/data/thumb-light/bar-label-rotation.jpg   |   Bin 28835 -> 28331 bytes
 examples/data/thumb-light/bar-large.jpg            |   Bin 24380 -> 21756 bytes
 examples/data/thumb-light/bar-negative.jpg         |   Bin 23126 -> 22978 bytes
 examples/data/thumb-light/bar-negative2.jpg        |   Bin 15274 -> 15127 bytes
 .../data/thumb-light/bar-polar-real-estate.jpg     |   Bin 23019 -> 24079 bytes
 .../data/thumb-light/bar-polar-stack-radial.jpg    |   Bin 17923 -> 17785 bytes
 examples/data/thumb-light/bar-polar-stack.jpg      |   Bin 20181 -> 20085 bytes
 examples/data/thumb-light/bar-rich-text.jpg        |   Bin 22300 -> 22267 bytes
 examples/data/thumb-light/bar-simple.jpg           |   Bin 13243 -> 13213 bytes
 examples/data/thumb-light/bar-stack.jpg            |   Bin 27070 -> 27273 bytes
 examples/data/thumb-light/bar-tick-align.jpg       |   Bin 13370 -> 13197 bytes
 examples/data/thumb-light/bar-waterfall.jpg        |   Bin 18465 -> 18057 bytes
 examples/data/thumb-light/bar-waterfall2.jpg       |   Bin 17989 -> 17864 bytes
 examples/data/thumb-light/bar-y-category-stack.jpg |   Bin 26459 -> 26316 bytes
 examples/data/thumb-light/bar-y-category.jpg       |   Bin 17381 -> 17314 bytes
 examples/data/thumb-light/bar1.jpg                 |   Bin 23323 -> 23252 bytes
 .../data/thumb-light/boxplot-light-velocity.jpg    |   Bin 17729 -> 17607 bytes
 .../data/thumb-light/boxplot-light-velocity2.jpg   |   Bin 16977 -> 16819 bytes
 examples/data/thumb-light/boxplot-multi.jpg        |   Bin 17036 -> 16935 bytes
 examples/data/thumb-light/bubble-gradient.jpg      |   Bin 18248 -> 18143 bytes
 examples/data/thumb-light/calendar-charts.jpg      |   Bin 21803 -> 21153 bytes
 .../data/thumb-light/calendar-effectscatter.jpg    |   Bin 45174 -> 45001 bytes
 examples/data/thumb-light/calendar-graph.jpg       |   Bin 19207 -> 18800 bytes
 examples/data/thumb-light/calendar-heatmap.jpg     |   Bin 24055 -> 23849 bytes
 examples/data/thumb-light/calendar-horizontal.jpg  |   Bin 46708 -> 46390 bytes
 examples/data/thumb-light/calendar-lunar.jpg       |   Bin 20546 -> 20170 bytes
 examples/data/thumb-light/calendar-pie.jpg         |   Bin 37503 -> 37700 bytes
 examples/data/thumb-light/calendar-simple.jpg      |   Bin 18295 -> 18187 bytes
 examples/data/thumb-light/calendar-vertical.jpg    |   Bin 36151 -> 36186 bytes
 examples/data/thumb-light/candlestick-brush.jpg    |   Bin 23682 -> 23735 bytes
 examples/data/thumb-light/candlestick-large.jpg    |   Bin 23965 -> 26741 bytes
 examples/data/thumb-light/candlestick-sh-2015.jpg  |   Bin 17262 -> 17569 bytes
 examples/data/thumb-light/candlestick-sh.jpg       |   Bin 32191 -> 32037 bytes
 examples/data/thumb-light/candlestick-simple.jpg   |   Bin 11131 -> 11098 bytes
 examples/data/thumb-light/candlestick-touch.jpg    |   Bin 22392 -> 23052 bytes
 examples/data/thumb-light/confidence-band.jpg      |   Bin 12886 -> 12761 bytes
 examples/data/thumb-light/custom-bar-trend.jpg     |   Bin 25678 -> 24770 bytes
 examples/data/thumb-light/custom-calendar-icon.jpg |   Bin 25171 -> 19689 bytes
 .../data/thumb-light/custom-cartesian-polygon.jpg  |   Bin 18092 -> 18530 bytes
 examples/data/thumb-light/custom-error-bar.jpg     |   Bin 22189 -> 22598 bytes
 examples/data/thumb-light/custom-error-scatter.jpg |   Bin 15735 -> 15741 bytes
 examples/data/thumb-light/custom-gantt-flight.jpg  |   Bin 32435 -> 32610 bytes
 examples/data/thumb-light/custom-hexbin.jpg        |   Bin 54317 -> 54253 bytes
 examples/data/thumb-light/custom-ohlc.jpg          |   Bin 18402 -> 18393 bytes
 examples/data/thumb-light/custom-polar-heatmap.jpg |   Bin 17273 -> 17523 bytes
 examples/data/thumb-light/custom-profile.jpg       |   Bin 17074 -> 17118 bytes
 examples/data/thumb-light/custom-profit.jpg        |   Bin 12992 -> 12957 bytes
 examples/data/thumb-light/custom-wind.jpg          |   Bin 53212 -> 53212 bytes
 examples/data/thumb-light/cycle-plot.jpg           |   Bin 19803 -> 19770 bytes
 examples/data/thumb-light/dataset-default.jpg      |   Bin 18567 -> 18131 bytes
 examples/data/thumb-light/dataset-encode0.jpg      |   Bin 18026 -> 17990 bytes
 examples/data/thumb-light/dataset-encode1.jpg      |   Bin 39821 -> 39818 bytes
 examples/data/thumb-light/dataset-link.jpg         |   Bin 20681 -> 20740 bytes
 .../data/thumb-light/dataset-series-layout-by.jpg  |   Bin 22206 -> 22217 bytes
 examples/data/thumb-light/dataset-simple0.jpg      |   Bin 16062 -> 16031 bytes
 examples/data/thumb-light/dataset-simple1.jpg      |   Bin 16062 -> 16031 bytes
 examples/data/thumb-light/dynamic-data.jpg         |   Bin 24047 -> 22414 bytes
 examples/data/thumb-light/dynamic-data2.jpg        |   Bin 12676 -> 12519 bytes
 examples/data/thumb-light/effectScatter-bmap.jpg   |   Bin 30243 -> 30114 bytes
 examples/data/thumb-light/effectScatter-map.jpg    |   Bin 18302 -> 18284 bytes
 examples/data/thumb-light/funnel-align.jpg         |   Bin 21977 -> 21726 bytes
 examples/data/thumb-light/funnel-customize.jpg     |   Bin 15250 -> 15122 bytes
 examples/data/thumb-light/funnel-mutiple.jpg       |   Bin 20970 -> 20788 bytes
 examples/data/thumb-light/funnel.jpg               |   Bin 13070 -> 12992 bytes
 examples/data/thumb-light/gauge-car-dark.jpg       |   Bin 17958 -> 17982 bytes
 examples/data/thumb-light/gauge-car.jpg            |   Bin 17650 -> 17656 bytes
 examples/data/thumb-light/gauge.jpg                |   Bin 12132 -> 12052 bytes
 examples/data/thumb-light/geo-lines.jpg            |   Bin 14096 -> 13343 bytes
 examples/data/thumb-light/geo-map-scatter.jpg      |   Bin 20176 -> 19776 bytes
 .../data/thumb-light/graph-circular-layout.jpg     |   Bin 43804 -> 43749 bytes
 examples/data/thumb-light/graph-force-dynamic.jpg  |   Bin 2975 -> 2883 bytes
 examples/data/thumb-light/graph-force.jpg          |   Bin 22144 -> 22215 bytes
 examples/data/thumb-light/graph-force2.jpg         |   Bin 16681 -> 16721 bytes
 examples/data/thumb-light/graph-grid.jpg           |   Bin 16486 -> 16230 bytes
 .../data/thumb-light/graph-life-expectancy.jpg     |   Bin 21904 -> 16401 bytes
 examples/data/thumb-light/graph-npm.jpg            |   Bin 21494 -> 21555 bytes
 examples/data/thumb-light/graph-simple.jpg         |   Bin 13081 -> 13013 bytes
 examples/data/thumb-light/graph-webkit-dep.jpg     |   Bin 37467 -> 37852 bytes
 examples/data/thumb-light/graph.jpg                |   Bin 24353 -> 24529 bytes
 examples/data/thumb-light/grid-multiple.jpg        |   Bin 25382 -> 25655 bytes
 examples/data/thumb-light/heatmap-bmap.jpg         |   Bin 52668 -> 50726 bytes
 examples/data/thumb-light/heatmap-cartesian.jpg    |   Bin 23158 -> 22905 bytes
 .../data/thumb-light/heatmap-large-piecewise.jpg   |   Bin 45566 -> 41558 bytes
 examples/data/thumb-light/heatmap-large.jpg        |   Bin 32397 -> 28416 bytes
 examples/data/thumb-light/heatmap-map.jpg          |   Bin 14088 -> 13997 bytes
 examples/data/thumb-light/line-aqi.jpg             |   Bin 35172 -> 35208 bytes
 examples/data/thumb-light/line-draggable.jpg       |   Bin 16530 -> 16482 bytes
 examples/data/thumb-light/line-easing.jpg          |   Bin 31239 -> 31179 bytes
 examples/data/thumb-light/line-function.jpg        |   Bin 0 -> 27070 bytes
 examples/data/thumb-light/line-gradient.jpg        |   Bin 20330 -> 20997 bytes
 examples/data/thumb-light/line-graphic.jpg         |   Bin 25196 -> 24073 bytes
 .../line-in-cartesian-coordinate-system.jpg        |   Bin 11357 -> 11357 bytes
 examples/data/thumb-light/line-log.jpg             |   Bin 16783 -> 23513 bytes
 examples/data/thumb-light/line-marker.jpg          |   Bin 21065 -> 20951 bytes
 examples/data/thumb-light/line-pen.jpg             |   Bin 14064 -> 13989 bytes
 examples/data/thumb-light/line-polar.jpg           |   Bin 19440 -> 19400 bytes
 examples/data/thumb-light/line-polar2.jpg          |   Bin 25496 -> 25401 bytes
 examples/data/thumb-light/line-sections.jpg        |   Bin 17802 -> 17648 bytes
 examples/data/thumb-light/line-simple.jpg          |   Bin 10357 -> 10328 bytes
 examples/data/thumb-light/line-smooth.jpg          |   Bin 10416 -> 10395 bytes
 examples/data/thumb-light/line-stack.jpg           |   Bin 20838 -> 20731 bytes
 examples/data/thumb-light/line-step.jpg            |   Bin 15857 -> 15822 bytes
 examples/data/thumb-light/line-style.jpg           |   Bin 12015 -> 12006 bytes
 examples/data/thumb-light/line-tooltip-touch.jpg   |   Bin 16178 -> 16187 bytes
 examples/data/thumb-light/line-y-category.jpg      |   Bin 16998 -> 16365 bytes
 examples/data/thumb-light/lines-airline.jpg        |   Bin 31628 -> 31682 bytes
 examples/data/thumb-light/lines-bmap-bus.jpg       |   Bin 52849 -> 52845 bytes
 examples/data/thumb-light/lines-bmap-effect.jpg    |   Bin 2490 -> 135693 bytes
 examples/data/thumb-light/lines-bmap-effect.png    |   Bin 2647 -> 597492 bytes
 examples/data/thumb-light/lines-bmap.jpg           |   Bin 39359 -> 39357 bytes
 examples/data/thumb-light/map-HK.jpg               |   Bin 28324 -> 28298 bytes
 examples/data/thumb-light/map-bin.jpg              |   Bin 43047 -> 43081 bytes
 examples/data/thumb-light/map-china-dataRange.jpg  |   Bin 29006 -> 29152 bytes
 examples/data/thumb-light/map-china.jpg            |   Bin 23485 -> 23455 bytes
 examples/data/thumb-light/map-labels.jpg           |   Bin 32133 -> 31528 bytes
 examples/data/thumb-light/map-locate.jpg           |   Bin 23325 -> 23258 bytes
 examples/data/thumb-light/map-parallel-prices.jpg  |   Bin 32704 -> 32548 bytes
 examples/data/thumb-light/map-polygon.jpg          |   Bin 31705 -> 31583 bytes
 examples/data/thumb-light/map-province.jpg         |   Bin 13103 -> 13113 bytes
 examples/data/thumb-light/map-usa.jpg              |   Bin 19235 -> 19275 bytes
 examples/data/thumb-light/map-world-dataRange.jpg  |   Bin 25438 -> 25381 bytes
 examples/data/thumb-light/mix-line-bar.jpg         |   Bin 21293 -> 21219 bytes
 examples/data/thumb-light/mix-timeline-finance.jpg |   Bin 31950 -> 31905 bytes
 examples/data/thumb-light/mix-zoom-on-value.jpg    |   Bin 25081 -> 25119 bytes
 examples/data/thumb-light/multiple-x-axis.jpg      |   Bin 17608 -> 17496 bytes
 examples/data/thumb-light/multiple-y-axis.jpg      |   Bin 24464 -> 24398 bytes
 examples/data/thumb-light/parallel-aqi.jpg         |   Bin 40032 -> 39713 bytes
 examples/data/thumb-light/parallel-nutrients.jpg   |   Bin 47015 -> 47250 bytes
 examples/data/thumb-light/parallel-simple.jpg      |   Bin 13375 -> 13354 bytes
 .../data/thumb-light/pictorialBar-body-fill.jpg    |   Bin 16267 -> 16221 bytes
 examples/data/thumb-light/pictorialBar-dotted.jpg  |   Bin 24595 -> 23741 bytes
 examples/data/thumb-light/pictorialBar-forest.jpg  |   Bin 6213 -> 6202 bytes
 examples/data/thumb-light/pictorialBar-hill.jpg    |   Bin 28099 -> 28049 bytes
 examples/data/thumb-light/pictorialBar-spirit.jpg  |   Bin 22905 -> 22818 bytes
 examples/data/thumb-light/pictorialBar-vehicle.jpg |   Bin 16985 -> 17050 bytes
 .../data/thumb-light/pictorialBar-velocity.jpg     |   Bin 13702 -> 13650 bytes
 examples/data/thumb-light/pie-alignTo.jpg          |   Bin 0 -> 12961 bytes
 examples/data/thumb-light/pie-custom.jpg           |   Bin 7792 -> 7785 bytes
 examples/data/thumb-light/pie-doughnut.jpg         |   Bin 12118 -> 11996 bytes
 examples/data/thumb-light/pie-legend.jpg           |   Bin 16022 -> 15499 bytes
 examples/data/thumb-light/pie-nest.jpg             |   Bin 28384 -> 27869 bytes
 examples/data/thumb-light/pie-pattern.jpg          |   Bin 39837 -> 39635 bytes
 examples/data/thumb-light/pie-rich-text.jpg        |   Bin 15554 -> 15373 bytes
 examples/data/thumb-light/pie-roseType.jpg         |   Bin 16276 -> 16044 bytes
 examples/data/thumb-light/pie-simple.jpg           |   Bin 14547 -> 14323 bytes
 examples/data/thumb-light/radar-aqi.jpg            |   Bin 17681 -> 17576 bytes
 examples/data/thumb-light/radar-custom.jpg         |   Bin 20396 -> 20204 bytes
 examples/data/thumb-light/radar-multiple.jpg       |   Bin 19935 -> 18235 bytes
 examples/data/thumb-light/radar.jpg                |   Bin 22193 -> 22126 bytes
 examples/data/thumb-light/radar2.jpg               |   Bin 24109 -> 23795 bytes
 examples/data/thumb-light/sankey-energy.jpg        |   Bin 39988 -> 40281 bytes
 examples/data/thumb-light/sankey-itemstyle.jpg     |   Bin 29408 -> 29334 bytes
 examples/data/thumb-light/sankey-levels.jpg        |   Bin 32339 -> 32630 bytes
 .../data/thumb-light/sankey-nodeAlign-left.jpg     |   Bin 39509 -> 39869 bytes
 .../data/thumb-light/sankey-nodeAlign-right.jpg    |   Bin 38382 -> 38678 bytes
 examples/data/thumb-light/sankey-simple.jpg        |   Bin 10405 -> 10388 bytes
 examples/data/thumb-light/sankey-vertical.jpg      |   Bin 9847 -> 9835 bytes
 .../data/thumb-light/scatter-anscombe-quartet.jpg  |   Bin 23871 -> 23793 bytes
 examples/data/thumb-light/scatter-aqi-color.jpg    |   Bin 24430 -> 23760 bytes
 .../thumb-light/scatter-clustering-process.jpg     |   Bin 18063 -> 18141 bytes
 examples/data/thumb-light/scatter-effect.jpg       |   Bin 16900 -> 16865 bytes
 .../thumb-light/scatter-exponential-regression.jpg |   Bin 25859 -> 25764 bytes
 examples/data/thumb-light/scatter-large.jpg        |   Bin 20966 -> 20886 bytes
 .../scatter-life-expectancy-timeline.jpg           |   Bin 17497 -> 17444 bytes
 .../data/thumb-light/scatter-linear-regression.jpg |   Bin 18692 -> 18622 bytes
 .../thumb-light/scatter-logarithmic-regression.jpg |   Bin 21092 -> 21089 bytes
 examples/data/thumb-light/scatter-map-brush.jpg    |   Bin 33077 -> 32916 bytes
 examples/data/thumb-light/scatter-map.jpg          |   Bin 18464 -> 18457 bytes
 examples/data/thumb-light/scatter-matrix.jpg       |   Bin 40506 -> 40475 bytes
 examples/data/thumb-light/scatter-nebula.jpg       |   Bin 33336 -> 33219 bytes
 .../data/thumb-light/scatter-nutrients-matrix.jpg  |   Bin 27160 -> 27131 bytes
 examples/data/thumb-light/scatter-nutrients.jpg    |   Bin 10785 -> 10822 bytes
 .../data/thumb-light/scatter-painter-choice.jpg    |   Bin 31434 -> 31551 bytes
 .../data/thumb-light/scatter-polar-punchCard.jpg   |   Bin 22921 -> 22953 bytes
 .../thumb-light/scatter-polynomial-regression.jpg  |   Bin 30362 -> 30140 bytes
 examples/data/thumb-light/scatter-punchCard.jpg    |   Bin 26016 -> 25862 bytes
 examples/data/thumb-light/scatter-simple.jpg       |   Bin 11427 -> 11400 bytes
 examples/data/thumb-light/scatter-single-axis.jpg  |   Bin 29146 -> 29081 bytes
 .../data/thumb-light/scatter-stream-visual.jpg     |   Bin 32075 -> 32101 bytes
 examples/data/thumb-light/scatter-weibo.jpg        |   Bin 33673 -> 33773 bytes
 examples/data/thumb-light/scatter-weight.jpg       |   Bin 33290 -> 33343 bytes
 .../data/thumb-light/scatter-world-population.jpg  |   Bin 15630 -> 15647 bytes
 examples/data/thumb-light/sunburst-book.jpg        |   Bin 37588 -> 36905 bytes
 examples/data/thumb-light/sunburst-drink.jpg       |   Bin 52036 -> 52160 bytes
 .../data/thumb-light/sunburst-label-rotate.jpg     |   Bin 17110 -> 17101 bytes
 examples/data/thumb-light/sunburst-simple.jpg      |   Bin 15447 -> 15422 bytes
 examples/data/thumb-light/sunburst-visualMap.jpg   |   Bin 17448 -> 17428 bytes
 examples/data/thumb-light/themeRiver-basic.jpg     |   Bin 20378 -> 20381 bytes
 examples/data/thumb-light/themeRiver-lastfm.jpg    |   Bin 22886 -> 22866 bytes
 examples/data/thumb-light/tree-basic.jpg           |   Bin 26699 -> 26938 bytes
 examples/data/thumb-light/tree-legend.jpg          |   Bin 34552 -> 34248 bytes
 .../data/thumb-light/tree-orient-bottom-top.jpg    |   Bin 36298 -> 36271 bytes
 .../data/thumb-light/tree-orient-right-left.jpg    |   Bin 30457 -> 30551 bytes
 examples/data/thumb-light/tree-polyline.jpg        |   Bin 0 -> 29218 bytes
 examples/data/thumb-light/tree-radial.jpg          |   Bin 58897 -> 58675 bytes
 examples/data/thumb-light/tree-vertical.jpg        |   Bin 32999 -> 32923 bytes
 examples/data/thumb-light/treemap-disk.jpg         |   Bin 28932 -> 28924 bytes
 examples/data/thumb-light/treemap-drill-down.jpg   |   Bin 31872 -> 31820 bytes
 examples/data/thumb-light/treemap-obama.jpg        |   Bin 32263 -> 32324 bytes
 examples/data/thumb-light/treemap-show-parent.jpg  |   Bin 29128 -> 29211 bytes
 examples/data/thumb-light/treemap-simple.jpg       |   Bin 9271 -> 9387 bytes
 examples/data/thumb-light/treemap-visual.jpg       |   Bin 24899 -> 24899 bytes
 examples/data/thumb-light/watermark.jpg            |   Bin 39514 -> 38642 bytes
 examples/data/thumb-light/wind-barb.jpg            |   Bin 33943 -> 34140 bytes
 examples/data/thumb-manual/lines-bmap-effect.jpg   |   Bin 0 -> 135693 bytes
 examples/data/thumb/area-basic.jpg                 |   Bin 10499 -> 10484 bytes
 examples/data/thumb/area-rainfall.jpg              |   Bin 24919 -> 24777 bytes
 examples/data/thumb/area-simple.jpg                |   Bin 17429 -> 19869 bytes
 examples/data/thumb/area-stack.jpg                 |   Bin 20223 -> 20116 bytes
 examples/data/thumb/bar-animation-delay.jpg        |   Bin 24849 -> 24711 bytes
 examples/data/thumb/bar-brush.jpg                  |   Bin 19292 -> 20718 bytes
 examples/data/thumb/bar-gradient.jpg               |   Bin 25577 -> 25448 bytes
 examples/data/thumb/bar-histogram.jpg              |   Bin 15032 -> 14846 bytes
 examples/data/thumb/bar-label-rotation.jpg         |   Bin 28835 -> 28331 bytes
 examples/data/thumb/bar-large.jpg                  |   Bin 22837 -> 23258 bytes
 examples/data/thumb/bar-negative.jpg               |   Bin 24734 -> 24599 bytes
 examples/data/thumb/bar-negative2.jpg              |   Bin 15852 -> 15728 bytes
 examples/data/thumb/bar-polar-real-estate.jpg      |   Bin 23590 -> 24676 bytes
 examples/data/thumb/bar-polar-stack-radial.jpg     |   Bin 19380 -> 19258 bytes
 examples/data/thumb/bar-polar-stack.jpg            |   Bin 22123 -> 22027 bytes
 examples/data/thumb/bar-rich-text.jpg              |   Bin 22896 -> 22839 bytes
 examples/data/thumb/bar-simple.jpg                 |   Bin 13432 -> 13399 bytes
 examples/data/thumb/bar-stack.jpg                  |   Bin 27234 -> 27407 bytes
 examples/data/thumb/bar-tick-align.jpg             |   Bin 13370 -> 13197 bytes
 examples/data/thumb/bar-waterfall.jpg              |   Bin 18684 -> 18402 bytes
 examples/data/thumb/bar-waterfall2.jpg             |   Bin 18606 -> 18511 bytes
 examples/data/thumb/bar-y-category-stack.jpg       |   Bin 26812 -> 26649 bytes
 examples/data/thumb/bar-y-category.jpg             |   Bin 17885 -> 17817 bytes
 examples/data/thumb/bar1.jpg                       |   Bin 24768 -> 24690 bytes
 examples/data/thumb/boxplot-light-velocity.jpg     |   Bin 17972 -> 17840 bytes
 examples/data/thumb/boxplot-light-velocity2.jpg    |   Bin 17304 -> 17163 bytes
 examples/data/thumb/boxplot-multi.jpg              |   Bin 17491 -> 17339 bytes
 examples/data/thumb/bubble-gradient.jpg            |   Bin 18248 -> 18143 bytes
 examples/data/thumb/calendar-charts.jpg            |   Bin 22078 -> 21225 bytes
 examples/data/thumb/calendar-effectscatter.jpg     |   Bin 45521 -> 45034 bytes
 examples/data/thumb/calendar-graph.jpg             |   Bin 19140 -> 18800 bytes
 examples/data/thumb/calendar-heatmap.jpg           |   Bin 24124 -> 23849 bytes
 examples/data/thumb/calendar-horizontal.jpg        |   Bin 46858 -> 46390 bytes
 examples/data/thumb/calendar-lunar.jpg             |   Bin 20790 -> 20195 bytes
 examples/data/thumb/calendar-pie.jpg               |   Bin 43985 -> 43510 bytes
 examples/data/thumb/calendar-simple.jpg            |   Bin 18230 -> 18187 bytes
 examples/data/thumb/calendar-vertical.jpg          |   Bin 36035 -> 36186 bytes
 examples/data/thumb/candlestick-brush.jpg          |   Bin 24825 -> 24875 bytes
 examples/data/thumb/candlestick-large.jpg          |   Bin 26708 -> 26741 bytes
 examples/data/thumb/candlestick-sh-2015.jpg        |   Bin 16206 -> 16524 bytes
 examples/data/thumb/candlestick-sh.jpg             |   Bin 34018 -> 33855 bytes
 examples/data/thumb/candlestick-simple.jpg         |   Bin 11131 -> 11098 bytes
 examples/data/thumb/candlestick-touch.jpg          |   Bin 22392 -> 23052 bytes
 examples/data/thumb/confidence-band.jpg            |   Bin 12886 -> 12761 bytes
 examples/data/thumb/custom-bar-trend.jpg           |   Bin 25970 -> 25456 bytes
 examples/data/thumb/custom-calendar-icon.jpg       |   Bin 22301 -> 19689 bytes
 examples/data/thumb/custom-cartesian-polygon.jpg   |   Bin 18844 -> 18317 bytes
 examples/data/thumb/custom-error-bar.jpg           |   Bin 22724 -> 23319 bytes
 examples/data/thumb/custom-error-scatter.jpg       |   Bin 16081 -> 16077 bytes
 examples/data/thumb/custom-gantt-flight.jpg        |   Bin 32669 -> 32781 bytes
 examples/data/thumb/custom-hexbin.jpg              |   Bin 54317 -> 54253 bytes
 examples/data/thumb/custom-ohlc.jpg                |   Bin 19030 -> 19011 bytes
 examples/data/thumb/custom-polar-heatmap.jpg       |   Bin 17273 -> 17523 bytes
 examples/data/thumb/custom-profile.jpg             |   Bin 16687 -> 16916 bytes
 examples/data/thumb/custom-profit.jpg              |   Bin 12992 -> 12957 bytes
 examples/data/thumb/custom-wind.jpg                |   Bin 53212 -> 53212 bytes
 examples/data/thumb/cycle-plot.jpg                 |   Bin 21486 -> 21428 bytes
 examples/data/thumb/dataset-default.jpg            |   Bin 21364 -> 20847 bytes
 examples/data/thumb/dataset-encode0.jpg            |   Bin 18026 -> 17990 bytes
 examples/data/thumb/dataset-encode1.jpg            |   Bin 41512 -> 41510 bytes
 examples/data/thumb/dataset-link.jpg               |   Bin 22775 -> 22806 bytes
 examples/data/thumb/dataset-series-layout-by.jpg   |   Bin 22798 -> 22788 bytes
 examples/data/thumb/dataset-simple0.jpg            |   Bin 16475 -> 16458 bytes
 examples/data/thumb/dataset-simple1.jpg            |   Bin 16475 -> 16458 bytes
 examples/data/thumb/dynamic-data.jpg               |   Bin 23756 -> 22941 bytes
 examples/data/thumb/dynamic-data2.jpg              |   Bin 13916 -> 12926 bytes
 examples/data/thumb/effectScatter-bmap.jpg         |   Bin 30247 -> 30070 bytes
 examples/data/thumb/effectScatter-map.jpg          |   Bin 18304 -> 18289 bytes
 examples/data/thumb/funnel-align.jpg               |   Bin 22820 -> 22702 bytes
 examples/data/thumb/funnel-customize.jpg           |   Bin 16064 -> 15949 bytes
 examples/data/thumb/funnel-mutiple.jpg             |   Bin 22011 -> 21859 bytes
 examples/data/thumb/funnel.jpg                     |   Bin 13474 -> 13396 bytes
 examples/data/thumb/gauge-car-dark.jpg             |   Bin 17958 -> 17982 bytes
 examples/data/thumb/gauge-car.jpg                  |   Bin 17650 -> 17656 bytes
 examples/data/thumb/gauge.jpg                      |   Bin 12132 -> 12052 bytes
 examples/data/thumb/geo-lines.jpg                  |   Bin 14015 -> 13335 bytes
 examples/data/thumb/geo-map-scatter.jpg            |   Bin 20054 -> 19776 bytes
 examples/data/thumb/graph-circular-layout.jpg      |   Bin 48609 -> 48632 bytes
 examples/data/thumb/graph-force-dynamic.jpg        |   Bin 2903 -> 2929 bytes
 examples/data/thumb/graph-force.jpg                |   Bin 22470 -> 22757 bytes
 examples/data/thumb/graph-force2.jpg               |   Bin 17477 -> 17405 bytes
 examples/data/thumb/graph-grid.jpg                 |   Bin 16841 -> 16832 bytes
 examples/data/thumb/graph-life-expectancy.jpg      |   Bin 21922 -> 16429 bytes
 examples/data/thumb/graph-npm.jpg                  |   Bin 21494 -> 21555 bytes
 examples/data/thumb/graph-simple.jpg               |   Bin 13513 -> 13433 bytes
 examples/data/thumb/graph-webkit-dep.jpg           |   Bin 39578 -> 39378 bytes
 examples/data/thumb/graph.jpg                      |   Bin 26361 -> 26535 bytes
 examples/data/thumb/grid-multiple.jpg              |   Bin 27035 -> 27385 bytes
 examples/data/thumb/heatmap-bmap.jpg               |   Bin 52668 -> 50726 bytes
 examples/data/thumb/heatmap-cartesian.jpg          |   Bin 23158 -> 22905 bytes
 examples/data/thumb/heatmap-large-piecewise.jpg    |   Bin 45294 -> 41558 bytes
 examples/data/thumb/heatmap-large.jpg              |   Bin 33545 -> 28416 bytes
 examples/data/thumb/heatmap-map.jpg                |   Bin 14088 -> 13997 bytes
 examples/data/thumb/line-aqi.jpg                   |   Bin 36015 -> 36030 bytes
 examples/data/thumb/line-draggable.jpg             |   Bin 16803 -> 16777 bytes
 examples/data/thumb/line-easing.jpg                |   Bin 32016 -> 31984 bytes
 examples/data/thumb/line-function.jpg              |   Bin 0 -> 27616 bytes
 examples/data/thumb/line-gradient.jpg              |   Bin 20330 -> 20997 bytes
 examples/data/thumb/line-graphic.jpg               |   Bin 25209 -> 24122 bytes
 .../thumb/line-in-cartesian-coordinate-system.jpg  |   Bin 11667 -> 11662 bytes
 examples/data/thumb/line-log.jpg                   |   Bin 17950 -> 24651 bytes
 examples/data/thumb/line-marker.jpg                |   Bin 23750 -> 23649 bytes
 examples/data/thumb/line-pen.jpg                   |   Bin 14515 -> 14452 bytes
 examples/data/thumb/line-polar.jpg                 |   Bin 19915 -> 19855 bytes
 examples/data/thumb/line-polar2.jpg                |   Bin 26583 -> 26513 bytes
 examples/data/thumb/line-sections.jpg              |   Bin 17760 -> 17651 bytes
 examples/data/thumb/line-simple.jpg                |   Bin 10539 -> 10522 bytes
 examples/data/thumb/line-smooth.jpg                |   Bin 10635 -> 10616 bytes
 examples/data/thumb/line-stack.jpg                 |   Bin 21333 -> 21105 bytes
 examples/data/thumb/line-step.jpg                  |   Bin 16370 -> 16326 bytes
 examples/data/thumb/line-style.jpg                 |   Bin 12015 -> 12006 bytes
 examples/data/thumb/line-tooltip-touch.jpg         |   Bin 17056 -> 16187 bytes
 examples/data/thumb/line-y-category.jpg            |   Bin 17513 -> 16870 bytes
 examples/data/thumb/lines-airline.jpg              |   Bin 28340 -> 28392 bytes
 examples/data/thumb/lines-bmap-bus.jpg             |   Bin 52849 -> 50623 bytes
 examples/data/thumb/lines-bmap-effect.jpg          |   Bin 2490 -> 135693 bytes
 examples/data/thumb/lines-bmap.jpg                 |   Bin 39359 -> 39357 bytes
 examples/data/thumb/map-HK.jpg                     |   Bin 28324 -> 28298 bytes
 examples/data/thumb/map-bin.jpg                    |   Bin 43047 -> 43081 bytes
 examples/data/thumb/map-china-dataRange.jpg        |   Bin 29026 -> 29178 bytes
 examples/data/thumb/map-china.jpg                  |   Bin 23485 -> 23455 bytes
 examples/data/thumb/map-labels.jpg                 |   Bin 32135 -> 31528 bytes
 examples/data/thumb/map-locate.jpg                 |   Bin 23325 -> 23258 bytes
 examples/data/thumb/map-parallel-prices.jpg        |   Bin 32704 -> 32548 bytes
 examples/data/thumb/map-polygon.jpg                |   Bin 31550 -> 31454 bytes
 examples/data/thumb/map-province.jpg               |   Bin 13103 -> 13113 bytes
 examples/data/thumb/map-usa.jpg                    |   Bin 19235 -> 19275 bytes
 examples/data/thumb/map-world-dataRange.jpg        |   Bin 25438 -> 25381 bytes
 examples/data/thumb/mix-line-bar.jpg               |   Bin 22190 -> 22126 bytes
 examples/data/thumb/mix-timeline-finance.jpg       |   Bin 31728 -> 31733 bytes
 examples/data/thumb/mix-zoom-on-value.jpg          |   Bin 26150 -> 26129 bytes
 examples/data/thumb/multiple-x-axis.jpg            |   Bin 17608 -> 17496 bytes
 examples/data/thumb/multiple-y-axis.jpg            |   Bin 24464 -> 24398 bytes
 examples/data/thumb/parallel-aqi.jpg               |   Bin 39858 -> 39518 bytes
 examples/data/thumb/parallel-nutrients.jpg         |   Bin 47015 -> 47250 bytes
 examples/data/thumb/parallel-simple.jpg            |   Bin 13818 -> 13761 bytes
 examples/data/thumb/pictorialBar-body-fill.jpg     |   Bin 17441 -> 17363 bytes
 examples/data/thumb/pictorialBar-dotted.jpg        |   Bin 22788 -> 24180 bytes
 examples/data/thumb/pictorialBar-forest.jpg        |   Bin 6213 -> 6202 bytes
 examples/data/thumb/pictorialBar-hill.jpg          |   Bin 28111 -> 28058 bytes
 examples/data/thumb/pictorialBar-spirit.jpg        |   Bin 22905 -> 22818 bytes
 examples/data/thumb/pictorialBar-vehicle.jpg       |   Bin 21533 -> 21544 bytes
 examples/data/thumb/pictorialBar-velocity.jpg      |   Bin 14476 -> 14433 bytes
 examples/data/thumb/pie-alignTo.jpg                |   Bin 0 -> 14573 bytes
 examples/data/thumb/pie-custom.jpg                 |   Bin 7792 -> 7785 bytes
 examples/data/thumb/pie-doughnut.jpg               |   Bin 11806 -> 11710 bytes
 examples/data/thumb/pie-legend.jpg                 |   Bin 16171 -> 16706 bytes
 examples/data/thumb/pie-nest.jpg                   |   Bin 30543 -> 30094 bytes
 examples/data/thumb/pie-pattern.jpg                |   Bin 39837 -> 39635 bytes
 examples/data/thumb/pie-rich-text.jpg              |   Bin 16392 -> 16200 bytes
 examples/data/thumb/pie-roseType.jpg               |   Bin 17039 -> 16819 bytes
 examples/data/thumb/pie-simple.jpg                 |   Bin 14930 -> 14702 bytes
 examples/data/thumb/radar-aqi.jpg                  |   Bin 17681 -> 17576 bytes
 examples/data/thumb/radar-custom.jpg               |   Bin 21231 -> 21077 bytes
 examples/data/thumb/radar-multiple.jpg             |   Bin 20138 -> 18377 bytes
 examples/data/thumb/radar.jpg                      |   Bin 23544 -> 23489 bytes
 examples/data/thumb/radar2.jpg                     |   Bin 24094 -> 23795 bytes
 examples/data/thumb/sankey-energy.jpg              |   Bin 40212 -> 40537 bytes
 examples/data/thumb/sankey-itemstyle.jpg           |   Bin 29408 -> 29334 bytes
 examples/data/thumb/sankey-levels.jpg              |   Bin 32339 -> 32630 bytes
 examples/data/thumb/sankey-nodeAlign-left.jpg      |   Bin 39130 -> 39435 bytes
 examples/data/thumb/sankey-nodeAlign-right.jpg     |   Bin 37680 -> 37965 bytes
 examples/data/thumb/sankey-simple.jpg              |   Bin 9854 -> 9847 bytes
 examples/data/thumb/sankey-vertical.jpg            |   Bin 10219 -> 10212 bytes
 examples/data/thumb/scatter-anscombe-quartet.jpg   |   Bin 25433 -> 25369 bytes
 examples/data/thumb/scatter-aqi-color.jpg          |   Bin 24430 -> 23760 bytes
 examples/data/thumb/scatter-clustering-process.jpg |   Bin 18734 -> 18758 bytes
 examples/data/thumb/scatter-effect.jpg             |   Bin 21266 -> 21259 bytes
 .../data/thumb/scatter-exponential-regression.jpg  |   Bin 26706 -> 26585 bytes
 examples/data/thumb/scatter-large.jpg              |   Bin 23805 -> 23674 bytes
 .../thumb/scatter-life-expectancy-timeline.jpg     |   Bin 17534 -> 17452 bytes
 examples/data/thumb/scatter-linear-regression.jpg  |   Bin 19274 -> 19210 bytes
 .../data/thumb/scatter-logarithmic-regression.jpg  |   Bin 21092 -> 21089 bytes
 examples/data/thumb/scatter-map-brush.jpg          |   Bin 33077 -> 32916 bytes
 examples/data/thumb/scatter-map.jpg                |   Bin 18434 -> 18434 bytes
 examples/data/thumb/scatter-matrix.jpg             |   Bin 40506 -> 40475 bytes
 examples/data/thumb/scatter-nebula.jpg             |   Bin 33336 -> 33219 bytes
 examples/data/thumb/scatter-nutrients-matrix.jpg   |   Bin 27154 -> 27147 bytes
 examples/data/thumb/scatter-nutrients.jpg          |   Bin 10791 -> 10822 bytes
 examples/data/thumb/scatter-painter-choice.jpg     |   Bin 31434 -> 31551 bytes
 examples/data/thumb/scatter-polar-punchCard.jpg    |   Bin 23740 -> 23760 bytes
 .../data/thumb/scatter-polynomial-regression.jpg   |   Bin 31177 -> 30961 bytes
 examples/data/thumb/scatter-punchCard.jpg          |   Bin 27132 -> 26993 bytes
 examples/data/thumb/scatter-simple.jpg             |   Bin 11654 -> 11613 bytes
 examples/data/thumb/scatter-single-axis.jpg        |   Bin 30546 -> 30478 bytes
 examples/data/thumb/scatter-stream-visual.jpg      |   Bin 32075 -> 32101 bytes
 examples/data/thumb/scatter-weibo.jpg              |   Bin 33699 -> 33773 bytes
 examples/data/thumb/scatter-weight.jpg             |   Bin 40414 -> 40490 bytes
 examples/data/thumb/scatter-world-population.jpg   |   Bin 15630 -> 15647 bytes
 examples/data/thumb/sunburst-book.jpg              |   Bin 37588 -> 36905 bytes
 examples/data/thumb/sunburst-drink.jpg             |   Bin 52036 -> 52160 bytes
 examples/data/thumb/sunburst-label-rotate.jpg      |   Bin 17110 -> 17101 bytes
 examples/data/thumb/sunburst-simple.jpg            |   Bin 17201 -> 17196 bytes
 examples/data/thumb/sunburst-visualMap.jpg         |   Bin 17448 -> 17428 bytes
 examples/data/thumb/themeRiver-basic.jpg           |   Bin 22143 -> 22135 bytes
 examples/data/thumb/themeRiver-lastfm.jpg          |   Bin 24609 -> 24605 bytes
 examples/data/thumb/tree-basic.jpg                 |   Bin 26699 -> 26938 bytes
 examples/data/thumb/tree-legend.jpg                |   Bin 34552 -> 34248 bytes
 examples/data/thumb/tree-orient-bottom-top.jpg     |   Bin 36298 -> 36271 bytes
 examples/data/thumb/tree-orient-right-left.jpg     |   Bin 30457 -> 30551 bytes
 examples/data/thumb/tree-polyline.jpg              |   Bin 0 -> 29218 bytes
 examples/data/thumb/tree-radial.jpg                |   Bin 58897 -> 58675 bytes
 examples/data/thumb/tree-vertical.jpg              |   Bin 32999 -> 32923 bytes
 examples/data/thumb/treemap-disk.jpg               |   Bin 27926 -> 27908 bytes
 examples/data/thumb/treemap-drill-down.jpg         |   Bin 30688 -> 30636 bytes
 examples/data/thumb/treemap-obama.jpg              |   Bin 32571 -> 32700 bytes
 examples/data/thumb/treemap-show-parent.jpg        |   Bin 28162 -> 28224 bytes
 examples/data/thumb/treemap-simple.jpg             |   Bin 9594 -> 9727 bytes
 examples/data/thumb/treemap-visual.jpg             |   Bin 24899 -> 24899 bytes
 examples/data/thumb/watermark.jpg                  |   Bin 41143 -> 40170 bytes
 examples/data/thumb/wind-barb.jpg                  |   Bin 33943 -> 34140 bytes
 examples/data/tree-basic.js                        |    18 +-
 examples/data/tree-legend.js                       |    38 +-
 examples/data/tree-orient-bottom-top.js            |    16 +-
 examples/data/tree-orient-right-left.js            |    12 +-
 examples/data/tree-polyline.js                     |   169 +
 examples/data/tree-vertical.js                     |    22 +-
 examples/data/treemap-disk.js                      |    24 +-
 examples/data/treemap-drill-down.js                |    29 +-
 examples/data/treemap-show-parent.js               |    46 +-
 examples/data/treemap-visual.js                    |    12 +-
 examples/data/watermark.js                         |    14 +-
 examples/data/wind-barb.js                         |    28 +-
 examples/en/editor.html                            |     4 +-
 examples/en/index.html                             |     4 +-
 examples/en/view.html                              |     4 +-
 examples/javascripts/chart-list-data.js            |     2 +-
 examples/javascripts/chart-list.js                 |     2 +-
 examples/javascripts/chart-list.tpl.js             |     2 +-
 examples/javascripts/common.js                     |     2 +-
 examples/javascripts/editor.js                     |     2 +-
 examples/javascripts/login.js                      |     2 +-
 examples/javascripts/view.js                       |     2 +-
 examples/screenshot.html                           |     6 +
 examples/stylesheets/main.css                      |     2 +-
 examples/vendors/echarts/echarts.js                |  2878 +-
 examples/vendors/echarts/echarts.min.js            |     2 +-
 .../vendors/echarts/map/json/province/tianjin.json |     2 +-
 examples/zh/editor.html                            |     4 +-
 examples/zh/index.html                             |     4 +-
 examples/zh/view.html                              |     4 +-
 images/404.png                                     |   Bin 72998 -> 25182 bytes
 images/about/1.png                                 |   Bin 36618 -> 35765 bytes
 images/about/2.png                                 |   Bin 77291 -> 76438 bytes
 images/about/3.png                                 |   Bin 114969 -> 114116 bytes
 images/about/4.png                                 |   Bin 67588 -> 66735 bytes
 images/about/5.png                                 |   Bin 140731 -> 139878 bytes
 images/about/6.png                                 |   Bin 56879 -> 56026 bytes
 images/about/7.png                                 |   Bin 102847 -> 101994 bytes
 images/about/8.png                                 |   Bin 17302 -> 17237 bytes
 images/about/xiaomi.png                            |   Bin 12462 -> 12397 bytes
 images/banners/2017-03-23-ife.png                  |   Bin 30268 -> 30255 bytes
 images/banners/2017-09-12-zhibo.png                |   Bin 93489 -> 60788 bytes
 images/bg.png                                      |   Bin 55761 -> 8242 bytes
 images/bg2.png                                     |   Bin 17932 -> 3966 bytes
 images/btn-arrow.png                               |   Bin 448 -> 435 bytes
 images/btn-download.png                            |   Bin 775 -> 762 bytes
 images/btn-email.png                               |   Bin 1226 -> 1213 bytes
 images/btn-github.png                              |   Bin 1178 -> 1165 bytes
 images/btn-weibo.png                               |   Bin 1661 -> 1648 bytes
 images/btn-weixin.png                              |   Bin 1383 -> 1370 bytes
 images/builder/checked.png                         |   Bin 1069 -> 216 bytes
 images/chart-icon.png                              |   Bin 13805 -> 7543 bytes
 images/company/company1.jpg                        |   Bin 0 -> 11324 bytes
 images/company/company10.jpg                       |   Bin 0 -> 7953 bytes
 images/company/company11.jpg                       |   Bin 0 -> 8823 bytes
 images/company/company12.jpg                       |   Bin 0 -> 9716 bytes
 images/company/company13.jpg                       |   Bin 0 -> 7639 bytes
 images/company/company14.jpg                       |   Bin 0 -> 7003 bytes
 images/company/company15.jpg                       |   Bin 0 -> 10120 bytes
 images/company/company16.jpg                       |   Bin 0 -> 10401 bytes
 images/company/company17.jpg                       |   Bin 0 -> 9665 bytes
 images/company/company17.png                       |   Bin 51321 -> 32161 bytes
 images/company/company18.jpg                       |   Bin 0 -> 11317 bytes
 images/company/company19.jpg                       |   Bin 0 -> 11519 bytes
 images/company/company2.jpg                        |   Bin 0 -> 10556 bytes
 images/company/company20.jpg                       |   Bin 0 -> 11313 bytes
 images/company/company21.jpg                       |   Bin 0 -> 6808 bytes
 images/company/company22.jpg                       |   Bin 0 -> 8389 bytes
 images/company/company23.jpg                       |   Bin 0 -> 9652 bytes
 images/company/company24.jpg                       |   Bin 0 -> 9962 bytes
 images/company/company3.jpg                        |   Bin 0 -> 14135 bytes
 images/company/company4.jpg                        |   Bin 0 -> 9337 bytes
 images/company/company5.jpg                        |   Bin 0 -> 11358 bytes
 images/company/company6.jpg                        |   Bin 0 -> 10886 bytes
 images/company/company7.jpg                        |   Bin 0 -> 10223 bytes
 images/company/company8.jpg                        |   Bin 0 -> 8969 bytes
 images/company/company9.jpg                        |   Bin 0 -> 6736 bytes
 images/echarts-footer-logo.png                     |   Bin 7564 -> 7551 bytes
 images/echarts-footer-text.png                     |   Bin 1272 -> 1259 bytes
 images/extensions/default-extension.png            |   Bin 2028 -> 2015 bytes
 images/favicon.png                                 |   Bin 1592 -> 1534 bytes
 images/feature-1.png                               |   Bin 116562 -> 38354 bytes
 images/features/capetown-taxi.jpg                  |   Bin 0 -> 260801 bytes
 images/features/population.jpg                     |   Bin 0 -> 264046 bytes
 images/features/scatterGL.jpg                      |   Bin 0 -> 272203 bytes
 images/features/scatterGL2.jpg                     |   Bin 0 -> 841023 bytes
 images/features/scatterGL3.jpg                     |   Bin 0 -> 676108 bytes
 images/features/scatterGL4.jpg                     |   Bin 0 -> 108548 bytes
 images/forie.png                                   |   Bin 171716 -> 170668 bytes
 images/github.png                                  |   Bin 2330 -> 1477 bytes
 images/gongzhonghao.png                            |   Bin 36677 -> 26811 bytes
 images/icon-email.png                              |   Bin 807 -> 794 bytes
 images/icon-github.png                             |   Bin 936 -> 923 bytes
 images/icon-twitter.png                            |   Bin 667 -> 654 bytes
 images/icon-weibo.png                              |   Bin 1334 -> 1321 bytes
 images/index-bg.jpg                                |   Bin 0 -> 89931 bytes
 images/index-chart/handle.png                      |   Bin 1252 -> 941 bytes
 images/index-chart/handle2.png                     |   Bin 567 -> 343 bytes
 images/index-chart/iphone.png                      |   Bin 98448 -> 40811 bytes
 images/index-feature.jpg                           |   Bin 0 -> 40717 bytes
 images/index/1.png                                 |   Bin 38600 -> 37747 bytes
 images/index/2.png                                 |   Bin 80174 -> 79321 bytes
 images/index/3.png                                 |   Bin 114969 -> 114116 bytes
 images/index/4.png                                 |   Bin 67588 -> 66735 bytes
 images/index/5.png                                 |   Bin 140731 -> 139878 bytes
 images/index/6.png                                 |   Bin 56760 -> 55907 bytes
 images/index/7.png                                 |   Bin 104606 -> 103753 bytes
 images/index/device.png                            |   Bin 85318 -> 84466 bytes
 images/index/device1.png                           |   Bin 87517 -> 84803 bytes
 images/index/earth.png                             |   Bin 79622 -> 79564 bytes
 images/index/echarts.png                           |   Bin 33008 -> 32076 bytes
 images/index/file.png                              |   Bin 5035 -> 4977 bytes
 images/index/footer.png                            |   Bin 4333 -> 3280 bytes
 images/index/header.png                            |   Bin 6172 -> 5119 bytes
 images/index/line.png                              |   Bin 32795 -> 31863 bytes
 images/index/shadow.png                            |   Bin 5919 -> 5861 bytes
 images/liquid-fill.png                             |   Bin 31358 -> 31345 bytes
 images/logo.png                                    |   Bin 3765 -> 3707 bytes
 images/map.png                                     |   Bin 283943 -> 213619 bytes
 images/no-map.png                                  |   Bin 8135 -> 5421 bytes
 images/people/JB.jpg                               |   Bin 0 -> 11124 bytes
 images/people/clement.jpg                          |   Bin 0 -> 15297 bytes
 images/people/company23.png                        |   Bin 0 -> 21862 bytes
 images/people/dave.jpg                             |   Bin 0 -> 16282 bytes
 images/people/erik.jpg                             |   Bin 0 -> 11633 bytes
 images/people/shengwu.jpg                          |   Bin 0 -> 21227 bytes
 images/people/tedliu.jpg                           |   Bin 0 -> 20061 bytes
 images/people/weizhi.jpg                           |   Bin 0 -> 2755 bytes
 "images/people/\345\221\250\346\211\254.jpg"       |   Bin 0 -> 12931 bytes
 "images/people/\345\221\250\347\216\211.jpg"       |   Bin 0 -> 10531 bytes
 "images/people/\345\244\247\344\275\233.jpg"       |   Bin 0 -> 15272 bytes
 .../\345\250\204\345\220\214\345\205\265.jpg"      |   Bin 0 -> 3781 bytes
 "images/people/\345\256\277\347\210\275.jpg"       |   Bin 0 -> 11379 bytes
 "images/people/\345\260\217\347\272\242.jpg"       |   Bin 0 -> 11866 bytes
 "images/people/\345\264\224\345\201\245.jpg"       |   Bin 59107 -> 16049 bytes
 "images/people/\345\276\267\346\270\205.jpg"       |   Bin 0 -> 12525 bytes
 "images/people/\346\235\216\346\271\233.jpg"       |   Bin 0 -> 8841 bytes
 "images/people/\346\235\250\351\252\245.jpg"       |   Bin 0 -> 7938 bytes
 "images/people/\346\236\227\345\263\260.jpg"       |   Bin 0 -> 11455 bytes
 .../\346\241\221\346\226\207\351\224\213.jpg"      |   Bin 0 -> 10187 bytes
 "images/people/\346\262\210\346\257\205.jpg"       |   Bin 0 -> 14879 bytes
 "images/people/\346\262\210\346\265\251.jpg"       |   Bin 0 -> 14390 bytes
 .../\347\216\213\344\277\212\345\251\267.jpg"      |   Bin 0 -> 15272 bytes
 "images/people/\347\216\213\347\220\274.jpg"       |   Bin 0 -> 11084 bytes
 "images/people/\347\224\260\345\275\247.jpg"       |   Bin 0 -> 10827 bytes
 "images/people/\347\245\226\346\230\216.jpg"       |   Bin 0 -> 9594 bytes
 "images/people/\347\246\271\345\263\260.jpg"       |   Bin 0 -> 45945 bytes
 "images/people/\347\272\242\350\226\257.jpg"       |   Bin 0 -> 9180 bytes
 "images/people/\347\276\241\350\276\231.jpg"       |   Bin 0 -> 10468 bytes
 .../\350\213\217\346\200\235\346\226\207.jpg"      |   Bin 0 -> 11949 bytes
 .../\350\242\201\346\231\223\345\246\202.jpg"      |   Bin 0 -> 9551 bytes
 .../\350\260\242\347\233\212\350\276\211.jpg"      |   Bin 0 -> 9078 bytes
 "images/people/\350\265\265\351\233\267.jpg"       |   Bin 0 -> 10305 bytes
 "images/people/\351\230\277\346\226\207.jpg"       |   Bin 0 -> 18650 bytes
 "images/people/\351\231\210\344\270\272.jpg"       |   Bin 0 -> 12405 bytes
 "images/people/\351\237\251\345\244\251.jpg"       |   Bin 0 -> 13641 bytes
 .../\351\241\276\350\275\266\347\201\265.jpg"      |   Bin 0 -> 12951 bytes
 .../\351\255\217\345\244\252\344\272\221.jpg"      |   Bin 0 -> 8541 bytes
 .../\351\273\204\345\277\227\346\225\217.jpg"      |   Bin 0 -> 9617 bytes
 "images/people/\351\273\204\346\202\246.jpg"       |   Bin 0 -> 10449 bytes
 images/pipeline.jpg                                |   Bin 0 -> 169902 bytes
 images/yinhao.png                                  |   Bin 2898 -> 1371 bytes
 layouts/basic.html                                 |    20 +
 layouts/doc-old.html                               |    66 +
 layouts/doc.html                                   |    22 +
 layouts/redirect.html                              |     6 +
 vendors/echarts/echarts-20190709.min.js            |    22 +
 video/feature-1.jpg                                |   Bin 167910 -> 52108 bytes
 video/feature-2.jpg                                |   Bin 165749 -> 46538 bytes
 video/feature-4.jpg                                |   Bin 0 -> 64394 bytes
 video/index-4.jpg                                  |   Bin 463029 -> 133895 bytes
 video/index.jpg                                    |   Bin 97216 -> 27348 bytes
 zh/404.html                                        |     2 +-
 zh/api.html                                        |    74 +-
 zh/builder.html                                    |     8 +-
 zh/builder3.html                                   |     4 +-
 zh/changelog.html                                  |  1252 +-
 zh/cheat-sheet.html                                |     6 +-
 zh/coding-standard.html                            |     2 +-
 zh/committers.html                                 |     6 +-
 zh/css/doc-bundle.css                              |  1009 +
 zh/css/ecOption.css                                |   723 +-
 zh/css/element-icons.ttf                           |   Bin 0 -> 55956 bytes
 zh/css/element-icons.woff                          |   Bin 0 -> 28200 bytes
 zh/css/main.css                                    |     2 +-
 zh/demo.html                                       |     4 +-
 zh/dependencies.html                               |     2 +-
 zh/download-extension.html                         |     4 +-
 zh/download-map.html                               |     2 +-
 zh/download-theme.html                             |     4 +-
 zh/download.html                                   |     8 +-
 zh/download3.html                                  |     4 +-
 zh/examples.html                                   |     2 +-
 zh/faq.html                                        |     2 +-
 zh/feature.html                                    |     4 +-
 zh/index.html                                      |     4 +-
 zh/js/chart-list.js                                |     2 +-
 zh/js/cheat-sheet-en.js                            |     2 +-
 zh/js/cheat-sheet.js                               |     2 +-
 zh/js/common.js                                    |     2 +-
 zh/js/doc-bundle.js                                |    14 +
 zh/js/docTool/main.js                              |     4 +-
 zh/js/download.js                                  |     2 +-
 zh/js/examples-nav.js                              |     2 +-
 zh/js/index.js                                     |     2 +-
 zh/maillist.html                                   |     2 +-
 zh/option-gl.html                                  |    62 +-
 zh/option.html                                     |    62 +-
 zh/option3.html                                    |     8 +-
 zh/spreadsheet.html                                |     8 +-
 zh/tutorial.html                                   |    76 +-
 1519 files changed, 72461 insertions(+), 50832 deletions(-)

diff --git a/builder/echarts.html b/builder/echarts.html
index 7c1851a..395f20e 100644
--- a/builder/echarts.html
+++ b/builder/echarts.html
@@ -56,7 +56,7 @@
                 'esprima': 'lib/esprima',
                 'estraverse': 'lib/estraverse'
             },
-            urlArgs: 'v=4.2.1'
+            urlArgs: 'v=1577826208731'
         });
 
         require(['build']);
diff --git a/builder/src/echarts/action/createDataSelectAction.js b/builder/src/echarts/action/createDataSelectAction.js
index f636a46..7ed8578 100644
--- a/builder/src/echarts/action/createDataSelectAction.js
+++ b/builder/src/echarts/action/createDataSelectAction.js
@@ -47,7 +47,8 @@ export default function (seriesType, actionInfos) {
       });
       return {
         name: payload.name,
-        selected: selected
+        selected: selected,
+        seriesId: payload.seriesId
       };
     });
   });
diff --git a/builder/src/echarts/chart/bar.js b/builder/src/echarts/chart/bar.js
index 3324318..16af134 100644
--- a/builder/src/echarts/chart/bar.js
+++ b/builder/src/echarts/chart/bar.js
@@ -24,9 +24,10 @@ import './bar/BarSeries';
 import './bar/BarView'; // In case developer forget to include grid component
 
 import '../component/gridSimple';
-echarts.registerLayout(zrUtil.curry(layout, 'bar')); // Should after normal bar layout, otherwise it is blocked by normal bar layout.
+echarts.registerLayout(echarts.PRIORITY.VISUAL.LAYOUT, zrUtil.curry(layout, 'bar')); // Use higher prority to avoid to be blocked by other overall layout, which do not
+// only exist in this module, but probably also exist in other modules, like `barPolar`.
 
-echarts.registerLayout(largeLayout);
+echarts.registerLayout(echarts.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, largeLayout);
 echarts.registerVisual({
   seriesType: 'bar',
   reset: function (seriesModel) {
diff --git a/builder/src/echarts/chart/bar/BarSeries.js b/builder/src/echarts/chart/bar/BarSeries.js
index f478ae6..df6f6aa 100644
--- a/builder/src/echarts/chart/bar/BarSeries.js
+++ b/builder/src/echarts/chart/bar/BarSeries.js
@@ -43,5 +43,13 @@ export default BaseBarSeries.extend({
     }
 
     return progressiveThreshold;
+  },
+  defaultOption: {
+    // If clipped
+    // Only available on cartesian2d
+    clip: true,
+    // If use caps on two sides of bars
+    // Only available on tangential polar bar
+    roundCap: false
   }
 });
\ No newline at end of file
diff --git a/builder/src/echarts/chart/bar/BarView.js b/builder/src/echarts/chart/bar/BarView.js
index c682286..96d8167 100644
--- a/builder/src/echarts/chart/bar/BarView.js
+++ b/builder/src/echarts/chart/bar/BarView.js
@@ -24,10 +24,39 @@ import { setLabel } from './helper';
 import Model from '../../model/Model';
 import barItemStyle from './barItemStyle';
 import Path from 'zrender/src/graphic/Path';
-var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth']; // FIXME
+import { throttle } from '../../util/throttle';
+import { createClipPath } from '../helper/createClipPathFromCoordSys';
+import Sausage from '../../util/shape/sausage';
+var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth'];
+var _eventPos = [0, 0]; // FIXME
 // Just for compatible with ec2.
 
 zrUtil.extend(Model.prototype, barItemStyle);
+
+function getClipArea(coord, data) {
+  var coordSysClipArea = coord.getArea && coord.getArea();
+
+  if (coord.type === 'cartesian2d') {
+    var baseAxis = coord.getBaseAxis(); // When boundaryGap is false or using time axis. bar may exceed the grid.
+    // We should not clip this part.
+    // See test/bar2.html
+
+    if (baseAxis.type !== 'category' || !baseAxis.onBand) {
+      var expandWidth = data.getLayout('bandWidth');
+
+      if (baseAxis.isHorizontal()) {
+        coordSysClipArea.x -= expandWidth;
+        coordSysClipArea.width += expandWidth * 2;
+      } else {
+        coordSysClipArea.y -= expandWidth;
+        coordSysClipArea.height += expandWidth * 2;
+      }
+    }
+  }
+
+  return coordSysClipArea;
+}
+
 export default echarts.extendChartView({
   type: 'bar',
   render: function (seriesModel, ecModel, api) {
@@ -74,6 +103,13 @@ export default echarts.extendChartView({
     }
 
     var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null;
+    var needsClip = seriesModel.get('clip', true);
+    var coordSysClipArea = getClipArea(coord, data); // If there is clipPath created in large mode. Remove it.
+
+    group.removeClipPath(); // We don't use clipPath in normal mode because we needs a perfect animation
+    // And don't want the label are clipped.
+
+    var roundCap = seriesModel.get('roundCap', true);
     data.diff(oldData).add(function (dataIndex) {
       if (!data.hasValue(dataIndex)) {
         return;
@@ -81,7 +117,19 @@ export default echarts.extendChartView({
 
       var itemModel = data.getItemModel(dataIndex);
       var layout = getLayout[coord.type](data, dataIndex, itemModel);
-      var el = elementCreator[coord.type](data, dataIndex, itemModel, layout, isHorizontalOrRadial, animationModel);
+
+      if (needsClip) {
+        // Clip will modify the layout params.
+        // And return a boolean to determine if the shape are fully clipped.
+        var isClipped = clip[coord.type](coordSysClipArea, layout);
+
+        if (isClipped) {
+          group.remove(el);
+          return;
+        }
+      }
+
+      var el = elementCreator[coord.type](dataIndex, layout, isHorizontalOrRadial, animationModel, false, roundCap);
       data.setItemGraphicEl(dataIndex, el);
       group.add(el);
       updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar');
@@ -96,12 +144,21 @@ export default echarts.extendChartView({
       var itemModel = data.getItemModel(newIndex);
       var layout = getLayout[coord.type](data, newIndex, itemModel);
 
+      if (needsClip) {
+        var isClipped = clip[coord.type](coordSysClipArea, layout);
+
+        if (isClipped) {
+          group.remove(el);
+          return;
+        }
+      }
+
       if (el) {
         graphic.updateProps(el, {
           shape: layout
         }, animationModel, newIndex);
       } else {
-        el = elementCreator[coord.type](data, newIndex, itemModel, layout, isHorizontalOrRadial, animationModel, true);
+        el = elementCreator[coord.type](newIndex, layout, isHorizontalOrRadial, animationModel, true, roundCap);
       }
 
       data.setItemGraphicEl(newIndex, el); // Add back
@@ -122,7 +179,15 @@ export default echarts.extendChartView({
   _renderLarge: function (seriesModel, ecModel, api) {
     this._clear();
 
-    createLarge(seriesModel, this.group);
+    createLarge(seriesModel, this.group); // Use clipPath in large mode.
+
+    var clipPath = seriesModel.get('clip', true) ? createClipPath(seriesModel.coordinateSystem, false, seriesModel) : null;
+
+    if (clipPath) {
+      this.group.setClipPath(clipPath);
+    } else {
+      this.group.removeClipPath();
+    }
   },
   _incrementalRenderLarge: function (params, seriesModel) {
     createLarge(seriesModel, this.group, true);
@@ -150,8 +215,51 @@ export default echarts.extendChartView({
     this._data = null;
   }
 });
+var mathMax = Math.max;
+var mathMin = Math.min;
+var clip = {
+  cartesian2d: function (coordSysBoundingRect, layout) {
+    var signWidth = layout.width < 0 ? -1 : 1;
+    var signHeight = layout.height < 0 ? -1 : 1; // Needs positive width and height
+
+    if (signWidth < 0) {
+      layout.x += layout.width;
+      layout.width = -layout.width;
+    }
+
+    if (signHeight < 0) {
+      layout.y += layout.height;
+      layout.height = -layout.height;
+    }
+
+    var x = mathMax(layout.x, coordSysBoundingRect.x);
+    var x2 = mathMin(layout.x + layout.width, coordSysBoundingRect.x + coordSysBoundingRect.width);
+    var y = mathMax(layout.y, coordSysBoundingRect.y);
+    var y2 = mathMin(layout.y + layout.height, coordSysBoundingRect.y + coordSysBoundingRect.height);
+    layout.x = x;
+    layout.y = y;
+    layout.width = x2 - x;
+    layout.height = y2 - y;
+    var clipped = layout.width < 0 || layout.height < 0; // Reverse back
+
+    if (signWidth < 0) {
+      layout.x += layout.width;
+      layout.width = -layout.width;
+    }
+
+    if (signHeight < 0) {
+      layout.y += layout.height;
+      layout.height = -layout.height;
+    }
+
+    return clipped;
+  },
+  polar: function (coordSysClipArea) {
+    return false;
+  }
+};
 var elementCreator = {
-  cartesian2d: function (data, dataIndex, itemModel, layout, isHorizontal, animationModel, isUpdate) {
+  cartesian2d: function (dataIndex, layout, isHorizontal, animationModel, isUpdate) {
     var rect = new graphic.Rect({
       shape: zrUtil.extend({}, layout)
     }); // Animation
@@ -169,13 +277,14 @@ var elementCreator = {
 
     return rect;
   },
-  polar: function (data, dataIndex, itemModel, layout, isRadial, animationModel, isUpdate) {
+  polar: function (dataIndex, layout, isRadial, animationModel, isUpdate, roundCap) {
     // Keep the same logic with bar in catesion: use end value to control
     // direction. Notice that if clockwise is true (by default), the sector
     // will always draw clockwisely, no matter whether endAngle is greater
     // or less than startAngle.
     var clockwise = layout.startAngle < layout.endAngle;
-    var sector = new graphic.Sector({
+    var ShapeClass = !isRadial && roundCap ? Sausage : graphic.Sector;
+    var sector = new ShapeClass({
       shape: zrUtil.defaults({
         clockwise: clockwise
       }, layout)
@@ -247,9 +356,14 @@ var getLayout = {
   }
 };
 
+function isZeroOnPolar(layout) {
+  return layout.startAngle != null && layout.endAngle != null && layout.startAngle === layout.endAngle;
+}
+
 function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar) {
   var color = data.getItemVisual(dataIndex, 'color');
   var opacity = data.getItemVisual(dataIndex, 'opacity');
+  var stroke = data.getVisual('borderColor');
   var itemStyleModel = itemModel.getModel('itemStyle');
   var hoverStyle = itemModel.getModel('emphasis.itemStyle').getBarItemStyle();
 
@@ -258,7 +372,8 @@ function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHori
   }
 
   el.useStyle(zrUtil.defaults({
-    fill: color,
+    stroke: isZeroOnPolar(layout) ? 'none' : stroke,
+    fill: isZeroOnPolar(layout) ? 'none' : color,
     opacity: opacity
   }, itemStyleModel.getBarItemStyle()));
   var cursorStyle = itemModel.getShallow('cursor');
@@ -269,6 +384,10 @@ function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHori
     setLabel(el.style, hoverStyle, itemModel, color, seriesModel, dataIndex, labelPositionOutside);
   }
 
+  if (isZeroOnPolar(layout)) {
+    hoverStyle.fill = hoverStyle.stroke = 'none';
+  }
+
   graphic.setHoverStyle(el, hoverStyle);
 } // In case width or height are too small.
 
@@ -288,10 +407,10 @@ var LargePath = Path.extend({
     // a whole line or drawing rects.
     var points = shape.points;
     var startPoint = this.__startPoint;
-    var valueIdx = this.__valueIdx;
+    var baseDimIdx = this.__baseDimIdx;
 
     for (var i = 0; i < points.length; i += 2) {
-      startPoint[this.__valueIdx] = points[i + valueIdx];
+      startPoint[baseDimIdx] = points[i + baseDimIdx];
       ctx.moveTo(startPoint[0], startPoint[1]);
       ctx.lineTo(points[i], points[i + 1]);
     }
@@ -302,18 +421,61 @@ function createLarge(seriesModel, group, incremental) {
   // TODO support polar
   var data = seriesModel.getData();
   var startPoint = [];
-  var valueIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
-  startPoint[1 - valueIdx] = data.getLayout('valueAxisStart');
+  var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
+  startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart');
   var el = new LargePath({
     shape: {
       points: data.getLayout('largePoints')
     },
     incremental: !!incremental,
     __startPoint: startPoint,
-    __valueIdx: valueIdx
+    __baseDimIdx: baseDimIdx,
+    __largeDataIndices: data.getLayout('largeDataIndices'),
+    __barWidth: data.getLayout('barWidth')
   });
   group.add(el);
-  setLargeStyle(el, seriesModel, data);
+  setLargeStyle(el, seriesModel, data); // Enable tooltip and user mouse/touch event handlers.
+
+  el.seriesIndex = seriesModel.seriesIndex;
+
+  if (!seriesModel.get('silent')) {
+    el.on('mousedown', largePathUpdateDataIndex);
+    el.on('mousemove', largePathUpdateDataIndex);
+  }
+} // Use throttle to avoid frequently traverse to find dataIndex.
+
+
+var largePathUpdateDataIndex = throttle(function (event) {
+  var largePath = this;
+  var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY);
+  largePath.dataIndex = dataIndex >= 0 ? dataIndex : null;
+}, 30, false);
+
+function largePathFindDataIndex(largePath, x, y) {
+  var baseDimIdx = largePath.__baseDimIdx;
+  var valueDimIdx = 1 - baseDimIdx;
+  var points = largePath.shape.points;
+  var largeDataIndices = largePath.__largeDataIndices;
+  var barWidthHalf = Math.abs(largePath.__barWidth / 2);
+  var startValueVal = largePath.__startPoint[valueDimIdx];
+  _eventPos[0] = x;
+  _eventPos[1] = y;
+  var pointerBaseVal = _eventPos[baseDimIdx];
+  var pointerValueVal = _eventPos[1 - baseDimIdx];
+  var baseLowerBound = pointerBaseVal - barWidthHalf;
+  var baseUpperBound = pointerBaseVal + barWidthHalf;
+
+  for (var i = 0, len = points.length / 2; i < len; i++) {
+    var ii = i * 2;
+    var barBaseVal = points[ii + baseDimIdx];
+    var barValueVal = points[ii + valueDimIdx];
+
+    if (barBaseVal >= baseLowerBound && barBaseVal <= baseUpperBound && (startValueVal <= barValueVal ? pointerValueVal >= startValueVal && pointerValueVal <= barValueVal : pointerValueVal >= barValueVal && pointerValueVal <= startValueVal)) {
+      return largeDataIndices[i];
+    }
+  }
+
+  return -1;
 }
 
 function setLargeStyle(el, seriesModel, data) {
diff --git a/builder/src/echarts/chart/bar/BaseBarSeries.js b/builder/src/echarts/chart/bar/BaseBarSeries.js
index efba127..6db321c 100644
--- a/builder/src/echarts/chart/bar/BaseBarSeries.js
+++ b/builder/src/echarts/chart/bar/BaseBarSeries.js
@@ -21,7 +21,9 @@ import createListFromArray from '../helper/createListFromArray';
 export default SeriesModel.extend({
   type: 'series.__base_bar__',
   getInitialData: function (option, ecModel) {
-    return createListFromArray(this.getSource(), this);
+    return createListFromArray(this.getSource(), this, {
+      useEncodeDefaulter: true
+    });
   },
   getMarkerPosition: function (value) {
     var coordSys = this.coordinateSystem;
@@ -60,6 +62,8 @@ export default SeriesModel.extend({
     progressive: 3e3,
     progressiveChunkMode: 'mod',
     // barMaxWidth: null,
+    // In cartesian, the default value is 1. Otherwise null.
+    // barMinWidth: null,
     // 默认自适应
     // barWidth: null,
     // 柱间距离,默认为柱形宽度的30%,可设固定值
diff --git a/builder/src/echarts/chart/candlestick/CandlestickSeries.js b/builder/src/echarts/chart/candlestick/CandlestickSeries.js
index 26aecad..34b3b1d 100644
--- a/builder/src/echarts/chart/candlestick/CandlestickSeries.js
+++ b/builder/src/echarts/chart/candlestick/CandlestickSeries.js
@@ -59,6 +59,7 @@ var CandlestickSeries = SeriesModel.extend({
     // yAxisIndex: 0,
     layout: null,
     // 'horizontal' or 'vertical'
+    clip: true,
     itemStyle: {
       color: '#c23531',
       // 阳线 positive
diff --git a/builder/src/echarts/chart/candlestick/CandlestickView.js b/builder/src/echarts/chart/candlestick/CandlestickView.js
index b1347a9..c651435 100644
--- a/builder/src/echarts/chart/candlestick/CandlestickView.js
+++ b/builder/src/echarts/chart/candlestick/CandlestickView.js
@@ -20,12 +20,16 @@ import * as zrUtil from 'zrender/src/core/util';
 import ChartView from '../../view/Chart';
 import * as graphic from '../../util/graphic';
 import Path from 'zrender/src/graphic/Path';
+import { createClipPath } from '../helper/createClipPathFromCoordSys';
 var NORMAL_ITEM_STYLE_PATH = ['itemStyle'];
 var EMPHASIS_ITEM_STYLE_PATH = ['emphasis', 'itemStyle'];
 var SKIP_PROPS = ['color', 'color0', 'borderColor', 'borderColor0'];
 var CandlestickView = ChartView.extend({
   type: 'candlestick',
   render: function (seriesModel, ecModel, api) {
+    // If there is clipPath created in large mode. Remove it.
+    this.group.removeClipPath();
+
     this._updateDrawMode(seriesModel);
 
     this._isLargeDraw ? this._renderLarge(seriesModel) : this._renderNormal(seriesModel);
@@ -51,7 +55,10 @@ var CandlestickView = ChartView.extend({
     var data = seriesModel.getData();
     var oldData = this._data;
     var group = this.group;
-    var isSimpleBox = data.getLayout('isSimpleBox'); // There is no old data only when first rendering or switching from
+    var isSimpleBox = data.getLayout('isSimpleBox');
+    var needsClip = seriesModel.get('clip', true);
+    var coord = seriesModel.coordinateSystem;
+    var clipArea = coord.getArea && coord.getArea(); // There is no old data only when first rendering or switching from
     // stream mode to normal mode, where previous elements should be removed.
 
     if (!this._data) {
@@ -62,6 +69,11 @@ var CandlestickView = ChartView.extend({
       if (data.hasValue(newIdx)) {
         var el;
         var itemLayout = data.getItemLayout(newIdx);
+
+        if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) {
+          return;
+        }
+
         el = createNormalBox(itemLayout, newIdx, true);
         graphic.initProps(el, {
           shape: {
@@ -82,6 +94,11 @@ var CandlestickView = ChartView.extend({
 
       var itemLayout = data.getItemLayout(newIdx);
 
+      if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) {
+        group.remove(el);
+        return;
+      }
+
       if (!el) {
         el = createNormalBox(itemLayout, newIdx);
       } else {
@@ -105,6 +122,13 @@ var CandlestickView = ChartView.extend({
     this._clear();
 
     createLarge(seriesModel, this.group);
+    var clipPath = seriesModel.get('clip', true) ? createClipPath(seriesModel.coordinateSystem, false, seriesModel) : null;
+
+    if (clipPath) {
+      this.group.setClipPath(clipPath);
+    } else {
+      this.group.removeClipPath();
+    }
   },
   _incrementalRenderNormal: function (params, seriesModel) {
     var data = seriesModel.getData();
@@ -165,6 +189,20 @@ function createNormalBox(itemLayout, dataIndex, isInit) {
   });
 }
 
+function isNormalBoxClipped(clipArea, itemLayout) {
+  var clipped = true;
+
+  for (var i = 0; i < itemLayout.ends.length; i++) {
+    // If any point are in the region.
+    if (clipArea.contain(itemLayout.ends[i][0], itemLayout.ends[i][1])) {
+      clipped = false;
+      break;
+    }
+  }
+
+  return clipped;
+}
+
 function setBoxCommon(el, data, dataIndex, isSimpleBox) {
   var itemModel = data.getItemModel(dataIndex);
   var normalItemStyleModel = itemModel.getModel(NORMAL_ITEM_STYLE_PATH);
diff --git a/builder/src/echarts/chart/candlestick/candlestickLayout.js b/builder/src/echarts/chart/candlestick/candlestickLayout.js
index f104d48..c30a6d9 100644
--- a/builder/src/echarts/chart/candlestick/candlestickLayout.js
+++ b/builder/src/echarts/chart/candlestick/candlestickLayout.js
@@ -117,7 +117,7 @@ export default {
 
     function largeProgress(params, data) {
       // Structure: [sign, x, yhigh, ylow, sign, x, yhigh, ylow, ...]
-      var points = new LargeArr(params.count * 5);
+      var points = new LargeArr(params.count * 4);
       var offset = 0;
       var point;
       var tmpIn = [];
@@ -133,7 +133,7 @@ export default {
 
         if (isNaN(axisDimVal) || isNaN(lowestVal) || isNaN(highestVal)) {
           points[offset++] = NaN;
-          offset += 4;
+          offset += 3;
           continue;
         }
 
diff --git a/builder/src/echarts/chart/chord/chordCircularLayout.js b/builder/src/echarts/chart/chord/chordCircularLayout.js
index b781393..0e8b8d3 100644
--- a/builder/src/echarts/chart/chord/chordCircularLayout.js
+++ b/builder/src/echarts/chart/chord/chordCircularLayout.js
@@ -16,12 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * Chord layout
- * @module echarts/chart/chord/chordCircularLayout
- * @author pissang(http://github.com/pissang)
- */
 import * as zrUtil from 'zrender/src/core/util';
 import { parsePercent } from '../../util/number';
 /**
diff --git a/builder/src/echarts/chart/custom.js b/builder/src/echarts/chart/custom.js
index 430aa6c..51bad24 100644
--- a/builder/src/echarts/chart/custom.js
+++ b/builder/src/echarts/chart/custom.js
@@ -24,12 +24,15 @@ import createListFromArray from './helper/createListFromArray';
 import { getLayoutOnAxis } from '../layout/barGrid';
 import DataDiffer from '../data/DataDiffer';
 import SeriesModel from '../model/Series';
+import Model from '../model/Model';
 import ChartView from '../view/Chart';
+import { createClipPath } from './helper/createClipPathFromCoordSys';
 import prepareCartesian2d from '../coord/cartesian/prepareCustom';
 import prepareGeo from '../coord/geo/prepareCustom';
 import prepareSingleAxis from '../coord/single/prepareCustom';
 import preparePolar from '../coord/polar/prepareCustom';
 import prepareCalendar from '../coord/calendar/prepareCustom';
+var CACHED_LABEL_STYLE_PROPERTIES = graphicUtil.CACHED_LABEL_STYLE_PROPERTIES;
 var ITEM_STYLE_NORMAL_PATH = ['itemStyle'];
 var ITEM_STYLE_EMPHASIS_PATH = ['emphasis', 'itemStyle'];
 var LABEL_NORMAL = ['label'];
@@ -68,7 +71,12 @@ SeriesModel.extend({
     zlevel: 0,
     z: 2,
     legendHoverLink: true,
-    useTransform: true // Cartesian coordinate system
+    useTransform: true,
+    // Custom series will not clip by default.
+    // Some case will use custom series to draw label
+    // For example https://echarts.apache.org/examples/en/editor.html?c=custom-gantt-flight
+    // Only works on polar and cartesian2d coordinate system.
+    clip: false // Cartesian coordinate system
     // xAxisIndex: 0,
     // yAxisIndex: 0,
     // Polar coordinate system
@@ -129,7 +137,16 @@ ChartView.extend({
     }).remove(function (oldIdx) {
       var el = oldData.getItemGraphicEl(oldIdx);
       el && group.remove(el);
-    }).execute();
+    }).execute(); // Do clipping
+
+    var clipPath = customSeries.get('clip', true) ? createClipPath(customSeries.coordinateSystem, false, customSeries) : null;
+
+    if (clipPath) {
+      group.setClipPath(clipPath);
+    } else {
+      group.removeClipPath();
+    }
+
     this._data = data;
   },
   incrementalPrepareRender: function (customSeries, ecModel, api) {
@@ -182,7 +199,8 @@ ChartView.extend({
 
 function createEl(elOption) {
   var graphicType = elOption.type;
-  var el;
+  var el; // Those graphic elements are not shapes. They should not be
+  // overwritten by users, so do them first.
 
   if (graphicType === 'path') {
     var shape = elOption.shape; // Using pathRect brings convenience to users sacle svg path.
@@ -203,8 +221,12 @@ function createEl(elOption) {
   } else if (graphicType === 'text') {
     el = new graphicUtil.Text({});
     el.__customText = elOption.style.text;
+  } else if (graphicType === 'group') {
+    el = new graphicUtil.Group();
+  } else if (graphicType === 'compoundPath') {
+    throw new Error('"compoundPath" is not supported yet.');
   } else {
-    var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)];
+    var Clz = graphicUtil.getShapeClass(graphicType);
     el = new Clz();
   }
 
@@ -273,18 +295,14 @@ function updateEl(el, dataIndex, elOption, animatableModel, data, isInit, isRoot
   elOption.hasOwnProperty('info') && el.attr('info', elOption.info); // If `elOption.styleEmphasis` is `false`, remove hover style. The
   // logic is ensured by `graphicUtil.setElementHoverStyle`.
 
-  var styleEmphasis = elOption.styleEmphasis;
-  var disableStyleEmphasis = styleEmphasis === false;
+  var styleEmphasis = elOption.styleEmphasis; // hoverStyle should always be set here, because if the hover style
+  // may already be changed, where the inner cache should be reset.
 
-  if (!( // Try to escapse setting hover style for performance.
-  el.__cusHasEmphStl && styleEmphasis == null || !el.__cusHasEmphStl && disableStyleEmphasis)) {
-    // Should not use graphicUtil.setHoverStyle, since the styleEmphasis
-    // should not be share by group and its descendants.
-    graphicUtil.setElementHoverStyle(el, styleEmphasis);
-    el.__cusHasEmphStl = !disableStyleEmphasis;
-  }
+  graphicUtil.setElementHoverStyle(el, styleEmphasis);
 
-  isRoot && graphicUtil.setAsHoverStyleTrigger(el, !disableStyleEmphasis);
+  if (isRoot) {
+    graphicUtil.setAsHighDownDispatcher(el, styleEmphasis !== false);
+  }
 }
 
 function prepareStyleTransition(prop, targetStyle, elOptionStyle, oldElStyle, isInit) {
@@ -387,12 +405,13 @@ function makeRenderItem(customSeries, data, ecModel, api) {
     currVisualColor != null && (itemStyle.fill = currVisualColor);
     var opacity = data.getItemVisual(dataIndexInside, 'opacity');
     opacity != null && (itemStyle.opacity = opacity);
-    graphicUtil.setTextStyle(itemStyle, currLabelNormalModel, null, {
+    var labelModel = extra ? applyExtraBefore(extra, currLabelNormalModel) : currLabelNormalModel;
+    graphicUtil.setTextStyle(itemStyle, labelModel, null, {
       autoColor: currVisualColor,
       isRectText: true
     });
-    itemStyle.text = currLabelNormalModel.getShallow('show') ? zrUtil.retrieve2(customSeries.getFormattedLabel(dataIndexInside, 'normal'), getDefaultLabel(data, dataIndexInside)) : null;
-    extra && zrUtil.extend(itemStyle, extra);
+    itemStyle.text = labelModel.getShallow('show') ? zrUtil.retrieve2(customSeries.getFormattedLabel(dataIndexInside, 'normal'), getDefaultLabel(data, dataIndexInside)) : null;
+    extra && applyExtraAfter(itemStyle, extra);
     return itemStyle;
   }
   /**
@@ -406,11 +425,12 @@ function makeRenderItem(customSeries, data, ecModel, api) {
     dataIndexInside == null && (dataIndexInside = currDataIndexInside);
     updateCache(dataIndexInside);
     var itemStyle = currItemModel.getModel(ITEM_STYLE_EMPHASIS_PATH).getItemStyle();
-    graphicUtil.setTextStyle(itemStyle, currLabelEmphasisModel, null, {
+    var labelModel = extra ? applyExtraBefore(extra, currLabelEmphasisModel) : currLabelEmphasisModel;
+    graphicUtil.setTextStyle(itemStyle, labelModel, null, {
       isRectText: true
     }, true);
-    itemStyle.text = currLabelEmphasisModel.getShallow('show') ? zrUtil.retrieve3(customSeries.getFormattedLabel(dataIndexInside, 'emphasis'), customSeries.getFormattedLabel(dataIndexInside, 'normal'), getDefaultLabel(data, dataIndexInside)) : null;
-    extra && zrUtil.extend(itemStyle, extra);
+    itemStyle.text = labelModel.getShallow('show') ? zrUtil.retrieve3(customSeries.getFormattedLabel(dataIndexInside, 'emphasis'), customSeries.getFormattedLabel(dataIndexInside, 'normal'), getDefaultLabel(data, dataIndexInside)) : null;
+    extra && applyExtraAfter(itemStyle, extra);
     return itemStyle;
   }
   /**
@@ -429,6 +449,7 @@ function makeRenderItem(customSeries, data, ecModel, api) {
    * @param {number} opt.count Positive interger.
    * @param {number} [opt.barWidth]
    * @param {number} [opt.barMaxWidth]
+   * @param {number} [opt.barMinWidth]
    * @param {number} [opt.barGap]
    * @param {number} [opt.barCategoryGap]
    * @return {Object} {width, offset, offsetCenter} is not support, return undefined.
@@ -595,6 +616,27 @@ function processAddUpdate(newIndex, oldIndex) {
   var childOption = newIndex != null ? context.newChildren[newIndex] : null;
   var child = oldIndex != null ? context.oldChildren[oldIndex] : null;
   doCreateOrUpdate(child, context.dataIndex, childOption, context.animatableModel, context.group, context.data);
+} // `graphic#applyDefaultTextStyle` will cache
+// textFill, textStroke, textStrokeWidth.
+// We have to do this trick.
+
+
+function applyExtraBefore(extra, model) {
+  var dummyModel = new Model({}, model);
+  zrUtil.each(CACHED_LABEL_STYLE_PROPERTIES, function (stylePropName, modelPropName) {
+    if (extra.hasOwnProperty(stylePropName)) {
+      dummyModel.option[modelPropName] = extra[stylePropName];
+    }
+  });
+  return dummyModel;
+}
+
+function applyExtraAfter(itemStyle, extra) {
+  for (var key in extra) {
+    if (extra.hasOwnProperty(key) || !CACHED_LABEL_STYLE_PROPERTIES.hasOwnProperty(key)) {
+      itemStyle[key] = extra[key];
+    }
+  }
 }
 
 function processRemove(oldIndex) {
diff --git a/builder/src/echarts/chart/effectScatter/EffectScatterSeries.js b/builder/src/echarts/chart/effectScatter/EffectScatterSeries.js
index 8aa9cca..7136f6b 100644
--- a/builder/src/echarts/chart/effectScatter/EffectScatterSeries.js
+++ b/builder/src/echarts/chart/effectScatter/EffectScatterSeries.js
@@ -22,7 +22,9 @@ export default SeriesModel.extend({
   type: 'series.effectScatter',
   dependencies: ['grid', 'polar'],
   getInitialData: function (option, ecModel) {
-    return createListFromArray(this.getSource(), this);
+    return createListFromArray(this.getSource(), this, {
+      useEncodeDefaulter: true
+    });
   },
   brushSelector: 'point',
   defaultOption: {
diff --git a/builder/src/echarts/chart/funnel/FunnelSeries.js b/builder/src/echarts/chart/funnel/FunnelSeries.js
index a0e08f2..eebf96b 100644
--- a/builder/src/echarts/chart/funnel/FunnelSeries.js
+++ b/builder/src/echarts/chart/funnel/FunnelSeries.js
@@ -17,23 +17,27 @@
 * under the License.
 */
 import * as echarts from '../../echarts';
+import * as zrUtil from 'zrender/src/core/util';
 import createListSimply from '../helper/createListSimply';
 import { defaultEmphasis } from '../../util/model';
+import { makeSeriesEncodeForNameBased } from '../../data/helper/sourceHelper';
+import LegendVisualProvider from '../../visual/LegendVisualProvider';
+import { bind } from 'zrender/src/core/util';
 var FunnelSeries = echarts.extendSeriesModel({
   type: 'series.funnel',
   init: function (option) {
     FunnelSeries.superApply(this, 'init', arguments); // Enable legend selection for each data item
     // Use a function instead of direct access because data reference may changed
 
-    this.legendDataProvider = function () {
-      return this.getRawData();
-    }; // Extend labelLine emphasis
-
+    this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); // Extend labelLine emphasis
 
     this._defaultLabelLine(option);
   },
   getInitialData: function (option, ecModel) {
-    return createListSimply(this, ['value']);
+    return createListSimply(this, {
+      coordDimensions: ['value'],
+      encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this)
+    });
   },
   _defaultLabelLine: function (option) {
     // Extend labelLine emphasis
diff --git a/builder/src/echarts/chart/funnel/FunnelView.js b/builder/src/echarts/chart/funnel/FunnelView.js
index 9345adf..5f0441d 100644
--- a/builder/src/echarts/chart/funnel/FunnelView.js
+++ b/builder/src/echarts/chart/funnel/FunnelView.js
@@ -33,19 +33,18 @@ function FunnelPiece(data, idx) {
   this.add(polygon);
   this.add(labelLine);
   this.add(text);
-  this.updateData(data, idx, true); // Hover to change label and labelLine
 
-  function onEmphasis() {
-    labelLine.ignore = labelLine.hoverIgnore;
-    text.ignore = text.hoverIgnore;
-  }
-
-  function onNormal() {
-    labelLine.ignore = labelLine.normalIgnore;
-    text.ignore = text.normalIgnore;
-  }
+  this.highDownOnUpdate = function (fromState, toState) {
+    if (toState === 'emphasis') {
+      labelLine.ignore = labelLine.hoverIgnore;
+      text.ignore = text.hoverIgnore;
+    } else {
+      labelLine.ignore = labelLine.normalIgnore;
+      text.ignore = text.normalIgnore;
+    }
+  };
 
-  this.on('emphasis', onEmphasis).on('normal', onNormal).on('mouseover', onEmphasis).on('mouseout', onNormal);
+  this.updateData(data, idx, true);
 }
 
 var funnelPieceProto = FunnelPiece.prototype;
diff --git a/builder/src/echarts/chart/funnel/funnelLayout.js b/builder/src/echarts/chart/funnel/funnelLayout.js
index 41ca62d..d262702 100644
--- a/builder/src/echarts/chart/funnel/funnelLayout.js
+++ b/builder/src/echarts/chart/funnel/funnelLayout.js
@@ -58,16 +58,27 @@ function labelLayout(data) {
     var labelLineModel = itemModel.getModel('labelLine');
     var layout = data.getItemLayout(idx);
     var points = layout.points;
-    var isLabelInside = labelPosition === 'inner' || labelPosition === 'inside' || labelPosition === 'center';
+    var isLabelInside = labelPosition === 'inner' || labelPosition === 'inside' || labelPosition === 'center' || labelPosition === 'insideLeft' || labelPosition === 'insideRight';
     var textAlign;
     var textX;
     var textY;
     var linePoints;
 
     if (isLabelInside) {
-      textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4;
-      textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4;
-      textAlign = 'center';
+      if (labelPosition === 'insideLeft') {
+        textX = (points[0][0] + points[3][0]) / 2 + 5;
+        textY = (points[0][1] + points[3][1]) / 2;
+        textAlign = 'left';
+      } else if (labelPosition === 'insideRight') {
+        textX = (points[1][0] + points[2][0]) / 2 - 5;
+        textY = (points[1][1] + points[2][1]) / 2;
+        textAlign = 'right';
+      } else {
+        textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4;
+        textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4;
+        textAlign = 'center';
+      }
+
       linePoints = [[textX, textY], [textX, textY]];
     } else {
       var x1;
@@ -82,6 +93,41 @@ function labelLayout(data) {
         x2 = x1 - labelLineLen;
         textX = x2 - 5;
         textAlign = 'right';
+      } else if (labelPosition === 'right') {
+        // Right 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';
+      } else if (labelPosition === 'rightTop') {
+        // RightTop side
+        x1 = points[1][0];
+        y1 = points[1][1];
+        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';
+      } else if (labelPosition === 'leftTop') {
+        // LeftTop side
+        x1 = points[0][0];
+        y1 = points[1][1];
+        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';
       } else {
         // Right side
         x1 = (points[1][0] + points[2][0]) / 2;
diff --git a/builder/src/echarts/chart/gauge/GaugeSeries.js b/builder/src/echarts/chart/gauge/GaugeSeries.js
index 5a2dbf5..aa87c10 100644
--- a/builder/src/echarts/chart/gauge/GaugeSeries.js
+++ b/builder/src/echarts/chart/gauge/GaugeSeries.js
@@ -18,17 +18,9 @@
 */
 import createListSimply from '../helper/createListSimply';
 import SeriesModel from '../../model/Series';
-import * as zrUtil from 'zrender/src/core/util';
 var GaugeSeries = SeriesModel.extend({
   type: 'series.gauge',
   getInitialData: function (option, ecModel) {
-    var dataOpt = option.data || [];
-
-    if (!zrUtil.isArray(dataOpt)) {
-      dataOpt = [dataOpt];
-    }
-
-    option.data = dataOpt;
     return createListSimply(this, ['value']);
   },
   defaultOption: {
diff --git a/builder/src/echarts/chart/gauge/GaugeView.js b/builder/src/echarts/chart/gauge/GaugeView.js
index 877935e..40030c3 100644
--- a/builder/src/echarts/chart/gauge/GaugeView.js
+++ b/builder/src/echarts/chart/gauge/GaugeView.js
@@ -69,8 +69,9 @@ var GaugeView = ChartView.extend({
     var angleRangeSpan = (endAngle - startAngle) % PI2;
     var prevEndAngle = startAngle;
     var axisLineWidth = lineStyleModel.get('width');
+    var showAxis = axisLineModel.get('show');
 
-    for (var i = 0; i < colorList.length; i++) {
+    for (var i = 0; showAxis && i < colorList.length; i++) {
       // Clamp
       var percent = Math.min(Math.max(colorList[i][0], 0), 1);
       var endAngle = startAngle + angleRangeSpan * percent;
diff --git a/builder/src/echarts/chart/graph.js b/builder/src/echarts/chart/graph.js
index bc1a77b..d44594c 100644
--- a/builder/src/echarts/chart/graph.js
+++ b/builder/src/echarts/chart/graph.js
@@ -33,7 +33,7 @@ echarts.registerVisual(visualSymbol('graph', 'circle', null));
 echarts.registerVisual(categoryVisual);
 echarts.registerVisual(edgeVisual);
 echarts.registerLayout(simpleLayout);
-echarts.registerLayout(circularLayout);
+echarts.registerLayout(echarts.PRIORITY.VISUAL.POST_CHART_LAYOUT, circularLayout);
 echarts.registerLayout(forceLayout); // Graph view coordinate system
 
 echarts.registerCoordinateSystem('graphView', {
diff --git a/builder/src/echarts/chart/graph/GraphSeries.js b/builder/src/echarts/chart/graph/GraphSeries.js
index 155bef8..6a68e4e 100644
--- a/builder/src/echarts/chart/graph/GraphSeries.js
+++ b/builder/src/echarts/chart/graph/GraphSeries.js
@@ -23,15 +23,19 @@ import { defaultEmphasis } from '../../util/model';
 import Model from '../../model/Model';
 import { encodeHTML } from '../../util/format';
 import createGraphFromNodeEdge from '../helper/createGraphFromNodeEdge';
+import LegendVisualProvider from '../../visual/LegendVisualProvider';
 var GraphSeries = echarts.extendSeriesModel({
   type: 'series.graph',
   init: function (option) {
-    GraphSeries.superApply(this, 'init', arguments); // Provide data for legend select
+    GraphSeries.superApply(this, 'init', arguments);
+    var self = this;
+
+    function getCategoriesData() {
+      return self._categoriesData;
+    } // Provide data for legend select
 
-    this.legendDataProvider = function () {
-      return this._categoriesData;
-    };
 
+    this.legendVisualProvider = new LegendVisualProvider(getCategoriesData, getCategoriesData);
     this.fillDataTextStyle(option.edges || option.links);
 
     this._updateCategoriesData();
@@ -185,6 +189,8 @@ var GraphSeries = echarts.extendSeriesModel({
       // Node repulsion. Can be an array to represent range.
       repulsion: [0, 50],
       gravity: 0.1,
+      // Initial friction
+      friction: 0.6,
       // Edge length. Can be an array to represent range.
       edgeLength: 30,
       layoutAnimation: true
diff --git a/builder/src/echarts/chart/graph/GraphView.js b/builder/src/echarts/chart/graph/GraphView.js
index 64e0a2e..c1fc4e8 100644
--- a/builder/src/echarts/chart/graph/GraphView.js
+++ b/builder/src/echarts/chart/graph/GraphView.js
@@ -25,13 +25,15 @@ import * as roamHelper from '../../component/helper/roamHelper';
 import { onIrrelevantElement } from '../../component/helper/cursorHelper';
 import * as graphic from '../../util/graphic';
 import adjustEdge from './adjustEdge';
+import { getNodeGlobalScale } from './graphHelper';
 var FOCUS_ADJACENCY = '__focusNodeAdjacency';
 var UNFOCUS_ADJACENCY = '__unfocusNodeAdjacency';
 var nodeOpacityPath = ['itemStyle', 'opacity'];
 var lineOpacityPath = ['lineStyle', 'opacity'];
 
 function getItemOpacity(item, opacityPath) {
-  return item.getVisual('opacity') || item.getModel().get(opacityPath);
+  var opacity = item.getVisual('opacity');
+  return opacity != null ? opacity : item.getModel().get(opacityPath);
 }
 
 function fadeOutItem(item, opacityPath, opacityRatio) {
@@ -45,7 +47,7 @@ function fadeOutItem(item, opacityPath, opacityRatio) {
 
   el.downplay && el.downplay();
   el.traverse(function (child) {
-    if (child.type !== 'group') {
+    if (!child.isGroup) {
       var opct = child.lineLabelOriginalOpacity;
 
       if (opct == null || opacityRatio != null) {
@@ -59,13 +61,14 @@ function fadeOutItem(item, opacityPath, opacityRatio) {
 
 function fadeInItem(item, opacityPath) {
   var opacity = getItemOpacity(item, opacityPath);
-  var el = item.getGraphicEl();
-  el.highlight && el.highlight();
+  var el = item.getGraphicEl(); // Should go back to normal opacity first, consider hoverLayer,
+  // where current state is copied to elMirror, and support
+  // emphasis opacity here.
+
   el.traverse(function (child) {
-    if (child.type !== 'group') {
-      child.setStyle('opacity', opacity);
-    }
+    !child.isGroup && child.setStyle('opacity', opacity);
   });
+  el.highlight && el.highlight();
 }
 
 export default echarts.extendChartView({
@@ -85,9 +88,9 @@ export default echarts.extendChartView({
     this._firstRender = true;
   },
   render: function (seriesModel, ecModel, api) {
+    var graphView = this;
     var coordSys = seriesModel.coordinateSystem;
     this._model = seriesModel;
-    this._nodeScaleRatio = seriesModel.get('nodeScaleRatio');
     var symbolDraw = this._symbolDraw;
     var lineDraw = this._lineDraw;
     var group = this.group;
@@ -106,7 +109,7 @@ export default echarts.extendChartView({
     } // Fix edge contact point with node
 
 
-    adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
+    adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));
     var data = seriesModel.getData();
     symbolDraw.updateData(data);
     var edgeData = seriesModel.getEdgeData();
@@ -152,6 +155,8 @@ export default echarts.extendChartView({
 
       if (itemModel.get('focusNodeAdjacency')) {
         el.on('mouseover', el[FOCUS_ADJACENCY] = function () {
+          graphView._clearTimer();
+
           api.dispatchAction({
             type: 'focusNodeAdjacency',
             seriesId: seriesModel.id,
@@ -159,10 +164,7 @@ export default echarts.extendChartView({
           });
         });
         el.on('mouseout', el[UNFOCUS_ADJACENCY] = function () {
-          api.dispatchAction({
-            type: 'unfocusNodeAdjacency',
-            seriesId: seriesModel.id
-          });
+          graphView._dispatchUnfocus(api);
         });
       }
     }, this);
@@ -173,6 +175,8 @@ export default echarts.extendChartView({
 
       if (edge.getModel().get('focusNodeAdjacency')) {
         el.on('mouseover', el[FOCUS_ADJACENCY] = function () {
+          graphView._clearTimer();
+
           api.dispatchAction({
             type: 'focusNodeAdjacency',
             seriesId: seriesModel.id,
@@ -180,10 +184,7 @@ export default echarts.extendChartView({
           });
         });
         el.on('mouseout', el[UNFOCUS_ADJACENCY] = function () {
-          api.dispatchAction({
-            type: 'unfocusNodeAdjacency',
-            seriesId: seriesModel.id
-          });
+          graphView._dispatchUnfocus(api);
         });
       }
     });
@@ -191,6 +192,8 @@ export default echarts.extendChartView({
     var cx = data.getLayout('cx');
     var cy = data.getLayout('cy');
     data.eachItemGraphicEl(function (el, idx) {
+      var itemModel = data.getItemModel(idx);
+      var labelRotate = itemModel.get('label.rotate') || 0;
       var symbolPath = el.getSymbolPath();
 
       if (circularRotateLabel) {
@@ -208,15 +211,16 @@ export default echarts.extendChartView({
         }
 
         var textPosition = isLeft ? 'left' : 'right';
-        symbolPath.setStyle({
+        graphic.modifyLabelStyle(symbolPath, {
           textRotation: -rad,
           textPosition: textPosition,
           textOrigin: 'center'
+        }, {
+          textPosition: textPosition
         });
-        symbolPath.hoverStyle && (symbolPath.hoverStyle.textPosition = textPosition);
       } else {
-        symbolPath.setStyle({
-          textRotation: 0
+        graphic.modifyLabelStyle(symbolPath, {
+          textRotation: labelRotate *= Math.PI / 180
         });
       }
     });
@@ -225,6 +229,27 @@ export default echarts.extendChartView({
   dispose: function () {
     this._controller && this._controller.dispose();
     this._controllerHost = {};
+
+    this._clearTimer();
+  },
+  _dispatchUnfocus: function (api, opt) {
+    var self = this;
+
+    this._clearTimer();
+
+    this._unfocusDelayTimer = setTimeout(function () {
+      self._unfocusDelayTimer = null;
+      api.dispatchAction({
+        type: 'unfocusNodeAdjacency',
+        seriesId: self._model.id
+      });
+    }, 500);
+  },
+  _clearTimer: function () {
+    if (this._unfocusDelayTimer) {
+      clearTimeout(this._unfocusDelayTimer);
+      this._unfocusDelayTimer = null;
+    }
   },
   focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
     var data = this._model.getData();
@@ -323,7 +348,7 @@ export default echarts.extendChartView({
 
       this._updateNodeAndLinkScale();
 
-      adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
+      adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));
 
       this._lineDraw.updateLayout();
     }, this);
@@ -331,31 +356,14 @@ export default echarts.extendChartView({
   _updateNodeAndLinkScale: function () {
     var seriesModel = this._model;
     var data = seriesModel.getData();
-
-    var nodeScale = this._getNodeGlobalScale(seriesModel);
-
+    var nodeScale = getNodeGlobalScale(seriesModel);
     var invScale = [nodeScale, nodeScale];
     data.eachItemGraphicEl(function (el, idx) {
       el.attr('scale', invScale);
     });
   },
-  _getNodeGlobalScale: function (seriesModel) {
-    var coordSys = seriesModel.coordinateSystem;
-
-    if (coordSys.type !== 'view') {
-      return 1;
-    }
-
-    var nodeScaleRatio = this._nodeScaleRatio;
-    var groupScale = coordSys.scale;
-    var groupZoom = groupScale && groupScale[0] || 1; // Scale node when zoom changes
-
-    var roamZoom = coordSys.getZoom();
-    var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
-    return nodeScale / groupZoom;
-  },
   updateLayout: function (seriesModel) {
-    adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
+    adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));
 
     this._symbolDraw.updateLayout();
 
diff --git a/builder/src/echarts/chart/graph/adjustEdge.js b/builder/src/echarts/chart/graph/adjustEdge.js
index 4550611..10ab767 100644
--- a/builder/src/echarts/chart/graph/adjustEdge.js
+++ b/builder/src/echarts/chart/graph/adjustEdge.js
@@ -18,6 +18,7 @@
 */
 import * as curveTool from 'zrender/src/core/curve';
 import * as vec2 from 'zrender/src/core/vector';
+import { getSymbolSize } from './graphHelper';
 var v1 = [];
 var v2 = [];
 var v3 = [];
@@ -92,17 +93,6 @@ export default function (graph, scale) {
   var pts2 = [[], []];
   var v = [];
   scale /= 2;
-
-  function getSymbolSize(node) {
-    var symbolSize = node.getVisual('symbolSize');
-
-    if (symbolSize instanceof Array) {
-      symbolSize = (symbolSize[0] + symbolSize[1]) / 2;
-    }
-
-    return symbolSize;
-  }
-
   graph.eachEdge(function (edge, idx) {
     var linePoints = edge.getLayout();
     var fromSymbol = edge.getVisual('fromSymbol');
diff --git a/builder/src/echarts/chart/graph/categoryVisual.js b/builder/src/echarts/chart/graph/categoryVisual.js
index 9e5e960..762a4d6 100644
--- a/builder/src/echarts/chart/graph/categoryVisual.js
+++ b/builder/src/echarts/chart/graph/categoryVisual.js
@@ -29,6 +29,15 @@ export default function (ecModel) {
       var itemModel = categoriesData.getItemModel(idx);
       var color = itemModel.get('itemStyle.color') || seriesModel.getColorFromPalette(name, paletteScope);
       categoriesData.setItemVisual(idx, 'color', color);
+      var itemStyleList = ['opacity', 'symbol', 'symbolSize', 'symbolKeepAspect'];
+
+      for (var i = 0; i < itemStyleList.length; i++) {
+        var itemStyle = itemModel.getShallow(itemStyleList[i], true);
+
+        if (itemStyle != null) {
+          categoriesData.setItemVisual(idx, itemStyleList[i], itemStyle);
+        }
+      }
     }); // Assign category color to visual
 
     if (categoriesData.count()) {
@@ -41,8 +50,12 @@ export default function (ecModel) {
             category = categoryNameIdxMap['ec-' + category];
           }
 
-          if (!data.getItemVisual(idx, 'color', true)) {
-            data.setItemVisual(idx, 'color', categoriesData.getItemVisual(category, 'color'));
+          var itemStyleList = ['color', 'opacity', 'symbol', 'symbolSize', 'symbolKeepAspect'];
+
+          for (var i = 0; i < itemStyleList.length; i++) {
+            if (data.getItemVisual(idx, itemStyleList[i], true) == null) {
+              data.setItemVisual(idx, itemStyleList[i], categoriesData.getItemVisual(category, itemStyleList[i]));
+            }
           }
         }
       });
diff --git a/builder/src/echarts/chart/graph/circularLayout.js b/builder/src/echarts/chart/graph/circularLayout.js
index d5f4804..0b3747c 100644
--- a/builder/src/echarts/chart/graph/circularLayout.js
+++ b/builder/src/echarts/chart/graph/circularLayout.js
@@ -20,7 +20,7 @@ import { circularLayout } from './circularLayoutHelper';
 export default function (ecModel) {
   ecModel.eachSeriesByType('graph', function (seriesModel) {
     if (seriesModel.get('layout') === 'circular') {
-      circularLayout(seriesModel);
+      circularLayout(seriesModel, 'symbolSize');
     }
   });
 }
\ No newline at end of file
diff --git a/builder/src/echarts/chart/graph/circularLayoutHelper.js b/builder/src/echarts/chart/graph/circularLayoutHelper.js
index 01273b9..3a57efc 100644
--- a/builder/src/echarts/chart/graph/circularLayoutHelper.js
+++ b/builder/src/echarts/chart/graph/circularLayoutHelper.js
@@ -17,7 +17,33 @@
 * under the License.
 */
 import * as vec2 from 'zrender/src/core/vector';
-export function circularLayout(seriesModel) {
+import { getSymbolSize, getNodeGlobalScale } from './graphHelper';
+var PI = Math.PI;
+var _symbolRadiansHalf = [];
+/**
+ * `basedOn` can be:
+ * 'value':
+ *     This layout is not accurate and have same bad case. For example,
+ *     if the min value is very smaller than the max value, the nodes
+ *     with the min value probably overlap even though there is enough
+ *     space to layout them. So we only use this approach in the as the
+ *     init layout of the force layout.
+ *     FIXME
+ *     Probably we do not need this method any more but use
+ *     `basedOn: 'symbolSize'` in force layout if
+ *     delay its init operations to GraphView.
+ * 'symbolSize':
+ *     This approach work only if all of the symbol size calculated.
+ *     That is, the progressive rendering is not applied to graph.
+ *     FIXME
+ *     If progressive rendering is applied to graph some day,
+ *     probably we have to use `basedOn: 'value'`.
+ *
+ * @param {module:echarts/src/model/Series} seriesModel
+ * @param {string} basedOn 'value' or 'symbolSize'
+ */
+
+export function circularLayout(seriesModel, basedOn) {
   var coordSys = seriesModel.coordinateSystem;
 
   if (coordSys && coordSys.type !== 'view') {
@@ -27,22 +53,21 @@ export function circularLayout(seriesModel) {
   var rect = coordSys.getBoundingRect();
   var nodeData = seriesModel.getData();
   var graph = nodeData.graph;
-  var angle = 0;
-  var sum = nodeData.getSum('value');
-  var unitAngle = Math.PI * 2 / (sum || nodeData.count());
   var cx = rect.width / 2 + rect.x;
   var cy = rect.height / 2 + rect.y;
   var r = Math.min(rect.width, rect.height) / 2;
-  graph.eachNode(function (node) {
-    var value = node.getValue('value');
-    angle += unitAngle * (sum ? value : 1) / 2;
-    node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]);
-    angle += unitAngle * (sum ? value : 1) / 2;
-  });
+  var count = nodeData.count();
   nodeData.setLayout({
     cx: cx,
     cy: cy
   });
+
+  if (!count) {
+    return;
+  }
+
+  _layoutNodesBasedOn[basedOn](seriesModel, coordSys, graph, nodeData, r, cx, cy, count);
+
   graph.eachEdge(function (edge) {
     var curveness = edge.getModel().get('lineStyle.curveness') || 0;
     var p1 = vec2.clone(edge.node1.getLayout());
@@ -58,4 +83,44 @@ export function circularLayout(seriesModel) {
 
     edge.setLayout([p1, p2, cp1]);
   });
-}
\ No newline at end of file
+}
+var _layoutNodesBasedOn = {
+  value: function (seriesModel, coordSys, graph, nodeData, r, cx, cy, count) {
+    var angle = 0;
+    var sum = nodeData.getSum('value');
+    var unitAngle = Math.PI * 2 / (sum || count);
+    graph.eachNode(function (node) {
+      var value = node.getValue('value');
+      var radianHalf = unitAngle * (sum ? value : 1) / 2;
+      angle += radianHalf;
+      node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]);
+      angle += radianHalf;
+    });
+  },
+  symbolSize: function (seriesModel, coordSys, graph, nodeData, r, cx, cy, count) {
+    var sumRadian = 0;
+    _symbolRadiansHalf.length = count;
+    var nodeScale = getNodeGlobalScale(seriesModel);
+    graph.eachNode(function (node) {
+      var symbolSize = getSymbolSize(node); // Normally this case will not happen, but we still add
+      // some the defensive code (2px is an arbitrary value).
+
+      isNaN(symbolSize) && (symbolSize = 2);
+      symbolSize < 0 && (symbolSize = 0);
+      symbolSize *= nodeScale;
+      var symbolRadianHalf = Math.asin(symbolSize / 2 / r); // when `symbolSize / 2` is bigger than `r`.
+
+      isNaN(symbolRadianHalf) && (symbolRadianHalf = PI / 2);
+      _symbolRadiansHalf[node.dataIndex] = symbolRadianHalf;
+      sumRadian += symbolRadianHalf * 2;
+    });
+    var halfRemainRadian = (2 * PI - sumRadian) / count / 2;
+    var angle = 0;
+    graph.eachNode(function (node) {
+      var radianHalf = halfRemainRadian + _symbolRadiansHalf[node.dataIndex];
+      angle += radianHalf;
+      node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]);
+      angle += radianHalf;
+    });
+  }
+};
\ No newline at end of file
diff --git a/builder/src/echarts/chart/graph/forceHelper.js b/builder/src/echarts/chart/graph/forceHelper.js
index d48a56e..45c5e23 100644
--- a/builder/src/echarts/chart/graph/forceHelper.js
+++ b/builder/src/echarts/chart/graph/forceHelper.js
@@ -62,10 +62,11 @@ export function forceLayout(nodes, edges, opts) {
   // var k2 = k * k;
 
 
-  var friction = 0.6;
+  var initialFriction = opts.friction == null ? 0.6 : opts.friction;
+  var friction = initialFriction;
   return {
     warmUp: function () {
-      friction = 0.5;
+      friction = initialFriction * 0.8;
     },
     setFixed: function (idx) {
       nodes[idx].fixed = true;
@@ -86,6 +87,11 @@ export function forceLayout(nodes, edges, opts) {
 
       for (var i = 0; i < edges.length; i++) {
         var e = edges[i];
+
+        if (e.ignoreForceLayout) {
+          continue;
+        }
+
         var n1 = e.n1;
         var n2 = e.n2;
         vec2.sub(v12, n2.p, n1.p);
diff --git a/builder/src/echarts/chart/graph/forceLayout.js b/builder/src/echarts/chart/graph/forceLayout.js
index ec20081..97a8fbb 100644
--- a/builder/src/echarts/chart/graph/forceLayout.js
+++ b/builder/src/echarts/chart/graph/forceLayout.js
@@ -46,7 +46,7 @@ export default function (ecModel) {
       } else if (!initLayout || initLayout === 'none') {
         simpleLayout(graphSeries);
       } else if (initLayout === 'circular') {
-        circularLayout(graphSeries);
+        circularLayout(graphSeries, 'value');
       }
 
       var nodeDataExtent = nodeData.getDataExtent('value');
@@ -88,18 +88,21 @@ export default function (ecModel) {
           d = (edgeLength[0] + edgeLength[1]) / 2;
         }
 
+        var edgeModel = edge.getModel();
         return {
           n1: nodes[edge.node1.dataIndex],
           n2: nodes[edge.node2.dataIndex],
           d: d,
-          curveness: edge.getModel().get('lineStyle.curveness') || 0
+          curveness: edgeModel.get('lineStyle.curveness') || 0,
+          ignoreForceLayout: edgeModel.get('ignoreForceLayout')
         };
       });
       var coordSys = graphSeries.coordinateSystem;
       var rect = coordSys.getBoundingRect();
       var forceInstance = forceLayout(nodes, edges, {
         rect: rect,
-        gravity: forceModel.get('gravity')
+        gravity: forceModel.get('gravity'),
+        friction: forceModel.get('friction')
       });
       var oldStep = forceInstance.step;
 
diff --git a/builder/src/echarts/chart/graph/graphHelper.js b/builder/src/echarts/chart/graph/graphHelper.js
new file mode 100644
index 0000000..0d5e3ba
--- /dev/null
+++ b/builder/src/echarts/chart/graph/graphHelper.js
@@ -0,0 +1,42 @@
+/*
+* 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.
+*/
+export function getNodeGlobalScale(seriesModel) {
+  var coordSys = seriesModel.coordinateSystem;
+
+  if (coordSys.type !== 'view') {
+    return 1;
+  }
+
+  var nodeScaleRatio = seriesModel.option.nodeScaleRatio;
+  var groupScale = coordSys.scale;
+  var groupZoom = groupScale && groupScale[0] || 1; // Scale node when zoom changes
+
+  var roamZoom = coordSys.getZoom();
+  var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
+  return nodeScale / groupZoom;
+}
+export function getSymbolSize(node) {
+  var symbolSize = node.getVisual('symbolSize');
+
+  if (symbolSize instanceof Array) {
+    symbolSize = (symbolSize[0] + symbolSize[1]) / 2;
+  }
+
+  return +symbolSize;
+}
\ No newline at end of file
diff --git a/builder/src/echarts/chart/heatmap/HeatmapLayer.js b/builder/src/echarts/chart/heatmap/HeatmapLayer.js
index 3fe50db..8b1bb81 100644
--- a/builder/src/echarts/chart/heatmap/HeatmapLayer.js
+++ b/builder/src/echarts/chart/heatmap/HeatmapLayer.js
@@ -18,14 +18,6 @@
 */
 
 /* global Uint8ClampedArray */
-
-/**
- * @file defines echarts Heatmap Chart
- * @author Ovilia (me@zhangwenli.com)
- * Inspired by https://github.com/mourner/simpleheat
- *
- * @module
- */
 import * as zrUtil from 'zrender/src/core/util';
 var GRADIENT_LEVELS = 256;
 /**
diff --git a/builder/src/echarts/chart/heatmap/HeatmapView.js b/builder/src/echarts/chart/heatmap/HeatmapView.js
index 10b4683..c25d6cf 100644
--- a/builder/src/echarts/chart/heatmap/HeatmapView.js
+++ b/builder/src/echarts/chart/heatmap/HeatmapView.js
@@ -140,10 +140,10 @@ export default echarts.extendChartView({
         var point = coordSys.dataToPoint([data.get(dataDims[0], idx), data.get(dataDims[1], idx)]);
         rect = new graphic.Rect({
           shape: {
-            x: point[0] - width / 2,
-            y: point[1] - height / 2,
-            width: width,
-            height: height
+            x: Math.floor(point[0] - width / 2),
+            y: Math.floor(point[1] - height / 2),
+            width: Math.ceil(width),
+            height: Math.ceil(height)
           },
           style: {
             fill: data.getItemVisual(idx, 'color'),
diff --git a/builder/src/echarts/chart/helper/EffectSymbol.js b/builder/src/echarts/chart/helper/EffectSymbol.js
index ee9ef41..3afb8a7 100644
--- a/builder/src/echarts/chart/helper/EffectSymbol.js
+++ b/builder/src/echarts/chart/helper/EffectSymbol.js
@@ -37,13 +37,14 @@ function normalizeSymbolSize(symbolSize) {
 }
 
 function updateRipplePath(rippleGroup, effectCfg) {
+  var color = effectCfg.rippleEffectColor || effectCfg.color;
   rippleGroup.eachChild(function (ripplePath) {
     ripplePath.attr({
       z: effectCfg.z,
       zlevel: effectCfg.zlevel,
       style: {
-        stroke: effectCfg.brushType === 'stroke' ? effectCfg.color : null,
-        fill: effectCfg.brushType === 'fill' ? effectCfg.color : null
+        stroke: effectCfg.brushType === 'stroke' ? color : null,
+        fill: effectCfg.brushType === 'fill' ? color : null
       }
     });
   });
@@ -82,9 +83,6 @@ effectSymbolProto.startEffectAnimation = function (effectCfg) {
   var rippleGroup = this.childAt(1);
 
   for (var i = 0; i < EFFECT_RIPPLE_NUMBER; i++) {
-    // var ripplePath = createSymbol(
-    //     symbolType, -0.5, -0.5, 1, 1, color
-    // );
     // If width/height are set too small (e.g., set to 1) on ios10
     // and macOS Sierra, a circle stroke become a rect, no matter what
     // the scale is set. So we set width/height as 2. See #4136.
@@ -189,6 +187,7 @@ effectSymbolProto.updateData = function (data, idx) {
   effectCfg.zlevel = itemModel.getShallow('zlevel') || 0;
   effectCfg.symbolType = symbolType;
   effectCfg.color = color;
+  effectCfg.rippleEffectColor = itemModel.get('rippleEffect.color');
   this.off('mouseover').off('mouseout').off('emphasis').off('normal');
 
   if (effectCfg.showEffectOn === 'render') {
diff --git a/builder/src/echarts/chart/helper/LargeSymbolDraw.js b/builder/src/echarts/chart/helper/LargeSymbolDraw.js
index b1613f6..d17858b 100644
--- a/builder/src/echarts/chart/helper/LargeSymbolDraw.js
+++ b/builder/src/echarts/chart/helper/LargeSymbolDraw.js
@@ -28,6 +28,7 @@ var LargeSymbolPath = graphic.extendShape({
     points: null
   },
   symbolProxy: null,
+  softClipShape: null,
   buildPath: function (path, shape) {
     var points = shape.points;
     var size = shape.size;
@@ -48,6 +49,10 @@ var LargeSymbolPath = graphic.extendShape({
         continue;
       }
 
+      if (this.softClipShape && !this.softClipShape.contain(x, y)) {
+        continue;
+      }
+
       symbolProxyShape.x = x - size[0] / 2;
       symbolProxyShape.y = y - size[1] / 2;
       symbolProxyShape.width = size[0];
@@ -73,6 +78,10 @@ var LargeSymbolPath = graphic.extendShape({
 
       if (isNaN(x) || isNaN(y)) {
         continue;
+      }
+
+      if (this.softClipShape && !this.softClipShape.contain(x, y)) {
+        continue;
       } // fillRect is faster than building a rect path and draw.
       // And it support light globalCompositeOperation.
 
@@ -119,10 +128,12 @@ largeSymbolProto.isPersistent = function () {
 /**
  * Update symbols draw by new data
  * @param {module:echarts/data/List} data
+ * @param {Object} opt
+ * @param {Object} [opt.clipShape]
  */
 
 
-largeSymbolProto.updateData = function (data) {
+largeSymbolProto.updateData = function (data, opt) {
   this.group.removeAll();
   var symbolEl = new LargeSymbolPath({
     rectHover: true,
@@ -132,7 +143,7 @@ largeSymbolProto.updateData = function (data) {
     points: data.getLayout('symbolPoints')
   });
 
-  this._setCommon(symbolEl, data);
+  this._setCommon(symbolEl, data, false, opt);
 
   this.group.add(symbolEl);
   this._incremental = null;
@@ -175,7 +186,7 @@ largeSymbolProto.incrementalPrepareUpdate = function (data) {
   }
 };
 
-largeSymbolProto.incrementalUpdate = function (taskParams, data) {
+largeSymbolProto.incrementalUpdate = function (taskParams, data, opt) {
   var symbolEl;
 
   if (this._incremental) {
@@ -197,11 +208,12 @@ largeSymbolProto.incrementalUpdate = function (taskParams, data) {
     points: data.getLayout('symbolPoints')
   });
 
-  this._setCommon(symbolEl, data, !!this._incremental);
+  this._setCommon(symbolEl, data, !!this._incremental, opt);
 };
 
-largeSymbolProto._setCommon = function (symbolEl, data, isIncremental) {
-  var hostModel = data.hostModel; // TODO
+largeSymbolProto._setCommon = function (symbolEl, data, isIncremental, opt) {
+  var hostModel = data.hostModel;
+  opt = opt || {}; // TODO
   // if (data.hasItemVisual.symbolSize) {
   //     // TODO typed array?
   //     symbolEl.setShape('sizes', data.mapArray(
@@ -215,7 +227,8 @@ largeSymbolProto._setCommon = function (symbolEl, data, isIncremental) {
 
   var size = data.getVisual('symbolSize');
   symbolEl.setShape('size', size instanceof Array ? size : [size, size]); // }
-  // Create symbolProxy to build path for each data
+
+  symbolEl.softClipShape = opt.clipShape || null; // Create symbolProxy to build path for each data
 
   symbolEl.symbolProxy = createSymbol(data.getVisual('symbol'), 0, 0, 0, 0); // Use symbolProxy setColor method
 
diff --git a/builder/src/echarts/chart/helper/Line.js b/builder/src/echarts/chart/helper/Line.js
index 437c806..1852a35 100644
--- a/builder/src/echarts/chart/helper/Line.js
+++ b/builder/src/echarts/chart/helper/Line.js
@@ -56,21 +56,20 @@ function createSymbol(name, lineData, idx) {
 
 function createLine(points) {
   var line = new LinePath({
-    name: 'line'
+    name: 'line',
+    subPixelOptimize: true
   });
   setLinePoints(line.shape, points);
   return line;
 }
 
 function setLinePoints(targetShape, points) {
-  var p1 = points[0];
-  var p2 = points[1];
-  var cp1 = points[2];
-  targetShape.x1 = p1[0];
-  targetShape.y1 = p1[1];
-  targetShape.x2 = p2[0];
-  targetShape.y2 = p2[1];
+  targetShape.x1 = points[0][0];
+  targetShape.y1 = points[0][1];
+  targetShape.x2 = points[1][0];
+  targetShape.y2 = points[1][1];
   targetShape.percent = 1;
+  var cp1 = points[2];
 
   if (cp1) {
     targetShape.cpx1 = cp1[0];
diff --git a/builder/src/echarts/chart/helper/LinePath.js b/builder/src/echarts/chart/helper/LinePath.js
index 8750832..42b9445 100644
--- a/builder/src/echarts/chart/helper/LinePath.js
+++ b/builder/src/echarts/chart/helper/LinePath.js
@@ -45,14 +45,19 @@ export default graphic.extendShape({
     cpy1: null
   },
   buildPath: function (ctx, shape) {
-    (isLine(shape) ? straightLineProto : bezierCurveProto).buildPath(ctx, shape);
+    this[isLine(shape) ? '_buildPathLine' : '_buildPathCurve'](ctx, shape);
   },
+  _buildPathLine: straightLineProto.buildPath,
+  _buildPathCurve: bezierCurveProto.buildPath,
   pointAt: function (t) {
-    return isLine(this.shape) ? straightLineProto.pointAt.call(this, t) : bezierCurveProto.pointAt.call(this, t);
+    return this[isLine(this.shape) ? '_pointAtLine' : '_pointAtCurve'](t);
   },
+  _pointAtLine: straightLineProto.pointAt,
+  _pointAtCurve: bezierCurveProto.pointAt,
   tangentAt: function (t) {
     var shape = this.shape;
-    var p = isLine(shape) ? [shape.x2 - shape.x1, shape.y2 - shape.y1] : bezierCurveProto.tangentAt.call(this, t);
+    var p = isLine(shape) ? [shape.x2 - shape.x1, shape.y2 - shape.y1] : this._tangentAtCurve(t);
     return vec2.normalize(p, p);
-  }
+  },
+  _tangentAtCurve: bezierCurveProto.tangentAt
 });
\ No newline at end of file
diff --git a/builder/src/echarts/chart/helper/Symbol.js b/builder/src/echarts/chart/helper/Symbol.js
index e70f85c..e926056 100644
--- a/builder/src/echarts/chart/helper/Symbol.js
+++ b/builder/src/echarts/chart/helper/Symbol.js
@@ -144,7 +144,7 @@ symbolProto.setZ = function (zlevel, z) {
 symbolProto.setDraggable = function (draggable) {
   var symbolPath = this.childAt(0);
   symbolPath.draggable = draggable;
-  symbolPath.cursor = draggable ? 'move' : 'pointer';
+  symbolPath.cursor = draggable ? 'move' : symbolPath.cursor;
 };
 /**
  * Update symbol properties
@@ -224,6 +224,14 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     symbolPath.useStyle({
       strokeNoScale: true
     });
+  } else {
+    symbolPath.setStyle({
+      opacity: null,
+      shadowBlur: null,
+      shadowOffsetX: null,
+      shadowOffsetY: null,
+      shadowColor: null
+    });
   }
 
   var itemStyle = seriesScope && seriesScope.itemStyle;
@@ -294,51 +302,35 @@ symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
     return useNameLabel ? data.getName(idx) : getDefaultLabel(data, idx);
   }
 
-  symbolPath.off('mouseover').off('mouseout').off('emphasis').off('normal');
-  symbolPath.hoverStyle = hoverItemStyle; // FIXME
-  // Do not use symbol.trigger('emphasis'), but use symbol.highlight() instead.
-
-  graphic.setHoverStyle(symbolPath);
   symbolPath.__symbolOriginalScale = getScale(symbolSize);
-
-  if (hoverAnimation && seriesModel.isAnimationEnabled()) {
-    // Note: consider `off`, should use static function here.
-    symbolPath.on('mouseover', onMouseOver).on('mouseout', onMouseOut).on('emphasis', onEmphasis).on('normal', onNormal);
-  }
+  symbolPath.hoverStyle = hoverItemStyle;
+  symbolPath.highDownOnUpdate = hoverAnimation && seriesModel.isAnimationEnabled() ? highDownOnUpdate : null;
+  graphic.setHoverStyle(symbolPath);
 };
 
-function onMouseOver() {
-  // see comment in `graphic.isInEmphasis`
-  !graphic.isInEmphasis(this) && onEmphasis.call(this);
-}
-
-function onMouseOut() {
-  // see comment in `graphic.isInEmphasis`
-  !graphic.isInEmphasis(this) && onNormal.call(this);
-}
-
-function onEmphasis() {
+function highDownOnUpdate(fromState, toState) {
   // Do not support this hover animation util some scenario required.
   // Animation can only be supported in hover layer when using `el.incremetal`.
   if (this.incremental || this.useHoverLayer) {
     return;
   }
 
-  var scale = this.__symbolOriginalScale;
-  var ratio = scale[1] / scale[0];
-  this.animateTo({
-    scale: [Math.max(scale[0] * 1.1, scale[0] + 3), Math.max(scale[1] * 1.1, scale[1] + 3 * ratio)]
-  }, 400, 'elasticOut');
-}
-
-function onNormal() {
-  if (this.incremental || this.useHoverLayer) {
-    return;
+  if (toState === 'emphasis') {
+    var scale = this.__symbolOriginalScale;
+    var ratio = scale[1] / scale[0];
+    var emphasisOpt = {
+      scale: [Math.max(scale[0] * 1.1, scale[0] + 3), Math.max(scale[1] * 1.1, scale[1] + 3 * ratio)]
+    }; // FIXME
+    // modify it after support stop specified animation.
+    // toState === fromState
+    //     ? (this.stopAnimation(), this.attr(emphasisOpt))
+
+    this.animateTo(emphasisOpt, 400, 'elasticOut');
+  } else if (toState === 'normal') {
+    this.animateTo({
+      scale: this.__symbolOriginalScale
+    }, 400, 'elasticOut');
   }
-
-  this.animateTo({
-    scale: this.__symbolOriginalScale
-  }, 400, 'elasticOut');
 }
 /**
  * @param {Function} cb
diff --git a/builder/src/echarts/chart/helper/createClipPathFromCoordSys.js b/builder/src/echarts/chart/helper/createClipPathFromCoordSys.js
new file mode 100644
index 0000000..b57df2f
--- /dev/null
+++ b/builder/src/echarts/chart/helper/createClipPathFromCoordSys.js
@@ -0,0 +1,96 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+import * as graphic from '../../util/graphic';
+import { round } from '../../util/number';
+
+function createGridClipPath(cartesian, hasAnimation, seriesModel) {
+  var rect = cartesian.getArea();
+  var isHorizontal = cartesian.getBaseAxis().isHorizontal();
+  var x = rect.x;
+  var y = rect.y;
+  var width = rect.width;
+  var height = rect.height;
+  var lineWidth = seriesModel.get('lineStyle.width') || 2; // Expand the clip path a bit to avoid the border is clipped and looks thinner
+
+  x -= lineWidth / 2;
+  y -= lineWidth / 2;
+  width += lineWidth;
+  height += lineWidth;
+  var clipPath = new graphic.Rect({
+    shape: {
+      x: x,
+      y: y,
+      width: width,
+      height: height
+    }
+  });
+
+  if (hasAnimation) {
+    clipPath.shape[isHorizontal ? 'width' : 'height'] = 0;
+    graphic.initProps(clipPath, {
+      shape: {
+        width: width,
+        height: height
+      }
+    }, seriesModel);
+  }
+
+  return clipPath;
+}
+
+function createPolarClipPath(polar, hasAnimation, seriesModel) {
+  var sectorArea = polar.getArea(); // Avoid float number rounding error for symbol on the edge of axis extent.
+
+  var clipPath = new graphic.Sector({
+    shape: {
+      cx: round(polar.cx, 1),
+      cy: round(polar.cy, 1),
+      r0: round(sectorArea.r0, 1),
+      r: round(sectorArea.r, 1),
+      startAngle: sectorArea.startAngle,
+      endAngle: sectorArea.endAngle,
+      clockwise: sectorArea.clockwise
+    }
+  });
+
+  if (hasAnimation) {
+    clipPath.shape.endAngle = sectorArea.startAngle;
+    graphic.initProps(clipPath, {
+      shape: {
+        endAngle: sectorArea.endAngle
+      }
+    }, seriesModel);
+  }
+
+  return clipPath;
+}
+
+function createClipPath(coordSys, hasAnimation, seriesModel) {
+  if (!coordSys) {
+    return null;
+  } else if (coordSys.type === 'polar') {
+    return createPolarClipPath(coordSys, hasAnimation, seriesModel);
+  } else if (coordSys.type === 'cartesian2d') {
+    return createGridClipPath(coordSys, hasAnimation, seriesModel);
+  }
+
+  return null;
+}
+
+export { createGridClipPath, createPolarClipPath, createClipPath };
\ No newline at end of file
diff --git a/builder/src/echarts/chart/helper/createListFromArray.js b/builder/src/echarts/chart/helper/createListFromArray.js
index 3170ae6..071e0a2 100644
--- a/builder/src/echarts/chart/helper/createListFromArray.js
+++ b/builder/src/echarts/chart/helper/createListFromArray.js
@@ -23,14 +23,16 @@ import { SOURCE_FORMAT_ORIGINAL } from '../../data/helper/sourceType';
 import { getDimensionTypeByAxis } from '../../data/helper/dimensionHelper';
 import { getDataItemValue } from '../../util/model';
 import CoordinateSystem from '../../CoordinateSystem';
-import { getCoordSysDefineBySeries } from '../../model/referHelper';
+import { getCoordSysInfoBySeries } from '../../model/referHelper';
 import Source from '../../data/Source';
 import { enableDataStack } from '../../data/helper/dataStackHelper';
+import { makeSeriesEncodeForAxisCoordSys } from '../../data/helper/sourceHelper';
 /**
  * @param {module:echarts/data/Source|Array} source Or raw data.
  * @param {module:echarts/model/Series} seriesModel
  * @param {Object} [opt]
  * @param {string} [opt.generateCoord]
+ * @param {boolean} [opt.useEncodeDefaulter]
  */
 
 function createListFromArray(source, seriesModel, opt) {
@@ -42,15 +44,15 @@ function createListFromArray(source, seriesModel, opt) {
 
   var coordSysName = seriesModel.get('coordinateSystem');
   var registeredCoordSys = CoordinateSystem.get(coordSysName);
-  var coordSysDefine = getCoordSysDefineBySeries(seriesModel);
+  var coordSysInfo = getCoordSysInfoBySeries(seriesModel);
   var coordSysDimDefs;
 
-  if (coordSysDefine) {
-    coordSysDimDefs = zrUtil.map(coordSysDefine.coordSysDims, function (dim) {
+  if (coordSysInfo) {
+    coordSysDimDefs = zrUtil.map(coordSysInfo.coordSysDims, function (dim) {
       var dimInfo = {
         name: dim
       };
-      var axisModel = coordSysDefine.axisMap.get(dim);
+      var axisModel = coordSysInfo.axisMap.get(dim);
 
       if (axisModel) {
         var axisType = axisModel.get('type');
@@ -68,13 +70,14 @@ function createListFromArray(source, seriesModel, opt) {
 
   var dimInfoList = createDimensions(source, {
     coordDimensions: coordSysDimDefs,
-    generateCoord: opt.generateCoord
+    generateCoord: opt.generateCoord,
+    encodeDefaulter: opt.useEncodeDefaulter ? zrUtil.curry(makeSeriesEncodeForAxisCoordSys, coordSysDimDefs, seriesModel) : null
   });
   var firstCategoryDimIndex;
   var hasNameEncode;
-  coordSysDefine && zrUtil.each(dimInfoList, function (dimInfo, dimIndex) {
+  coordSysInfo && zrUtil.each(dimInfoList, function (dimInfo, dimIndex) {
     var coordDim = dimInfo.coordDim;
-    var categoryAxisModel = coordSysDefine.categoryAxisMap.get(coordDim);
+    var categoryAxisModel = coordSysInfo.categoryAxisMap.get(coordDim);
 
     if (categoryAxisModel) {
       if (firstCategoryDimIndex == null) {
diff --git a/builder/src/echarts/chart/helper/whiskerBoxCommon.js b/builder/src/echarts/chart/helper/whiskerBoxCommon.js
index 728aed4..b85632b 100644
--- a/builder/src/echarts/chart/helper/whiskerBoxCommon.js
+++ b/builder/src/echarts/chart/helper/whiskerBoxCommon.js
@@ -19,6 +19,7 @@
 import createListSimply from '../helper/createListSimply';
 import * as zrUtil from 'zrender/src/core/util';
 import { getDimensionTypeByAxis } from '../../data/helper/dimensionHelper';
+import { makeSeriesEncodeForAxisCoordSys } from '../../data/helper/sourceHelper';
 export var seriesModelMixin = {
   /**
    * @private
@@ -39,7 +40,7 @@ export var seriesModelMixin = {
     var xAxisType = xAxisModel.get('type');
     var yAxisType = yAxisModel.get('type');
     var addOrdinal; // FIXME
-    // 考虑时间轴
+    // Consider time axis.
 
     if (xAxisType === 'category') {
       option.layout = 'horizontal';
@@ -84,22 +85,24 @@ export var seriesModelMixin = {
     }
 
     var defaultValueDimensions = this.defaultValueDimensions;
+    var coordDimensions = [{
+      name: baseAxisDim,
+      type: getDimensionTypeByAxis(baseAxisType),
+      ordinalMeta: ordinalMeta,
+      otherDims: {
+        tooltip: false,
+        itemName: 0
+      },
+      dimsDef: ['base']
+    }, {
+      name: otherAxisDim,
+      type: getDimensionTypeByAxis(otherAxisType),
+      dimsDef: defaultValueDimensions.slice()
+    }];
     return createListSimply(this, {
-      coordDimensions: [{
-        name: baseAxisDim,
-        type: getDimensionTypeByAxis(baseAxisType),
-        ordinalMeta: ordinalMeta,
-        otherDims: {
-          tooltip: false,
-          itemName: 0
-        },
-        dimsDef: ['base']
-      }, {
-        name: otherAxisDim,
-        type: getDimensionTypeByAxis(otherAxisType),
-        dimsDef: defaultValueDimensions.slice()
-      }],
-      dimensionsCount: defaultValueDimensions.length + 1
+      coordDimensions: coordDimensions,
+      dimensionsCount: defaultValueDimensions.length + 1,
+      encodeDefaulter: zrUtil.curry(makeSeriesEncodeForAxisCoordSys, coordDimensions, this)
     });
   },
 
diff --git a/builder/src/echarts/chart/line/LineSeries.js b/builder/src/echarts/chart/line/LineSeries.js
index bf53f8f..417bb75 100644
--- a/builder/src/echarts/chart/line/LineSeries.js
+++ b/builder/src/echarts/chart/line/LineSeries.js
@@ -23,7 +23,9 @@ export default SeriesModel.extend({
   type: 'series.line',
   dependencies: ['grid', 'polar'],
   getInitialData: function (option, ecModel) {
-    return createListFromArray(this.getSource(), this);
+    return createListFromArray(this.getSource(), this, {
+      useEncodeDefaulter: true
+    });
   },
   defaultOption: {
     zlevel: 0,
@@ -36,7 +38,7 @@ export default SeriesModel.extend({
     // yAxisIndex: 0,
     // polarIndex: 0,
     // If clip the overflow value
-    clipOverflow: true,
+    clip: true,
     // cursor: null,
     label: {
       position: 'top'
diff --git a/builder/src/echarts/chart/line/LineView.js b/builder/src/echarts/chart/line/LineView.js
index 07707ae..603777b 100644
--- a/builder/src/echarts/chart/line/LineView.js
+++ b/builder/src/echarts/chart/line/LineView.js
@@ -26,8 +26,8 @@ import * as graphic from '../../util/graphic';
 import * as modelUtil from '../../util/model';
 import { Polyline, Polygon } from './poly';
 import ChartView from '../../view/Chart';
-import { round } from '../../util/number';
 import { prepareDataCoordInfo, getStackedOnPoint } from './helper';
+import { createGridClipPath, createPolarClipPath } from '../helper/createClipPathFromCoordSys';
 
 function isPointsSame(points1, points2) {
   if (points1.length !== points2.length) {
@@ -49,20 +49,6 @@ function isPointsSame(points1, points2) {
 function getSmooth(smooth) {
   return typeof smooth === 'number' ? smooth : smooth ? 0.5 : 0;
 }
-
-function getAxisExtentWithGap(axis) {
-  var extent = axis.getGlobalExtent();
-
-  if (axis.onBand) {
-    // Remove extra 1px to avoid line miter in clipped edge
-    var halfBandWidth = axis.getBandWidth() / 2 - 1;
-    var dir = extent[1] > extent[0] ? 1 : -1;
-    extent[0] += dir * halfBandWidth;
-    extent[1] -= dir * halfBandWidth;
-  }
-
-  return extent;
-}
 /**
  * @param {module:echarts/coord/cartesian/Cartesian2D|module:echarts/coord/polar/Polar} coordSys
  * @param {module:echarts/data/List} data
@@ -85,98 +71,6 @@ function getStackedOnPoints(coordSys, data, dataCoordInfo) {
   return points;
 }
 
-function createGridClipShape(cartesian, hasAnimation, forSymbol, seriesModel) {
-  var xExtent = getAxisExtentWithGap(cartesian.getAxis('x'));
-  var yExtent = getAxisExtentWithGap(cartesian.getAxis('y'));
-  var isHorizontal = cartesian.getBaseAxis().isHorizontal();
-  var x = Math.min(xExtent[0], xExtent[1]);
-  var y = Math.min(yExtent[0], yExtent[1]);
-  var width = Math.max(xExtent[0], xExtent[1]) - x;
-  var height = Math.max(yExtent[0], yExtent[1]) - y; // Avoid float number rounding error for symbol on the edge of axis extent.
-  // See #7913 and `test/dataZoom-clip.html`.
-
-  if (forSymbol) {
-    x -= 0.5;
-    width += 0.5;
-    y -= 0.5;
-    height += 0.5;
-  } else {
-    var lineWidth = seriesModel.get('lineStyle.width') || 2; // Expand clip shape to avoid clipping when line value exceeds axis
-
-    var expandSize = seriesModel.get('clipOverflow') ? lineWidth / 2 : Math.max(width, height);
-
-    if (isHorizontal) {
-      y -= expandSize;
-      height += expandSize * 2;
-    } else {
-      x -= expandSize;
-      width += expandSize * 2;
-    }
-  }
-
-  var clipPath = new graphic.Rect({
-    shape: {
-      x: x,
-      y: y,
-      width: width,
-      height: height
-    }
-  });
-
-  if (hasAnimation) {
-    clipPath.shape[isHorizontal ? 'width' : 'height'] = 0;
-    graphic.initProps(clipPath, {
-      shape: {
-        width: width,
-        height: height
-      }
-    }, seriesModel);
-  }
-
-  return clipPath;
-}
-
-function createPolarClipShape(polar, hasAnimation, forSymbol, seriesModel) {
-  var angleAxis = polar.getAngleAxis();
-  var radiusAxis = polar.getRadiusAxis();
-  var radiusExtent = radiusAxis.getExtent().slice();
-  radiusExtent[0] > radiusExtent[1] && radiusExtent.reverse();
-  var angleExtent = angleAxis.getExtent();
-  var RADIAN = Math.PI / 180; // Avoid float number rounding error for symbol on the edge of axis extent.
-
-  if (forSymbol) {
-    radiusExtent[0] -= 0.5;
-    radiusExtent[1] += 0.5;
-  }
-
-  var clipPath = new graphic.Sector({
-    shape: {
-      cx: round(polar.cx, 1),
-      cy: round(polar.cy, 1),
-      r0: round(radiusExtent[0], 1),
-      r: round(radiusExtent[1], 1),
-      startAngle: -angleExtent[0] * RADIAN,
-      endAngle: -angleExtent[1] * RADIAN,
-      clockwise: angleAxis.inverse
-    }
-  });
-
-  if (hasAnimation) {
-    clipPath.shape.endAngle = -angleExtent[0] * RADIAN;
-    graphic.initProps(clipPath, {
-      shape: {
-        endAngle: -angleExtent[1] * RADIAN
-      }
-    }, seriesModel);
-  }
-
-  return clipPath;
-}
-
-function createClipShape(coordSys, hasAnimation, forSymbol, seriesModel) {
-  return coordSys.type === 'polar' ? createPolarClipShape(coordSys, hasAnimation, forSymbol, seriesModel) : createGridClipShape(coordSys, hasAnimation, forSymbol, seriesModel);
-}
-
 function turnPointsIntoStep(points, coordSys, stepTurnAt) {
   var baseAxis = coordSys.getBaseAxis();
   var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1;
@@ -362,6 +256,30 @@ function canShowAllSymbolForCategory(categoryAxis, data) {
   return true;
 }
 
+function createLineClipPath(coordSys, hasAnimation, seriesModel) {
+  if (coordSys.type === 'cartesian2d') {
+    var isHorizontal = coordSys.getBaseAxis().isHorizontal();
+    var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel); // Expand clip shape to avoid clipping when line value exceeds axis
+
+    if (!seriesModel.get('clip', true)) {
+      var rectShape = clipPath.shape;
+      var expandSize = Math.max(rectShape.width, rectShape.height);
+
+      if (isHorizontal) {
+        rectShape.y -= expandSize;
+        rectShape.height += expandSize * 2;
+      } else {
+        rectShape.x -= expandSize;
+        rectShape.width += expandSize * 2;
+      }
+    }
+
+    return clipPath;
+  } else {
+    return createPolarClipPath(coordSys, hasAnimation, seriesModel);
+  }
+}
+
 export default ChartView.extend({
   type: 'line',
   init: function () {
@@ -406,12 +324,30 @@ export default ChartView.extend({
 
     group.add(lineGroup); // FIXME step not support polar
 
-    var step = !isCoordSysPolar && seriesModel.get('step'); // Initialization animation or coordinate system changed
+    var step = !isCoordSysPolar && seriesModel.get('step');
+    var clipShapeForSymbol;
+
+    if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) {
+      clipShapeForSymbol = coordSys.getArea(); // Avoid float number rounding error for symbol on the edge of axis extent.
+      // See #7913 and `test/dataZoom-clip.html`.
+
+      if (clipShapeForSymbol.width != null) {
+        clipShapeForSymbol.x -= 0.1;
+        clipShapeForSymbol.y -= 0.1;
+        clipShapeForSymbol.width += 0.2;
+        clipShapeForSymbol.height += 0.2;
+      } else if (clipShapeForSymbol.r0) {
+        clipShapeForSymbol.r0 -= 0.5;
+        clipShapeForSymbol.r1 += 0.5;
+      }
+    }
+
+    this._clipShapeForSymbol = clipShapeForSymbol; // Initialization animation or coordinate system changed
 
     if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) {
       showSymbol && symbolDraw.updateData(data, {
         isIgnore: isIgnoreFunc,
-        clipShape: createClipShape(coordSys, false, true, seriesModel)
+        clipShape: clipShapeForSymbol
       });
 
       if (step) {
@@ -426,7 +362,7 @@ export default ChartView.extend({
         polygon = this._newPolygon(points, stackedOnPoints, coordSys, hasAnimation);
       }
 
-      lineGroup.setClipPath(createClipShape(coordSys, true, false, seriesModel));
+      lineGroup.setClipPath(createLineClipPath(coordSys, true, seriesModel));
     } else {
       if (isAreaChart && !polygon) {
         // If areaStyle is added
@@ -438,12 +374,12 @@ export default ChartView.extend({
       } // Update clipPath
 
 
-      lineGroup.setClipPath(createClipShape(coordSys, false, false, seriesModel)); // Always update, or it is wrong in the case turning on legend
+      lineGroup.setClipPath(createLineClipPath(coordSys, false, seriesModel)); // Always update, or it is wrong in the case turning on legend
       // because points are not changed
 
       showSymbol && symbolDraw.updateData(data, {
         isIgnore: isIgnoreFunc,
-        clipShape: createClipShape(coordSys, false, true, seriesModel)
+        clipShape: clipShapeForSymbol
       }); // Stop symbol animation and sync with line points
       // FIXME performance?
 
@@ -533,6 +469,11 @@ export default ChartView.extend({
         if (!pt) {
           // Null data
           return;
+        } // fix #11360: should't draw symbol outside clipShapeForSymbol
+
+
+        if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(pt[0], pt[1])) {
+          return;
         }
 
         symbol = new SymbolClz(data, dataIndex);
diff --git a/builder/src/echarts/chart/lines/LinesSeries.js b/builder/src/echarts/chart/lines/LinesSeries.js
index 95ff6c1..4622ae7 100644
--- a/builder/src/echarts/chart/lines/LinesSeries.js
+++ b/builder/src/echarts/chart/lines/LinesSeries.js
@@ -282,6 +282,9 @@ var LinesSeries = SeriesModel.extend({
     // If lines are polyline
     // polyline not support curveness, label, animation
     polyline: false,
+    // If clip the overflow.
+    // Available when coordinateSystem is cartesian or polar.
+    clip: true,
     label: {
       show: false,
       position: 'end' // distance: 5,
diff --git a/builder/src/echarts/chart/lines/LinesView.js b/builder/src/echarts/chart/lines/LinesView.js
index eaa3139..5c00bb2 100644
--- a/builder/src/echarts/chart/lines/LinesView.js
+++ b/builder/src/echarts/chart/lines/LinesView.js
@@ -25,6 +25,7 @@ import Polyline from '../helper/Polyline';
 import EffectPolyline from '../helper/EffectPolyline';
 import LargeLineDraw from '../helper/LargeLineDraw';
 import linesLayout from './linesLayout';
+import { createClipPath } from '../helper/createClipPathFromCoordSys';
 export default echarts.extendChartView({
   type: 'lines',
   init: function () {},
@@ -62,6 +63,14 @@ export default echarts.extendChartView({
     }
 
     lineDraw.updateData(data);
+    var clipPath = seriesModel.get('clip', true) && createClipPath(seriesModel.coordinateSystem, false, seriesModel);
+
+    if (clipPath) {
+      this.group.setClipPath(clipPath);
+    } else {
+      this.group.removeClipPath();
+    }
+
     this._lastZlevel = zlevel;
     this._finished = true;
   },
diff --git a/builder/src/echarts/chart/map/MapSeries.js b/builder/src/echarts/chart/map/MapSeries.js
index bb7fa46..dcdec13 100644
--- a/builder/src/echarts/chart/map/MapSeries.js
+++ b/builder/src/echarts/chart/map/MapSeries.js
@@ -23,6 +23,7 @@ import { encodeHTML, addCommas } from '../../util/format';
 import dataSelectableMixin from '../../component/helper/selectableMixin';
 import { retrieveRawAttr } from '../../data/helper/dataProvider';
 import geoSourceManager from '../../coord/geo/geoSourceManager';
+import { makeSeriesEncodeForNameBased } from '../../data/helper/sourceHelper';
 var MapSeries = SeriesModel.extend({
   type: 'series.map',
   dependencies: ['geo'],
@@ -40,7 +41,10 @@ var MapSeries = SeriesModel.extend({
    */
   seriesGroup: [],
   getInitialData: function (option) {
-    var data = createListSimply(this, ['value']);
+    var data = createListSimply(this, {
+      coordDimensions: ['value'],
+      encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this)
+    });
     var valueDim = data.mapDimension('value');
     var dataNameMap = zrUtil.createHashMap();
     var selectTargetList = [];
diff --git a/builder/src/echarts/chart/pie/PieSeries.js b/builder/src/echarts/chart/pie/PieSeries.js
index 8c741ad..c33c757 100644
--- a/builder/src/echarts/chart/pie/PieSeries.js
+++ b/builder/src/echarts/chart/pie/PieSeries.js
@@ -23,6 +23,8 @@ import * as modelUtil from '../../util/model';
 import { getPercentWithPrecision } from '../../util/number';
 import dataSelectableMixin from '../../component/helper/selectableMixin';
 import { retrieveRawAttr } from '../../data/helper/dataProvider';
+import { makeSeriesEncodeForNameBased } from '../../data/helper/sourceHelper';
+import LegendVisualProvider from '../../visual/LegendVisualProvider';
 var PieSeries = echarts.extendSeriesModel({
   type: 'series.pie',
   // Overwrite
@@ -30,10 +32,7 @@ var PieSeries = echarts.extendSeriesModel({
     PieSeries.superApply(this, 'init', arguments); // Enable legend selection for each data item
     // Use a function instead of direct access because data reference may changed
 
-    this.legendDataProvider = function () {
-      return this.getRawData();
-    };
-
+    this.legendVisualProvider = new LegendVisualProvider(zrUtil.bind(this.getData, this), zrUtil.bind(this.getRawData, this));
     this.updateSelectedMap(this._createSelectableList());
 
     this._defaultLabelLine(option);
@@ -44,7 +43,10 @@ var PieSeries = echarts.extendSeriesModel({
     this.updateSelectedMap(this._createSelectableList());
   },
   getInitialData: function (option, ecModel) {
-    return createListSimply(this, ['value']);
+    return createListSimply(this, {
+      coordDimensions: ['value'],
+      encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this)
+    });
   },
   _createSelectableList: function () {
     var data = this.getRawData();
@@ -96,6 +98,9 @@ var PieSeries = echarts.extendSeriesModel({
     startAngle: 90,
     // 最小角度改为0
     minAngle: 0,
+    // If the angle of a sector less than `minShowLabelAngle`,
+    // the label will not be displayed.
+    minShowLabelAngle: 0,
     // 选中时扇区偏移量
     selectedOffset: 10,
     // 高亮扇区偏移量
@@ -110,12 +115,27 @@ var PieSeries = echarts.extendSeriesModel({
     // If still show when all data zero.
     stillShowZeroSum: true,
     // cursor: null,
+    left: 0,
+    top: 0,
+    right: 0,
+    bottom: 0,
+    width: null,
+    height: null,
     label: {
       // If rotate around circle
       rotate: false,
       show: true,
       // 'outer', 'inside', 'center'
-      position: 'outer' // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
+      position: 'outer',
+      // 'none', 'labelLine', 'edge'. Works only when position is 'outer'
+      alignTo: 'none',
+      // Closest distance between label and chart edge.
+      // Works only position is 'outer' and alignTo is 'edge'.
+      margin: '25%',
+      // Works only position is 'outer' and alignTo is not 'edge'.
+      bleedMargin: 10,
+      // Distance between text and label line.
+      distanceToLabelLine: 5 // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
       // 默认使用全局文本样式,详见TEXTSTYLE
       // distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数
 
@@ -137,8 +157,10 @@ var PieSeries = echarts.extendSeriesModel({
     itemStyle: {
       borderWidth: 1
     },
-    // Animation type canbe expansion, scale
+    // Animation type. Valid values: expansion, scale
     animationType: 'expansion',
+    // Animation type when update. Valid values: transition, expansion
+    animationTypeUpdate: 'transition',
     animationEasing: 'cubicOut'
   }
 });
diff --git a/builder/src/echarts/chart/pie/PieView.js b/builder/src/echarts/chart/pie/PieView.js
index cfb3742..2658eee 100644
--- a/builder/src/echarts/chart/pie/PieView.js
+++ b/builder/src/echarts/chart/pie/PieView.js
@@ -78,30 +78,21 @@ function PiePiece(data, idx) {
   this.add(sector);
   this.add(polyline);
   this.add(text);
-  this.updateData(data, idx, true); // Hover to change label and labelLine
-
-  function onEmphasis() {
-    polyline.ignore = polyline.hoverIgnore;
-    text.ignore = text.hoverIgnore;
-  }
-
-  function onNormal() {
-    polyline.ignore = polyline.normalIgnore;
-    text.ignore = text.normalIgnore;
-  }
-
-  this.on('emphasis', onEmphasis).on('normal', onNormal).on('mouseover', onEmphasis).on('mouseout', onNormal);
+  this.updateData(data, idx, true);
 }
 
 var piePieceProto = PiePiece.prototype;
 
 piePieceProto.updateData = function (data, idx, firstCreate) {
   var sector = this.childAt(0);
+  var labelLine = this.childAt(1);
+  var labelText = this.childAt(2);
   var seriesModel = data.hostModel;
   var itemModel = data.getItemModel(idx);
   var layout = data.getItemLayout(idx);
   var sectorShape = zrUtil.extend({}, layout);
   sectorShape.label = null;
+  var animationTypeUpdate = seriesModel.getShallow('animationTypeUpdate');
 
   if (firstCreate) {
     sector.setShape(sectorShape);
@@ -124,9 +115,15 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
         }, seriesModel, idx);
       }
   } else {
-    graphic.updateProps(sector, {
-      shape: sectorShape
-    }, seriesModel, idx);
+    if (animationTypeUpdate === 'expansion') {
+      // Sectors are set to be target shape and an overlaying clipPath is used for animation
+      sector.setShape(sectorShape);
+    } else {
+      // Transition animation from the old shape
+      graphic.updateProps(sector, {
+        shape: sectorShape
+      }, seriesModel, idx);
+    }
   } // Update common style
 
 
@@ -139,40 +136,39 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
   var cursorStyle = itemModel.getShallow('cursor');
   cursorStyle && sector.attr('cursor', cursorStyle); // Toggle selected
 
-  toggleItemSelected(this, data.getItemLayout(idx), seriesModel.isSelected(null, idx), seriesModel.get('selectedOffset'), seriesModel.get('animation'));
-
-  function onEmphasis() {
-    // Sector may has animation of updating data. Force to move to the last frame
-    // Or it may stopped on the wrong shape
-    sector.stopAnimation(true);
-    sector.animateTo({
-      shape: {
-        r: layout.r + seriesModel.get('hoverOffset')
-      }
-    }, 300, 'elasticOut');
-  }
-
-  function onNormal() {
-    sector.stopAnimation(true);
-    sector.animateTo({
-      shape: {
-        r: layout.r
-      }
-    }, 300, 'elasticOut');
-  }
+  toggleItemSelected(this, data.getItemLayout(idx), seriesModel.isSelected(null, idx), seriesModel.get('selectedOffset'), seriesModel.get('animation')); // Label and text animation should be applied only for transition type animation when update
 
-  sector.off('mouseover').off('mouseout').off('emphasis').off('normal');
+  var withAnimation = !firstCreate && animationTypeUpdate === 'transition';
 
-  if (itemModel.get('hoverAnimation') && seriesModel.isAnimationEnabled()) {
-    sector.on('mouseover', onEmphasis).on('mouseout', onNormal).on('emphasis', onEmphasis).on('normal', onNormal);
-  }
+  this._updateLabel(data, idx, withAnimation);
 
-  this._updateLabel(data, idx);
+  this.highDownOnUpdate = itemModel.get('hoverAnimation') && seriesModel.isAnimationEnabled() ? function (fromState, toState) {
+    if (toState === 'emphasis') {
+      labelLine.ignore = labelLine.hoverIgnore;
+      labelText.ignore = labelText.hoverIgnore; // Sector may has animation of updating data. Force to move to the last frame
+      // Or it may stopped on the wrong shape
 
+      sector.stopAnimation(true);
+      sector.animateTo({
+        shape: {
+          r: layout.r + seriesModel.get('hoverOffset')
+        }
+      }, 300, 'elasticOut');
+    } else {
+      labelLine.ignore = labelLine.normalIgnore;
+      labelText.ignore = labelText.normalIgnore;
+      sector.stopAnimation(true);
+      sector.animateTo({
+        shape: {
+          r: layout.r
+        }
+      }, 300, 'elasticOut');
+    }
+  } : null;
   graphic.setHoverStyle(this);
 };
 
-piePieceProto._updateLabel = function (data, idx) {
+piePieceProto._updateLabel = function (data, idx, withAnimation) {
   var labelLine = this.childAt(1);
   var labelText = this.childAt(2);
   var seriesModel = data.hostModel;
@@ -180,17 +176,36 @@ piePieceProto._updateLabel = function (data, idx) {
   var layout = data.getItemLayout(idx);
   var labelLayout = layout.label;
   var visualColor = data.getItemVisual(idx, 'color');
-  graphic.updateProps(labelLine, {
-    shape: {
-      points: labelLayout.linePoints || [[labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y]]
-    }
-  }, seriesModel, idx);
-  graphic.updateProps(labelText, {
-    style: {
-      x: labelLayout.x,
-      y: labelLayout.y
-    }
-  }, seriesModel, idx);
+
+  if (!labelLayout || isNaN(labelLayout.x) || isNaN(labelLayout.y)) {
+    labelText.ignore = labelText.normalIgnore = labelText.hoverIgnore = labelLine.ignore = labelLine.normalIgnore = labelLine.hoverIgnore = true;
+    return;
+  }
+
+  var targetLineShape = {
+    points: labelLayout.linePoints || [[labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y]]
+  };
+  var targetTextStyle = {
+    x: labelLayout.x,
+    y: labelLayout.y
+  };
+
+  if (withAnimation) {
+    graphic.updateProps(labelLine, {
+      shape: targetLineShape
+    }, seriesModel, idx);
+    graphic.updateProps(labelText, {
+      style: targetTextStyle
+    }, seriesModel, idx);
+  } else {
+    labelLine.attr({
+      shape: targetLineShape
+    });
+    labelText.attr({
+      style: targetTextStyle
+    });
+  }
+
   labelText.attr({
     rotation: labelLayout.rotation,
     origin: [labelLayout.x, labelLayout.y],
@@ -204,7 +219,7 @@ piePieceProto._updateLabel = function (data, idx) {
   graphic.setLabelStyle(labelText.style, labelText.hoverStyle = {}, labelModel, labelHoverModel, {
     labelFetcher: data.hostModel,
     labelDataIndex: idx,
-    defaultText: data.getName(idx),
+    defaultText: labelLayout.text,
     autoColor: visualColor,
     useInsideStyle: !!labelLayout.inside
   }, {
@@ -253,6 +268,7 @@ var PieView = ChartView.extend({
     var hasAnimation = ecModel.get('animation');
     var isFirstRender = !oldData;
     var animationType = seriesModel.get('animationType');
+    var animationTypeUpdate = seriesModel.get('animationTypeUpdate');
     var onSectorClick = zrUtil.curry(updateDataSelected, this.uid, seriesModel, hasAnimation, api);
     var selectedMode = seriesModel.get('selectedMode');
     data.diff(oldData).add(function (idx) {
@@ -269,6 +285,13 @@ var PieView = ChartView.extend({
       group.add(piePiece);
     }).update(function (newIdx, oldIdx) {
       var piePiece = oldData.getItemGraphicEl(oldIdx);
+
+      if (!isFirstRender && animationTypeUpdate !== 'transition') {
+        piePiece.eachChild(function (child) {
+          child.stopAnimation(true);
+        });
+      }
+
       piePiece.updateData(data, newIdx);
       piePiece.off('click');
       selectedMode && piePiece.on('click', onSectorClick);
@@ -279,12 +302,16 @@ var PieView = ChartView.extend({
       group.remove(piePiece);
     }).execute();
 
-    if (hasAnimation && isFirstRender && data.count() > 0 // Default expansion animation
-    && animationType !== 'scale') {
+    if (hasAnimation && data.count() > 0 && (isFirstRender ? animationType !== 'scale' : animationTypeUpdate !== 'transition')) {
       var shape = data.getItemLayout(0);
+
+      for (var s = 1; isNaN(shape.startAngle) && s < data.count(); ++s) {
+        shape = data.getItemLayout(s);
+      }
+
       var r = Math.max(api.getWidth(), api.getHeight()) / 2;
       var removeClipPath = zrUtil.bind(group.removeClipPath, group);
-      group.setClipPath(this._createClipPath(shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel));
+      group.setClipPath(this._createClipPath(shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel, isFirstRender));
     } else {
       // clipPath is used in first-time animation, so remove it when otherwise. See: #8994
       group.removeClipPath();
@@ -293,7 +320,7 @@ var PieView = ChartView.extend({
     this._data = data;
   },
   dispose: function () {},
-  _createClipPath: function (cx, cy, r, startAngle, clockwise, cb, seriesModel) {
+  _createClipPath: function (cx, cy, r, startAngle, clockwise, cb, seriesModel, isFirstRender) {
     var clipPath = new graphic.Sector({
       shape: {
         cx: cx,
@@ -305,7 +332,8 @@ var PieView = ChartView.extend({
         clockwise: clockwise
       }
     });
-    graphic.initProps(clipPath, {
+    var initOrUpdate = isFirstRender ? graphic.initProps : graphic.updateProps;
+    initOrUpdate(clipPath, {
       shape: {
         endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2
       }
diff --git a/builder/src/echarts/chart/pie/labelLayout.js b/builder/src/echarts/chart/pie/labelLayout.js
index d6e9adc..96af908 100644
--- a/builder/src/echarts/chart/pie/labelLayout.js
+++ b/builder/src/echarts/chart/pie/labelLayout.js
@@ -18,14 +18,20 @@
 */
 // FIXME emphasis label position is not same with normal label position
 import * as textContain from 'zrender/src/contain/text';
+import { parsePercent } from '../../util/number';
+var RADIAN = Math.PI / 180;
 
-function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
+function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight, viewLeft, viewTop, farthestX) {
   list.sort(function (a, b) {
     return a.y - b.y;
   });
 
   function shiftDown(start, end, delta, dir) {
     for (var j = start; j < end; j++) {
+      if (list[j].y + delta > viewTop + viewHeight) {
+        break;
+      }
+
       list[j].y += delta;
 
       if (j > start && j + 1 < end && list[j + 1].y > list[j].y + list[j].height) {
@@ -39,6 +45,10 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
 
   function shiftUp(end, delta) {
     for (var j = end; j >= 0; j--) {
+      if (list[j].y - delta < viewTop) {
+        break;
+      }
+
       list[j].y -= delta;
 
       if (j > 0 && list[j].y > list[j - 1].y + list[j - 1].height) {
@@ -56,6 +66,10 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
     : 0; // up
 
     for (var i = 0, l = list.length; i < l; i++) {
+      if (list[i].labelAlignTo !== 'none') {
+        continue;
+      }
+
       var deltaY = Math.abs(list[i].y - cy);
       var length = list[i].len;
       var length2 = list[i].len2;
@@ -83,6 +97,12 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
   var downList = [];
 
   for (var i = 0; i < len; i++) {
+    if (list[i].position === 'outer' && list[i].labelAlignTo === 'labelLine') {
+      var dx = list[i].x - farthestX;
+      list[i].linePoints[1][0] += dx;
+      list[i].x = farthestX;
+    }
+
     delta = list[i].y - lastY;
 
     if (delta < 0) {
@@ -108,9 +128,11 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
   changeX(downList, true, cx, cy, r, dir);
 }
 
-function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) {
+function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop) {
   var leftList = [];
   var rightList = [];
+  var leftmostX = Number.MAX_VALUE;
+  var rightmostX = -Number.MAX_VALUE;
 
   for (var i = 0; i < labelLayoutList.length; i++) {
     if (isPositionCenter(labelLayoutList[i])) {
@@ -118,33 +140,72 @@ function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) {
     }
 
     if (labelLayoutList[i].x < cx) {
+      leftmostX = Math.min(leftmostX, labelLayoutList[i].x);
       leftList.push(labelLayoutList[i]);
     } else {
+      rightmostX = Math.max(rightmostX, labelLayoutList[i].x);
       rightList.push(labelLayoutList[i]);
     }
   }
 
-  adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight);
-  adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight);
+  adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight, viewLeft, viewTop, rightmostX);
+  adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight, viewLeft, viewTop, leftmostX);
 
   for (var i = 0; i < labelLayoutList.length; i++) {
-    if (isPositionCenter(labelLayoutList[i])) {
+    var layout = labelLayoutList[i];
+
+    if (isPositionCenter(layout)) {
       continue;
     }
 
-    var linePoints = labelLayoutList[i].linePoints;
+    var linePoints = layout.linePoints;
 
     if (linePoints) {
+      var isAlignToEdge = layout.labelAlignTo === 'edge';
+      var realTextWidth = layout.textRect.width;
+      var targetTextWidth;
+
+      if (isAlignToEdge) {
+        if (layout.x < cx) {
+          targetTextWidth = linePoints[2][0] - layout.labelDistance - viewLeft - layout.labelMargin;
+        } else {
+          targetTextWidth = viewLeft + viewWidth - layout.labelMargin - linePoints[2][0] - layout.labelDistance;
+        }
+      } else {
+        if (layout.x < cx) {
+          targetTextWidth = layout.x - viewLeft - layout.bleedMargin;
+        } else {
+          targetTextWidth = viewLeft + viewWidth - layout.x - layout.bleedMargin;
+        }
+      }
+
+      if (targetTextWidth < layout.textRect.width) {
+        layout.text = textContain.truncateText(layout.text, targetTextWidth, layout.font);
+
+        if (layout.labelAlignTo === 'edge') {
+          realTextWidth = textContain.getWidth(layout.text, layout.font);
+        }
+      }
+
       var dist = linePoints[1][0] - linePoints[2][0];
 
-      if (labelLayoutList[i].x < cx) {
-        linePoints[2][0] = labelLayoutList[i].x + 3;
+      if (isAlignToEdge) {
+        if (layout.x < cx) {
+          linePoints[2][0] = viewLeft + layout.labelMargin + realTextWidth + layout.labelDistance;
+        } else {
+          linePoints[2][0] = viewLeft + viewWidth - layout.labelMargin - realTextWidth - layout.labelDistance;
+        }
       } else {
-        linePoints[2][0] = labelLayoutList[i].x - 3;
+        if (layout.x < cx) {
+          linePoints[2][0] = layout.x + layout.labelDistance;
+        } else {
+          linePoints[2][0] = layout.x - layout.labelDistance;
+        }
+
+        linePoints[1][0] = linePoints[2][0] + dist;
       }
 
-      linePoints[1][1] = linePoints[2][1] = labelLayoutList[i].y;
-      linePoints[1][0] = linePoints[2][0] + dist;
+      linePoints[1][1] = linePoints[2][1] = layout.y;
     }
   }
 }
@@ -154,21 +215,34 @@ function isPositionCenter(layout) {
   return layout.position === 'center';
 }
 
-export default function (seriesModel, r, viewWidth, viewHeight) {
+export default function (seriesModel, r, viewWidth, viewHeight, viewLeft, viewTop) {
   var data = seriesModel.getData();
   var labelLayoutList = [];
   var cx;
   var cy;
   var hasLabelRotate = false;
+  var minShowLabelRadian = (seriesModel.get('minShowLabelAngle') || 0) * RADIAN;
   data.each(function (idx) {
     var layout = data.getItemLayout(idx);
     var itemModel = data.getItemModel(idx);
     var labelModel = itemModel.getModel('label'); // Use position in normal or emphasis
 
     var labelPosition = labelModel.get('position') || itemModel.get('emphasis.label.position');
+    var labelDistance = labelModel.get('distanceToLabelLine');
+    var labelAlignTo = labelModel.get('alignTo');
+    var labelMargin = parsePercent(labelModel.get('margin'), viewWidth);
+    var bleedMargin = labelModel.get('bleedMargin');
+    var font = labelModel.getFont();
     var labelLineModel = itemModel.getModel('labelLine');
     var labelLineLen = labelLineModel.get('length');
+    labelLineLen = parsePercent(labelLineLen, viewWidth);
     var labelLineLen2 = labelLineModel.get('length2');
+    labelLineLen2 = parsePercent(labelLineLen2, viewWidth);
+
+    if (layout.angle < minShowLabelRadian) {
+      return;
+    }
+
     var midAngle = (layout.startAngle + layout.endAngle) / 2;
     var dx = Math.cos(midAngle);
     var dy = Math.sin(midAngle);
@@ -178,6 +252,8 @@ export default function (seriesModel, r, viewWidth, viewHeight) {
     var textAlign;
     cx = layout.cx;
     cy = layout.cy;
+    var text = seriesModel.getFormattedLabel(idx, 'normal') || data.getName(idx);
+    var textRect = textContain.getBoundingRect(text, font, textAlign, 'top');
     var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
 
     if (labelPosition === 'center') {
@@ -196,18 +272,30 @@ export default function (seriesModel, r, viewWidth, viewHeight) {
         var y2 = y1 + dy * (labelLineLen + r - layout.r);
         var x3 = x2 + (dx < 0 ? -1 : 1) * labelLineLen2;
         var y3 = y2;
-        textX = x3 + (dx < 0 ? -5 : 5);
+
+        if (labelAlignTo === 'edge') {
+          // Adjust textX because text align of edge is opposite
+          textX = dx < 0 ? viewLeft + labelMargin : viewLeft + viewWidth - labelMargin;
+        } else {
+          textX = x3 + (dx < 0 ? -labelDistance : labelDistance);
+        }
+
         textY = y3;
         linePoints = [[x1, y1], [x2, y2], [x3, y3]];
       }
 
-      textAlign = isLabelInside ? 'center' : dx > 0 ? 'left' : 'right';
+      textAlign = isLabelInside ? 'center' : labelAlignTo === 'edge' ? dx > 0 ? 'right' : 'left' : dx > 0 ? 'left' : 'right';
+    }
+
+    var labelRotate;
+    var rotate = labelModel.get('rotate');
+
+    if (typeof rotate === 'number') {
+      labelRotate = rotate * (Math.PI / 180);
+    } else {
+      labelRotate = rotate ? dx < 0 ? -midAngle + Math.PI : -midAngle : 0;
     }
 
-    var font = labelModel.getFont();
-    var labelRotate = labelModel.get('rotate') ? dx < 0 ? -midAngle + Math.PI : -midAngle : 0;
-    var text = seriesModel.getFormattedLabel(idx, 'normal') || data.getName(idx);
-    var textRect = textContain.getBoundingRect(text, font, textAlign, 'top');
     hasLabelRotate = !!labelRotate;
     layout.label = {
       x: textX,
@@ -220,7 +308,14 @@ export default function (seriesModel, r, viewWidth, viewHeight) {
       textAlign: textAlign,
       verticalAlign: 'middle',
       rotation: labelRotate,
-      inside: isLabelInside
+      inside: isLabelInside,
+      labelDistance: labelDistance,
+      labelAlignTo: labelAlignTo,
+      labelMargin: labelMargin,
+      bleedMargin: bleedMargin,
+      textRect: textRect,
+      text: text,
+      font: font
     }; // Not layout the inside label
 
     if (!isLabelInside) {
@@ -229,6 +324,6 @@ export default function (seriesModel, r, viewWidth, viewHeight) {
   });
 
   if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) {
-    avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight);
+    avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop);
   }
 }
\ No newline at end of file
diff --git a/builder/src/echarts/chart/pie/pieLayout.js b/builder/src/echarts/chart/pie/pieLayout.js
index ca40df9..d741723 100644
--- a/builder/src/echarts/chart/pie/pieLayout.js
+++ b/builder/src/echarts/chart/pie/pieLayout.js
@@ -17,14 +17,24 @@
 * under the License.
 */
 import { parsePercent, linearMap } from '../../util/number';
+import * as layout from '../../util/layout';
 import labelLayout from './labelLayout';
 import * as zrUtil from 'zrender/src/core/util';
 var PI2 = Math.PI * 2;
 var RADIAN = Math.PI / 180;
+
+function getViewRect(seriesModel, api) {
+  return layout.getLayoutRect(seriesModel.getBoxLayoutParams(), {
+    width: api.getWidth(),
+    height: api.getHeight()
+  });
+}
+
 export default function (seriesType, ecModel, api, payload) {
   ecModel.eachSeriesByType(seriesType, function (seriesModel) {
     var data = seriesModel.getData();
     var valueDim = data.mapDimension('value');
+    var viewRect = getViewRect(seriesModel, api);
     var center = seriesModel.get('center');
     var radius = seriesModel.get('radius');
 
@@ -36,11 +46,11 @@ export default function (seriesType, ecModel, api, payload) {
       center = [center, center];
     }
 
-    var width = api.getWidth();
-    var height = api.getHeight();
+    var width = parsePercent(viewRect.width, api.getWidth());
+    var height = parsePercent(viewRect.height, api.getHeight());
     var size = Math.min(width, height);
-    var cx = parsePercent(center[0], width);
-    var cy = parsePercent(center[1], height);
+    var cx = parsePercent(center[0], width) + viewRect.x;
+    var cy = parsePercent(center[1], height) + viewRect.y;
     var r0 = parsePercent(radius[0], size / 2);
     var r = parsePercent(radius[1], size / 2);
     var startAngle = -seriesModel.get('startAngle') * RADIAN;
@@ -75,7 +85,8 @@ export default function (seriesType, ecModel, api, payload) {
           cx: cx,
           cy: cy,
           r0: r0,
-          r: roseType ? NaN : r
+          r: roseType ? NaN : r,
+          viewRect: viewRect
         });
         return;
       } // FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样?
@@ -103,7 +114,8 @@ export default function (seriesType, ecModel, api, payload) {
         cx: cx,
         cy: cy,
         r0: r0,
-        r: roseType ? linearMap(value, extent, [r0, r]) : r
+        r: roseType ? linearMap(value, extent, [r0, r]) : r,
+        viewRect: viewRect
       });
       currentAngle = endAngle;
     }); // Some sector is constrained by minAngle
@@ -137,6 +149,6 @@ export default function (seriesType, ecModel, api, payload) {
       }
     }
 
-    labelLayout(seriesModel, r, width, height);
+    labelLayout(seriesModel, r, viewRect.width, viewRect.height, viewRect.x, viewRect.y);
   });
 }
\ No newline at end of file
diff --git a/builder/src/echarts/chart/radar/RadarSeries.js b/builder/src/echarts/chart/radar/RadarSeries.js
index 7cac5d4..25209d4 100644
--- a/builder/src/echarts/chart/radar/RadarSeries.js
+++ b/builder/src/echarts/chart/radar/RadarSeries.js
@@ -20,6 +20,7 @@ import SeriesModel from '../../model/Series';
 import createListSimply from '../helper/createListSimply';
 import * as zrUtil from 'zrender/src/core/util';
 import { encodeHTML } from '../../util/format';
+import LegendVisualProvider from '../../visual/LegendVisualProvider';
 var RadarSeries = SeriesModel.extend({
   type: 'series.radar',
   dependencies: ['radar'],
@@ -28,9 +29,7 @@ var RadarSeries = SeriesModel.extend({
     RadarSeries.superApply(this, 'init', arguments); // Enable legend selection for each data item
     // Use a function instead of direct access because data reference may changed
 
-    this.legendDataProvider = function () {
-      return this.getRawData();
-    };
+    this.legendVisualProvider = new LegendVisualProvider(zrUtil.bind(this.getData, this), zrUtil.bind(this.getRawData, this));
   },
   getInitialData: function (option, ecModel) {
     return createListSimply(this, {
diff --git a/builder/src/echarts/chart/radar/RadarView.js b/builder/src/echarts/chart/radar/RadarView.js
index b60c130..9c02b66 100644
--- a/builder/src/echarts/chart/radar/RadarView.js
+++ b/builder/src/echarts/chart/radar/RadarView.js
@@ -164,26 +164,22 @@ export default echarts.extendChartView({
       symbolGroup.eachChild(function (symbolPath) {
         symbolPath.setStyle(itemStyle);
         symbolPath.hoverStyle = zrUtil.clone(itemHoverStyle);
+        var defaultText = data.get(data.dimensions[symbolPath.__dimIdx], idx);
+        (defaultText == null || isNaN(defaultText)) && (defaultText = '');
         graphic.setLabelStyle(symbolPath.style, symbolPath.hoverStyle, labelModel, labelHoverModel, {
           labelFetcher: data.hostModel,
           labelDataIndex: idx,
           labelDimIndex: symbolPath.__dimIdx,
-          defaultText: data.get(data.dimensions[symbolPath.__dimIdx], idx),
+          defaultText: defaultText,
           autoColor: color,
           isRectText: true
         });
       });
 
-      function onEmphasis() {
-        polygon.attr('ignore', hoverPolygonIgnore);
-      }
-
-      function onNormal() {
-        polygon.attr('ignore', polygonIgnore);
-      }
+      itemGroup.highDownOnUpdate = function (fromState, toState) {
+        polygon.attr('ignore', toState === 'emphasis' ? hoverPolygonIgnore : polygonIgnore);
+      };
 
-      itemGroup.off('mouseover').off('mouseout').off('normal').off('emphasis');
-      itemGroup.on('emphasis', onEmphasis).on('mouseover', onEmphasis).on('normal', onNormal).on('mouseout', onNormal);
       graphic.setHoverStyle(itemGroup);
     });
     this._data = data;
diff --git a/builder/src/echarts/chart/radar/radarLayout.js b/builder/src/echarts/chart/radar/radarLayout.js
index 9665875..de8be05 100644
--- a/builder/src/echarts/chart/radar/radarLayout.js
+++ b/builder/src/echarts/chart/radar/radarLayout.js
@@ -16,6 +16,7 @@
 * specific language governing permissions and limitations
 * under the License.
 */
+import * as zrUtil from 'zrender/src/core/util';
 export default function (ecModel) {
   ecModel.eachSeriesByType('radar', function (seriesModel) {
     var data = seriesModel.getData();
@@ -26,21 +27,35 @@ export default function (ecModel) {
       return;
     }
 
-    function pointsConverter(val, idx) {
-      points[idx] = points[idx] || [];
-      points[idx][i] = coordSys.dataToPoint(val, i);
-    }
-
     var axes = coordSys.getIndicatorAxes();
-
-    for (var i = 0; i < axes.length; i++) {
-      data.each(data.mapDimension(axes[i].dim), pointsConverter);
-    }
+    zrUtil.each(axes, function (axis, axisIndex) {
+      data.each(data.mapDimension(axes[axisIndex].dim), function (val, dataIndex) {
+        points[dataIndex] = points[dataIndex] || [];
+        var point = coordSys.dataToPoint(val, axisIndex);
+        points[dataIndex][axisIndex] = isValidPoint(point) ? point : getValueMissingPoint(coordSys);
+      });
+    }); // Close polygon
 
     data.each(function (idx) {
-      // Close polygon
-      points[idx][0] && points[idx].push(points[idx][0].slice());
+      // TODO
+      // Is it appropriate to connect to the next data when some data is missing?
+      // Or, should trade it like `connectNull` in line chart?
+      var firstPoint = zrUtil.find(points[idx], function (point) {
+        return isValidPoint(point);
+      }) || getValueMissingPoint(coordSys); // Copy the first actual point to the end of the array
+
+      points[idx].push(firstPoint.slice());
       data.setItemLayout(idx, points[idx]);
     });
   });
+}
+
+function isValidPoint(point) {
+  return !isNaN(point[0]) && !isNaN(point[1]);
+}
+
+function getValueMissingPoint(coordSys) {
+  // It is error-prone to input [NaN, NaN] into polygon, polygon.
+  // (probably cause problem when refreshing or animating)
+  return [coordSys.cx, coordSys.cy];
 }
\ No newline at end of file
diff --git a/builder/src/echarts/chart/sankey/SankeySeries.js b/builder/src/echarts/chart/sankey/SankeySeries.js
index b640528..c85eb1a 100644
--- a/builder/src/echarts/chart/sankey/SankeySeries.js
+++ b/builder/src/echarts/chart/sankey/SankeySeries.js
@@ -16,17 +16,15 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file Get initial data and define sankey view's series model
- * @author Deqing Li(annong035@gmail.com)
- */
 import SeriesModel from '../../model/Series';
 import createGraphFromNodeEdge from '../helper/createGraphFromNodeEdge';
 import { encodeHTML } from '../../util/format';
+import Model from '../../model/Model';
+import { __DEV__ } from '../../config';
 var SankeySeries = SeriesModel.extend({
   type: 'series.sankey',
   layoutInfo: null,
+  levelModels: null,
 
   /**
    * Init a graph data structure from data in option series
@@ -34,14 +32,44 @@ var SankeySeries = SeriesModel.extend({
    * @param  {Object} option  the object used to config echarts view
    * @return {module:echarts/data/List} storage initial data
    */
-  getInitialData: function (option) {
+  getInitialData: function (option, ecModel) {
     var links = option.edges || option.links;
     var nodes = option.data || option.nodes;
+    var levels = option.levels;
+    var levelModels = this.levelModels = {};
+
+    for (var i = 0; i < levels.length; i++) {
+      if (levels[i].depth != null && levels[i].depth >= 0) {
+        levelModels[levels[i].depth] = new Model(levels[i], this, ecModel);
+      } else {}
+    }
 
     if (nodes && links) {
-      var graph = createGraphFromNodeEdge(nodes, links, this, true);
+      var graph = createGraphFromNodeEdge(nodes, links, this, true, beforeLink);
       return graph.data;
     }
+
+    function beforeLink(nodeData, edgeData) {
+      nodeData.wrapMethod('getItemModel', function (model, idx) {
+        model.customizeGetParent(function (path) {
+          var parentModel = this.parentModel;
+          var nodeDepth = parentModel.getData().getItemLayout(idx).depth;
+          var levelModel = parentModel.levelModels[nodeDepth];
+          return levelModel || this.parentModel;
+        });
+        return model;
+      });
+      edgeData.wrapMethod('getItemModel', function (model, idx) {
+        model.customizeGetParent(function (path) {
+          var parentModel = this.parentModel;
+          var edge = parentModel.getGraph().getEdgeByIndex(idx);
+          var depth = edge.node1.getLayout().depth;
+          var levelModel = parentModel.levelModels[depth];
+          return levelModel || this.parentModel;
+        });
+        return model;
+      });
+    }
   },
   setNodePosition: function (dataIndex, localPosition) {
     var dataItem = this.option.data[dataIndex];
@@ -82,6 +110,16 @@ var SankeySeries = SeriesModel.extend({
       }
 
       return encodeHTML(html);
+    } else if (dataType === 'node') {
+      var node = this.getGraph().getNodeByIndex(dataIndex);
+      var value = node.getLayout().value;
+      var name = this.getDataParams(dataIndex, dataType).data.name;
+
+      if (value) {
+        var html = name + ' : ' + value;
+      }
+
+      return encodeHTML(html);
     }
 
     return SankeySeries.superCall(this, 'formatTooltip', dataIndex, multipleSeries);
@@ -121,6 +159,9 @@ var SankeySeries = SeriesModel.extend({
       color: '#000',
       fontSize: 12
     },
+    levels: [],
+    // Value can be 'left' or 'right'
+    nodeAlign: 'justify',
     itemStyle: {
       borderWidth: 1,
       borderColor: '#333'
diff --git a/builder/src/echarts/chart/sankey/SankeyView.js b/builder/src/echarts/chart/sankey/SankeyView.js
index e4cee73..64316e5 100644
--- a/builder/src/echarts/chart/sankey/SankeyView.js
+++ b/builder/src/echarts/chart/sankey/SankeyView.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file  The file used to draw sankey view
- * @author  Deqing Li(annong035@gmail.com)
- */
 import * as graphic from '../../util/graphic';
 import * as echarts from '../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
@@ -74,16 +69,13 @@ var SankeyShape = graphic.extendShape({
   },
   buildPath: function (ctx, shape) {
     var extent = shape.extent;
-    var orient = shape.orient;
+    ctx.moveTo(shape.x1, shape.y1);
+    ctx.bezierCurveTo(shape.cpx1, shape.cpy1, shape.cpx2, shape.cpy2, shape.x2, shape.y2);
 
-    if (orient === 'vertical') {
-      ctx.moveTo(shape.x1, shape.y1);
-      ctx.bezierCurveTo(shape.cpx1, shape.cpy1, shape.cpx2, shape.cpy2, shape.x2, shape.y2);
+    if (shape.orient === 'vertical') {
       ctx.lineTo(shape.x2 + extent, shape.y2);
       ctx.bezierCurveTo(shape.cpx2 + extent, shape.cpy2, shape.cpx1 + extent, shape.cpy1, shape.x1 + extent, shape.y1);
     } else {
-      ctx.moveTo(shape.x1, shape.y1);
-      ctx.bezierCurveTo(shape.cpx1, shape.cpy1, shape.cpx2, shape.cpy2, shape.x2, shape.y2);
       ctx.lineTo(shape.x2, shape.y2 + extent);
       ctx.bezierCurveTo(shape.cpx2, shape.cpy2 + extent, shape.cpx1, shape.cpy1 + extent, shape.x1, shape.y1 + extent);
     }
@@ -253,6 +245,8 @@ export default echarts.extendChartView({
       if (itemModel.get('focusNodeAdjacency')) {
         el.off('mouseover').on('mouseover', function () {
           if (!sankeyView._focusAdjacencyDisabled) {
+            sankeyView._clearTimer();
+
             api.dispatchAction({
               type: 'focusNodeAdjacency',
               seriesId: seriesModel.id,
@@ -262,10 +256,7 @@ export default echarts.extendChartView({
         });
         el.off('mouseout').on('mouseout', function () {
           if (!sankeyView._focusAdjacencyDisabled) {
-            api.dispatchAction({
-              type: 'unfocusNodeAdjacency',
-              seriesId: seriesModel.id
-            });
+            sankeyView._dispatchUnfocus(api);
           }
         });
       }
@@ -276,6 +267,8 @@ export default echarts.extendChartView({
       if (edgeModel.get('focusNodeAdjacency')) {
         el.off('mouseover').on('mouseover', function () {
           if (!sankeyView._focusAdjacencyDisabled) {
+            sankeyView._clearTimer();
+
             api.dispatchAction({
               type: 'focusNodeAdjacency',
               seriesId: seriesModel.id,
@@ -285,10 +278,7 @@ export default echarts.extendChartView({
         });
         el.off('mouseout').on('mouseout', function () {
           if (!sankeyView._focusAdjacencyDisabled) {
-            api.dispatchAction({
-              type: 'unfocusNodeAdjacency',
-              seriesId: seriesModel.id
-            });
+            sankeyView._dispatchUnfocus(api);
           }
         });
       }
@@ -302,7 +292,28 @@ export default echarts.extendChartView({
 
     this._data = seriesModel.getData();
   },
-  dispose: function () {},
+  dispose: function () {
+    this._clearTimer();
+  },
+  _dispatchUnfocus: function (api) {
+    var self = this;
+
+    this._clearTimer();
+
+    this._unfocusDelayTimer = setTimeout(function () {
+      self._unfocusDelayTimer = null;
+      api.dispatchAction({
+        type: 'unfocusNodeAdjacency',
+        seriesId: self._model.id
+      });
+    }, 500);
+  },
+  _clearTimer: function () {
+    if (this._unfocusDelayTimer) {
+      clearTimeout(this._unfocusDelayTimer);
+      this._unfocusDelayTimer = null;
+    }
+  },
   focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
     var data = this._model.getData();
 
diff --git a/builder/src/echarts/chart/sankey/sankeyAction.js b/builder/src/echarts/chart/sankey/sankeyAction.js
index ac171cf..2329240 100644
--- a/builder/src/echarts/chart/sankey/sankeyAction.js
+++ b/builder/src/echarts/chart/sankey/sankeyAction.js
@@ -16,16 +16,11 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file The interactive action of sankey view
- * @author Deqing Li(annong035@gmail.com)
- */
 import * as echarts from '../../echarts';
 import '../helper/focusNodeAdjacencyAction';
 echarts.registerAction({
   type: 'dragNode',
-  event: 'dragNode',
+  event: 'dragnode',
   // here can only use 'update' now, other value is not support in echarts.
   update: 'update'
 }, function (payload, ecModel) {
diff --git a/builder/src/echarts/chart/sankey/sankeyLayout.js b/builder/src/echarts/chart/sankey/sankeyLayout.js
index b4ac602..84e7bca 100644
--- a/builder/src/echarts/chart/sankey/sankeyLayout.js
+++ b/builder/src/echarts/chart/sankey/sankeyLayout.js
@@ -16,15 +16,9 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file The layout algorithm of sankey view
- * @author Deqing Li(annong035@gmail.com)
- */
 import * as layout from '../../util/layout';
 import * as zrUtil from 'zrender/src/core/util';
 import { groupData } from '../../util/model';
-import { __DEV__ } from '../../config';
 export default function (ecModel, api, payload) {
   ecModel.eachSeriesByType('sankey', function (seriesModel) {
     var nodeWidth = seriesModel.get('nodeWidth');
@@ -42,7 +36,8 @@ export default function (ecModel, api, payload) {
     });
     var iterations = filteredNodes.length !== 0 ? 0 : seriesModel.get('layoutIterations');
     var orient = seriesModel.get('orient');
-    layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient);
+    var nodeAlign = seriesModel.get('nodeAlign');
+    layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign);
   });
 }
 /**
@@ -60,8 +55,8 @@ function getViewRect(seriesModel, api) {
   });
 }
 
-function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient) {
-  computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient);
+function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign) {
+  computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign);
   computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient);
   computeEdgeDepths(nodes, orient);
 }
@@ -94,7 +89,7 @@ function computeNodeValues(nodes) {
  */
 
 
-function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient) {
+function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign) {
   // Used to mark whether the edge is deleted. if it is deleted,
   // the value is 0, otherwise it is 1.
   var remainEdges = []; // Storage each node's indegree.
@@ -102,7 +97,7 @@ function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient) {
   var indegreeArr = []; //Used to storage the node with indegree is equal to 0.
 
   var zeroIndegrees = [];
-  var nextNode = [];
+  var nextTargetNode = [];
   var x = 0;
   var kx = 0;
 
@@ -118,78 +113,121 @@ function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient) {
     }
   }
 
+  var maxNodeDepth = -1; // Traversing nodes using topological sorting to calculate the
+  // horizontal(if orient === 'horizontal') or vertical(if orient === 'vertical')
+  // position of the nodes.
+
   while (zeroIndegrees.length) {
     for (var idx = 0; idx < zeroIndegrees.length; idx++) {
       var node = zeroIndegrees[idx];
+      var item = node.hostGraph.data.getRawDataItem(node.dataIndex);
+      var isItemDepth = item.depth != null && item.depth >= 0;
 
-      if (orient === 'vertical') {
-        node.setLayout({
-          y: x
-        }, true);
-        node.setLayout({
-          dy: nodeWidth
-        }, true);
-      } else {
-        node.setLayout({
-          x: x
-        }, true);
-        node.setLayout({
-          dx: nodeWidth
-        }, true);
+      if (isItemDepth && item.depth > maxNodeDepth) {
+        maxNodeDepth = item.depth;
       }
 
-      for (var oidx = 0; oidx < node.outEdges.length; oidx++) {
-        var edge = node.outEdges[oidx];
+      node.setLayout({
+        depth: isItemDepth ? item.depth : x
+      }, true);
+      orient === 'vertical' ? node.setLayout({
+        dy: nodeWidth
+      }, true) : node.setLayout({
+        dx: nodeWidth
+      }, true);
+
+      for (var edgeIdx = 0; edgeIdx < node.outEdges.length; edgeIdx++) {
+        var edge = node.outEdges[edgeIdx];
         var indexEdge = edges.indexOf(edge);
         remainEdges[indexEdge] = 0;
         var targetNode = edge.node2;
         var nodeIndex = nodes.indexOf(targetNode);
 
-        if (--indegreeArr[nodeIndex] === 0) {
-          nextNode.push(targetNode);
+        if (--indegreeArr[nodeIndex] === 0 && nextTargetNode.indexOf(targetNode) < 0) {
+          nextTargetNode.push(targetNode);
         }
       }
     }
 
     ++x;
-    zeroIndegrees = nextNode;
-    nextNode = [];
+    zeroIndegrees = nextTargetNode;
+    nextTargetNode = [];
   }
 
-  for (i = 0; i < remainEdges.length; i++) {}
+  for (i = 0; i < remainEdges.length; i++) {
+    if (remainEdges[i] === 1) {
+      throw new Error('Sankey is a DAG, the original data has cycle!');
+    }
+  }
 
-  moveSinksRight(nodes, x, orient);
+  var maxDepth = maxNodeDepth > x - 1 ? maxNodeDepth : x - 1;
 
-  if (orient === 'vertical') {
-    kx = (height - nodeWidth) / (x - 1);
-  } else {
-    kx = (width - nodeWidth) / (x - 1);
+  if (nodeAlign && nodeAlign !== 'left') {
+    adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth);
   }
 
+  var kx = orient === 'vertical' ? (height - nodeWidth) / maxDepth : (width - nodeWidth) / maxDepth;
   scaleNodeBreadths(nodes, kx, orient);
 }
+
+function isNodeDepth(node) {
+  var item = node.hostGraph.data.getRawDataItem(node.dataIndex);
+  return item.depth != null && item.depth >= 0;
+}
+
+function adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth) {
+  if (nodeAlign === 'right') {
+    var nextSourceNode = [];
+    var remainNodes = nodes;
+    var nodeHeight = 0;
+
+    while (remainNodes.length) {
+      for (var i = 0; i < remainNodes.length; i++) {
+        var node = remainNodes[i];
+        node.setLayout({
+          skNodeHeight: nodeHeight
+        }, true);
+
+        for (var j = 0; j < node.inEdges.length; j++) {
+          var edge = node.inEdges[j];
+
+          if (nextSourceNode.indexOf(edge.node1) < 0) {
+            nextSourceNode.push(edge.node1);
+          }
+        }
+      }
+
+      remainNodes = nextSourceNode;
+      nextSourceNode = [];
+      ++nodeHeight;
+    }
+
+    zrUtil.each(nodes, function (node) {
+      if (!isNodeDepth(node)) {
+        node.setLayout({
+          depth: Math.max(0, maxDepth - node.getLayout().skNodeHeight)
+        }, true);
+      }
+    });
+  } else if (nodeAlign === 'justify') {
+    moveSinksRight(nodes, maxDepth);
+  }
+}
 /**
  * All the node without outEgdes are assigned maximum x-position and
  *     be aligned in the last column.
  *
- * @param {module:echarts/data/Graph~Node} nodes  node of sankey view
- * @param {number} x  value (x-1) use to assign to node without outEdges
- *     as x-position
+ * @param {module:echarts/data/Graph~Node} nodes.  node of sankey view.
+ * @param {number} maxDepth.  use to assign to node without outEdges as x-position.
  */
 
 
-function moveSinksRight(nodes, x, orient) {
+function moveSinksRight(nodes, maxDepth) {
   zrUtil.each(nodes, function (node) {
-    if (!node.outEdges.length) {
-      if (orient === 'vertical') {
-        node.setLayout({
-          y: x - 1
-        }, true);
-      } else {
-        node.setLayout({
-          x: x - 1
-        }, true);
-      }
+    if (!isNodeDepth(node) && !node.outEdges.length) {
+      node.setLayout({
+        depth: maxDepth
+      }, true);
     }
   });
 }
@@ -203,17 +241,12 @@ function moveSinksRight(nodes, x, orient) {
 
 function scaleNodeBreadths(nodes, kx, orient) {
   zrUtil.each(nodes, function (node) {
-    if (orient === 'vertical') {
-      var nodeY = node.getLayout().y * kx;
-      node.setLayout({
-        y: nodeY
-      }, true);
-    } else {
-      var nodeX = node.getLayout().x * kx;
-      node.setLayout({
-        x: nodeX
-      }, true);
-    }
+    var nodeDepth = node.getLayout().depth * kx;
+    orient === 'vertical' ? node.setLayout({
+      y: nodeDepth
+    }, true) : node.setLayout({
+      x: nodeDepth
+    }, true);
   });
 }
 /**
@@ -230,7 +263,7 @@ function scaleNodeBreadths(nodes, kx, orient) {
 
 function computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient) {
   var nodesByBreadth = prepareNodesByBreadth(nodes, orient);
-  initializeNodeDepth(nodes, nodesByBreadth, edges, height, width, nodeGap, orient);
+  initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient);
   resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);
 
   for (var alpha = 1; iterations > 0; iterations--) {
@@ -270,31 +303,23 @@ function prepareNodesByBreadth(nodes, orient) {
  */
 
 
-function initializeNodeDepth(nodes, nodesByBreadth, edges, height, width, nodeGap, orient) {
-  var kyArray = [];
+function initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient) {
+  var minKy = Infinity;
   zrUtil.each(nodesByBreadth, function (nodes) {
     var n = nodes.length;
     var sum = 0;
-    var ky = 0;
     zrUtil.each(nodes, function (node) {
       sum += node.getLayout().value;
     });
+    var ky = orient === 'vertical' ? (width - (n - 1) * nodeGap) / sum : (height - (n - 1) * nodeGap) / sum;
 
-    if (orient === 'vertical') {
-      ky = (width - (n - 1) * nodeGap) / sum;
-    } else {
-      ky = (height - (n - 1) * nodeGap) / sum;
+    if (ky < minKy) {
+      minKy = ky;
     }
-
-    kyArray.push(ky);
-  });
-  kyArray.sort(function (a, b) {
-    return a - b;
   });
-  var ky0 = kyArray[0];
   zrUtil.each(nodesByBreadth, function (nodes) {
     zrUtil.each(nodes, function (node, i) {
-      var nodeDy = node.getLayout().value * ky0;
+      var nodeDy = node.getLayout().value * minKy;
 
       if (orient === 'vertical') {
         node.setLayout({
@@ -314,7 +339,7 @@ function initializeNodeDepth(nodes, nodesByBreadth, edges, height, width, nodeGa
     });
   });
   zrUtil.each(edges, function (edge) {
-    var edgeDy = +edge.getValue() * ky0;
+    var edgeDy = +edge.getValue() * minKy;
     edge.setLayout({
       dy: edgeDy
     }, true);
@@ -331,100 +356,61 @@ function initializeNodeDepth(nodes, nodesByBreadth, edges, height, width, nodeGa
 
 
 function resolveCollisions(nodesByBreadth, nodeGap, height, width, orient) {
+  var keyAttr = orient === 'vertical' ? 'x' : 'y';
   zrUtil.each(nodesByBreadth, function (nodes) {
+    nodes.sort(function (a, b) {
+      return a.getLayout()[keyAttr] - b.getLayout()[keyAttr];
+    });
+    var nodeX;
     var node;
     var dy;
     var y0 = 0;
     var n = nodes.length;
-    var i;
-
-    if (orient === 'vertical') {
-      var nodeX;
-      nodes.sort(function (a, b) {
-        return a.getLayout().x - b.getLayout().x;
-      });
+    var nodeDyAttr = orient === 'vertical' ? 'dx' : 'dy';
 
-      for (i = 0; i < n; i++) {
-        node = nodes[i];
-        dy = y0 - node.getLayout().x;
-
-        if (dy > 0) {
-          nodeX = node.getLayout().x + dy;
-          node.setLayout({
-            x: nodeX
-          }, true);
-        }
-
-        y0 = node.getLayout().x + node.getLayout().dx + nodeGap;
-      } // If the bottommost node goes outside the bounds, push it back up
-
-
-      dy = y0 - nodeGap - width;
+    for (var i = 0; i < n; i++) {
+      node = nodes[i];
+      dy = y0 - node.getLayout()[keyAttr];
 
       if (dy > 0) {
-        nodeX = node.getLayout().x - dy;
-        node.setLayout({
+        nodeX = node.getLayout()[keyAttr] + dy;
+        orient === 'vertical' ? node.setLayout({
           x: nodeX
+        }, true) : node.setLayout({
+          y: nodeX
         }, true);
-        y0 = nodeX;
+      }
+
+      y0 = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap;
+    }
 
-        for (i = n - 2; i >= 0; --i) {
-          node = nodes[i];
-          dy = node.getLayout().x + node.getLayout().dx + nodeGap - y0;
+    var viewWidth = orient === 'vertical' ? width : height; // If the bottommost node goes outside the bounds, push it back up
 
-          if (dy > 0) {
-            nodeX = node.getLayout().x - dy;
-            node.setLayout({
-              x: nodeX
-            }, true);
-          }
+    dy = y0 - nodeGap - viewWidth;
 
-          y0 = node.getLayout().x;
-        }
-      }
-    } else {
-      var nodeY;
-      nodes.sort(function (a, b) {
-        return a.getLayout().y - b.getLayout().y;
-      });
+    if (dy > 0) {
+      nodeX = node.getLayout()[keyAttr] - dy;
+      orient === 'vertical' ? node.setLayout({
+        x: nodeX
+      }, true) : node.setLayout({
+        y: nodeX
+      }, true);
+      y0 = nodeX;
 
-      for (i = 0; i < n; i++) {
+      for (i = n - 2; i >= 0; --i) {
         node = nodes[i];
-        dy = y0 - node.getLayout().y;
+        dy = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap - y0;
 
         if (dy > 0) {
-          nodeY = node.getLayout().y + dy;
-          node.setLayout({
-            y: nodeY
+          nodeX = node.getLayout()[keyAttr] - dy;
+          orient === 'vertical' ? node.setLayout({
+            x: nodeX
+          }, true) : node.setLayout({
+            y: nodeX
           }, true);
         }
 
-        y0 = node.getLayout().y + node.getLayout().dy + nodeGap;
-      } // If the bottommost node goes outside the bounds, push it back up
-
-
-      dy = y0 - nodeGap - height;
-
-      if (dy > 0) {
-        nodeY = node.getLayout().y - dy;
-        node.setLayout({
-          y: nodeY
-        }, true);
-        y0 = nodeY;
-
-        for (i = n - 2; i >= 0; --i) {
-          node = nodes[i];
-          dy = node.getLayout().y + node.getLayout().dy + nodeGap - y0;
-
-          if (dy > 0) {
-            nodeY = node.getLayout().y - dy;
-            node.setLayout({
-              y: nodeY
-            }, true);
-          }
-
-          y0 = node.getLayout().y;
-        }
+        y0 = node.getLayout()[keyAttr];
       }
     }
   });
@@ -469,11 +455,7 @@ function weightedSource(edge, orient) {
 }
 
 function center(node, orient) {
-  if (orient === 'vertical') {
-    return node.getLayout().x + node.getLayout().dx / 2;
-  }
-
-  return node.getLayout().y + node.getLayout().dy / 2;
+  return orient === 'vertical' ? node.getLayout().x + node.getLayout().dx / 2 : node.getLayout().y + node.getLayout().dy / 2;
 }
 
 function getEdgeValue(edge) {
@@ -533,22 +515,14 @@ function relaxLeftToRight(nodesByBreadth, alpha, orient) {
 
 
 function computeEdgeDepths(nodes, orient) {
+  var keyAttr = orient === 'vertical' ? 'x' : 'y';
   zrUtil.each(nodes, function (node) {
-    if (orient === 'vertical') {
-      node.outEdges.sort(function (a, b) {
-        return a.node2.getLayout().x - b.node2.getLayout().x;
-      });
-      node.inEdges.sort(function (a, b) {
-        return a.node1.getLayout().x - b.node1.getLayout().x;
-      });
-    } else {
-      node.outEdges.sort(function (a, b) {
-        return a.node2.getLayout().y - b.node2.getLayout().y;
-      });
-      node.inEdges.sort(function (a, b) {
-        return a.node1.getLayout().y - b.node1.getLayout().y;
-      });
-    }
+    node.outEdges.sort(function (a, b) {
+      return a.node2.getLayout()[keyAttr] - b.node2.getLayout()[keyAttr];
+    });
+    node.inEdges.sort(function (a, b) {
+      return a.node1.getLayout()[keyAttr] - b.node1.getLayout()[keyAttr];
+    });
   });
   zrUtil.each(nodes, function (node) {
     var sy = 0;
diff --git a/builder/src/echarts/chart/sankey/sankeyVisual.js b/builder/src/echarts/chart/sankey/sankeyVisual.js
index 0a407fc..45cfb8f 100644
--- a/builder/src/echarts/chart/sankey/sankeyVisual.js
+++ b/builder/src/echarts/chart/sankey/sankeyVisual.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file Visual encoding for sankey view
- * @author  Deqing Li(annong035@gmail.com)
- */
 import VisualMapping from '../../visual/VisualMapping';
 import * as zrUtil from 'zrender/src/core/util';
 export default function (ecModel, payload) {
@@ -50,14 +45,8 @@ export default function (ecModel, payload) {
           visual: seriesModel.get('color')
         });
         var mapValueToColor = mapping.mapValueToVisual(node.getLayout().value);
-        node.setVisual('color', mapValueToColor); // If set itemStyle.normal.color
-
-        var itemModel = node.getModel();
-        var customColor = itemModel.get('itemStyle.color');
-
-        if (customColor != null) {
-          node.setVisual('color', customColor);
-        }
+        var customColor = node.getModel().get('itemStyle.color');
+        customColor != null ? node.setVisual('color', customColor) : node.setVisual('color', mapValueToColor);
       });
     }
   });
diff --git a/builder/src/echarts/chart/scatter/ScatterSeries.js b/builder/src/echarts/chart/scatter/ScatterSeries.js
index f66944c..194f8c0 100644
--- a/builder/src/echarts/chart/scatter/ScatterSeries.js
+++ b/builder/src/echarts/chart/scatter/ScatterSeries.js
@@ -22,7 +22,9 @@ export default SeriesModel.extend({
   type: 'series.scatter',
   dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'],
   getInitialData: function (option, ecModel) {
-    return createListFromArray(this.getSource(), this);
+    return createListFromArray(this.getSource(), this, {
+      useEncodeDefaulter: true
+    });
   },
   brushSelector: 'point',
   getProgressive: function () {
@@ -76,8 +78,11 @@ export default SeriesModel.extend({
     // },
     itemStyle: {
       opacity: 0.8 // color: 各异
-      // progressive: null
 
-    }
+    },
+    // If clip the overflow graphics
+    // Works on cartesian / polar series
+    clip: true // progressive: null
+
   }
 });
\ No newline at end of file
diff --git a/builder/src/echarts/chart/scatter/ScatterView.js b/builder/src/echarts/chart/scatter/ScatterView.js
index c3b0f04..686924d 100644
--- a/builder/src/echarts/chart/scatter/ScatterView.js
+++ b/builder/src/echarts/chart/scatter/ScatterView.js
@@ -27,7 +27,13 @@ echarts.extendChartView({
 
     var symbolDraw = this._updateSymbolDraw(data, seriesModel);
 
-    symbolDraw.updateData(data);
+    symbolDraw.updateData(data, {
+      // TODO
+      // If this parameter should be a shape or a bounding volume
+      // shape will be more general.
+      // But bounding volume like bounding rect will be much faster in the contain calculation
+      clipShape: this._getClipShape(seriesModel)
+    });
     this._finished = true;
   },
   incrementalPrepareRender: function (seriesModel, ecModel, api) {
@@ -39,7 +45,9 @@ echarts.extendChartView({
     this._finished = false;
   },
   incrementalRender: function (taskParams, seriesModel, ecModel) {
-    this._symbolDraw.incrementalUpdate(taskParams, seriesModel.getData());
+    this._symbolDraw.incrementalUpdate(taskParams, seriesModel.getData(), {
+      clipShape: this._getClipShape(seriesModel)
+    });
 
     this._finished = taskParams.end === seriesModel.getData().count();
   },
@@ -66,6 +74,11 @@ echarts.extendChartView({
       this._symbolDraw.updateLayout(data);
     }
   },
+  _getClipShape: function (seriesModel) {
+    var coordSys = seriesModel.coordinateSystem;
+    var clipArea = coordSys && coordSys.getArea && coordSys.getArea();
+    return seriesModel.get('clip', true) ? clipArea : null;
+  },
   _updateSymbolDraw: function (data, seriesModel) {
     var symbolDraw = this._symbolDraw;
     var pipelineContext = seriesModel.pipelineContext;
diff --git a/builder/src/echarts/chart/sunburst/SunburstPiece.js b/builder/src/echarts/chart/sunburst/SunburstPiece.js
index 4d7df30..5f0942b 100644
--- a/builder/src/echarts/chart/sunburst/SunburstPiece.js
+++ b/builder/src/echarts/chart/sunburst/SunburstPiece.js
@@ -165,7 +165,7 @@ 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, 'normal', null, null, 'label'), this.node.name);
+  var text = zrUtil.retrieve(seriesModel.getFormattedLabel(this.node.dataIndex, state, null, null, 'label'), this.node.name);
 
   if (getLabelAttr('show') === false) {
     text = '';
diff --git a/builder/src/echarts/chart/sunburst/sunburstLayout.js b/builder/src/echarts/chart/sunburst/sunburstLayout.js
index 82585cc..a764421 100644
--- a/builder/src/echarts/chart/sunburst/sunburstLayout.js
+++ b/builder/src/echarts/chart/sunburst/sunburstLayout.js
@@ -17,8 +17,8 @@
 * under the License.
 */
 import { parsePercent } from '../../util/number';
-import * as zrUtil from 'zrender/src/core/util';
-var PI2 = Math.PI * 2;
+import * as zrUtil from 'zrender/src/core/util'; // var PI2 = Math.PI * 2;
+
 var RADIAN = Math.PI / 180;
 export default function (seriesType, ecModel, api, payload) {
   ecModel.eachSeriesByType(seriesType, function (seriesModel) {
@@ -63,9 +63,9 @@ export default function (seriesType, ecModel, api, payload) {
     var rPerLevel = (r - r0) / (levels || 1);
     var clockwise = seriesModel.get('clockwise');
     var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); // In the case some sector angle is smaller than minAngle
+    // var restAngle = PI2;
+    // var valueSumLargerThanMinAngle = 0;
 
-    var restAngle = PI2;
-    var valueSumLargerThanMinAngle = 0;
     var dir = clockwise ? 1 : -1;
     /**
      * Render a tree
@@ -85,11 +85,11 @@ export default function (seriesType, ecModel, api, payload) {
         var angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian;
 
         if (angle < minAngle) {
-          angle = minAngle;
-          restAngle -= minAngle;
-        } else {
-          valueSumLargerThanMinAngle += value;
-        }
+          angle = minAngle; // restAngle -= minAngle;
+        } // else {
+        //     valueSumLargerThanMinAngle += value;
+        // }
+
 
         endAngle = startAngle + dir * angle;
         var depth = node.depth - rootDepth - (renderRollupNode ? -1 : 1);
diff --git a/builder/src/echarts/chart/themeRiver/ThemeRiverSeries.js b/builder/src/echarts/chart/themeRiver/ThemeRiverSeries.js
index 11749d5..e56ff67 100644
--- a/builder/src/echarts/chart/themeRiver/ThemeRiverSeries.js
+++ b/builder/src/echarts/chart/themeRiver/ThemeRiverSeries.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file  Define the themeRiver view's series model
- * @author Deqing Li(annong035@gmail.com)
- */
 import SeriesModel from '../../model/Series';
 import createDimensions from '../../data/helper/createDimensions';
 import { getDimensionTypeByAxis } from '../../data/helper/dimensionHelper';
@@ -28,6 +23,7 @@ import List from '../../data/List';
 import * as zrUtil from 'zrender/src/core/util';
 import { groupData } from '../../util/model';
 import { encodeHTML } from '../../util/format';
+import LegendVisualProvider from '../../visual/LegendVisualProvider';
 var DATA_NAME_INDEX = 2;
 var ThemeRiverSeries = SeriesModel.extend({
   type: 'series.themeRiver',
@@ -48,9 +44,7 @@ var ThemeRiverSeries = SeriesModel.extend({
     // Enable legend selection for each data item
     // Use a function instead of direct access because data reference may changed
 
-    this.legendDataProvider = function () {
-      return this.getRawData();
-    };
+    this.legendVisualProvider = new LegendVisualProvider(zrUtil.bind(this.getData, this), zrUtil.bind(this.getRawData, this));
   },
 
   /**
@@ -209,8 +203,7 @@ var ThemeRiverSeries = SeriesModel.extend({
 
   /**
    * Get data indices for show tooltip content
-   *
-   * @param {Array.<string>|string} dim  single coordinate dimension
+    * @param {Array.<string>|string} dim  single coordinate dimension
    * @param {number} value axis value
    * @param {module:echarts/coord/single/SingleAxis} baseAxis  single Axis used
    *     the themeRiver.
diff --git a/builder/src/echarts/chart/themeRiver/ThemeRiverView.js b/builder/src/echarts/chart/themeRiver/ThemeRiverView.js
index a496959..7b84e29 100644
--- a/builder/src/echarts/chart/themeRiver/ThemeRiverView.js
+++ b/builder/src/echarts/chart/themeRiver/ThemeRiverView.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file  The file used to draw themeRiver view
- * @author  Deqing Li(annong035@gmail.com)
- */
 import * as echarts from '../../echarts';
 import { Polygon } from '../line/poly';
 import * as graphic from '../../util/graphic';
diff --git a/builder/src/echarts/chart/themeRiver/themeRiverLayout.js b/builder/src/echarts/chart/themeRiver/themeRiverLayout.js
index f60e0db..79fb47c 100644
--- a/builder/src/echarts/chart/themeRiver/themeRiverLayout.js
+++ b/builder/src/echarts/chart/themeRiver/themeRiverLayout.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file  Using layout algorithm transform the raw data to layout information.
- * @author Deqing Li(annong035@gmail.com)
- */
 import * as zrUtil from 'zrender/src/core/util';
 import * as numberUtil from '../../util/number';
 export default function (ecModel, api) {
diff --git a/builder/src/echarts/chart/themeRiver/themeRiverVisual.js b/builder/src/echarts/chart/themeRiver/themeRiverVisual.js
index a78b591..e9ce012 100644
--- a/builder/src/echarts/chart/themeRiver/themeRiverVisual.js
+++ b/builder/src/echarts/chart/themeRiver/themeRiverVisual.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file Visual encoding for themeRiver view
- * @author Deqing Li(annong035@gmail.com)
- */
 import { createHashMap } from 'zrender/src/core/util';
 export default function (ecModel) {
   ecModel.eachSeriesByType('themeRiver', function (seriesModel) {
diff --git a/builder/src/echarts/chart/tree/TreeSeries.js b/builder/src/echarts/chart/tree/TreeSeries.js
index d8e79a5..7e2417e 100644
--- a/builder/src/echarts/chart/tree/TreeSeries.js
+++ b/builder/src/echarts/chart/tree/TreeSeries.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file Create data struct and define tree view's series model
- * @author Deqing Li(annong035@gmail.com)
- */
 import SeriesModel from '../../model/Series';
 import Tree from '../../data/Tree';
 import { encodeHTML } from '../../util/format';
@@ -45,7 +40,21 @@ export default SeriesModel.extend({
     var leaves = option.leaves || {};
     var treeOption = {};
     treeOption.leaves = leaves;
-    var tree = Tree.createTree(root, this, treeOption);
+    var tree = Tree.createTree(root, this, treeOption, beforeLink);
+
+    function beforeLink(nodeData) {
+      nodeData.wrapMethod('getItemModel', function (model, idx) {
+        var node = tree.getNodeByDataIndex(idx);
+        var leavesModel = node.getLeavesModel();
+
+        if (!node.children.length || !node.isExpand) {
+          model.parentModel = leavesModel;
+        }
+
+        return model;
+      });
+    }
+
     var treeDepth = 0;
     tree.eachNode('preorder', function (node) {
       if (node.depth > treeDepth) {
@@ -113,8 +122,8 @@ export default SeriesModel.extend({
     bottom: '12%',
     // the layout of the tree, two value can be selected, 'orthogonal' or 'radial'
     layout: 'orthogonal',
-    roam: false,
     // true | false | 'move' | 'scale', see module:component/helper/RoamController.
+    roam: false,
     // Symbol size scale ratio in roam
     nodeScaleRatio: 0.4,
     // Default on center of graph
diff --git a/builder/src/echarts/chart/tree/TreeView.js b/builder/src/echarts/chart/tree/TreeView.js
index 8501ada..750975e 100644
--- a/builder/src/echarts/chart/tree/TreeView.js
+++ b/builder/src/echarts/chart/tree/TreeView.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file This file used to draw tree view.
- * @author Deqing Li(annong035@gmail.com)
- */
 import * as zrUtil from 'zrender/src/core/util';
 import * as graphic from '../../util/graphic';
 import SymbolClz from '../helper/Symbol';
@@ -75,7 +70,7 @@ export default echarts.extendChartView({
       group.attr('position', [layoutInfo.x, layoutInfo.y]);
     }
 
-    this._updateViewCoordSys(seriesModel);
+    this._updateViewCoordSys(seriesModel, layoutInfo, layout);
 
     this._updateController(seriesModel, ecModel, api);
 
@@ -147,16 +142,20 @@ export default echarts.extendChartView({
     });
     var min = [];
     var max = [];
-    bbox.fromPoints(points, min, max); // If width or height is 0
+    bbox.fromPoints(points, min, max); // If don't Store min max when collapse the root node after roam,
+    // the root node will disappear.
+
+    var oldMin = this._min;
+    var oldMax = this._max; // If width or height is 0
 
     if (max[0] - min[0] === 0) {
-      max[0] += 1;
-      min[0] -= 1;
+      min[0] = oldMin ? oldMin[0] : min[0] - 1;
+      max[0] = oldMax ? oldMax[0] : max[0] + 1;
     }
 
     if (max[1] - min[1] === 0) {
-      max[1] += 1;
-      min[1] -= 1;
+      min[1] = oldMin ? oldMin[1] : min[1] - 1;
+      max[1] = oldMax ? oldMax[1] : max[1] + 1;
     }
 
     var viewCoordSys = seriesModel.coordinateSystem = new View();
@@ -170,6 +169,8 @@ export default echarts.extendChartView({
       scale: viewCoordSys.scale
     });
     this._viewCoordSys = viewCoordSys;
+    this._min = min;
+    this._max = max;
   },
   _updateController: function (seriesModel, ecModel, api) {
     var controller = this._controller;
@@ -342,9 +343,11 @@ function updateNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope)
     }
 
     var textPosition = isLeft ? 'left' : 'right';
+    var rotate = seriesScope.labelModel.get('rotate');
+    var labelRotateRadian = rotate * (Math.PI / 180);
     symbolPath.setStyle({
-      textPosition: textPosition,
-      textRotation: -rad,
+      textPosition: seriesScope.labelModel.get('position') || textPosition,
+      textRotation: rotate == null ? -rad : labelRotateRadian,
       textOrigin: 'center',
       verticalAlign: 'middle'
     });
diff --git a/builder/src/echarts/chart/tree/treeAction.js b/builder/src/echarts/chart/tree/treeAction.js
index d928444..15992ec 100644
--- a/builder/src/echarts/chart/tree/treeAction.js
+++ b/builder/src/echarts/chart/tree/treeAction.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file Register the actions of the tree
- * @author Deqing Li(annong035@gmail.com)
- */
 import * as echarts from '../../echarts';
 import { updateCenterAndZoom } from '../../action/roamHelper';
 echarts.registerAction({
diff --git a/builder/src/echarts/chart/treemap/TreemapSeries.js b/builder/src/echarts/chart/treemap/TreemapSeries.js
index 208ed89..7cc6006 100644
--- a/builder/src/echarts/chart/treemap/TreemapSeries.js
+++ b/builder/src/echarts/chart/treemap/TreemapSeries.js
@@ -26,6 +26,7 @@ export default SeriesModel.extend({
   type: 'series.treemap',
   layoutMode: 'box',
   dependencies: ['grid', 'polar'],
+  preventUsingHoverLayer: true,
 
   /**
    * @type {module:echarts/data/Tree~Node}
@@ -34,7 +35,6 @@ export default SeriesModel.extend({
   defaultOption: {
     // Disable progressive rendering
     progressive: 0,
-    hoverLayerThreshold: Infinity,
     // center: ['50%', '50%'],          // not supported in ec3.
     // size: ['80%', '80%'],            // deprecated, compatible with ec2.
     left: 'center',
diff --git a/builder/src/echarts/component/axis/AngleAxisView.js b/builder/src/echarts/component/axis/AngleAxisView.js
index fde1574..c501441 100644
--- a/builder/src/echarts/component/axis/AngleAxisView.js
+++ b/builder/src/echarts/component/axis/AngleAxisView.js
@@ -20,7 +20,8 @@ import * as zrUtil from 'zrender/src/core/util';
 import * as graphic from '../../util/graphic';
 import Model from '../../model/Model';
 import AxisView from './AxisView';
-var elementList = ['axisLine', 'axisLabel', 'axisTick', 'splitLine', 'splitArea'];
+import AxisBuilder from './AxisBuilder';
+var elementList = ['axisLine', 'axisLabel', 'axisTick', 'minorTick', 'splitLine', 'minorSplitLine', 'splitArea'];
 
 function getAxisLineShape(polar, rExtent, angle) {
   rExtent[1] > rExtent[0] && (rExtent = rExtent.slice().reverse());
@@ -63,6 +64,7 @@ export default AxisView.extend({
     var polar = angleAxis.polar;
     var radiusExtent = polar.getRadiusAxis().getExtent();
     var ticksAngles = angleAxis.getTicksCoords();
+    var minorTickAngles = angleAxis.getMinorTicksCoords();
     var labels = zrUtil.map(angleAxis.getViewLabels(), function (labelItem) {
       var labelItem = zrUtil.clone(labelItem);
       labelItem.coord = angleAxis.dataToCoord(labelItem.tickValue);
@@ -72,7 +74,7 @@ export default AxisView.extend({
     fixAngleOverlap(ticksAngles);
     zrUtil.each(elementList, function (name) {
       if (angleAxisModel.get(name + '.show') && (!angleAxis.scale.isBlank() || name === 'axisLine')) {
-        this['_' + name](angleAxisModel, polar, ticksAngles, radiusExtent, labels);
+        this['_' + name](angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels);
       }
     }, this);
   },
@@ -80,26 +82,46 @@ export default AxisView.extend({
   /**
    * @private
    */
-  _axisLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
-    var lineStyleModel = angleAxisModel.getModel('axisLine.lineStyle');
-    var circle = new graphic.Circle({
-      shape: {
-        cx: polar.cx,
-        cy: polar.cy,
-        r: radiusExtent[getRadiusIdx(polar)]
-      },
-      style: lineStyleModel.getLineStyle(),
-      z2: 1,
-      silent: true
-    });
-    circle.style.fill = null;
-    this.group.add(circle);
+  _axisLine: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
+    var lineStyleModel = angleAxisModel.getModel('axisLine.lineStyle'); // extent id of the axis radius (r0 and r)
+
+    var rId = getRadiusIdx(polar);
+    var r0Id = rId ? 0 : 1;
+    var shape;
+
+    if (radiusExtent[r0Id] === 0) {
+      shape = new graphic.Circle({
+        shape: {
+          cx: polar.cx,
+          cy: polar.cy,
+          r: radiusExtent[rId]
+        },
+        style: lineStyleModel.getLineStyle(),
+        z2: 1,
+        silent: true
+      });
+    } else {
+      shape = new graphic.Ring({
+        shape: {
+          cx: polar.cx,
+          cy: polar.cy,
+          r: radiusExtent[rId],
+          r0: radiusExtent[r0Id]
+        },
+        style: lineStyleModel.getLineStyle(),
+        z2: 1,
+        silent: true
+      });
+    }
+
+    shape.style.fill = null;
+    this.group.add(shape);
   },
 
   /**
    * @private
    */
-  _axisTick: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
+  _axisTick: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
     var tickModel = angleAxisModel.getModel('axisTick');
     var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length');
     var radius = radiusExtent[getRadiusIdx(polar)];
@@ -118,10 +140,40 @@ export default AxisView.extend({
   /**
    * @private
    */
-  _axisLabel: function (angleAxisModel, polar, ticksAngles, radiusExtent, labels) {
+  _minorTick: function (angleAxisModel, polar, tickAngles, minorTickAngles, radiusExtent) {
+    if (!minorTickAngles.length) {
+      return;
+    }
+
+    var tickModel = angleAxisModel.getModel('axisTick');
+    var minorTickModel = angleAxisModel.getModel('minorTick');
+    var tickLen = (tickModel.get('inside') ? -1 : 1) * minorTickModel.get('length');
+    var radius = radiusExtent[getRadiusIdx(polar)];
+    var lines = [];
+
+    for (var i = 0; i < minorTickAngles.length; i++) {
+      for (var k = 0; k < minorTickAngles[i].length; k++) {
+        lines.push(new graphic.Line({
+          shape: getAxisLineShape(polar, [radius, radius + tickLen], minorTickAngles[i][k].coord)
+        }));
+      }
+    }
+
+    this.group.add(graphic.mergePath(lines, {
+      style: zrUtil.defaults(minorTickModel.getModel('lineStyle').getLineStyle(), zrUtil.defaults(tickModel.getLineStyle(), {
+        stroke: angleAxisModel.get('axisLine.lineStyle.color')
+      }))
+    }));
+  },
+
+  /**
+   * @private
+   */
+  _axisLabel: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels) {
     var rawCategoryData = angleAxisModel.getCategories(true);
     var commonLabelModel = angleAxisModel.getModel('axisLabel');
-    var labelMargin = commonLabelModel.get('margin'); // Use length of ticksAngles because it may remove the last tick to avoid overlapping
+    var labelMargin = commonLabelModel.get('margin');
+    var triggerEvent = angleAxisModel.get('triggerEvent'); // Use length of ticksAngles because it may remove the last tick to avoid overlapping
 
     zrUtil.each(labels, function (labelItem, idx) {
       var labelModel = commonLabelModel;
@@ -138,7 +190,7 @@ export default AxisView.extend({
       }
 
       var textEl = new graphic.Text({
-        silent: true
+        silent: AxisBuilder.isLabelSilent(angleAxisModel)
       });
       this.group.add(textEl);
       graphic.setTextStyle(textEl.style, labelModel, {
@@ -148,14 +200,20 @@ export default AxisView.extend({
         text: labelItem.formattedLabel,
         textAlign: labelTextAlign,
         textVerticalAlign: labelTextVerticalAlign
-      });
+      }); // Pack data for mouse event
+
+      if (triggerEvent) {
+        textEl.eventData = AxisBuilder.makeAxisEventDataBase(angleAxisModel);
+        textEl.eventData.targetType = 'axisLabel';
+        textEl.eventData.value = labelItem.rawLabel;
+      }
     }, this);
   },
 
   /**
    * @private
    */
-  _splitLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
+  _splitLine: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
     var splitLineModel = angleAxisModel.getModel('splitLine');
     var lineStyleModel = splitLineModel.getModel('lineStyle');
     var lineColors = lineStyleModel.get('color');
@@ -187,7 +245,34 @@ export default AxisView.extend({
   /**
    * @private
    */
-  _splitArea: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
+  _minorSplitLine: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
+    if (!minorTickAngles.length) {
+      return;
+    }
+
+    var minorSplitLineModel = angleAxisModel.getModel('minorSplitLine');
+    var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
+    var lines = [];
+
+    for (var i = 0; i < minorTickAngles.length; i++) {
+      for (var k = 0; k < minorTickAngles[i].length; k++) {
+        lines.push(new graphic.Line({
+          shape: getAxisLineShape(polar, radiusExtent, minorTickAngles[i][k].coord)
+        }));
+      }
+    }
+
+    this.group.add(graphic.mergePath(lines, {
+      style: lineStyleModel.getLineStyle(),
+      silent: true,
+      z: angleAxisModel.get('z')
+    }));
+  },
+
+  /**
+   * @private
+   */
+  _splitArea: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
     if (!ticksAngles.length) {
       return;
     }
diff --git a/builder/src/echarts/component/axis/AxisBuilder.js b/builder/src/echarts/component/axis/AxisBuilder.js
index 03ee3d3..dfb33d4 100644
--- a/builder/src/echarts/component/axis/AxisBuilder.js
+++ b/builder/src/echarts/component/axis/AxisBuilder.js
@@ -16,7 +16,7 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-import { retrieve, defaults, extend, each } from 'zrender/src/core/util';
+import { retrieve, defaults, extend, each, map } from 'zrender/src/core/util';
 import * as formatUtil from '../../util/format';
 import * as graphic from '../../util/graphic';
 import Model from '../../model/Model';
@@ -26,15 +26,6 @@ import * as matrixUtil from 'zrender/src/core/matrix';
 import { applyTransform as v2ApplyTransform } from 'zrender/src/core/vector';
 import { shouldShowAllLabels } from '../../coord/axisHelper';
 var PI = Math.PI;
-
-function makeAxisEventDataBase(axisModel) {
-  var eventData = {
-    componentType: axisModel.mainType,
-    componentIndex: axisModel.componentIndex
-  };
-  eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex;
-  return eventData;
-}
 /**
  * A final axis is translated and rotated from a "standard axis".
  * So opt.position and opt.rotation is required.
@@ -74,7 +65,6 @@ function makeAxisEventDataBase(axisModel) {
  * @param {number} [opt.nameTruncateMaxWidth]
  */
 
-
 var AxisBuilder = function (axisModel, opt) {
   /**
    * @readOnly
@@ -147,9 +137,10 @@ var builders = {
     var lineStyle = extend({
       lineCap: 'round'
     }, axisModel.getModel('axisLine.lineStyle').getLineStyle());
-    this.group.add(new graphic.Line(graphic.subPixelOptimizeLine({
+    this.group.add(new graphic.Line({
       // Id for animation
       anid: 'line',
+      subPixelOptimize: true,
       shape: {
         x1: pt1[0],
         y1: pt1[1],
@@ -160,7 +151,7 @@ var builders = {
       strokeContainThreshold: opt.strokeContainThreshold || 5,
       silent: true,
       z2: 1
-    })));
+    }));
     var arrows = axisModel.get('axisLine.symbol');
     var arrowSize = axisModel.get('axisLine.symbolSize');
     var arrowOffset = axisModel.get('axisLine.symbolOffset') || 0;
@@ -214,9 +205,10 @@ var builders = {
   axisTickLabel: function () {
     var axisModel = this.axisModel;
     var opt = this.opt;
-    var tickEls = buildAxisTick(this, axisModel, opt);
+    var ticksEls = buildAxisMajorTicks(this, axisModel, opt);
     var labelEls = buildAxisLabel(this, axisModel, opt);
-    fixMinMaxLabelShow(axisModel, labelEls, tickEls);
+    fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
+    buildAxisMinorTicks(this, axisModel, opt);
   },
 
   /**
@@ -287,7 +279,7 @@ var builders = {
       __truncatedText: truncatedText,
       position: pos,
       rotation: labelLayout.rotation,
-      silent: isSilent(axisModel),
+      silent: isLabelSilent(axisModel),
       z2: 1,
       tooltip: tooltipOpt && tooltipOpt.show ? extend({
         content: name,
@@ -301,8 +293,8 @@ var builders = {
       text: truncatedText,
       textFont: textFont,
       textFill: textStyleModel.getTextColor() || axisModel.get('axisLine.lineStyle.color'),
-      textAlign: labelLayout.textAlign,
-      textVerticalAlign: labelLayout.textVerticalAlign
+      textAlign: textStyleModel.get('align') || labelLayout.textAlign,
+      textVerticalAlign: textStyleModel.get('verticalAlign') || labelLayout.textVerticalAlign
     });
 
     if (axisModel.get('triggerEvent')) {
@@ -319,6 +311,15 @@ var builders = {
     textEl.decomposeTransform();
   }
 };
+
+var makeAxisEventDataBase = AxisBuilder.makeAxisEventDataBase = function (axisModel) {
+  var eventData = {
+    componentType: axisModel.mainType,
+    componentIndex: axisModel.componentIndex
+  };
+  eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex;
+  return eventData;
+};
 /**
  * @public
  * @static
@@ -333,6 +334,7 @@ var builders = {
  * }
  */
 
+
 var innerTextLayout = AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) {
   var rotationDiff = remRadian(textRotation - axisRotation);
   var textAlign;
@@ -393,11 +395,11 @@ function endTextLayout(opt, textPosition, textRotate, extent) {
   };
 }
 
-function isSilent(axisModel) {
+var isLabelSilent = AxisBuilder.isLabelSilent = function (axisModel) {
   var tooltipOpt = axisModel.get('tooltip');
   return axisModel.get('silent') // Consider mouse cursor, add these restrictions.
   || !(axisModel.get('triggerEvent') || tooltipOpt && tooltipOpt.show);
-}
+};
 
 function fixMinMaxLabelShow(axisModel, labelEls, tickEls) {
   if (shouldShowAllLabels(axisModel.axis)) {
@@ -475,57 +477,95 @@ function isNameLocationCenter(nameLocation) {
   return nameLocation === 'middle' || nameLocation === 'center';
 }
 
-function buildAxisTick(axisBuilder, axisModel, opt) {
-  var axis = axisModel.axis;
-
-  if (!axisModel.get('axisTick.show') || axis.scale.isBlank()) {
-    return;
-  }
-
-  var tickModel = axisModel.getModel('axisTick');
-  var lineStyleModel = tickModel.getModel('lineStyle');
-  var tickLen = tickModel.get('length');
-  var ticksCoords = axis.getTicksCoords();
+function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, aniid) {
+  var tickEls = [];
   var pt1 = [];
   var pt2 = [];
-  var matrix = axisBuilder._transform;
-  var tickEls = [];
 
   for (var i = 0; i < ticksCoords.length; i++) {
     var tickCoord = ticksCoords[i].coord;
     pt1[0] = tickCoord;
     pt1[1] = 0;
     pt2[0] = tickCoord;
-    pt2[1] = opt.tickDirection * tickLen;
+    pt2[1] = tickEndCoord;
 
-    if (matrix) {
-      v2ApplyTransform(pt1, pt1, matrix);
-      v2ApplyTransform(pt2, pt2, matrix);
+    if (tickTransform) {
+      v2ApplyTransform(pt1, pt1, tickTransform);
+      v2ApplyTransform(pt2, pt2, tickTransform);
     } // Tick line, Not use group transform to have better line draw
 
 
-    var tickEl = new graphic.Line(graphic.subPixelOptimizeLine({
+    var tickEl = new graphic.Line({
       // Id for animation
-      anid: 'tick_' + ticksCoords[i].tickValue,
+      anid: aniid + '_' + ticksCoords[i].tickValue,
+      subPixelOptimize: true,
       shape: {
         x1: pt1[0],
         y1: pt1[1],
         x2: pt2[0],
         y2: pt2[1]
       },
-      style: defaults(lineStyleModel.getLineStyle(), {
-        stroke: axisModel.get('axisLine.lineStyle.color')
-      }),
+      style: tickLineStyle,
       z2: 2,
       silent: true
-    }));
-    axisBuilder.group.add(tickEl);
+    });
     tickEls.push(tickEl);
   }
 
   return tickEls;
 }
 
+function buildAxisMajorTicks(axisBuilder, axisModel, opt) {
+  var axis = axisModel.axis;
+  var tickModel = axisModel.getModel('axisTick');
+
+  if (!tickModel.get('show') || axis.scale.isBlank()) {
+    return;
+  }
+
+  var lineStyleModel = tickModel.getModel('lineStyle');
+  var tickEndCoord = opt.tickDirection * tickModel.get('length');
+  var ticksCoords = axis.getTicksCoords();
+  var ticksEls = createTicks(ticksCoords, axisBuilder._transform, tickEndCoord, defaults(lineStyleModel.getLineStyle(), {
+    stroke: axisModel.get('axisLine.lineStyle.color')
+  }), 'ticks');
+
+  for (var i = 0; i < ticksEls.length; i++) {
+    axisBuilder.group.add(ticksEls[i]);
+  }
+
+  return ticksEls;
+}
+
+function buildAxisMinorTicks(axisBuilder, axisModel, opt) {
+  var axis = axisModel.axis;
+  var minorTickModel = axisModel.getModel('minorTick');
+
+  if (!minorTickModel.get('show') || axis.scale.isBlank()) {
+    return;
+  }
+
+  var minorTicksCoords = axis.getMinorTicksCoords();
+
+  if (!minorTicksCoords.length) {
+    return;
+  }
+
+  var lineStyleModel = minorTickModel.getModel('lineStyle');
+  var tickEndCoord = opt.tickDirection * minorTickModel.get('length');
+  var minorTickLineStyle = defaults(lineStyleModel.getLineStyle(), defaults(axisModel.getModel('axisTick').getLineStyle(), {
+    stroke: axisModel.get('axisLine.lineStyle.color')
+  }));
+
+  for (var i = 0; i < minorTicksCoords.length; i++) {
+    var minorTicksEls = createTicks(minorTicksCoords[i], axisBuilder._transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i);
+
+    for (var k = 0; k < minorTicksEls.length; k++) {
+      axisBuilder.group.add(minorTicksEls[k]);
+    }
+  }
+}
+
 function buildAxisLabel(axisBuilder, axisModel, opt) {
   var axis = axisModel.axis;
   var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show'));
@@ -540,9 +580,9 @@ function buildAxisLabel(axisBuilder, axisModel, opt) {
 
   var labelRotation = (retrieve(opt.labelRotate, labelModel.get('rotate')) || 0) * PI / 180;
   var labelLayout = innerTextLayout(opt.rotation, labelRotation, opt.labelDirection);
-  var rawCategoryData = axisModel.getCategories(true);
+  var rawCategoryData = axisModel.getCategories && axisModel.getCategories(true);
   var labelEls = [];
-  var silent = isSilent(axisModel);
+  var silent = isLabelSilent(axisModel);
   var triggerEvent = axisModel.get('triggerEvent');
   each(labels, function (labelItem, index) {
     var tickValue = labelItem.tickValue;
diff --git a/builder/src/echarts/component/axis/CartesianAxisView.js b/builder/src/echarts/component/axis/CartesianAxisView.js
index 8f9a38f..ccf5c08 100644
--- a/builder/src/echarts/component/axis/CartesianAxisView.js
+++ b/builder/src/echarts/component/axis/CartesianAxisView.js
@@ -22,14 +22,7 @@ import AxisBuilder from './AxisBuilder';
 import AxisView from './AxisView';
 import * as cartesianAxisHelper from '../../coord/cartesian/cartesianAxisHelper';
 var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName'];
-var selfBuilderAttrs = ['splitArea', 'splitLine']; // function getAlignWithLabel(model, axisModel) {
-//     var alignWithLabel = model.get('alignWithLabel');
-//     if (alignWithLabel === 'auto') {
-//         alignWithLabel = axisModel.get('axisTick.alignWithLabel');
-//     }
-//     return alignWithLabel;
-// }
-
+var selfBuilderAttrs = ['splitArea', 'splitLine', 'minorSplitLine'];
 var CartesianAxisView = AxisView.extend({
   type: 'cartesianAxis',
   axisPointerClass: 'CartesianAxisPointer',
@@ -89,9 +82,7 @@ var CartesianAxisView = AxisView.extend({
       tickModel: splitLineModel
     });
     var p1 = [];
-    var p2 = []; // Simple optimization
-    // Batching the lines if color are the same
-
+    var p2 = [];
     var lineStyle = lineStyleModel.getLineStyle();
 
     for (var i = 0; i < ticksCoords.length; i++) {
@@ -112,8 +103,9 @@ var CartesianAxisView = AxisView.extend({
       var colorIndex = lineCount++ % lineColors.length;
       var tickValue = ticksCoords[i].tickValue;
 
-      this._axisGroup.add(new graphic.Line(graphic.subPixelOptimizeLine({
+      this._axisGroup.add(new graphic.Line({
         anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null,
+        subPixelOptimize: true,
         shape: {
           x1: p1[0],
           y1: p1[1],
@@ -124,7 +116,60 @@ var CartesianAxisView = AxisView.extend({
           stroke: lineColors[colorIndex]
         }, lineStyle),
         silent: true
-      })));
+      }));
+    }
+  },
+
+  /**
+   * @param {module:echarts/coord/cartesian/AxisModel} axisModel
+   * @param {module:echarts/coord/cartesian/GridModel} gridModel
+   * @private
+   */
+  _minorSplitLine: function (axisModel, gridModel) {
+    var axis = axisModel.axis;
+    var minorSplitLineModel = axisModel.getModel('minorSplitLine');
+    var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
+    var gridRect = gridModel.coordinateSystem.getRect();
+    var isHorizontal = axis.isHorizontal();
+    var minorTicksCoords = axis.getMinorTicksCoords();
+
+    if (!minorTicksCoords.length) {
+      return;
+    }
+
+    var p1 = [];
+    var p2 = [];
+    var lineStyle = lineStyleModel.getLineStyle();
+
+    for (var i = 0; i < minorTicksCoords.length; i++) {
+      for (var k = 0; k < minorTicksCoords[i].length; k++) {
+        var tickCoord = axis.toGlobalCoord(minorTicksCoords[i][k].coord);
+
+        if (isHorizontal) {
+          p1[0] = tickCoord;
+          p1[1] = gridRect.y;
+          p2[0] = tickCoord;
+          p2[1] = gridRect.y + gridRect.height;
+        } else {
+          p1[0] = gridRect.x;
+          p1[1] = tickCoord;
+          p2[0] = gridRect.x + gridRect.width;
+          p2[1] = tickCoord;
+        }
+
+        this._axisGroup.add(new graphic.Line({
+          anid: 'minor_line_' + minorTicksCoords[i][k].tickValue,
+          subPixelOptimize: true,
+          shape: {
+            x1: p1[0],
+            y1: p1[1],
+            x2: p2[0],
+            y2: p2[1]
+          },
+          style: lineStyle,
+          silent: true
+        }));
+      }
     }
   },
 
diff --git a/builder/src/echarts/component/axis/RadiusAxisView.js b/builder/src/echarts/component/axis/RadiusAxisView.js
index ce81f8d..8f8c120 100644
--- a/builder/src/echarts/component/axis/RadiusAxisView.js
+++ b/builder/src/echarts/component/axis/RadiusAxisView.js
@@ -21,7 +21,7 @@ import * as graphic from '../../util/graphic';
 import AxisBuilder from './AxisBuilder';
 import AxisView from './AxisView';
 var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName'];
-var selfBuilderAttrs = ['splitLine', 'splitArea'];
+var selfBuilderAttrs = ['splitLine', 'splitArea', 'minorSplitLine'];
 export default AxisView.extend({
   type: 'radiusAxis',
   axisPointerClass: 'PolarAxisPointer',
@@ -36,6 +36,7 @@ export default AxisView.extend({
     var polar = radiusAxis.polar;
     var angleAxis = polar.getAngleAxis();
     var ticksCoords = radiusAxis.getTicksCoords();
+    var minorTicksCoords = radiusAxis.getMinorTicksCoords();
     var axisAngle = angleAxis.getExtent()[0];
     var radiusExtent = radiusAxis.getExtent();
     var layout = layoutAxis(polar, radiusAxisModel, axisAngle);
@@ -44,7 +45,7 @@ export default AxisView.extend({
     this.group.add(axisBuilder.getGroup());
     zrUtil.each(selfBuilderAttrs, function (name) {
       if (radiusAxisModel.get(name + '.show') && !radiusAxis.scale.isBlank()) {
-        this['_' + name](radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords);
+        this['_' + name](radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords);
       }
     }, this);
   },
@@ -68,8 +69,7 @@ export default AxisView.extend({
           cx: polar.cx,
           cy: polar.cy,
           r: ticksCoords[i].coord
-        },
-        silent: true
+        }
       }));
     } // Simple optimization
     // Batching the lines if color are the same
@@ -89,6 +89,38 @@ export default AxisView.extend({
   /**
    * @private
    */
+  _minorSplitLine: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords) {
+    if (!minorTicksCoords.length) {
+      return;
+    }
+
+    var minorSplitLineModel = radiusAxisModel.getModel('minorSplitLine');
+    var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
+    var lines = [];
+
+    for (var i = 0; i < minorTicksCoords.length; i++) {
+      for (var k = 0; k < minorTicksCoords[i].length; k++) {
+        lines.push(new graphic.Circle({
+          shape: {
+            cx: polar.cx,
+            cy: polar.cy,
+            r: minorTicksCoords[i][k].coord
+          }
+        }));
+      }
+    }
+
+    this.group.add(graphic.mergePath(lines, {
+      style: zrUtil.defaults({
+        fill: null
+      }, lineStyleModel.getLineStyle()),
+      silent: true
+    }));
+  },
+
+  /**
+   * @private
+   */
   _splitArea: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
     if (!ticksCoords.length) {
       return;
diff --git a/builder/src/echarts/component/axis/SingleAxisView.js b/builder/src/echarts/component/axis/SingleAxisView.js
index 1306095..98179f0 100644
--- a/builder/src/echarts/component/axis/SingleAxisView.js
+++ b/builder/src/echarts/component/axis/SingleAxisView.js
@@ -79,7 +79,8 @@ var SingleAxisView = AxisView.extend({
 
       var colorIndex = lineCount++ % lineColors.length;
       splitLines[colorIndex] = splitLines[colorIndex] || [];
-      splitLines[colorIndex].push(new graphic.Line(graphic.subPixelOptimizeLine({
+      splitLines[colorIndex].push(new graphic.Line({
+        subPixelOptimize: true,
         shape: {
           x1: p1[0],
           y1: p1[1],
@@ -90,7 +91,7 @@ var SingleAxisView = AxisView.extend({
           lineWidth: lineWidth
         },
         silent: true
-      })));
+      }));
     }
 
     for (var i = 0; i < splitLines.length; ++i) {
diff --git a/builder/src/echarts/component/axisPointer/BaseAxisPointer.js b/builder/src/echarts/component/axisPointer/BaseAxisPointer.js
index 9d4236e..25a5e68 100644
--- a/builder/src/echarts/component/axisPointer/BaseAxisPointer.js
+++ b/builder/src/echarts/component/axisPointer/BaseAxisPointer.js
@@ -223,7 +223,7 @@ BaseAxisPointer.prototype = {
   updatePointerEl: function (group, elOption, updateProps) {
     var pointerEl = inner(group).pointerEl;
 
-    if (pointerEl) {
+    if (pointerEl && elOption.pointer) {
       pointerEl.setStyle(elOption.pointer.style);
       updateProps(pointerEl, {
         shape: elOption.pointer.shape
diff --git a/builder/src/echarts/component/axisPointer/CartesianAxisPointer.js b/builder/src/echarts/component/axisPointer/CartesianAxisPointer.js
index 6d94226..eef3b3b 100644
--- a/builder/src/echarts/component/axisPointer/CartesianAxisPointer.js
+++ b/builder/src/echarts/component/axisPointer/CartesianAxisPointer.js
@@ -16,7 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-import * as graphic from '../../util/graphic';
 import BaseAxisPointer from './BaseAxisPointer';
 import * as viewHelper from './viewHelper';
 import * as cartesianAxisHelper from '../../coord/cartesian/cartesianAxisHelper';
@@ -34,7 +33,7 @@ var CartesianAxisPointer = BaseAxisPointer.extend({
 
     if (axisPointerType && axisPointerType !== 'none') {
       var elStyle = viewHelper.buildElStyle(axisPointerModel);
-      var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent, elStyle);
+      var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent);
       pointerOption.style = elStyle;
       elOption.graphicKey = pointerOption.type;
       elOption.pointer = pointerOption;
@@ -96,18 +95,15 @@ function getCartesian(grid, axis) {
 }
 
 var pointerShapeBuilder = {
-  line: function (axis, pixelValue, otherExtent, elStyle) {
+  line: function (axis, pixelValue, otherExtent) {
     var targetShape = viewHelper.makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getAxisDimIndex(axis));
-    graphic.subPixelOptimizeLine({
-      shape: targetShape,
-      style: elStyle
-    });
     return {
       type: 'Line',
+      subPixelOptimize: true,
       shape: targetShape
     };
   },
-  shadow: function (axis, pixelValue, otherExtent, elStyle) {
+  shadow: function (axis, pixelValue, otherExtent) {
     var bandWidth = Math.max(1, axis.getBandWidth());
     var span = otherExtent[1] - otherExtent[0];
     return {
diff --git a/builder/src/echarts/component/axisPointer/SingleAxisPointer.js b/builder/src/echarts/component/axisPointer/SingleAxisPointer.js
index b3b93a5..2852a2a 100644
--- a/builder/src/echarts/component/axisPointer/SingleAxisPointer.js
+++ b/builder/src/echarts/component/axisPointer/SingleAxisPointer.js
@@ -16,7 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-import * as graphic from '../../util/graphic';
 import BaseAxisPointer from './BaseAxisPointer';
 import * as viewHelper from './viewHelper';
 import * as singleAxisHelper from '../../coord/single/singleAxisHelper';
@@ -36,7 +35,7 @@ var SingleAxisPointer = BaseAxisPointer.extend({
 
     if (axisPointerType && axisPointerType !== 'none') {
       var elStyle = viewHelper.buildElStyle(axisPointerModel);
-      var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent, elStyle);
+      var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent);
       pointerOption.style = elStyle;
       elOption.graphicKey = pointerOption.type;
       elOption.pointer = pointerOption;
@@ -87,18 +86,15 @@ var SingleAxisPointer = BaseAxisPointer.extend({
   }
 });
 var pointerShapeBuilder = {
-  line: function (axis, pixelValue, otherExtent, elStyle) {
+  line: function (axis, pixelValue, otherExtent) {
     var targetShape = viewHelper.makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getPointDimIndex(axis));
-    graphic.subPixelOptimizeLine({
-      shape: targetShape,
-      style: elStyle
-    });
     return {
       type: 'Line',
+      subPixelOptimize: true,
       shape: targetShape
     };
   },
-  shadow: function (axis, pixelValue, otherExtent, elStyle) {
+  shadow: function (axis, pixelValue, otherExtent) {
     var bandWidth = axis.getBandWidth();
     var span = otherExtent[1] - otherExtent[0];
     return {
diff --git a/builder/src/echarts/component/axisPointer/viewHelper.js b/builder/src/echarts/component/axisPointer/viewHelper.js
index 3de1dd9..650c507 100644
--- a/builder/src/echarts/component/axisPointer/viewHelper.js
+++ b/builder/src/echarts/component/axisPointer/viewHelper.js
@@ -89,6 +89,7 @@ export function buildLabelElOption(elOption, axisModel, axisPointerModel, api, l
       textFont: font,
       textFill: labelModel.getTextColor(),
       textPosition: 'inside',
+      textPadding: paddings,
       fill: bgColor,
       stroke: labelModel.get('borderColor') || 'transparent',
       lineWidth: labelModel.get('borderWidth') || 0,
@@ -133,6 +134,8 @@ export function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) {
   if (formatter) {
     var params = {
       value: axisHelper.getAxisRawValue(axis, value),
+      axisDimension: axis.dim,
+      axisIndex: axis.index,
       seriesData: []
     };
     zrUtil.each(seriesDataIndices, function (idxItem) {
diff --git a/builder/src/echarts/component/brush/BrushView.js b/builder/src/echarts/component/brush/BrushView.js
index 8a3a0f5..23929fe 100644
--- a/builder/src/echarts/component/brush/BrushView.js
+++ b/builder/src/echarts/component/brush/BrushView.js
@@ -96,6 +96,12 @@ export default echarts.extendComponentView({
       areas: zrUtil.clone(areas),
       $from: modelId
     });
+    opt.isEnd && this.api.dispatchAction({
+      type: 'brushEnd',
+      brushId: modelId,
+      areas: zrUtil.clone(areas),
+      $from: modelId
+    });
   }
 });
 
diff --git a/builder/src/echarts/component/brush/brushAction.js b/builder/src/echarts/component/brush/brushAction.js
index 2d3bd6b..09b618c 100644
--- a/builder/src/echarts/component/brush/brushAction.js
+++ b/builder/src/echarts/component/brush/brushAction.js
@@ -65,4 +65,9 @@ echarts.registerAction({
   type: 'brushSelect',
   event: 'brushSelected',
   update: 'none'
+}, function () {});
+echarts.registerAction({
+  type: 'brushEnd',
+  event: 'brushEnd',
+  update: 'none'
 }, function () {});
\ No newline at end of file
diff --git a/builder/src/echarts/component/brush/selector.js b/builder/src/echarts/component/brush/selector.js
index bf57d60..3179b51 100644
--- a/builder/src/echarts/component/brush/selector.js
+++ b/builder/src/echarts/component/brush/selector.js
@@ -17,7 +17,8 @@
 * under the License.
 */
 import * as polygonContain from 'zrender/src/contain/polygon';
-import BoundingRect from 'zrender/src/core/BoundingRect'; // Key of the first level is brushType: `line`, `rect`, `polygon`.
+import BoundingRect from 'zrender/src/core/BoundingRect';
+import { linePolygonIntersect } from '../../util/graphic'; // Key of the first level is brushType: `line`, `rect`, `polygon`.
 // Key of the second level is chart element type: `point`, `rect`.
 // See moudule:echarts/component/helper/BrushController
 // function param:
@@ -55,7 +56,7 @@ var selector = {
       var height = itemLayout.height;
       var p = points[0];
 
-      if (polygonContain.contain(points, x, y) || polygonContain.contain(points, x + width, y) || polygonContain.contain(points, x, y + height) || polygonContain.contain(points, x + width, y + height) || BoundingRect.create(itemLayout).contain(p[0], p[1]) || lineIntersectPolygon(x, y, x + width, y, points) || lineIntersectPolygon(x, y, x, y + height, points) || lineIntersectPolygon(x + width, y, x + width, y + height, points) || lineIntersectPolygon(x, y + height, x + width, y + height,  [...]
+      if (polygonContain.contain(points, x, y) || polygonContain.contain(points, x + width, y) || polygonContain.contain(points, x, y + height) || polygonContain.contain(points, x + width, y + height) || BoundingRect.create(itemLayout).contain(p[0], p[1]) || linePolygonIntersect(x, y, x + width, y, points) || linePolygonIntersect(x, y, x, y + height, points) || linePolygonIntersect(x + width, y, x + width, y + height, points) || linePolygonIntersect(x, y + height, x + width, y + height,  [...]
         return true;
       }
     }
@@ -88,49 +89,4 @@ function inLineRange(p, range) {
   return range[0] <= p && p <= range[1];
 }
 
-function lineIntersectPolygon(lx, ly, l2x, l2y, points) {
-  for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) {
-    var p = points[i];
-
-    if (lineIntersect(lx, ly, l2x, l2y, p[0], p[1], p2[0], p2[1])) {
-      return true;
-    }
-
-    p2 = p;
-  }
-} // Code from <http://blog.csdn.net/rickliuxiao/article/details/6259322> with some fix.
-// See <https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection>
-
-
-function lineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) {
-  var delta = determinant(a2x - a1x, b1x - b2x, a2y - a1y, b1y - b2y);
-
-  if (nearZero(delta)) {
-    // parallel
-    return false;
-  }
-
-  var namenda = determinant(b1x - a1x, b1x - b2x, b1y - a1y, b1y - b2y) / delta;
-
-  if (namenda < 0 || namenda > 1) {
-    return false;
-  }
-
-  var miu = determinant(a2x - a1x, b1x - a1x, a2y - a1y, b1y - a1y) / delta;
-
-  if (miu < 0 || miu > 1) {
-    return false;
-  }
-
-  return true;
-}
-
-function nearZero(val) {
-  return val <= 1e-6 && val >= -1e-6;
-}
-
-function determinant(v1, v2, v3, v4) {
-  return v1 * v4 - v2 * v3;
-}
-
 export default selector;
\ No newline at end of file
diff --git a/builder/src/echarts/component/calendar.js b/builder/src/echarts/component/calendar.js
index a578ee6..6905de2 100644
--- a/builder/src/echarts/component/calendar.js
+++ b/builder/src/echarts/component/calendar.js
@@ -16,11 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * @file calendar.js
- * @author dxh
- */
 import '../coord/calendar/Calendar';
 import '../coord/calendar/CalendarModel';
 import './calendar/CalendarView';
\ No newline at end of file
diff --git a/builder/src/echarts/component/dataZoom.js b/builder/src/echarts/component/dataZoom.js
index 99810c6..efa6481 100644
--- a/builder/src/echarts/component/dataZoom.js
+++ b/builder/src/echarts/component/dataZoom.js
@@ -16,16 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * DataZoom component entry
- */
-import './dataZoom/typeDefaulter';
-import './dataZoom/DataZoomModel';
-import './dataZoom/DataZoomView';
-import './dataZoom/SliderZoomModel';
-import './dataZoom/SliderZoomView';
-import './dataZoom/InsideZoomModel';
-import './dataZoom/InsideZoomView';
-import './dataZoom/dataZoomProcessor';
-import './dataZoom/dataZoomAction';
\ No newline at end of file
+import './dataZoomSlider';
+import './dataZoomInside'; // Do not include './dataZoomSelect',
+// since it only work for toolbox dataZoom.
\ No newline at end of file
diff --git a/builder/src/echarts/component/dataZoom/AxisProxy.js b/builder/src/echarts/component/dataZoom/AxisProxy.js
index 6198773..7581c3d 100644
--- a/builder/src/echarts/component/dataZoom/AxisProxy.js
+++ b/builder/src/echarts/component/dataZoom/AxisProxy.js
@@ -19,6 +19,7 @@
 import * as zrUtil from 'zrender/src/core/util';
 import * as numberUtil from '../../util/number';
 import * as helper from './helper';
+import sliderMove from '../helper/sliderMove';
 var each = zrUtil.each;
 var asc = numberUtil.asc;
 /**
@@ -185,38 +186,36 @@ AxisProxy.prototype = {
     var rangePropMode = this._dataZoomModel.getRangePropMode();
 
     var percentExtent = [0, 100];
-    var percentWindow = [opt.start, opt.end];
+    var percentWindow = [];
     var valueWindow = [];
-    each(['startValue', 'endValue'], function (prop) {
-      valueWindow.push(opt[prop] != null ? scale.parse(opt[prop]) : null);
-    }); // Normalize bound.
-
-    each([0, 1], function (idx) {
-      var boundValue = valueWindow[idx];
-      var boundPercent = percentWindow[idx]; // Notice: dataZoom is based either on `percentProp` ('start', 'end') or
-      // on `valueProp` ('startValue', 'endValue'). The former one is suitable
-      // for cases that a dataZoom component controls multiple axes with different
-      // unit or extent, and the latter one is suitable for accurate zoom by pixel
-      // (e.g., in dataZoomSelect). `valueProp` can be calculated from `percentProp`,
-      // but it is awkward that `percentProp` can not be obtained from `valueProp`
-      // accurately (because all of values that are overflow the `dataExtent` will
-      // be calculated to percent '100%'). So we have to use
-      // `dataZoom.getRangePropMode()` to mark which prop is used.
-      // `rangePropMode` is updated only when setOption or dispatchAction, otherwise
-      // it remains its original value.
+    var hasPropModeValue;
+    each(['start', 'end'], function (prop, idx) {
+      var boundPercent = opt[prop];
+      var boundValue = opt[prop + 'Value']; // Notice: dataZoom is based either on `percentProp` ('start', 'end') or
+      // on `valueProp` ('startValue', 'endValue'). (They are based on the data extent
+      // but not min/max of axis, which will be calculated by data window then).
+      // The former one is suitable for cases that a dataZoom component controls multiple
+      // axes with different unit or extent, and the latter one is suitable for accurate
+      // zoom by pixel (e.g., in dataZoomSelect).
+      // we use `getRangePropMode()` to mark which prop is used. `rangePropMode` is updated
+      // only when setOption or dispatchAction, otherwise it remains its original value.
+      // (Why not only record `percentProp` and always map to `valueProp`? Because
+      // the map `valueProp` -> `percentProp` -> `valueProp` probably not the original
+      // `valueProp`. consider two axes constrolled by one dataZoom. They have different
+      // data extent. All of values that are overflow the `dataExtent` will be calculated
+      // to percent '100%').
 
       if (rangePropMode[idx] === 'percent') {
-        if (boundPercent == null) {
-          boundPercent = percentExtent[idx];
-        } // Use scale.parse to math round for category or time axis.
+        boundPercent == null && (boundPercent = percentExtent[idx]); // Use scale.parse to math round for category or time axis.
 
-
-        boundValue = scale.parse(numberUtil.linearMap(boundPercent, percentExtent, dataExtent, true));
+        boundValue = scale.parse(numberUtil.linearMap(boundPercent, percentExtent, dataExtent));
       } else {
-        // Calculating `percent` from `value` may be not accurate, because
+        hasPropModeValue = true;
+        boundValue = boundValue == null ? dataExtent[idx] : scale.parse(boundValue); // Calculating `percent` from `value` may be not accurate, because
         // This calculation can not be inversed, because all of values that
         // are overflow the `dataExtent` will be calculated to percent '100%'
-        boundPercent = numberUtil.linearMap(boundValue, dataExtent, percentExtent, true);
+
+        boundPercent = numberUtil.linearMap(boundValue, dataExtent, percentExtent);
       } // valueWindow[idx] = round(boundValue);
       // percentWindow[idx] = round(boundPercent);
 
@@ -224,9 +223,29 @@ AxisProxy.prototype = {
       valueWindow[idx] = boundValue;
       percentWindow[idx] = boundPercent;
     });
+    asc(valueWindow);
+    asc(percentWindow); // The windows from user calling of `dispatchAction` might be out of the extent,
+    // or do not obey the `min/maxSpan`, `min/maxValueSpan`. But we dont restrict window
+    // by `zoomLock` here, because we see `zoomLock` just as a interaction constraint,
+    // where API is able to initialize/modify the window size even though `zoomLock`
+    // specified.
+
+    var spans = this._minMaxSpan;
+    hasPropModeValue ? restrictSet(valueWindow, percentWindow, dataExtent, percentExtent, false) : restrictSet(percentWindow, valueWindow, percentExtent, dataExtent, true);
+
+    function restrictSet(fromWindow, toWindow, fromExtent, toExtent, toValue) {
+      var suffix = toValue ? 'Span' : 'ValueSpan';
+      sliderMove(0, fromWindow, fromExtent, 'all', spans['min' + suffix], spans['max' + suffix]);
+
+      for (var i = 0; i < 2; i++) {
+        toWindow[i] = numberUtil.linearMap(fromWindow[i], fromExtent, toExtent, true);
+        toValue && (toWindow[i] = scale.parse(toWindow[i]));
+      }
+    }
+
     return {
-      valueWindow: asc(valueWindow),
-      percentWindow: asc(percentWindow)
+      valueWindow: valueWindow,
+      percentWindow: percentWindow
     };
   },
 
@@ -253,11 +272,12 @@ AxisProxy.prototype = {
     // this.hasSeriesStacked = true;
     // }
     // }, this);
+    // `calculateDataWindow` uses min/maxSpan.
 
-    var dataWindow = this.calculateDataWindow(dataZoomModel.option);
+    setMinMaxSpan(this);
+    var dataWindow = this.calculateDataWindow(dataZoomModel.settledOption);
     this._valueWindow = dataWindow.valueWindow;
-    this._percentWindow = dataWindow.percentWindow;
-    setMinMaxSpan(this); // Update axis setting then.
+    this._percentWindow = dataWindow.percentWindow; // Update axis setting then.
 
     setAxisModel(this);
   },
@@ -345,7 +365,7 @@ AxisProxy.prototype = {
       } else {
         each(dataDims, function (dim) {
           if (filterMode === 'empty') {
-            seriesModel.setData(seriesData.map(dim, function (value) {
+            seriesModel.setData(seriesData = seriesData.map(dim, function (value) {
               return !isInWindow(value) ? NaN : value;
             }));
           } else {
@@ -453,20 +473,20 @@ function setAxisModel(axisProxy, isRestore) {
 function setMinMaxSpan(axisProxy) {
   var minMaxSpan = axisProxy._minMaxSpan = {};
   var dataZoomModel = axisProxy._dataZoomModel;
+  var dataExtent = axisProxy._dataExtent;
   each(['min', 'max'], function (minMax) {
-    minMaxSpan[minMax + 'Span'] = dataZoomModel.get(minMax + 'Span'); // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan
-
+    var percentSpan = dataZoomModel.get(minMax + 'Span');
     var valueSpan = dataZoomModel.get(minMax + 'ValueSpan');
+    valueSpan != null && (valueSpan = axisProxy.getAxisModel().axis.scale.parse(valueSpan)); // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan
 
     if (valueSpan != null) {
-      minMaxSpan[minMax + 'ValueSpan'] = valueSpan;
-      valueSpan = axisProxy.getAxisModel().axis.scale.parse(valueSpan);
-
-      if (valueSpan != null) {
-        var dataExtent = axisProxy._dataExtent;
-        minMaxSpan[minMax + 'Span'] = numberUtil.linearMap(dataExtent[0] + valueSpan, dataExtent, [0, 100], true);
-      }
+      percentSpan = numberUtil.linearMap(dataExtent[0] + valueSpan, dataExtent, [0, 100], true);
+    } else if (percentSpan != null) {
+      valueSpan = numberUtil.linearMap(percentSpan, [0, 100], dataExtent, true) - dataExtent[0];
     }
+
+    minMaxSpan[minMax + 'Span'] = percentSpan;
+    minMaxSpan[minMax + 'ValueSpan'] = valueSpan;
   });
 }
 
diff --git a/builder/src/echarts/component/dataZoom/DataZoomModel.js b/builder/src/echarts/component/dataZoom/DataZoomModel.js
index 8310e26..00fa67a 100644
--- a/builder/src/echarts/component/dataZoom/DataZoomModel.js
+++ b/builder/src/echarts/component/dataZoom/DataZoomModel.js
@@ -115,45 +115,86 @@ var DataZoomModel = echarts.extendComponentModel({
 
     this._autoThrottle = true;
     /**
-     * 'percent' or 'value'
+     * It is `[rangeModeForMin, rangeModeForMax]`.
+     * The optional values for `rangeMode`:
+     * + `'value'` mode: the axis extent will always be determined by
+     *     `dataZoom.startValue` and `dataZoom.endValue`, despite
+     *     how data like and how `axis.min` and `axis.max` are.
+     * + `'percent'` mode: `100` represents 100% of the `[dMin, dMax]`,
+     *     where `dMin` is `axis.min` if `axis.min` specified, otherwise `data.extent[0]`,
+     *     and `dMax` is `axis.max` if `axis.max` specified, otherwise `data.extent[1]`.
+     *     Axis extent will be determined by the result of the percent of `[dMin, dMax]`.
+     *
+     * For example, when users are using dynamic data (update data periodically via `setOption`),
+     * if in `'value`' mode, the window will be kept in a fixed value range despite how
+     * data are appended, while if in `'percent'` mode, whe window range will be changed alone with
+     * the appended data (suppose `axis.min` and `axis.max` are not specified).
+     *
      * @private
      */
 
     this._rangePropMode = ['percent', 'percent'];
-    var rawOption = retrieveRaw(option);
+    var inputRawOption = retrieveRawOption(option);
+    /**
+     * Suppose a "main process" start at the point that model prepared (that is,
+     * model initialized or merged or method called in `action`).
+     * We should keep the `main process` idempotent, that is, given a set of values
+     * on `option`, we get the same result.
+     *
+     * But sometimes, values on `option` will be updated for providing users
+     * a "final calculated value" (`dataZoomProcessor` will do that). Those value
+     * should not be the base/input of the `main process`.
+     *
+     * So in that case we should save and keep the input of the `main process`
+     * separately, called `settledOption`.
+     *
+     * For example, consider the case:
+     * (Step_1) brush zoom the grid by `toolbox.dataZoom`,
+     *     where the original input `option.startValue`, `option.endValue` are earsed by
+     *     calculated value.
+     * (Step)2) click the legend to hide and show a series,
+     *     where the new range is calculated by the earsed `startValue` and `endValue`,
+     *     which brings incorrect result.
+     *
+     * @readOnly
+     */
+
+    this.settledOption = inputRawOption;
     this.mergeDefaultAndTheme(option, ecModel);
-    this.doInit(rawOption);
+    this.doInit(inputRawOption);
   },
 
   /**
    * @override
    */
   mergeOption: function (newOption) {
-    var rawOption = retrieveRaw(newOption); //FIX #2591
+    var inputRawOption = retrieveRawOption(newOption); //FIX #2591
 
     zrUtil.merge(this.option, newOption, true);
-    this.doInit(rawOption);
+    zrUtil.merge(this.settledOption, inputRawOption, true);
+    this.doInit(inputRawOption);
   },
 
   /**
    * @protected
    */
-  doInit: function (rawOption) {
+  doInit: function (inputRawOption) {
     var thisOption = this.option; // Disable realtime view update if canvas is not supported.
 
     if (!env.canvasSupported) {
       thisOption.realtime = false;
     }
 
-    this._setDefaultThrottle(rawOption);
+    this._setDefaultThrottle(inputRawOption);
 
-    updateRangeUse(this, rawOption);
+    updateRangeUse(this, inputRawOption);
+    var settledOption = this.settledOption;
     each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
       // start/end has higher priority over startValue/endValue if they
       // both set, but we should make chart.setOption({endValue: 1000})
       // effective, rather than chart.setOption({endValue: 1000, end: null}).
       if (this._rangePropMode[index] === 'value') {
-        thisOption[names[0]] = null;
+        thisOption[names[0]] = settledOption[names[0]] = null;
       } // Otherwise do nothing and use the merge result.
 
     }, this);
@@ -345,9 +386,9 @@ var DataZoomModel = echarts.extendComponentModel({
   /**
    * @private
    */
-  _setDefaultThrottle: function (rawOption) {
+  _setDefaultThrottle: function (inputRawOption) {
     // When first time user set throttle, auto throttle ends.
-    if (rawOption.hasOwnProperty('throttle')) {
+    if (inputRawOption.hasOwnProperty('throttle')) {
       this._autoThrottle = false;
     }
 
@@ -415,22 +456,41 @@ var DataZoomModel = echarts.extendComponentModel({
    * @param {number} [opt.end]
    * @param {number} [opt.startValue]
    * @param {number} [opt.endValue]
-   * @param {boolean} [ignoreUpdateRangeUsg=false]
    */
-  setRawRange: function (opt, ignoreUpdateRangeUsg) {
-    var option = this.option;
+  setRawRange: function (opt) {
+    var thisOption = this.option;
+    var settledOption = this.settledOption;
     each([['start', 'startValue'], ['end', 'endValue']], function (names) {
-      // If only one of 'start' and 'startValue' is not null/undefined, the other
-      // should be cleared, which enable clear the option.
-      // If both of them are not set, keep option with the original value, which
-      // enable use only set start but not set end when calling `dispatchAction`.
-      // The same as 'end' and 'endValue'.
+      // Consider the pair <start, startValue>:
+      // If one has value and the other one is `null/undefined`, we both set them
+      // to `settledOption`. This strategy enables the feature to clear the original
+      // value in `settledOption` to `null/undefined`.
+      // But if both of them are `null/undefined`, we do not set them to `settledOption`
+      // and keep `settledOption` with the original value. This strategy enables users to
+      // only set <end or endValue> but not set <start or startValue> when calling
+      // `dispatchAction`.
+      // The pair <end, endValue> is treated in the same way.
       if (opt[names[0]] != null || opt[names[1]] != null) {
-        option[names[0]] = opt[names[0]];
-        option[names[1]] = opt[names[1]];
+        thisOption[names[0]] = settledOption[names[0]] = opt[names[0]];
+        thisOption[names[1]] = settledOption[names[1]] = opt[names[1]];
       }
     }, this);
-    !ignoreUpdateRangeUsg && updateRangeUse(this, opt);
+    updateRangeUse(this, opt);
+  },
+
+  /**
+   * @public
+   * @param {Object} opt
+   * @param {number} [opt.start]
+   * @param {number} [opt.end]
+   * @param {number} [opt.startValue]
+   * @param {number} [opt.endValue]
+   */
+  setCalculatedRange: function (opt) {
+    var option = this.option;
+    each(['start', 'startValue', 'end', 'endValue'], function (name) {
+      option[name] = opt[name];
+    });
   },
 
   /**
@@ -504,8 +564,13 @@ var DataZoomModel = echarts.extendComponentModel({
     return this._rangePropMode.slice();
   }
 });
+/**
+ * Retrieve the those raw params from option, which will be cached separately.
+ * becasue they will be overwritten by normalized/calculated values in the main
+ * process.
+ */
 
-function retrieveRaw(option) {
+function retrieveRawOption(option) {
   var ret = {};
   each(['start', 'end', 'startValue', 'endValue', 'throttle'], function (name) {
     option.hasOwnProperty(name) && (ret[name] = option[name]);
@@ -513,12 +578,12 @@ function retrieveRaw(option) {
   return ret;
 }
 
-function updateRangeUse(dataZoomModel, rawOption) {
+function updateRangeUse(dataZoomModel, inputRawOption) {
   var rangePropMode = dataZoomModel._rangePropMode;
   var rangeModeInOption = dataZoomModel.get('rangeMode');
   each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
-    var percentSpecified = rawOption[names[0]] != null;
-    var valueSpecified = rawOption[names[1]] != null;
+    var percentSpecified = inputRawOption[names[0]] != null;
+    var valueSpecified = inputRawOption[names[1]] != null;
 
     if (percentSpecified && !valueSpecified) {
       rangePropMode[index] = 'percent';
diff --git a/builder/src/echarts/component/dataZoom/InsideZoomView.js b/builder/src/echarts/component/dataZoom/InsideZoomView.js
index ea9c0ff..4d128f2 100644
--- a/builder/src/echarts/component/dataZoom/InsideZoomView.js
+++ b/builder/src/echarts/component/dataZoom/InsideZoomView.js
@@ -41,7 +41,7 @@ var InsideZoomView = DataZoomView.extend({
    * @override
    */
   render: function (dataZoomModel, ecModel, api, payload) {
-    InsideZoomView.superApply(this, 'render', arguments); // Hance the `throttle` util ensures to preserve command order,
+    InsideZoomView.superApply(this, 'render', arguments); // Hence the `throttle` util ensures to preserve command order,
     // here simply updating range all the time will not cause missing
     // any of the the roam change.
 
diff --git a/builder/src/echarts/component/dataZoom/SliderZoomView.js b/builder/src/echarts/component/dataZoom/SliderZoomView.js
index ec79146..e1849d1 100644
--- a/builder/src/echarts/component/dataZoom/SliderZoomView.js
+++ b/builder/src/echarts/component/dataZoom/SliderZoomView.js
@@ -407,10 +407,6 @@ var SliderZoomView = DataZoomView.extend({
       draggable: true,
       cursor: getCursor(this._orient),
       drift: bind(this._onDragMove, this, 'all'),
-      onmousemove: function (e) {
-        // Fot mobile devicem, prevent screen slider on the button.
-        eventTool.stop(e.event);
-      },
       ondragstart: bind(this._showDataInfo, this, true),
       ondragend: bind(this._onDragEnd, this),
       onmouseover: bind(this._showDataInfo, this, true),
@@ -421,8 +417,9 @@ var SliderZoomView = DataZoomView.extend({
       }
     })); // Frame border.
 
-    barGroup.add(new Rect(graphic.subPixelOptimizeRect({
+    barGroup.add(new Rect({
       silent: true,
+      subPixelOptimize: true,
       shape: {
         x: 0,
         y: 0,
@@ -434,16 +431,12 @@ var SliderZoomView = DataZoomView.extend({
         lineWidth: DEFAULT_FRAME_BORDER_WIDTH,
         fill: 'rgba(0,0,0,0)'
       }
-    })));
+    }));
     each([0, 1], function (handleIndex) {
       var path = graphic.createIcon(dataZoomModel.get('handleIcon'), {
         cursor: getCursor(this._orient),
         draggable: true,
         drift: bind(this._onDragMove, this, handleIndex),
-        onmousemove: function (e) {
-          // Fot mobile devicem, prevent screen slider on the button.
-          eventTool.stop(e.event);
-        },
         ondragend: bind(this._onDragEnd, this),
         onmouseover: bind(this._showDataInfo, this, true),
         onmouseout: bind(this._showDataInfo, this, false)
@@ -618,8 +611,10 @@ var SliderZoomView = DataZoomView.extend({
     handleLabels[0].attr('invisible', !showOrHide);
     handleLabels[1].attr('invisible', !showOrHide);
   },
-  _onDragMove: function (handleIndex, dx, dy) {
-    this._dragging = true; // Transform dx, dy to bar coordination.
+  _onDragMove: function (handleIndex, dx, dy, event) {
+    this._dragging = true; // For mobile device, prevent screen slider on the button.
+
+    eventTool.stop(event.event); // Transform dx, dy to bar coordination.
 
     var barTransform = this._displayables.barGroup.getLocalTransform();
 
diff --git a/builder/src/echarts/component/dataZoom/dataZoomProcessor.js b/builder/src/echarts/component/dataZoom/dataZoomProcessor.js
index 8546346..7ef87c5 100644
--- a/builder/src/echarts/component/dataZoom/dataZoomProcessor.js
+++ b/builder/src/echarts/component/dataZoom/dataZoomProcessor.js
@@ -70,12 +70,12 @@ echarts.registerProcessor({
       var axisProxy = dataZoomModel.findRepresentativeAxisProxy();
       var percentRange = axisProxy.getDataPercentWindow();
       var valueRange = axisProxy.getDataValueWindow();
-      dataZoomModel.setRawRange({
+      dataZoomModel.setCalculatedRange({
         start: percentRange[0],
         end: percentRange[1],
         startValue: valueRange[0],
         endValue: valueRange[1]
-      }, true);
+      });
     });
   }
 });
\ No newline at end of file
diff --git a/builder/src/echarts/component/dataZoomInside.js b/builder/src/echarts/component/dataZoomInside.js
index def2738..8c1cc1a 100644
--- a/builder/src/echarts/component/dataZoomInside.js
+++ b/builder/src/echarts/component/dataZoomInside.js
@@ -16,10 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * DataZoom component entry
- */
 import './dataZoom/typeDefaulter';
 import './dataZoom/DataZoomModel';
 import './dataZoom/DataZoomView';
diff --git a/builder/src/echarts/component/dataZoomSelect.js b/builder/src/echarts/component/dataZoomSelect.js
index 61922e5..72171a0 100644
--- a/builder/src/echarts/component/dataZoomSelect.js
+++ b/builder/src/echarts/component/dataZoomSelect.js
@@ -18,7 +18,8 @@
 */
 
 /**
- * DataZoom component entry
+ * Only work for toolbox dataZoom. User
+ * MUST NOT import this module directly.
  */
 import './dataZoom/typeDefaulter';
 import './dataZoom/DataZoomModel';
diff --git a/builder/src/echarts/component/dataZoomSlider.js b/builder/src/echarts/component/dataZoomSlider.js
new file mode 100644
index 0000000..39769e6
--- /dev/null
+++ b/builder/src/echarts/component/dataZoomSlider.js
@@ -0,0 +1,25 @@
+/*
+* 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 './dataZoom/typeDefaulter';
+import './dataZoom/DataZoomModel';
+import './dataZoom/DataZoomView';
+import './dataZoom/SliderZoomModel';
+import './dataZoom/SliderZoomView';
+import './dataZoom/dataZoomProcessor';
+import './dataZoom/dataZoomAction';
\ No newline at end of file
diff --git a/builder/src/echarts/component/graphic.js b/builder/src/echarts/component/graphic.js
index 29fc378..cff3410 100644
--- a/builder/src/echarts/component/graphic.js
+++ b/builder/src/echarts/component/graphic.js
@@ -21,7 +21,17 @@ import * as echarts from '../echarts';
 import * as zrUtil from 'zrender/src/core/util';
 import * as modelUtil from '../util/model';
 import * as graphicUtil from '../util/graphic';
-import * as layoutUtil from '../util/layout'; // -------------
+import * as layoutUtil from '../util/layout';
+import { parsePercent } from '../util/number';
+var _nonShapeGraphicElements = {
+  // Reserved but not supported in graphic component.
+  path: null,
+  compoundPath: null,
+  // Supported in graphic component.
+  group: graphicUtil.Group,
+  image: graphicUtil.Image,
+  text: graphicUtil.Text
+}; // -------------
 // Preprocessor
 // -------------
 
@@ -292,8 +302,8 @@ echarts.extendComponentView({
       var el = elMap.get(id);
 
       if (el) {
-        el.__ecGraphicWidth = elOption.width;
-        el.__ecGraphicHeight = elOption.height;
+        el.__ecGraphicWidthOption = elOption.width;
+        el.__ecGraphicHeightOption = elOption.height;
         setEventData(el, graphicModel, elOption);
       }
     });
@@ -309,7 +319,25 @@ echarts.extendComponentView({
   _relocate: function (graphicModel, api) {
     var elOptions = graphicModel.option.elements;
     var rootGroup = this.group;
-    var elMap = this._elMap; // Bottom-up tranvese all elements (consider ec resize) to locate elements.
+    var elMap = this._elMap;
+    var apiWidth = api.getWidth();
+    var apiHeight = api.getHeight(); // Top-down to calculate percentage width/height of group
+
+    for (var i = 0; i < elOptions.length; i++) {
+      var elOption = elOptions[i];
+      var el = elMap.get(elOption.id);
+
+      if (!el || !el.isGroup) {
+        continue;
+      }
+
+      var parentEl = el.parent;
+      var isParentRoot = parentEl === rootGroup; // Like 'position:absolut' in css, default 0.
+
+      el.__ecGraphicWidth = parsePercent(el.__ecGraphicWidthOption, isParentRoot ? apiWidth : parentEl.__ecGraphicWidth) || 0;
+      el.__ecGraphicHeight = parsePercent(el.__ecGraphicHeightOption, isParentRoot ? apiHeight : parentEl.__ecGraphicHeight) || 0;
+    } // Bottom-up tranvese all elements (consider ec resize) to locate elements.
+
 
     for (var i = elOptions.length - 1; i >= 0; i--) {
       var elOption = elOptions[i];
@@ -321,13 +349,16 @@ echarts.extendComponentView({
 
       var parentEl = el.parent;
       var containerInfo = parentEl === rootGroup ? {
-        width: api.getWidth(),
-        height: api.getHeight()
+        width: apiWidth,
+        height: apiHeight
       } : {
-        // Like 'position:absolut' in css, default 0.
-        width: parentEl.__ecGraphicWidth || 0,
-        height: parentEl.__ecGraphicHeight || 0
-      };
+        width: parentEl.__ecGraphicWidth,
+        height: parentEl.__ecGraphicHeight
+      }; // PENDING
+      // Currently, when `bounding: 'all'`, the union bounding rect of the group
+      // does not include the rect of [0, 0, group.width, group.height], which
+      // is probably weird for users. Should we make a break change for it?
+
       layoutUtil.positionElement(el, elOption, containerInfo, null, {
         hv: elOption.hv,
         boundingMode: elOption.bounding
@@ -358,7 +389,9 @@ echarts.extendComponentView({
 
 function createEl(id, targetElParent, elOption, elMap) {
   var graphicType = elOption.type;
-  var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)];
+  var Clz = _nonShapeGraphicElements.hasOwnProperty(graphicType) // Those graphic elements are not shapes. They should not be
+  // overwritten by users, so do them first.
+  ? _nonShapeGraphicElements[graphicType] : graphicUtil.getShapeClass(graphicType);
   var el = new Clz(elOption);
   targetElParent.add(el);
   elMap.set(id, el);
diff --git a/builder/src/echarts/component/helper/BrushController.js b/builder/src/echarts/component/helper/BrushController.js
index 315e786..99d8cd2 100644
--- a/builder/src/echarts/component/helper/BrushController.js
+++ b/builder/src/echarts/component/helper/BrushController.js
@@ -166,7 +166,7 @@ function BrushController(zr) {
    */
 
   this._handlers = {};
-  each(mouseHandlers, function (handler, eventName) {
+  each(pointerHandlers, function (handler, eventName) {
     this._handlers[eventName] = zrUtil.bind(handler, this);
   }, this);
 }
@@ -317,9 +317,7 @@ function doEnableBrush(controller, brushOption) {
     interactionMutex.take(zr, MUTEX_RESOURCE_KEY, controller._uid);
   }
 
-  each(controller._handlers, function (handler, eventName) {
-    zr.on(eventName, handler);
-  });
+  mountHandlers(zr, controller._handlers);
   controller._brushType = brushOption.brushType;
   controller._brushOption = zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true);
 }
@@ -327,10 +325,20 @@ function doEnableBrush(controller, brushOption) {
 function doDisableBrush(controller) {
   var zr = controller._zr;
   interactionMutex.release(zr, MUTEX_RESOURCE_KEY, controller._uid);
-  each(controller._handlers, function (handler, eventName) {
+  unmountHandlers(zr, controller._handlers);
+  controller._brushType = controller._brushOption = null;
+}
+
+function mountHandlers(zr, handlers) {
+  each(handlers, function (handler, eventName) {
+    zr.on(eventName, handler);
+  });
+}
+
+function unmountHandlers(zr, handlers) {
+  each(handlers, function (handler, eventName) {
     zr.off(eventName, handler);
   });
-  controller._brushType = controller._brushOption = null;
 }
 
 function createCover(controller, brushOption) {
@@ -633,8 +641,11 @@ function pointsToRect(points) {
 }
 
 function resetCursor(controller, e, localCursorPoint) {
-  // Check active
-  if (!controller._brushType) {
+  if ( // Check active
+  !controller._brushType // resetCursor should be always called when mouse is in zr area,
+  // but not called when mouse is out of zr area to avoid bad influence
+  // if `mousemove`, `mouseup` are triggered from `document` event.
+  || isOutsideZrArea(controller, e)) {
     return;
   }
 
@@ -724,12 +735,12 @@ function determineBrushType(brushType, panel) {
   return brushType;
 }
 
-var mouseHandlers = {
+var pointerHandlers = {
   mousedown: function (e) {
     if (this._dragging) {
       // In case some browser do not support globalOut,
       // and release mose out side the browser.
-      handleDragEnd.call(this, e);
+      handleDragEnd(this, e);
     } else if (!e.target || !e.target.draggable) {
       preventDefault(e);
       var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);
@@ -743,7 +754,9 @@ var mouseHandlers = {
     }
   },
   mousemove: function (e) {
-    var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);
+    var x = e.offsetX;
+    var y = e.offsetY;
+    var localCursorPoint = this.group.transformCoordToLocal(x, y);
     resetCursor(this, e, localCursorPoint);
 
     if (this._dragging) {
@@ -752,25 +765,30 @@ var mouseHandlers = {
       eventParams && trigger(this, eventParams);
     }
   },
-  mouseup: handleDragEnd //,
-  // FIXME
-  // in tooltip, globalout should not be triggered.
-  // globalout: handleDragEnd
-
+  mouseup: function (e) {
+    handleDragEnd(this, e);
+  }
 };
 
-function handleDragEnd(e) {
-  if (this._dragging) {
+function handleDragEnd(controller, e) {
+  if (controller._dragging) {
     preventDefault(e);
-    var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);
-    var eventParams = updateCoverByMouse(this, e, localCursorPoint, true);
-    this._dragging = false;
-    this._track = [];
-    this._creatingCover = null; // trigger event shoule be at final, after procedure will be nested.
-
-    eventParams && trigger(this, eventParams);
+    var x = e.offsetX;
+    var y = e.offsetY;
+    var localCursorPoint = controller.group.transformCoordToLocal(x, y);
+    var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true);
+    controller._dragging = false;
+    controller._track = [];
+    controller._creatingCover = null; // trigger event shoule be at final, after procedure will be nested.
+
+    eventParams && trigger(controller, eventParams);
   }
 }
+
+function isOutsideZrArea(controller, x, y) {
+  var zr = controller._zr;
+  return x < 0 || x > zr.getWidth() || y < 0 || y > zr.getHeight();
+}
 /**
  * key: brushType
  * @type {Object}
diff --git a/builder/src/echarts/component/helper/MapDraw.js b/builder/src/echarts/component/helper/MapDraw.js
index ece3519..84fe81b 100644
--- a/builder/src/echarts/component/helper/MapDraw.js
+++ b/builder/src/echarts/component/helper/MapDraw.js
@@ -24,7 +24,7 @@ import * as graphic from '../../util/graphic';
 import geoSourceManager from '../../coord/geo/geoSourceManager';
 import { getUID } from '../../util/component';
 
-function getFixedItemStyle(model, scale) {
+function getFixedItemStyle(model) {
   var itemStyle = model.getItemStyle();
   var areaColor = model.get('areaColor'); // If user want the color not to be changed when hover,
   // they should both set areaColor and color to be null.
@@ -176,18 +176,14 @@ MapDraw.prototype = {
 
     var regionsGroup = this._regionsGroup;
     var group = this.group;
-    var scale = geo.scale;
-    var transform = {
-      position: geo.position,
-      scale: scale
-    }; // No animation when first draw or in action
-
-    if (!regionsGroup.childAt(0) || payload) {
-      group.attr(transform);
-    } else {
-      graphic.updateProps(group, transform, mapOrGeoModel);
+
+    if (geo._roamTransformable.transform) {
+      group.transform = geo._roamTransformable.transform.slice();
+      group.decomposeTransform();
     }
 
+    var scale = geo._rawTransformable.scale;
+    var position = geo._rawTransformable.position;
     regionsGroup.removeAll();
     var itemStyleAccessPath = ['itemStyle'];
     var hoverItemStyleAccessPath = ['emphasis', 'itemStyle'];
@@ -202,6 +198,7 @@ MapDraw.prototype = {
       // location calculation.
       var regionGroup = nameMap.get(region.name) || nameMap.set(region.name, new graphic.Group());
       var compoundPath = new graphic.CompoundPath({
+        segmentIgnoreThreshold: 1,
         shape: {
           paths: []
         }
@@ -210,8 +207,8 @@ MapDraw.prototype = {
       var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel;
       var itemStyleModel = regionModel.getModel(itemStyleAccessPath);
       var hoverItemStyleModel = regionModel.getModel(hoverItemStyleAccessPath);
-      var itemStyle = getFixedItemStyle(itemStyleModel, scale);
-      var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel, scale);
+      var itemStyle = getFixedItemStyle(itemStyleModel);
+      var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel);
       var labelModel = regionModel.getModel(labelAccessPath);
       var hoverLabelModel = regionModel.getModel(hoverLabelAccessPath);
       var dataIdx; // Use the itemStyle in data if has data
@@ -229,21 +226,40 @@ MapDraw.prototype = {
         }
       }
 
+      var transformPoint = function (point) {
+        return [point[0] * scale[0] + position[0], point[1] * scale[1] + position[1]];
+      };
+
       zrUtil.each(region.geometries, function (geometry) {
         if (geometry.type !== 'polygon') {
           return;
         }
 
+        var points = [];
+
+        for (var i = 0; i < geometry.exterior.length; ++i) {
+          points.push(transformPoint(geometry.exterior[i]));
+        }
+
         compoundPath.shape.paths.push(new graphic.Polygon({
+          segmentIgnoreThreshold: 1,
           shape: {
-            points: geometry.exterior
+            points: points
           }
         }));
 
-        for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); i++) {
+        for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); ++i) {
+          var interior = geometry.interiors[i];
+          var points = [];
+
+          for (var j = 0; j < interior.length; ++j) {
+            points.push(transformPoint(interior[j]));
+          }
+
           compoundPath.shape.paths.push(new graphic.Polygon({
+            segmentIgnoreThreshold: 1,
             shape: {
-              points: geometry.interiors[i]
+              points: points
             }
           }));
         }
@@ -269,12 +285,12 @@ MapDraw.prototype = {
         }
 
         var textEl = new graphic.Text({
-          position: region.center.slice(),
+          position: transformPoint(region.center.slice()),
           // FIXME
           // label rotation is not support yet in geo or regions of series-map
           // that has no data. The rotation will be effected by this `scale`.
           // So needed to change to RectText?
-          scale: [1 / scale[0], 1 / scale[1]],
+          scale: [1 / group.scale[0], 1 / group.scale[1]],
           z2: 10,
           silent: true
         });
@@ -308,9 +324,8 @@ MapDraw.prototype = {
 
       var groupRegions = regionGroup.__regions || (regionGroup.__regions = []);
       groupRegions.push(region);
-      graphic.setHoverStyle(regionGroup, hoverItemStyle, {
-        hoverSilentOnTouch: !!mapOrGeoModel.get('selectedMode')
-      });
+      regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode');
+      graphic.setHoverStyle(regionGroup, hoverItemStyle);
       regionsGroup.add(regionGroup);
     });
 
diff --git a/builder/src/echarts/component/helper/sliderMove.js b/builder/src/echarts/component/helper/sliderMove.js
index 38cbb97..305dbea 100644
--- a/builder/src/echarts/component/helper/sliderMove.js
+++ b/builder/src/echarts/component/helper/sliderMove.js
@@ -29,8 +29,7 @@
  *              handleEnds will be modified in this method.
  * @param {Array.<number>} extent handleEnds is restricted by extent.
  *              extent[0] should less or equals than extent[1].
- * @param {number|string} handleIndex Can be 'all', means that both move the two handleEnds,
- *              where the input minSpan and maxSpan will not work.
+ * @param {number|string} handleIndex Can be 'all', means that both move the two handleEnds.
  * @param {number} [minSpan] The range of dataZoom can not be smaller than that.
  *              If not set, handle0 and cross handle1. If set as a non-negative
  *              number (including `0`), handles will push each other when reaching
@@ -39,9 +38,6 @@
  * @return {Array.<number>} The input handleEnds.
  */
 export default function (delta, handleEnds, extent, handleIndex, minSpan, maxSpan) {
-  // Normalize firstly.
-  handleEnds[0] = restrict(handleEnds[0], extent);
-  handleEnds[1] = restrict(handleEnds[1], extent);
   delta = delta || 0;
   var extentSpan = extent[1] - extent[0]; // Notice maxSpan and minSpan can be null/undefined.
 
@@ -54,10 +50,14 @@ export default function (delta, handleEnds, extent, handleIndex, minSpan, maxSpa
   }
 
   if (handleIndex === 'all') {
-    minSpan = maxSpan = Math.abs(handleEnds[1] - handleEnds[0]);
+    var handleSpan = Math.abs(handleEnds[1] - handleEnds[0]);
+    handleSpan = restrict(handleSpan, [0, extentSpan]);
+    minSpan = maxSpan = restrict(handleSpan, [minSpan, maxSpan]);
     handleIndex = 0;
   }
 
+  handleEnds[0] = restrict(handleEnds[0], extent);
+  handleEnds[1] = restrict(handleEnds[1], extent);
   var originalDistSign = getSpanSign(handleEnds, handleIndex);
   handleEnds[handleIndex] += delta; // Restrict in extent.
 
@@ -69,7 +69,7 @@ export default function (delta, handleEnds, extent, handleIndex, minSpan, maxSpa
   var currDistSign = getSpanSign(handleEnds, handleIndex);
 
   if (minSpan != null && (currDistSign.sign !== originalDistSign.sign || currDistSign.span < minSpan)) {
-    // If minSpan exists, 'cross' is forbinden.
+    // If minSpan exists, 'cross' is forbidden.
     handleEnds[1 - handleIndex] = handleEnds[handleIndex] + originalDistSign.sign * minSpan;
   } // Shrink span.
 
@@ -94,5 +94,5 @@ function getSpanSign(handleEnds, handleIndex) {
 }
 
 function restrict(value, extend) {
-  return Math.min(extend[1], Math.max(extend[0], value));
+  return Math.min(extend[1] != null ? extend[1] : Infinity, Math.max(extend[0] != null ? extend[0] : -Infinity, value));
 }
\ No newline at end of file
diff --git a/builder/src/echarts/component/legend.js b/builder/src/echarts/component/legend.js
index 79064fd..1b1da85 100644
--- a/builder/src/echarts/component/legend.js
+++ b/builder/src/echarts/component/legend.js
@@ -24,7 +24,7 @@ import './legend/LegendView';
 import legendFilter from './legend/legendFilter';
 import Component from '../model/Component'; // Series Filter
 
-echarts.registerProcessor(legendFilter);
+echarts.registerProcessor(echarts.PRIORITY.PROCESSOR.SERIES_FILTER, legendFilter);
 Component.registerSubTypeDefaulter('legend', function () {
   // Default 'plain' when no type specified.
   return 'plain';
diff --git a/builder/src/echarts/component/legend/LegendModel.js b/builder/src/echarts/component/legend/LegendModel.js
index 9a70336..8eb4a14 100644
--- a/builder/src/echarts/component/legend/LegendModel.js
+++ b/builder/src/echarts/component/legend/LegendModel.js
@@ -20,6 +20,18 @@ import * as echarts from '../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
 import Model from '../../model/Model';
 import { isNameSpecified } from '../../util/model';
+import lang from '../../lang';
+var langSelector = lang.legend.selector;
+var defaultSelectorOption = {
+  all: {
+    type: 'all',
+    title: zrUtil.clone(langSelector.all)
+  },
+  inverse: {
+    type: 'inverse',
+    title: zrUtil.clone(langSelector.inverse)
+  }
+};
 var LegendModel = echarts.extendComponentModel({
   type: 'legend.plain',
   dependencies: ['series'],
@@ -37,9 +49,29 @@ var LegendModel = echarts.extendComponentModel({
   init: function (option, parentModel, ecModel) {
     this.mergeDefaultAndTheme(option, ecModel);
     option.selected = option.selected || {};
+
+    this._updateSelector(option);
   },
   mergeOption: function (option) {
     LegendModel.superCall(this, 'mergeOption', option);
+
+    this._updateSelector(option);
+  },
+  _updateSelector: function (option) {
+    var selector = option.selector;
+
+    if (selector === true) {
+      selector = option.selector = ['all', 'inverse'];
+    }
+
+    if (zrUtil.isArray(selector)) {
+      zrUtil.each(selector, function (item, index) {
+        zrUtil.isString(item) && (item = {
+          type: item
+        });
+        selector[index] = zrUtil.merge(item, defaultSelectorOption[item.type]);
+      });
+    }
   },
   optionUpdated: function () {
     this._updateData(this.ecModel);
@@ -72,9 +104,9 @@ var LegendModel = echarts.extendComponentModel({
       availableNames.push(seriesName);
       var isPotential;
 
-      if (seriesModel.legendDataProvider) {
-        var data = seriesModel.legendDataProvider();
-        var names = data.mapArray(data.getName);
+      if (seriesModel.legendVisualProvider) {
+        var provider = seriesModel.legendVisualProvider;
+        var names = provider.getAllNames();
 
         if (!ecModel.isSeriesFiltered(seriesModel)) {
           availableNames = availableNames.concat(names);
@@ -165,6 +197,26 @@ var LegendModel = echarts.extendComponentModel({
 
     this[selected[name] ? 'unSelect' : 'select'](name);
   },
+  allSelect: function () {
+    var data = this._data;
+    var selected = this.option.selected;
+    zrUtil.each(data, function (dataItem) {
+      selected[dataItem.get('name', true)] = true;
+    });
+  },
+  inverseSelect: function () {
+    var data = this._data;
+    var selected = this.option.selected;
+    zrUtil.each(data, function (dataItem) {
+      var name = dataItem.get('name', true); // Initially, default value is true
+
+      if (!selected.hasOwnProperty(name)) {
+        selected[name] = true;
+      }
+
+      selected[name] = !selected[name];
+    });
+  },
 
   /**
    * @param {string} name
@@ -173,6 +225,15 @@ var LegendModel = echarts.extendComponentModel({
     var selected = this.option.selected;
     return !(selected.hasOwnProperty(name) && !selected[name]) && zrUtil.indexOf(this._availableNames, name) >= 0;
   },
+  getOrient: function () {
+    return this.get('orient') === 'vertical' ? {
+      index: 1,
+      name: 'vertical'
+    } : {
+      index: 0,
+      name: 'horizontal'
+    };
+  },
   defaultOption: {
     // 一级层叠
     zlevel: 0,
@@ -202,12 +263,18 @@ var LegendModel = echarts.extendComponentModel({
     // 各个item之间的间隔,单位px,默认为10,
     // 横向布局时为水平间隔,纵向布局时为纵向间隔
     itemGap: 10,
-    // 图例图形宽度
+    // the width of legend symbol
     itemWidth: 25,
-    // 图例图形高度
+    // the height of legend symbol
     itemHeight: 14,
-    // 图例关闭时候的颜色
+    // the color of unselected legend symbol
     inactiveColor: '#ccc',
+    // the borderColor of unselected legend symbol
+    inactiveBorderColor: '#ccc',
+    itemStyle: {
+      // the default borderWidth of legend symbol
+      borderWidth: 0
+    },
     textStyle: {
       // 图例文字颜色
       color: '#333'
@@ -219,6 +286,34 @@ var LegendModel = echarts.extendComponentModel({
     // selected: null,
     // 图例内容(详见legend.data,数组中每一项代表一个item
     // data: [],
+    // Usage:
+    // selector: [{type: 'all or inverse', title: xxx}]
+    // or
+    // selector: true
+    // or
+    // selector: ['all', 'inverse']
+    selector: false,
+    selectorLabel: {
+      show: true,
+      borderRadius: 10,
+      padding: [3, 5, 3, 5],
+      fontSize: 12,
+      fontFamily: ' sans-serif',
+      color: '#666',
+      borderWidth: 1,
+      borderColor: '#666'
+    },
+    emphasis: {
+      selectorLabel: {
+        show: true,
+        color: '#eee',
+        backgroundColor: '#666'
+      }
+    },
+    // Value can be 'start' or 'end'
+    selectorPosition: 'auto',
+    selectorItemGap: 7,
+    selectorButtonGap: 10,
     // Tooltip 相关配置
     tooltip: {
       show: false
diff --git a/builder/src/echarts/component/legend/LegendView.js b/builder/src/echarts/component/legend/LegendView.js
index 4bd0001..570baaa 100644
--- a/builder/src/echarts/component/legend/LegendView.js
+++ b/builder/src/echarts/component/legend/LegendView.js
@@ -46,6 +46,12 @@ export default echarts.extendComponentView({
 
     this._backgroundEl;
     /**
+     * @private
+     * @type {module:zrender/container/Group}
+     */
+
+    this.group.add(this._selectorGroup = new Group());
+    /**
      * If first rendering, `contentGroup.position` is [0, 0], which
      * does not make sense and may cause unexepcted animation if adopted.
      * @private
@@ -63,6 +69,13 @@ export default echarts.extendComponentView({
   },
 
   /**
+   * @protected
+   */
+  getSelectorGroup: function () {
+    return this._selectorGroup;
+  },
+
+  /**
    * @override
    */
   render: function (legendModel, ecModel, api) {
@@ -75,12 +88,20 @@ export default echarts.extendComponentView({
     }
 
     var itemAlign = legendModel.get('align');
+    var orient = legendModel.get('orient');
 
     if (!itemAlign || itemAlign === 'auto') {
-      itemAlign = legendModel.get('left') === 'right' && legendModel.get('orient') === 'vertical' ? 'right' : 'left';
+      itemAlign = legendModel.get('left') === 'right' && orient === 'vertical' ? 'right' : 'left';
     }
 
-    this.renderInner(itemAlign, legendModel, ecModel, api); // Perform layout.
+    var selector = legendModel.get('selector', true);
+    var selectorPosition = legendModel.get('selectorPosition', true);
+
+    if (selector && (!selectorPosition || selectorPosition === 'auto')) {
+      selectorPosition = orient === 'horizontal' ? 'end' : 'start';
+    }
+
+    this.renderInner(itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition); // Perform layout.
 
     var positionInfo = legendModel.getBoxLayoutParams();
     var viewportSize = {
@@ -89,7 +110,7 @@ export default echarts.extendComponentView({
     };
     var padding = legendModel.get('padding');
     var maxSize = layoutUtil.getLayoutRect(positionInfo, viewportSize, padding);
-    var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender); // Place mainGroup, based on the calculated `mainRect`.
+    var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition); // Place mainGroup, based on the calculated `mainRect`.
 
     var layoutRect = layoutUtil.getLayoutRect(zrUtil.defaults({
       width: mainRect.width,
@@ -106,12 +127,13 @@ export default echarts.extendComponentView({
   resetInner: function () {
     this.getContentGroup().removeAll();
     this._backgroundEl && this.group.remove(this._backgroundEl);
+    this.getSelectorGroup().removeAll();
   },
 
   /**
    * @protected
    */
-  renderInner: function (itemAlign, legendModel, ecModel, api) {
+  renderInner: function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
     var contentGroup = this.getContentGroup();
     var legendDrawnMap = zrUtil.createHashMap();
     var selectMode = legendModel.get('selectedMode');
@@ -135,49 +157,57 @@ export default echarts.extendComponentView({
       if (legendDrawnMap.get(name)) {
         // Have been drawed
         return;
-      } // Series legend
+      } // Legend to control series.
 
 
       if (seriesModel) {
         var data = seriesModel.getData();
-        var color = data.getVisual('color'); // If color is a callback function
+        var color = data.getVisual('color');
+        var borderColor = data.getVisual('borderColor'); // If color is a callback function
 
         if (typeof color === 'function') {
           // Use the first data
           color = color(seriesModel.getDataParams(0));
+        } // If borderColor is a callback function
+
+
+        if (typeof borderColor === 'function') {
+          // Use the first data
+          borderColor = borderColor(seriesModel.getDataParams(0));
         } // Using rect symbol defaultly
 
 
         var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect';
         var symbolType = data.getVisual('symbol');
 
-        var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, selectMode);
+        var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, borderColor, selectMode);
 
-        itemGroup.on('click', curry(dispatchSelectAction, name, api)).on('mouseover', curry(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));
+        itemGroup.on('click', curry(dispatchSelectAction, name, null, api, excludeSeriesId)).on('mouseover', curry(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));
         legendDrawnMap.set(name, true);
       } else {
-        // Data legend of pie, funnel
+        // Legend to control data. In pie and funnel.
         ecModel.eachRawSeries(function (seriesModel) {
           // In case multiple series has same data name
           if (legendDrawnMap.get(name)) {
             return;
           }
 
-          if (seriesModel.legendDataProvider) {
-            var data = seriesModel.legendDataProvider();
-            var idx = data.indexOfName(name);
+          if (seriesModel.legendVisualProvider) {
+            var provider = seriesModel.legendVisualProvider;
 
-            if (idx < 0) {
+            if (!provider.containName(name)) {
               return;
             }
 
-            var color = data.getItemVisual(idx, 'color');
+            var idx = provider.indexOfName(name);
+            var color = provider.getItemVisual(idx, 'color');
+            var borderColor = provider.getItemVisual(idx, 'borderColor');
             var legendSymbolType = 'roundRect';
 
-            var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, null, itemAlign, color, selectMode); // FIXME: consider different series has items with the same name.
+            var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, null, itemAlign, color, borderColor, selectMode); // FIXME: consider different series has items with the same name.
 
 
-            itemGroup.on('click', curry(dispatchSelectAction, name, api)) // Should not specify the series name, consider legend controls
+            itemGroup.on('click', curry(dispatchSelectAction, null, name, api, excludeSeriesId)) // Should not specify the series name, consider legend controls
             // more than one pie series.
             .on('mouseover', curry(dispatchHighlightAction, null, name, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, null, name, api, excludeSeriesId));
             legendDrawnMap.set(name, true);
@@ -185,12 +215,49 @@ export default echarts.extendComponentView({
         }, this);
       }
     }, this);
+
+    if (selector) {
+      this._createSelector(selector, legendModel, api, orient, selectorPosition);
+    }
   },
-  _createItem: function (name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, selectMode) {
+  _createSelector: function (selector, legendModel, api, orient, selectorPosition) {
+    var selectorGroup = this.getSelectorGroup();
+    each(selector, function (selectorItem) {
+      createSelectorButton(selectorItem);
+    });
+
+    function createSelectorButton(selectorItem) {
+      var type = selectorItem.type;
+      var labelText = new graphic.Text({
+        style: {
+          x: 0,
+          y: 0,
+          align: 'center',
+          verticalAlign: 'middle'
+        },
+        onclick: function () {
+          api.dispatchAction({
+            type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect'
+          });
+        }
+      });
+      selectorGroup.add(labelText);
+      var labelModel = legendModel.getModel('selectorLabel');
+      var emphasisLabelModel = legendModel.getModel('emphasis.selectorLabel');
+      graphic.setLabelStyle(labelText.style, labelText.hoverStyle = {}, labelModel, emphasisLabelModel, {
+        defaultText: selectorItem.title,
+        isRectText: false
+      });
+      graphic.setHoverStyle(labelText);
+    }
+  },
+  _createItem: function (name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, borderColor, selectMode) {
     var itemWidth = legendModel.get('itemWidth');
     var itemHeight = legendModel.get('itemHeight');
     var inactiveColor = legendModel.get('inactiveColor');
+    var inactiveBorderColor = legendModel.get('inactiveBorderColor');
     var symbolKeepAspect = legendModel.get('symbolKeepAspect');
+    var legendModelItemStyle = legendModel.getModel('itemStyle');
     var isSelected = legendModel.isSelected(name);
     var itemGroup = new Group();
     var textStyleModel = itemModel.getModel('textStyle');
@@ -199,8 +266,9 @@ export default echarts.extendComponentView({
     var legendGlobalTooltipModel = tooltipModel.parentModel; // Use user given icon first
 
     legendSymbolType = itemIcon || legendSymbolType;
-    itemGroup.add(createSymbol(legendSymbolType, 0, 0, itemWidth, itemHeight, isSelected ? color : inactiveColor, // symbolKeepAspect default true for legend
-    symbolKeepAspect == null ? true : symbolKeepAspect)); // Compose symbols
+    var legendSymbol = createSymbol(legendSymbolType, 0, 0, itemWidth, itemHeight, isSelected ? color : inactiveColor, // symbolKeepAspect default true for legend
+    symbolKeepAspect == null ? true : symbolKeepAspect);
+    itemGroup.add(setSymbolStyle(legendSymbol, legendSymbolType, legendModelItemStyle, borderColor, inactiveBorderColor, isSelected)); // Compose symbols
     // PENDING
 
     if (!itemIcon && symbolType // At least show one symbol, can't be all none
@@ -209,11 +277,12 @@ export default echarts.extendComponentView({
 
       if (symbolType === 'none') {
         symbolType = 'circle';
-      } // Put symbol in the center
+      }
 
+      var legendSymbolCenter = createSymbol(symbolType, (itemWidth - size) / 2, (itemHeight - size) / 2, size, size, isSelected ? color : inactiveColor, // symbolKeepAspect default true for legend
+      symbolKeepAspect == null ? true : symbolKeepAspect); // Put symbol in the center
 
-      itemGroup.add(createSymbol(symbolType, (itemWidth - size) / 2, (itemHeight - size) / 2, size, size, isSelected ? color : inactiveColor, // symbolKeepAspect default true for legend
-      symbolKeepAspect == null ? true : symbolKeepAspect));
+      itemGroup.add(setSymbolStyle(legendSymbolCenter, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, isSelected));
     }
 
     var textX = itemAlign === 'left' ? itemWidth + 5 : -5;
@@ -269,13 +338,48 @@ export default echarts.extendComponentView({
   /**
    * @protected
    */
-  layoutInner: function (legendModel, itemAlign, maxSize) {
-    var contentGroup = this.getContentGroup(); // Place items in contentGroup.
+  layoutInner: function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
+    var contentGroup = this.getContentGroup();
+    var selectorGroup = this.getSelectorGroup(); // Place items in contentGroup.
 
     layoutUtil.box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), maxSize.width, maxSize.height);
     var contentRect = contentGroup.getBoundingRect();
-    contentGroup.attr('position', [-contentRect.x, -contentRect.y]);
-    return this.group.getBoundingRect();
+    var contentPos = [-contentRect.x, -contentRect.y];
+
+    if (selector) {
+      // Place buttons in selectorGroup
+      layoutUtil.box( // Buttons in selectorGroup always layout horizontally
+      'horizontal', selectorGroup, legendModel.get('selectorItemGap', true));
+      var selectorRect = selectorGroup.getBoundingRect();
+      var selectorPos = [-selectorRect.x, -selectorRect.y];
+      var selectorButtonGap = legendModel.get('selectorButtonGap', true);
+      var orientIdx = legendModel.getOrient().index;
+      var wh = orientIdx === 0 ? 'width' : 'height';
+      var hw = orientIdx === 0 ? 'height' : 'width';
+      var yx = orientIdx === 0 ? 'y' : 'x';
+
+      if (selectorPosition === 'end') {
+        selectorPos[orientIdx] += contentRect[wh] + selectorButtonGap;
+      } else {
+        contentPos[orientIdx] += selectorRect[wh] + selectorButtonGap;
+      } //Always align selector to content as 'middle'
+
+
+      selectorPos[1 - orientIdx] += contentRect[hw] / 2 - selectorRect[hw] / 2;
+      selectorGroup.attr('position', selectorPos);
+      contentGroup.attr('position', contentPos);
+      var mainRect = {
+        x: 0,
+        y: 0
+      };
+      mainRect[wh] = contentRect[wh] + selectorButtonGap + selectorRect[wh];
+      mainRect[hw] = Math.max(contentRect[hw], selectorRect[hw]);
+      mainRect[yx] = Math.min(0, selectorRect[yx] + selectorPos[1 - orientIdx]);
+      return mainRect;
+    } else {
+      contentGroup.attr('position', contentPos);
+      return this.group.getBoundingRect();
+    }
   },
 
   /**
@@ -287,11 +391,32 @@ export default echarts.extendComponentView({
   }
 });
 
-function dispatchSelectAction(name, api) {
+function setSymbolStyle(symbol, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, isSelected) {
+  var itemStyle;
+
+  if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) {
+    itemStyle = legendModelItemStyle.getItemStyle();
+    symbol.style.stroke = borderColor;
+
+    if (!isSelected) {
+      itemStyle.stroke = inactiveBorderColor;
+    }
+  } else {
+    itemStyle = legendModelItemStyle.getItemStyle(['borderWidth', 'borderColor']);
+  }
+
+  return symbol.setStyle(itemStyle);
+}
+
+function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) {
+  // downplay before unselect
+  dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId);
   api.dispatchAction({
     type: 'legendToggleSelect',
-    name: name
-  });
+    name: seriesName != null ? seriesName : dataName
+  }); // highlight after select
+
+  dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId);
 }
 
 function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) {
diff --git a/builder/src/echarts/component/legend/ScrollableLegendModel.js b/builder/src/echarts/component/legend/ScrollableLegendModel.js
index bdfaea0..073b108 100644
--- a/builder/src/echarts/component/legend/ScrollableLegendModel.js
+++ b/builder/src/echarts/component/legend/ScrollableLegendModel.js
@@ -64,15 +64,6 @@ var ScrollableLegendModel = LegendModel.extend({
   mergeOption: function (option, extraOpt) {
     ScrollableLegendModel.superCall(this, 'mergeOption', option, extraOpt);
     mergeAndNormalizeLayoutParams(this, this.option, option);
-  },
-  getOrient: function () {
-    return this.get('orient') === 'vertical' ? {
-      index: 1,
-      name: 'vertical'
-    } : {
-      index: 0,
-      name: 'horizontal'
-    };
   }
 }); // Do not `ignoreSize` to enable setting {left: 10, right: 10}.
 
diff --git a/builder/src/echarts/component/legend/ScrollableLegendView.js b/builder/src/echarts/component/legend/ScrollableLegendView.js
index ed83724..b15c96e 100644
--- a/builder/src/echarts/component/legend/ScrollableLegendView.js
+++ b/builder/src/echarts/component/legend/ScrollableLegendView.js
@@ -77,10 +77,10 @@ var ScrollableLegendView = LegendView.extend({
   /**
    * @override
    */
-  renderInner: function (itemAlign, legendModel, ecModel, api) {
+  renderInner: function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
     var me = this; // Render content items.
 
-    ScrollableLegendView.superCall(this, 'renderInner', itemAlign, legendModel, ecModel, api);
+    ScrollableLegendView.superCall(this, 'renderInner', itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition);
     var controllerGroup = this._controllerGroup; // FIXME: support be 'auto' adapt to size number text length,
     // e.g., '3/12345' should not overlap with the control arrow button.
 
@@ -124,14 +124,45 @@ var ScrollableLegendView = LegendView.extend({
   /**
    * @override
    */
-  layoutInner: function (legendModel, itemAlign, maxSize, isFirstRender) {
-    var contentGroup = this.getContentGroup();
-    var containerGroup = this._containerGroup;
-    var controllerGroup = this._controllerGroup;
+  layoutInner: function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
+    var selectorGroup = this.getSelectorGroup();
     var orientIdx = legendModel.getOrient().index;
     var wh = WH[orientIdx];
+    var xy = XY[orientIdx];
     var hw = WH[1 - orientIdx];
-    var yx = XY[1 - orientIdx]; // Place items in contentGroup.
+    var yx = XY[1 - orientIdx];
+    selector && layoutUtil.box( // Buttons in selectorGroup always layout horizontally
+    'horizontal', selectorGroup, legendModel.get('selectorItemGap', true));
+    var selectorButtonGap = legendModel.get('selectorButtonGap', true);
+    var selectorRect = selectorGroup.getBoundingRect();
+    var selectorPos = [-selectorRect.x, -selectorRect.y];
+    var processMaxSize = zrUtil.clone(maxSize);
+    selector && (processMaxSize[wh] = maxSize[wh] - selectorRect[wh] - selectorButtonGap);
+
+    var mainRect = this._layoutContentAndController(legendModel, isFirstRender, processMaxSize, orientIdx, wh, hw, yx);
+
+    if (selector) {
+      if (selectorPosition === 'end') {
+        selectorPos[orientIdx] += mainRect[wh] + selectorButtonGap;
+      } else {
+        var offset = selectorRect[wh] + selectorButtonGap;
+        selectorPos[orientIdx] -= offset;
+        mainRect[xy] -= offset;
+      }
+
+      mainRect[wh] += selectorRect[wh] + selectorButtonGap;
+      selectorPos[1 - orientIdx] += mainRect[yx] + mainRect[hw] / 2 - selectorRect[hw] / 2;
+      mainRect[hw] = Math.max(mainRect[hw], selectorRect[hw]);
+      mainRect[yx] = Math.min(mainRect[yx], selectorRect[yx] + selectorPos[1 - orientIdx]);
+      selectorGroup.attr('position', selectorPos);
+    }
+
+    return mainRect;
+  },
+  _layoutContentAndController: function (legendModel, isFirstRender, maxSize, orientIdx, wh, hw, yx) {
+    var contentGroup = this.getContentGroup();
+    var containerGroup = this._containerGroup;
+    var controllerGroup = this._controllerGroup; // Place items in contentGroup.
 
     layoutUtil.box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), !orientIdx ? null : maxSize.width, orientIdx ? null : maxSize.height);
     layoutUtil.box( // Buttons in controller are layout always horizontally.
@@ -171,7 +202,6 @@ var ScrollableLegendView = LegendView.extend({
     // mainRect should not be calculated by `this.group.getBoundingRect()`
     // for sake of the overflow.
 
-    var mainRect = this.group.getBoundingRect();
     var mainRect = {
       x: 0,
       y: 0
@@ -197,7 +227,7 @@ var ScrollableLegendView = LegendView.extend({
 
       containerGroup.__rectSize = clipShape[wh];
     } else {
-      // Do not remove or ignore controller. Keep them set as place holders.
+      // Do not remove or ignore controller. Keep them set as placeholders.
       controllerGroup.eachChild(function (child) {
         child.attr({
           invisible: true,
@@ -212,7 +242,7 @@ var ScrollableLegendView = LegendView.extend({
     pageInfo.pageIndex != null && graphic.updateProps(contentGroup, {
       position: pageInfo.contentPosition
     }, // When switch from "show controller" to "not show controller", view should be
-    // updated immediately without animation, otherwise causes weird efffect.
+    // updated immediately without animation, otherwise causes weird effect.
     showController ? legendModel : false);
 
     this._updatePageInfoView(legendModel, pageInfo);
@@ -256,8 +286,8 @@ var ScrollableLegendView = LegendView.extend({
    *  contentPosition: Array.<number>, null when data item not found.
    *  pageIndex: number, null when data item not found.
    *  pageCount: number, always be a number, can be 0.
-   *  pagePrevDataIndex: number, null when no next page.
-   *  pageNextDataIndex: number, null when no previous page.
+   *  pagePrevDataIndex: number, null when no previous page.
+   *  pageNextDataIndex: number, null when no next page.
    * }
    */
   _getPageInfo: function (legendModel) {
@@ -366,18 +396,27 @@ var ScrollableLegendView = LegendView.extend({
   _findTargetItemIndex: function (targetDataIndex) {
     var index;
     var contentGroup = this.getContentGroup();
+    var defaultIndex;
 
     if (this._showController) {
       contentGroup.eachChild(function (child, idx) {
-        if (child.__legendDataIndex === targetDataIndex) {
+        var legendDataIdx = child.__legendDataIndex; // FIXME
+        // If the given targetDataIndex (from model) is illegal,
+        // we use defualtIndex. But the index on the legend model and
+        // action payload is still illegal. That case will not be
+        // changed until some scenario requires.
+
+        if (defaultIndex == null && legendDataIdx != null) {
+          defaultIndex = idx;
+        }
+
+        if (legendDataIdx === targetDataIndex) {
           index = idx;
         }
       });
-    } else {
-      index = 0;
     }
 
-    return index;
+    return index != null ? index : defaultIndex;
   }
 });
 export default ScrollableLegendView;
\ No newline at end of file
diff --git a/builder/src/echarts/component/legend/legendAction.js b/builder/src/echarts/component/legend/legendAction.js
index 91850a2..c7c352c 100644
--- a/builder/src/echarts/component/legend/legendAction.js
+++ b/builder/src/echarts/component/legend/legendAction.js
@@ -31,6 +31,8 @@ function legendSelectActionHandler(methodName, payload, ecModel) {
       // In the case one legend has some item unSelected in option. And if other legend
       // doesn't has the item, they will assume it is selected.
       legendModel[isSelected ? 'select' : 'unSelect'](payload.name);
+    } else if (methodName === 'allSelect' || methodName === 'inverseSelect') {
+      legendModel[methodName]();
     } else {
       legendModel[methodName](payload.name);
       isSelected = legendModel.isSelected(payload.name);
@@ -55,7 +57,9 @@ function legendSelectActionHandler(methodName, payload, ecModel) {
     });
   }); // Return the event explicitly
 
-  return {
+  return methodName === 'allSelect' || methodName === 'inverseSelect' ? {
+    selected: selectedMap
+  } : {
     name: payload.name,
     selected: selectedMap
   };
@@ -70,6 +74,8 @@ function legendSelectActionHandler(methodName, payload, ecModel) {
 
 
 echarts.registerAction('legendToggleSelect', 'legendselectchanged', zrUtil.curry(legendSelectActionHandler, 'toggleSelected'));
+echarts.registerAction('legendAllSelect', 'legendselectall', zrUtil.curry(legendSelectActionHandler, 'allSelect'));
+echarts.registerAction('legendInverseSelect', 'legendinverseselect', zrUtil.curry(legendSelectActionHandler, 'inverseSelect'));
 /**
  * @event legendSelect
  * @type {Object}
diff --git a/builder/src/echarts/component/marker/MarkLineView.js b/builder/src/echarts/component/marker/MarkLineView.js
index 0b587d6..9962bf9 100644
--- a/builder/src/echarts/component/marker/MarkLineView.js
+++ b/builder/src/echarts/component/marker/MarkLineView.js
@@ -22,6 +22,7 @@ import * as numberUtil from '../../util/number';
 import * as markerHelper from './markerHelper';
 import LineDraw from '../../chart/helper/LineDraw';
 import MarkerView from './MarkerView';
+import { getStackedDimension } from '../../data/helper/dataStackHelper';
 
 var markLineTransform = function (seriesModel, coordSys, mlModel, item) {
   var data = seriesModel.getData(); // Special type markLine like 'min', 'max', 'average', 'median'
@@ -34,21 +35,19 @@ var markLineTransform = function (seriesModel, coordSys, mlModel, item) {
   // }]
   || item.xAxis != null || item.yAxis != null)) {
     var valueAxis;
-    var valueDataDim;
     var value;
 
     if (item.yAxis != null || item.xAxis != null) {
-      valueDataDim = item.yAxis != null ? 'y' : 'x';
-      valueAxis = coordSys.getAxis(valueDataDim);
+      valueAxis = coordSys.getAxis(item.yAxis != null ? 'y' : 'x');
       value = zrUtil.retrieve(item.yAxis, item.xAxis);
     } else {
       var axisInfo = markerHelper.getAxisInfo(item, data, coordSys, seriesModel);
-      valueDataDim = axisInfo.valueDataDim;
       valueAxis = axisInfo.valueAxis;
+      var valueDataDim = getStackedDimension(data, axisInfo.valueDataDim);
       value = markerHelper.numCalculate(data, valueDataDim, mlType);
     }
 
-    var valueIndex = valueDataDim === 'x' ? 0 : 1;
+    var valueIndex = valueAxis.dim === 'x' ? 0 : 1;
     var baseIndex = 1 - valueIndex;
     var mlFrom = zrUtil.clone(item);
     var mlTo = {};
diff --git a/builder/src/echarts/component/marker/MarkPointView.js b/builder/src/echarts/component/marker/MarkPointView.js
index e5e66b3..8e7c18b 100644
--- a/builder/src/echarts/component/marker/MarkPointView.js
+++ b/builder/src/echarts/component/marker/MarkPointView.js
@@ -89,17 +89,29 @@ export default MarkerView.extend({
     updateMarkerLayout(mpModel.getData(), seriesModel, api);
     mpData.each(function (idx) {
       var itemModel = mpData.getItemModel(idx);
+      var symbol = itemModel.getShallow('symbol');
       var symbolSize = itemModel.getShallow('symbolSize');
+      var isFnSymbol = zrUtil.isFunction(symbol);
+      var isFnSymbolSize = zrUtil.isFunction(symbolSize);
 
-      if (typeof symbolSize === 'function') {
-        // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据?
-        symbolSize = symbolSize(mpModel.getRawValue(idx), mpModel.getDataParams(idx));
+      if (isFnSymbol || isFnSymbolSize) {
+        var rawIdx = mpModel.getRawValue(idx);
+        var dataParams = mpModel.getDataParams(idx);
+
+        if (isFnSymbol) {
+          symbol = symbol(rawIdx, dataParams);
+        }
+
+        if (isFnSymbolSize) {
+          // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据?
+          symbolSize = symbolSize(rawIdx, dataParams);
+        }
       }
 
       mpData.setItemVisual(idx, {
+        symbol: symbol,
         symbolSize: symbolSize,
-        color: itemModel.get('itemStyle.color') || seriesData.getVisual('color'),
-        symbol: itemModel.getShallow('symbol')
+        color: itemModel.get('itemStyle.color') || seriesData.getVisual('color')
       });
     }); // TODO Text are wrong
 
diff --git a/builder/src/echarts/component/marker/MarkerModel.js b/builder/src/echarts/component/marker/MarkerModel.js
index 500a6e7..c104533 100644
--- a/builder/src/echarts/component/marker/MarkerModel.js
+++ b/builder/src/echarts/component/marker/MarkerModel.js
@@ -37,9 +37,10 @@ var MarkerModel = echarts.extendComponentModel({
   /**
    * @overrite
    */
-  init: function (option, parentModel, ecModel, extraOpt) {
+  init: function (option, parentModel, ecModel) {
     this.mergeDefaultAndTheme(option, ecModel);
-    this.mergeOption(option, ecModel, extraOpt.createdBySelf, true);
+
+    this._mergeOption(option, ecModel, false, true);
   },
 
   /**
@@ -53,7 +54,14 @@ var MarkerModel = echarts.extendComponentModel({
     var hostSeries = this.__hostSeries;
     return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled();
   },
-  mergeOption: function (newOpt, ecModel, createdBySelf, isInit) {
+
+  /**
+   * @overrite
+   */
+  mergeOption: function (newOpt, ecModel) {
+    this._mergeOption(newOpt, ecModel, false, false);
+  },
+  _mergeOption: function (newOpt, ecModel, createdBySelf, isInit) {
     var MarkerModel = this.constructor;
     var modelPropName = this.mainType + 'Model';
 
@@ -92,7 +100,7 @@ var MarkerModel = echarts.extendComponentModel({
           });
           markerModel.__hostSeries = seriesModel;
         } else {
-          markerModel.mergeOption(markerOpt, ecModel, true);
+          markerModel._mergeOption(markerOpt, ecModel, true);
         }
 
         seriesModel[modelPropName] = markerModel;
diff --git a/builder/src/echarts/component/title.js b/builder/src/echarts/component/title.js
index e7045b9..ef07247 100644
--- a/builder/src/echarts/component/title.js
+++ b/builder/src/echarts/component/title.js
@@ -16,6 +16,7 @@
 * specific language governing permissions and limitations
 * under the License.
 */
+import * as zrUtil from 'zrender/src/core/util';
 import * as echarts from '../echarts';
 import * as graphic from '../util/graphic';
 import { getLayoutRect } from '../util/layout'; // Model
@@ -56,7 +57,8 @@ echarts.extendComponentModel({
     // 垂直对齐
     // 'auto' | 'top' | 'bottom' | 'middle'
     // 默认根据 top 位置判断是上对齐还是下对齐
-    // textBaseline: null
+    // textVerticalAlign: null
+    // textBaseline: null // The same as textVerticalAlign.
     backgroundColor: 'rgba(0,0,0,0)',
     // 标题边框颜色
     borderColor: '#ccc',
@@ -91,7 +93,7 @@ echarts.extendComponentView({
     var textStyleModel = titleModel.getModel('textStyle');
     var subtextStyleModel = titleModel.getModel('subtextStyle');
     var textAlign = titleModel.get('textAlign');
-    var textBaseline = titleModel.get('textBaseline');
+    var textVerticalAlign = zrUtil.retrieve2(titleModel.get('textBaseline'), titleModel.get('textVerticalAlign'));
     var textEl = new graphic.Text({
       style: graphic.setTextStyle({}, textStyleModel, {
         text: titleModel.get('text'),
@@ -164,26 +166,26 @@ echarts.extendComponentView({
       }
     }
 
-    if (!textBaseline) {
-      textBaseline = titleModel.get('top') || titleModel.get('bottom');
+    if (!textVerticalAlign) {
+      textVerticalAlign = titleModel.get('top') || titleModel.get('bottom');
 
-      if (textBaseline === 'center') {
-        textBaseline = 'middle';
+      if (textVerticalAlign === 'center') {
+        textVerticalAlign = 'middle';
       }
 
-      if (textBaseline === 'bottom') {
+      if (textVerticalAlign === 'bottom') {
         layoutRect.y += layoutRect.height;
-      } else if (textBaseline === 'middle') {
+      } else if (textVerticalAlign === 'middle') {
         layoutRect.y += layoutRect.height / 2;
       }
 
-      textBaseline = textBaseline || 'top';
+      textVerticalAlign = textVerticalAlign || 'top';
     }
 
     group.attr('position', [layoutRect.x, layoutRect.y]);
     var alignStyle = {
       textAlign: textAlign,
-      textVerticalAlign: textBaseline
+      textVerticalAlign: textVerticalAlign
     };
     textEl.setStyle(alignStyle);
     subTextEl.setStyle(alignStyle); // Render background
@@ -202,9 +204,9 @@ echarts.extendComponentView({
         r: titleModel.get('borderRadius')
       },
       style: style,
+      subPixelOptimize: true,
       silent: true
     });
-    graphic.subPixelOptimizeRect(rect);
     group.add(rect);
   }
 });
\ No newline at end of file
diff --git a/builder/src/echarts/component/toolbox/ToolboxModel.js b/builder/src/echarts/component/toolbox/ToolboxModel.js
index 4bc7a23..c3a099f 100644
--- a/builder/src/echarts/component/toolbox/ToolboxModel.js
+++ b/builder/src/echarts/component/toolbox/ToolboxModel.js
@@ -56,9 +56,12 @@ var ToolboxModel = echarts.extendComponentModel({
     emphasis: {
       iconStyle: {
         borderColor: '#3E98C5'
-      } // textStyle: {},
-      // feature
-
+      }
+    },
+    // textStyle: {},
+    // feature
+    tooltip: {
+      show: false
     }
   }
 });
diff --git a/builder/src/echarts/component/toolbox/ToolboxView.js b/builder/src/echarts/component/toolbox/ToolboxView.js
index bf2605c..72df0cb 100644
--- a/builder/src/echarts/component/toolbox/ToolboxView.js
+++ b/builder/src/echarts/component/toolbox/ToolboxView.js
@@ -50,7 +50,11 @@ export default echarts.extendComponentView({
       var oldName = featureNames[oldIndex];
       var featureOpt = featureOpts[featureName];
       var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel);
-      var feature;
+      var feature; // FIX#11236, merge feature title from MagicType newOption. TODO: consider seriesIndex ?
+
+      if (payload && payload.newTitle != null) {
+        featureOpt.title = payload.newTitle;
+      }
 
       if (featureName && !oldName) {
         // Create
@@ -144,7 +148,33 @@ export default echarts.extendComponentView({
           height: itemSize
         });
         path.setStyle(iconStyleModel.getItemStyle());
-        path.hoverStyle = iconStyleEmphasisModel.getItemStyle();
+        path.hoverStyle = iconStyleEmphasisModel.getItemStyle(); // Text position calculation
+
+        path.setStyle({
+          text: titles[iconName],
+          textAlign: iconStyleEmphasisModel.get('textAlign'),
+          textBorderRadius: iconStyleEmphasisModel.get('textBorderRadius'),
+          textPadding: iconStyleEmphasisModel.get('textPadding'),
+          textFill: null
+        });
+        var tooltipModel = toolboxModel.getModel('tooltip');
+
+        if (tooltipModel && tooltipModel.get('show')) {
+          path.attr('tooltip', zrUtil.extend({
+            content: titles[iconName],
+            formatter: tooltipModel.get('formatter', true) || function () {
+              return titles[iconName];
+            },
+            formatterParams: {
+              componentType: 'toolbox',
+              name: iconName,
+              title: titles[iconName],
+              $vars: ['name', 'title']
+            },
+            position: tooltipModel.get('position', true) || 'bottom'
+          }, tooltipModel.option));
+        }
+
         graphic.setHoverStyle(path);
 
         if (toolboxModel.get('showTitle')) {
@@ -152,15 +182,16 @@ export default echarts.extendComponentView({
           path.on('mouseover', function () {
             // Should not reuse above hoverStyle, which might be modified.
             var hoverStyle = iconStyleEmphasisModel.getItemStyle();
+            var defaultTextPosition = toolboxModel.get('orient') === 'vertical' ? toolboxModel.get('right') == null ? 'right' : 'left' : toolboxModel.get('bottom') == null ? 'bottom' : 'top';
             path.setStyle({
-              text: titles[iconName],
-              textPosition: hoverStyle.textPosition || 'bottom',
-              textFill: hoverStyle.fill || hoverStyle.stroke || '#000',
-              textAlign: hoverStyle.textAlign || 'center'
+              textFill: iconStyleEmphasisModel.get('textFill') || hoverStyle.fill || hoverStyle.stroke || '#000',
+              textBackgroundColor: iconStyleEmphasisModel.get('textBackgroundColor'),
+              textPosition: iconStyleEmphasisModel.get('textPosition') || defaultTextPosition
             });
           }).on('mouseout', function () {
             path.setStyle({
-              textFill: null
+              textFill: null,
+              textBackgroundColor: null
             });
           });
         }
diff --git a/builder/src/echarts/component/toolbox/feature/DataView.js b/builder/src/echarts/component/toolbox/feature/DataView.js
index 752d851..7e4923a 100644
--- a/builder/src/echarts/component/toolbox/feature/DataView.js
+++ b/builder/src/echarts/component/toolbox/feature/DataView.js
@@ -398,22 +398,7 @@ DataView.prototype.onclick = function (ecModel, api) {
   refreshButton.style.cssText = buttonStyle;
   closeButton.style.cssText = buttonStyle;
   !model.get('readOnly') && buttonContainer.appendChild(refreshButton);
-  buttonContainer.appendChild(closeButton); // http://stackoverflow.com/questions/6637341/use-tab-to-indent-in-textarea
-
-  eventTool.addEventListener(textarea, 'keydown', function (e) {
-    if ((e.keyCode || e.which) === 9) {
-      // get caret position/selection
-      var val = this.value;
-      var start = this.selectionStart;
-      var end = this.selectionEnd; // set textarea value to: text before caret + tab + text after caret
-
-      this.value = val.substring(0, start) + ITEM_SPLITER + val.substring(end); // put caret at right position again
-
-      this.selectionStart = this.selectionEnd = start + 1; // prevent the focus lose
-
-      eventTool.stop(e);
-    }
-  });
+  buttonContainer.appendChild(closeButton);
   root.appendChild(header);
   root.appendChild(viewMain);
   root.appendChild(buttonContainer);
diff --git a/builder/src/echarts/component/toolbox/feature/DataZoom.js b/builder/src/echarts/component/toolbox/feature/DataZoom.js
index 17c1892..65abfa5 100644
--- a/builder/src/echarts/component/toolbox/feature/DataZoom.js
+++ b/builder/src/echarts/component/toolbox/feature/DataZoom.js
@@ -47,6 +47,7 @@ function DataZoom(model, ecModel, api) {
 
 DataZoom.defaultOption = {
   show: true,
+  filterMode: 'filter',
   // Icon group
   icon: {
     zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1',
@@ -273,6 +274,8 @@ echarts.registerPreprocessor(function (option) {
       var newOpt = {
         type: 'select',
         $fromToolbox: true,
+        // Default to be filter
+        filterMode: dataZoomOpt.filterMode || 'filter',
         // Id for merge mapping.
         id: DATA_ZOOM_ID_BASE + axisName + axisIndex
       }; // FIXME
diff --git a/builder/src/echarts/component/toolbox/feature/MagicType.js b/builder/src/echarts/component/toolbox/feature/MagicType.js
index 6f0c594..39d06d5 100644
--- a/builder/src/echarts/component/toolbox/feature/MagicType.js
+++ b/builder/src/echarts/component/toolbox/feature/MagicType.js
@@ -21,6 +21,7 @@ import * as zrUtil from 'zrender/src/core/util';
 import lang from '../../../lang';
 import * as featureManager from '../featureManager';
 var magicTypeLang = lang.toolbox.magicType;
+var INNER_STACK_KEYWORD = '__ec_magicType_stack__';
 
 function MagicType(model) {
   this.model = model;
@@ -34,9 +35,8 @@ MagicType.defaultOption = {
     /* eslint-disable */
     line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4',
     bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7',
-    stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z',
-    // jshint ignore:line
-    tiled: 'M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z'
+    stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z' // jshint ignore:line
+
     /* eslint-enable */
 
   },
@@ -87,23 +87,18 @@ var seriesOptGenreator = {
     }
   },
   'stack': function (seriesType, seriesId, seriesModel, model) {
+    var isStack = seriesModel.get('stack') === INNER_STACK_KEYWORD;
+
     if (seriesType === 'line' || seriesType === 'bar') {
+      model.setIconStatus('stack', isStack ? 'normal' : 'emphasis');
       return zrUtil.merge({
         id: seriesId,
-        stack: '__ec_magicType_stack__'
+        stack: isStack ? '' : INNER_STACK_KEYWORD
       }, model.get('option.stack') || {}, true);
     }
-  },
-  'tiled': function (seriesType, seriesId, seriesModel, model) {
-    if (seriesType === 'line' || seriesType === 'bar') {
-      return zrUtil.merge({
-        id: seriesId,
-        stack: ''
-      }, model.get('option.tiled') || {}, true);
-    }
   }
 };
-var radioTypes = [['line', 'bar'], ['stack', 'tiled']];
+var radioTypes = [['line', 'bar'], ['stack']];
 
 proto.onclick = function (ecModel, api, type) {
   var model = this.model;
@@ -168,10 +163,20 @@ proto.onclick = function (ecModel, api, type) {
       seriesIndex: seriesIndex
     }
   }, generateNewSeriesTypes);
+  var newTitle; // Change title of stack
+
+  if (type === 'stack') {
+    var isStack = newOption.series && newOption.series[0] && newOption.series[0].stack === INNER_STACK_KEYWORD;
+    newTitle = isStack ? zrUtil.merge({
+      stack: magicTypeLang.title.tiled
+    }, magicTypeLang.title) : zrUtil.clone(magicTypeLang.title);
+  }
+
   api.dispatchAction({
     type: 'changeMagicType',
     currentType: type,
-    newOption: newOption
+    newOption: newOption,
+    newTitle: newTitle
   });
 };
 
diff --git a/builder/src/echarts/component/toolbox/feature/SaveAsImage.js b/builder/src/echarts/component/toolbox/feature/SaveAsImage.js
index c6e51c4..e7389cc 100644
--- a/builder/src/echarts/component/toolbox/feature/SaveAsImage.js
+++ b/builder/src/echarts/component/toolbox/feature/SaveAsImage.js
@@ -34,6 +34,7 @@ SaveAsImage.defaultOption = {
   type: 'png',
   // Default use option.backgroundColor
   // backgroundColor: '#fff',
+  connectedBackgroundColor: '#fff',
   name: '',
   excludeComponents: ['toolbox'],
   pixelRatio: 1,
@@ -45,19 +46,20 @@ var proto = SaveAsImage.prototype;
 proto.onclick = function (ecModel, api) {
   var model = this.model;
   var title = model.get('name') || ecModel.get('title.0.text') || 'echarts';
-  var $a = document.createElement('a');
   var type = model.get('type', true) || 'png';
-  $a.download = title + '.' + type;
-  $a.target = '_blank';
   var url = api.getConnectedDataURL({
     type: type,
     backgroundColor: model.get('backgroundColor', true) || ecModel.get('backgroundColor') || '#fff',
+    connectedBackgroundColor: model.get('connectedBackgroundColor'),
     excludeComponents: model.get('excludeComponents'),
     pixelRatio: model.get('pixelRatio')
-  });
-  $a.href = url; // Chrome and Firefox
+  }); // Chrome and Firefox
 
   if (typeof MouseEvent === 'function' && !env.browser.ie && !env.browser.edge) {
+    var $a = document.createElement('a');
+    $a.download = title + '.' + type;
+    $a.target = '_blank';
+    $a.href = url;
     var evt = new MouseEvent('click', {
       view: window,
       bubbles: true,
diff --git a/builder/src/echarts/component/tooltip/TooltipContent.js b/builder/src/echarts/component/tooltip/TooltipContent.js
index ef22fba..20e0ee4 100644
--- a/builder/src/echarts/component/tooltip/TooltipContent.js
+++ b/builder/src/echarts/component/tooltip/TooltipContent.js
@@ -123,7 +123,10 @@ function TooltipContent(container, api) {
    * @private
    */
 
-  this._hideTimeout;
+  this._hideTimeout; // FIXME
+  // Is it needed to trigger zr event manually if
+  // the browser do not support `pointer-events: none`.
+
   var self = this;
 
   el.onmouseenter = function () {
@@ -140,6 +143,10 @@ function TooltipContent(container, api) {
     e = e || window.event;
 
     if (!self._enterable) {
+      // `pointer-events: none` is set to tooltip content div
+      // if `enterable` is set as `false`, and `el.onmousemove`
+      // can not be triggered. But in browser that do not
+      // support `pointer-events`, we need to do this:
       // Try trigger zrender event to avoid mouse
       // in and out shape too frequently
       var handler = zr.handler;
@@ -188,7 +195,9 @@ TooltipContent.prototype = {
   show: function (tooltipModel) {
     clearTimeout(this._hideTimeout);
     var el = this.el;
-    el.style.cssText = gCssText + assembleCssText(tooltipModel) // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
+    el.style.cssText = gCssText + assembleCssText(tooltipModel) // Because of the reason described in:
+    // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
+    // we should set initial value to `left` and `top`.
     + ';left:' + this._x + 'px;top:' + this._y + 'px;' + (tooltipModel.get('extraCssText') || '');
     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
@@ -255,8 +264,8 @@ TooltipContent.prototype = {
       var stl = document.defaultView.getComputedStyle(this.el);
 
       if (stl) {
-        width += parseInt(stl.paddingLeft, 10) + parseInt(stl.paddingRight, 10) + parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10);
-        height += parseInt(stl.paddingTop, 10) + parseInt(stl.paddingBottom, 10) + parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10);
+        width += parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10);
+        height += parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10);
       }
     }
 
diff --git a/builder/src/echarts/component/tooltip/TooltipContentManager.js b/builder/src/echarts/component/tooltip/TooltipContentManager.js
new file mode 100755
index 0000000..8adff7d
--- /dev/null
+++ b/builder/src/echarts/component/tooltip/TooltipContentManager.js
@@ -0,0 +1,103 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+import * as zrUtil from 'zrender/src/core/util';
+import TooltipContent from './TooltipContent'; // var each = zrUtil.each;
+
+/**
+ * @alias module:echarts/component/tooltip/TooltipContentManager
+ * @constructor
+ */
+
+function TooltipContentManager(container, api) {
+  /**
+   * @private
+   */
+  this._contents = {
+    // Default tooltip content
+    main: new TooltipContent(container, api)
+  };
+}
+
+TooltipContentManager.prototype = {
+  constructor: TooltipContentManager,
+
+  /**
+   * Update when tooltip is rendered
+   */
+  update: function () {
+    this._each('update');
+  },
+
+  /**
+   * @param {module:echarts/component/tooltip/TooltipModel}
+   * @param {string} [key='main']
+   */
+  show: function (tooltipModel, key) {
+    key = key || 'main';
+
+    this._giveContent(key).show(tooltipModel);
+  },
+
+  /**
+   * Create content if not exists.
+   */
+  _giveContent: function (key) {
+    return this._contents[key] || (this._contents[key] = new TooltipContent());
+  },
+  setContent: function (content) {
+    this.el.innerHTML = content;
+  },
+  setEnterable: function (enterable) {
+    this._enterable = enterable;
+  },
+  getSize: function () {
+    var el = this.el;
+    return [el.clientWidth, el.clientHeight];
+  },
+  moveTo: function (x, y) {
+    var style = this.el.style;
+    style.left = x + 'px';
+    style.top = y + 'px';
+    this._x = x;
+    this._y = y;
+  },
+  hide: function () {
+    this.el.style.display = 'none';
+    this._show = false;
+  },
+  // showLater: function ()
+  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._show = false;
+        this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time);
+      } else {
+        this.hide();
+      }
+    }
+  },
+  _each: function (method, args) {
+    zrUtil.each(this._contents, function (content) {
+      content[method].apply(content, args);
+    });
+  }
+};
+export default TooltipContentManager;
\ No newline at end of file
diff --git a/builder/src/echarts/component/tooltip/TooltipRichContent.js b/builder/src/echarts/component/tooltip/TooltipRichContent.js
index 260087c..54c1d95 100644
--- a/builder/src/echarts/component/tooltip/TooltipRichContent.js
+++ b/builder/src/echarts/component/tooltip/TooltipRichContent.js
@@ -149,7 +149,10 @@ TooltipRichContent.prototype = {
     }
   },
   hide: function () {
-    this.el.hide();
+    if (this.el) {
+      this.el.hide();
+    }
+
     this._show = false;
   },
   hideLater: function (time) {
@@ -168,7 +171,11 @@ TooltipRichContent.prototype = {
     return this._show;
   },
   getOuterSize: function () {
-    return this.getSize();
+    var size = this.getSize();
+    return {
+      width: size[0],
+      height: size[1]
+    };
   }
 };
 export default TooltipRichContent;
\ No newline at end of file
diff --git a/builder/src/echarts/component/tooltip/TooltipView.js b/builder/src/echarts/component/tooltip/TooltipView.js
index fc80e32..4ed5387 100644
--- a/builder/src/echarts/component/tooltip/TooltipView.js
+++ b/builder/src/echarts/component/tooltip/TooltipView.js
@@ -139,7 +139,7 @@ export default echarts.extendComponentView({
         // Show tip next tick after other charts are rendered
         // In case highlight action has wrong result
         // FIXME
-        self.manuallyShowTip(tooltipModel, ecModel, api, {
+        !api.isDisposed() && self.manuallyShowTip(tooltipModel, ecModel, api, {
           x: self._lastX,
           y: self._lastY
         });
diff --git a/builder/src/echarts/component/visualMap/ContinuousView.js b/builder/src/echarts/component/visualMap/ContinuousView.js
index 99c221c..fb5cbd2 100644
--- a/builder/src/echarts/component/visualMap/ContinuousView.js
+++ b/builder/src/echarts/component/visualMap/ContinuousView.js
@@ -617,9 +617,9 @@ var ContinuousView = VisualMapView.extend({
 
     var resultBatches = modelUtil.compressBatches(oldBatch, newBatch);
 
-    this._dispatchHighDown('downplay', helper.convertDataIndex(resultBatches[0]));
+    this._dispatchHighDown('downplay', helper.makeHighDownBatch(resultBatches[0], visualMapModel));
 
-    this._dispatchHighDown('highlight', helper.convertDataIndex(resultBatches[1]));
+    this._dispatchHighDown('highlight', helper.makeHighDownBatch(resultBatches[1], visualMapModel));
   },
 
   /**
@@ -664,7 +664,7 @@ var ContinuousView = VisualMapView.extend({
 
     var indices = this._hoverLinkDataIndices;
 
-    this._dispatchHighDown('downplay', helper.convertDataIndex(indices));
+    this._dispatchHighDown('downplay', helper.makeHighDownBatch(indices, this.visualMapModel));
 
     indices.length = 0;
   },
diff --git a/builder/src/echarts/component/visualMap/PiecewiseModel.js b/builder/src/echarts/component/visualMap/PiecewiseModel.js
index 9d546cf..978b6a9 100644
--- a/builder/src/echarts/component/visualMap/PiecewiseModel.js
+++ b/builder/src/echarts/component/visualMap/PiecewiseModel.js
@@ -252,7 +252,7 @@ var PiecewiseModel = VisualMapModel.extend({
   /**
    * @public
    * @params {number} pieceIndex piece index in visualMapModel.getPieceList()
-   * @return {Array.<Object>} [{seriesId, dataIndices: <Array.<number>>}, ...]
+   * @return {Array.<Object>} [{seriesId, dataIndex: <Array.<number>>}, ...]
    */
   findTargetDataIndices: function (pieceIndex) {
     var result = [];
diff --git a/builder/src/echarts/component/visualMap/PiecewiseView.js b/builder/src/echarts/component/visualMap/PiecewiseView.js
index df985b7..8615707 100644
--- a/builder/src/echarts/component/visualMap/PiecewiseView.js
+++ b/builder/src/echarts/component/visualMap/PiecewiseView.js
@@ -94,7 +94,7 @@ var PiecewiseVisualMapView = VisualMapView.extend({
       var visualMapModel = this.visualMapModel;
       visualMapModel.option.hoverLink && this.api.dispatchAction({
         type: method,
-        batch: helper.convertDataIndex(visualMapModel.findTargetDataIndices(pieceIndex))
+        batch: helper.makeHighDownBatch(visualMapModel.findTargetDataIndices(pieceIndex), visualMapModel)
       });
     }
   },
diff --git a/builder/src/echarts/component/visualMap/helper.js b/builder/src/echarts/component/visualMap/helper.js
index 666f226..197d465 100644
--- a/builder/src/echarts/component/visualMap/helper.js
+++ b/builder/src/echarts/component/visualMap/helper.js
@@ -58,12 +58,14 @@ export function getItemAlign(visualMapModel, api, itemSize) {
  * dataIndexInside means filtered index.
  */
 
-export function convertDataIndex(batch) {
+export function makeHighDownBatch(batch, visualMapModel) {
   zrUtil.each(batch || [], function (batchItem) {
-    if (batch.dataIndex != null) {
-      batch.dataIndexInside = batch.dataIndex;
-      batch.dataIndex = null;
+    if (batchItem.dataIndex != null) {
+      batchItem.dataIndexInside = batchItem.dataIndex;
+      batchItem.dataIndex = null;
     }
+
+    batchItem.highlightKey = 'visualMap' + (visualMapModel ? visualMapModel.componentIndex : '');
   });
   return batch;
 }
\ No newline at end of file
diff --git a/builder/src/echarts/coord/Axis.js b/builder/src/echarts/coord/Axis.js
index 1509bc4..6ec4bb7 100644
--- a/builder/src/echarts/coord/Axis.js
+++ b/builder/src/echarts/coord/Axis.js
@@ -17,7 +17,7 @@
 * under the License.
 */
 import { each, map } from 'zrender/src/core/util';
-import { linearMap, getPixelPrecision } from '../util/number';
+import { linearMap, getPixelPrecision, round } from '../util/number';
 import { createAxisTicks, createAxisLabels, calculateCategoryInterval } from './axisTickLabelBuilder';
 var NORMALIZED_EXTENT = [0, 1];
 /**
@@ -77,7 +77,7 @@ Axis.prototype = {
    * @return {boolean}
    */
   containData: function (data) {
-    return this.contain(this.dataToCoord(data));
+    return this.scale.contain(data);
   },
 
   /**
@@ -160,7 +160,7 @@ Axis.prototype = {
    * `axis.getTicksCoords` considers `onBand`, which is used by
    * `boundaryGap:true` of category axis and splitLine and splitArea.
    * @param {Object} [opt]
-   * @param {number} [opt.tickModel=axis.model.getModel('axisTick')]
+   * @param {Model} [opt.tickModel=axis.model.getModel('axisTick')]
    * @param {boolean} [opt.clamp] If `true`, the first and the last
    *        tick must be at the axis end points. Otherwise, clip ticks
    *        that outside the axis extent.
@@ -181,11 +181,39 @@ Axis.prototype = {
       };
     }, this);
     var alignWithLabel = tickModel.get('alignWithLabel');
-    fixOnBandTicksCoords(this, ticksCoords, result.tickCategoryInterval, alignWithLabel, opt.clamp);
+    fixOnBandTicksCoords(this, ticksCoords, alignWithLabel, opt.clamp);
     return ticksCoords;
   },
 
   /**
+   * @return {Array.<Array.<Object>>} [{ coord: ..., tickValue: ...}]
+   */
+  getMinorTicksCoords: function () {
+    if (this.scale.type === 'ordinal') {
+      // Category axis doesn't support minor ticks
+      return [];
+    }
+
+    var minorTickModel = this.model.getModel('minorTick');
+    var splitNumber = minorTickModel.get('splitNumber'); // Protection.
+
+    if (!(splitNumber > 0 && splitNumber < 100)) {
+      splitNumber = 5;
+    }
+
+    var minorTicks = this.scale.getMinorTicks(splitNumber);
+    var minorTicksCoords = map(minorTicks, function (minorTicksGroup) {
+      return map(minorTicksGroup, function (minorTick) {
+        return {
+          coord: this.dataToCoord(minorTick),
+          tickValue: minorTick
+        };
+      }, this);
+    }, this);
+    return minorTicksCoords;
+  },
+
+  /**
    * @return {Array.<Object>} [{
    *     formattedLabel: string,
    *     rawLabel: axis.scale.getLabel(tickValue)
@@ -268,7 +296,7 @@ function fixExtentWithBands(extent, nTick) {
 // case).
 
 
-function fixOnBandTicksCoords(axis, ticksCoords, tickCategoryInterval, alignWithLabel, clamp) {
+function fixOnBandTicksCoords(axis, ticksCoords, alignWithLabel, clamp) {
   var ticksLen = ticksCoords.length;
 
   if (!axis.onBand || alignWithLabel || !ticksLen) {
@@ -277,6 +305,7 @@ function fixOnBandTicksCoords(axis, ticksCoords, tickCategoryInterval, alignWith
 
   var axisExtent = axis.getExtent();
   var last;
+  var diffSize;
 
   if (ticksLen === 1) {
     ticksCoords[0].coord = axisExtent[0];
@@ -284,22 +313,20 @@ function fixOnBandTicksCoords(axis, ticksCoords, tickCategoryInterval, alignWith
       coord: axisExtent[0]
     };
   } else {
-    var shift = ticksCoords[1].coord - ticksCoords[0].coord;
+    var crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue;
+    var shift = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen;
     each(ticksCoords, function (ticksItem) {
       ticksItem.coord -= shift / 2;
-      var tickCategoryInterval = tickCategoryInterval || 0; // Avoid split a single data item when odd interval.
-
-      if (tickCategoryInterval % 2 > 0) {
-        ticksItem.coord -= shift / ((tickCategoryInterval + 1) * 2);
-      }
     });
+    var dataExtent = axis.scale.getExtent();
+    diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue;
     last = {
-      coord: ticksCoords[ticksLen - 1].coord + shift
+      coord: ticksCoords[ticksLen - 1].coord + shift * diffSize
     };
     ticksCoords.push(last);
   }
 
-  var inverse = axisExtent[0] > axisExtent[1];
+  var inverse = axisExtent[0] > axisExtent[1]; // Handling clamp.
 
   if (littleThan(ticksCoords[0].coord, axisExtent[0])) {
     clamp ? ticksCoords[0].coord = axisExtent[0] : ticksCoords.shift();
@@ -322,6 +349,10 @@ function fixOnBandTicksCoords(axis, ticksCoords, tickCategoryInterval, alignWith
   }
 
   function littleThan(a, b) {
+    // Avoid rounding error cause calculated tick coord different with extent.
+    // It may cause an extra unecessary tick added.
+    a = round(a);
+    b = round(b);
     return inverse ? a > b : a < b;
   }
 }
diff --git a/builder/src/echarts/coord/axisDefault.js b/builder/src/echarts/coord/axisDefault.js
index b7b3695..b690a5c 100644
--- a/builder/src/echarts/coord/axisDefault.js
+++ b/builder/src/echarts/coord/axisDefault.js
@@ -149,13 +149,32 @@ axisDefault.valueAxis = zrUtil.merge({
   // + `true`: the extent do not consider value 0.
   // scale: false,
   // AxisTick and axisLabel and splitLine are caculated based on splitNumber.
-  splitNumber: 5 // Interval specifies the span of the ticks is mandatorily.
+  splitNumber: 5,
+  // Interval specifies the span of the ticks is mandatorily.
   // interval: null
   // Specify min interval when auto calculate tick interval.
   // minInterval: null
   // Specify max interval when auto calculate tick interval.
   // maxInterval: null
-
+  minorTick: {
+    // Minor tick, not available for cateogry axis.
+    show: false,
+    // Split number of minor ticks. The value should be in range of (0, 100)
+    splitNumber: 5,
+    // Lenght of minor tick
+    length: 3,
+    // Same inside with axisTick
+    // Line style
+    lineStyle: {// Default to be same with axisTick
+    }
+  },
+  minorSplitLine: {
+    show: false,
+    lineStyle: {
+      color: '#eee',
+      width: 1
+    }
+  }
 }, defaultOption);
 axisDefault.timeAxis = zrUtil.defaults({
   scale: true,
diff --git a/builder/src/echarts/coord/axisTickLabelBuilder.js b/builder/src/echarts/coord/axisTickLabelBuilder.js
index 0b883b9..e33a8a9 100644
--- a/builder/src/echarts/coord/axisTickLabelBuilder.js
+++ b/builder/src/echarts/coord/axisTickLabelBuilder.js
@@ -227,20 +227,28 @@ export function calculateCategoryInterval(axis) {
   isNaN(dh) && (dh = Infinity);
   var interval = Math.max(0, Math.floor(Math.min(dw, dh)));
   var cache = inner(axis.model);
+  var axisExtent = axis.getExtent();
   var lastAutoInterval = cache.lastAutoInterval;
   var lastTickCount = cache.lastTickCount; // Use cache to keep interval stable while moving zoom window,
   // otherwise the calculated interval might jitter when the zoom
   // window size is close to the interval-changing size.
+  // For example, if all of the axis labels are `a, b, c, d, e, f, g`.
+  // The jitter will cause that sometimes the displayed labels are
+  // `a, d, g` (interval: 2) sometimes `a, c, e`(interval: 1).
 
   if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 // Always choose the bigger one, otherwise the critical
   // point is not the same when zooming in or zooming out.
-  && lastAutoInterval > interval) {
+  && lastAutoInterval > interval // If the axis change is caused by chart resize, the cache should not
+  // be used. Otherwise some hiden labels might not be shown again.
+  && cache.axisExtend0 === axisExtent[0] && cache.axisExtend1 === axisExtent[1]) {
     interval = lastAutoInterval;
   } // Only update cache if cache not used, otherwise the
   // changing of interval is too insensitive.
   else {
       cache.lastTickCount = tickCount;
       cache.lastAutoInterval = interval;
+      cache.axisExtend0 = axisExtent[0];
+      cache.axisExtend1 = axisExtent[1];
     }
 
   return interval;
@@ -293,7 +301,7 @@ function makeLabelsByNumericCategoryInterval(axis, categoryInterval, onlyTick) {
     addItem(tickValue);
   }
 
-  if (includeMaxLabel && tickValue !== ordinalExtent[1]) {
+  if (includeMaxLabel && tickValue - step !== ordinalExtent[1]) {
     addItem(ordinalExtent[1]);
   }
 
diff --git a/builder/src/echarts/coord/cartesian/Cartesian2D.js b/builder/src/echarts/coord/cartesian/Cartesian2D.js
index 9127e01..f926d5a 100644
--- a/builder/src/echarts/coord/cartesian/Cartesian2D.js
+++ b/builder/src/echarts/coord/cartesian/Cartesian2D.js
@@ -17,6 +17,7 @@
 * under the License.
 */
 import * as zrUtil from 'zrender/src/core/util';
+import BoundingRect from 'zrender/src/core/BoundingRect';
 import Cartesian from './Cartesian';
 
 function Cartesian2D(name) {
@@ -114,6 +115,22 @@ Cartesian2D.prototype = {
    */
   getOtherAxis: function (axis) {
     return this.getAxis(axis.dim === 'x' ? 'y' : 'x');
+  },
+
+  /**
+   * Get rect area of cartesian.
+   * Area will have a contain function to determine if a point is in the coordinate system.
+   * @return {BoundingRect}
+   */
+  getArea: function () {
+    var xExtent = this.getAxis('x').getGlobalExtent();
+    var yExtent = this.getAxis('y').getGlobalExtent();
+    var x = Math.min(xExtent[0], xExtent[1]);
+    var y = Math.min(yExtent[0], yExtent[1]);
+    var width = Math.max(xExtent[0], xExtent[1]) - x;
+    var height = Math.max(yExtent[0], yExtent[1]) - y;
+    var rect = new BoundingRect(x, y, width, height);
+    return rect;
   }
 };
 zrUtil.inherits(Cartesian2D, Cartesian);
diff --git a/builder/src/echarts/coord/cartesian/Grid.js b/builder/src/echarts/coord/cartesian/Grid.js
index 3772f2c..86bc47e 100644
--- a/builder/src/echarts/coord/cartesian/Grid.js
+++ b/builder/src/echarts/coord/cartesian/Grid.js
@@ -54,7 +54,7 @@ function Grid(gridModel, ecModel, api) {
 
   this._coordsList = [];
   /**
-   * @type {Object.<string, module:echarts/coord/cartesian/Axis2D>}
+   * @type {Object.<string, Array.<module:echarts/coord/cartesian/Axis2D>>}
    * @private
    */
 
@@ -395,21 +395,13 @@ gridProto._initCartesian = function (gridModel, ecModel, api) {
         // Fix position
         if (axisPosition !== 'top' && axisPosition !== 'bottom') {
           // Default bottom of X
-          axisPosition = 'bottom';
-
-          if (axisPositionUsed[axisPosition]) {
-            axisPosition = axisPosition === 'top' ? 'bottom' : 'top';
-          }
+          axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom';
         }
       } else {
         // Fix position
         if (axisPosition !== 'left' && axisPosition !== 'right') {
           // Default left of Y
-          axisPosition = 'left';
-
-          if (axisPositionUsed[axisPosition]) {
-            axisPosition = axisPosition === 'left' ? 'right' : 'left';
-          }
+          axisPosition = axisPositionUsed.left ? 'right' : 'left';
         }
       }
 
diff --git a/builder/src/echarts/coord/geo/GeoModel.js b/builder/src/echarts/coord/geo/GeoModel.js
index ff33e6d..d4b8380 100644
--- a/builder/src/echarts/coord/geo/GeoModel.js
+++ b/builder/src/echarts/coord/geo/GeoModel.js
@@ -118,7 +118,7 @@ var GeoModel = ComponentModel.extend({
    */
   getFormattedLabel: function (name, status) {
     var regionModel = this.getRegionModel(name);
-    var formatter = regionModel.get('label.' + status + '.formatter');
+    var formatter = regionModel.get('label' + (status === 'normal' ? '.' : status + '.') + 'formatter');
     var params = {
       name: name
     };
diff --git a/builder/src/echarts/coord/geo/geoJSONLoader.js b/builder/src/echarts/coord/geo/geoJSONLoader.js
index 6c42fd9..9d42ac9 100644
--- a/builder/src/echarts/coord/geo/geoJSONLoader.js
+++ b/builder/src/echarts/coord/geo/geoJSONLoader.js
@@ -48,6 +48,7 @@ export default {
       throw new Error('Invalid geoJson format\n' + e.message);
     }
 
+    fixNanhai(mapName, regions);
     each(regions, function (region) {
       var regionName = region.name;
       fixTextCoord(mapName, region);
@@ -61,7 +62,6 @@ export default {
         region.transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height);
       }
     });
-    fixNanhai(mapName, regions);
     return inner(mapRecord).parsed = {
       regions: regions,
       boundingRect: getBoundingRect(regions)
diff --git a/builder/src/echarts/coord/polar/Polar.js b/builder/src/echarts/coord/polar/Polar.js
index 35e84b0..34b83b1 100644
--- a/builder/src/echarts/coord/polar/Polar.js
+++ b/builder/src/echarts/coord/polar/Polar.js
@@ -231,6 +231,39 @@ Polar.prototype = {
 
     var y = -Math.sin(radian) * radius + this.cy;
     return [x, y];
+  },
+
+  /**
+   * Get ring area of cartesian.
+   * Area will have a contain function to determine if a point is in the coordinate system.
+   * @return {Ring}
+   */
+  getArea: function () {
+    var angleAxis = this.getAngleAxis();
+    var radiusAxis = this.getRadiusAxis();
+    var radiusExtent = radiusAxis.getExtent().slice();
+    radiusExtent[0] > radiusExtent[1] && radiusExtent.reverse();
+    var angleExtent = angleAxis.getExtent();
+    var RADIAN = Math.PI / 180;
+    return {
+      cx: this.cx,
+      cy: this.cy,
+      r0: radiusExtent[0],
+      r: radiusExtent[1],
+      startAngle: -angleExtent[0] * RADIAN,
+      endAngle: -angleExtent[1] * RADIAN,
+      clockwise: angleAxis.inverse,
+      contain: function (x, y) {
+        // It's a ring shape.
+        // Start angle and end angle don't matter
+        var dx = x - this.cx;
+        var dy = y - this.cy;
+        var d2 = dx * dx + dy * dy;
+        var r = this.r;
+        var r0 = this.r0;
+        return d2 <= r * r && d2 >= r0 * r0;
+      }
+    };
   }
 };
 export default Polar;
\ No newline at end of file
diff --git a/builder/src/echarts/coord/polar/polarCreator.js b/builder/src/echarts/coord/polar/polarCreator.js
index a4d56a1..f0a931d 100644
--- a/builder/src/echarts/coord/polar/polarCreator.js
+++ b/builder/src/echarts/coord/polar/polarCreator.js
@@ -39,8 +39,17 @@ function resizePolar(polar, polarModel, api) {
   polar.cy = parsePercent(center[1], height);
   var radiusAxis = polar.getRadiusAxis();
   var size = Math.min(width, height) / 2;
-  var radius = parsePercent(polarModel.get('radius'), size);
-  radiusAxis.inverse ? radiusAxis.setExtent(radius, 0) : radiusAxis.setExtent(0, radius);
+  var radius = polarModel.get('radius');
+
+  if (radius == null) {
+    radius = [0, '100%'];
+  } else if (!zrUtil.isArray(radius)) {
+    // r0 = 0
+    radius = [0, radius];
+  }
+
+  radius = [parsePercent(radius[0], size), parsePercent(radius[1], size)];
+  radiusAxis.inverse ? radiusAxis.setExtent(radius[1], radius[0]) : radiusAxis.setExtent(radius[0], radius[1]);
 }
 /**
  * Update polar
diff --git a/builder/src/echarts/coord/radar/Radar.js b/builder/src/echarts/coord/radar/Radar.js
index 187a362..749d6b8 100644
--- a/builder/src/echarts/coord/radar/Radar.js
+++ b/builder/src/echarts/coord/radar/Radar.js
@@ -23,6 +23,7 @@ import IntervalScale from '../../scale/Interval';
 import * as numberUtil from '../../util/number';
 import { getScaleExtent, niceScaleExtent } from '../axisHelper';
 import CoordinateSystem from '../../CoordinateSystem';
+import LogScale from '../../scale/Log';
 
 function Radar(radarModel, ecModel, api) {
   this._model = radarModel;
@@ -34,7 +35,7 @@ function Radar(radarModel, ecModel, api) {
   this.dimensions = [];
   this._indicatorAxes = zrUtil.map(radarModel.getIndicatorModels(), function (indicatorModel, idx) {
     var dim = 'indicator_' + idx;
-    var indicatorAxis = new IndicatorAxis(dim, new IntervalScale());
+    var indicatorAxis = new IndicatorAxis(dim, indicatorModel.get('axisType') === 'log' ? new LogScale() : new IntervalScale());
     indicatorAxis.name = indicatorModel.get('name'); // Inject model and axis
 
     indicatorAxis.model = indicatorModel;
@@ -116,7 +117,7 @@ Radar.prototype.pointToData = function (pt) {
     }
   }
 
-  return [closestAxisIdx, +(closestAxis && closestAxis.coodToData(radius))];
+  return [closestAxisIdx, +(closestAxis && closestAxis.coordToData(radius))];
 };
 
 Radar.prototype.resize = function (radarModel, api) {
diff --git a/builder/src/echarts/coord/radar/RadarModel.js b/builder/src/echarts/coord/radar/RadarModel.js
index 365a3bb..06063ca 100644
--- a/builder/src/echarts/coord/radar/RadarModel.js
+++ b/builder/src/echarts/coord/radar/RadarModel.js
@@ -37,6 +37,7 @@ var RadarModel = echarts.extendComponentModel({
     var scale = this.get('scale');
     var axisLine = this.get('axisLine');
     var axisTick = this.get('axisTick');
+    var axisType = this.get('axisType');
     var axisLabel = this.get('axisLabel');
     var nameTextStyle = this.get('name');
     var showName = this.get('name.show');
@@ -66,8 +67,9 @@ var RadarModel = echarts.extendComponentModel({
         scale: scale,
         axisLine: axisLine,
         axisTick: axisTick,
+        axisType: axisType,
         axisLabel: axisLabel,
-        // Competitable with 2 and use text
+        // Compatible with 2 and use text
         name: indicatorOpt.text,
         nameLocation: 'end',
         nameGap: nameGap,
@@ -122,6 +124,7 @@ var RadarModel = echarts.extendComponentModel({
     }, valueAxisDefault.axisLine),
     axisLabel: defaultsShow(valueAxisDefault.axisLabel, false),
     axisTick: defaultsShow(valueAxisDefault.axisTick, false),
+    axisType: 'interval',
     splitLine: defaultsShow(valueAxisDefault.splitLine, true),
     splitArea: defaultsShow(valueAxisDefault.splitArea, true),
     // {text, min, max}
diff --git a/builder/src/echarts/coord/single/AxisModel.js b/builder/src/echarts/coord/single/AxisModel.js
index 57b631c..1ed84c5 100644
--- a/builder/src/echarts/coord/single/AxisModel.js
+++ b/builder/src/echarts/coord/single/AxisModel.js
@@ -52,7 +52,7 @@ var defaultOption = {
   axisLine: {
     show: true,
     lineStyle: {
-      width: 2,
+      width: 1,
       type: 'solid'
     }
   },
@@ -66,7 +66,7 @@ var defaultOption = {
     show: true,
     length: 6,
     lineStyle: {
-      width: 2
+      width: 1
     }
   },
   axisLabel: {
diff --git a/builder/src/echarts/data/DataDiffer.js b/builder/src/echarts/data/DataDiffer.js
index 9845f1c..7927eb0 100644
--- a/builder/src/echarts/data/DataDiffer.js
+++ b/builder/src/echarts/data/DataDiffer.js
@@ -71,9 +71,7 @@ DataDiffer.prototype = {
     var newDataKeyArr = [];
     var i;
     initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter', this);
-    initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter', this); // Travel by inverted order to make sure order consistency
-    // when duplicate keys exists (consider newDataIndex.pop() below).
-    // For performance consideration, these code below do not look neat.
+    initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter', this);
 
     for (i = 0; i < oldArr.length; i++) {
       var key = oldDataKeyArr[i];
@@ -86,7 +84,7 @@ DataDiffer.prototype = {
 
         if (len) {
           len === 1 && (newDataIndexMap[key] = null);
-          idx = idx.unshift();
+          idx = idx.shift();
         } else {
           newDataIndexMap[key] = null;
         }
diff --git a/builder/src/echarts/data/DataDimensionInfo.js b/builder/src/echarts/data/DataDimensionInfo.js
new file mode 100644
index 0000000..0b96211
--- /dev/null
+++ b/builder/src/echarts/data/DataDimensionInfo.js
@@ -0,0 +1,135 @@
+/*
+* 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';
+/**
+ * @class
+ * @param {Object|DataDimensionInfo} [opt] All of the fields will be shallow copied.
+ */
+
+function DataDimensionInfo(opt) {
+  if (opt != null) {
+    zrUtil.extend(this, opt);
+  }
+  /**
+   * Dimension name.
+   * Mandatory.
+   * @type {string}
+   */
+  // this.name;
+
+  /**
+   * The origin name in dimsDef, see source helper.
+   * If displayName given, the tooltip will displayed vertically.
+   * Optional.
+   * @type {string}
+   */
+  // this.displayName;
+
+  /**
+   * Which coordSys dimension this dimension mapped to.
+   * A `coordDim` can be a "coordSysDim" that the coordSys required
+   * (for example, an item in `coordSysDims` of `model/referHelper#CoordSysInfo`),
+   * or an generated "extra coord name" if does not mapped to any "coordSysDim"
+   * (That is determined by whether `isExtraCoord` is `true`).
+   * Mandatory.
+   * @type {string}
+   */
+  // this.coordDim;
+
+  /**
+   * The index of this dimension in `series.encode[coordDim]`.
+   * Mandatory.
+   * @type {number}
+   */
+  // this.coordDimIndex;
+
+  /**
+   * Dimension type. The enumerable values are the key of
+   * `dataCtors` of `data/List`.
+   * Optional.
+   * @type {string}
+   */
+  // this.type;
+
+  /**
+   * This index of this dimension info in `data/List#_dimensionInfos`.
+   * Mandatory after added to `data/List`.
+   * @type {number}
+   */
+  // this.index;
+
+  /**
+   * The format of `otherDims` is:
+   * ```js
+   * {
+   *     tooltip: number optional,
+   *     label: number optional,
+   *     itemName: number optional,
+   *     seriesName: number optional,
+   * }
+   * ```
+   *
+   * A `series.encode` can specified these fields:
+   * ```js
+   * encode: {
+   *     // "3, 1, 5" is the index of data dimension.
+   *     tooltip: [3, 1, 5],
+   *     label: [0, 3],
+   *     ...
+   * }
+   * ```
+   * `otherDims` is the parse result of the `series.encode` above, like:
+   * ```js
+   * // Suppose the index of this data dimension is `3`.
+   * this.otherDims = {
+   *     // `3` is at the index `0` of the `encode.tooltip`
+   *     tooltip: 0,
+   *     // `3` is at the index `1` of the `encode.tooltip`
+   *     label: 1
+   * };
+   * ```
+   *
+   * This prop should never be `null`/`undefined` after initialized.
+   * @type {Object}
+   */
+
+
+  this.otherDims = {};
+  /**
+   * Be `true` if this dimension is not mapped to any "coordSysDim" that the
+   * "coordSys" required.
+   * Mandatory.
+   * @type {boolean}
+   */
+  // this.isExtraCoord;
+
+  /**
+   * @type {module:data/OrdinalMeta}
+   */
+  // this.ordinalMeta;
+
+  /**
+   * Whether to create inverted indices.
+   * @type {boolean}
+   */
+  // this.createInvertedIndices;
+}
+
+;
+export default DataDimensionInfo;
\ No newline at end of file
diff --git a/builder/src/echarts/data/Graph.js b/builder/src/echarts/data/Graph.js
index 3d63b04..87ef723 100644
--- a/builder/src/echarts/data/Graph.js
+++ b/builder/src/echarts/data/Graph.js
@@ -16,13 +16,6 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-
-/**
- * Graph data structure
- *
- * @module echarts/data/Graph
- * @author Yi Shen(https://www.github.com/pissang)
- */
 import { __DEV__ } from '../config';
 import * as zrUtil from 'zrender/src/core/util';
 import { enableClassCheck } from '../util/clazz'; // id may be function name of Object, add a prefix to avoid this problem.
@@ -104,7 +97,7 @@ graphProto.isDirected = function () {
 
 
 graphProto.addNode = function (id, dataIndex) {
-  id = id || '' + dataIndex;
+  id = id == null ? '' + dataIndex : '' + id;
   var nodesMap = this._nodesMap;
 
   if (nodesMap[generateNodeKey(id)]) {
diff --git a/builder/src/echarts/data/List.js b/builder/src/echarts/data/List.js
index 2e151b0..7778a5a 100644
--- a/builder/src/echarts/data/List.js
+++ b/builder/src/echarts/data/List.js
@@ -30,6 +30,7 @@ import DataDiffer from './DataDiffer';
 import Source from './Source';
 import { defaultDimValueGetters, DefaultDataProvider } from './helper/dataProvider';
 import { summarizeDimensions } from './helper/dimensionHelper';
+import DataDimensionInfo from './DataDimensionInfo';
 var isObject = zrUtil.isObject;
 var UNDEFINED = 'undefined';
 var INDEX_NOT_FOUND = -1; // Use prefix to avoid index to be the same as otherIdList[idx],
@@ -80,13 +81,9 @@ function transferProperties(target, source) {
  * @constructor
  * @alias module:echarts/data/List
  *
- * @param {Array.<string|Object>} dimensions
+ * @param {Array.<string|Object|module:data/DataDimensionInfo>} dimensions
  *      For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
  *      Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
- *      Spetial fields: {
- *          ordinalMeta: <module:echarts/data/OrdinalMeta>
- *          createInvertedIndices: <boolean>
- *      }
  * @param {module:echarts/model/Model} hostModel
  */
 
@@ -102,9 +99,11 @@ var List = function (dimensions, hostModel) {
     var dimensionInfo = dimensions[i];
 
     if (zrUtil.isString(dimensionInfo)) {
-      dimensionInfo = {
+      dimensionInfo = new DataDimensionInfo({
         name: dimensionInfo
-      };
+      });
+    } else if (!(dimensionInfo instanceof DataDimensionInfo)) {
+      dimensionInfo = new DataDimensionInfo(dimensionInfo);
     }
 
     var dimensionName = dimensionInfo.name;
@@ -285,6 +284,21 @@ var List = function (dimensions, hostModel) {
    */
 
   this._calculationInfo = {};
+  /**
+   * User output info of this data.
+   * DO NOT use it in other places!
+   *
+   * When preparing user params for user callbacks, we have
+   * to clone these inner data structures to prevent users
+   * from modifying them to effect built-in logic. And for
+   * performance consideration we make this `userOutput` to
+   * avoid clone them too many times.
+   *
+   * @type {Object}
+   * @readOnly
+   */
+
+  this.userOutput = this._dimensionsSummary.userOutput;
 };
 
 var listProto = List.prototype;
@@ -296,16 +310,30 @@ listProto.type = 'list';
 
 listProto.hasItemOption = true;
 /**
+ * The meanings of the input parameter `dim`:
+ *
+ * + If dim is a number (e.g., `1`), it means the index of the dimension.
+ *   For example, `getDimension(0)` will return 'x' or 'lng' or 'radius'.
+ * + If dim is a number-like string (e.g., `"1"`):
+ *     + If there is the same concrete dim name defined in `this.dimensions`, it means that concrete name.
+ *     + If not, it will be converted to a number, which means the index of the dimension.
+ *        (why? because of the backward compatbility. We have been tolerating number-like string in
+ *        dimension setting, although now it seems that it is not a good idea.)
+ *     For example, `visualMap[i].dimension: "1"` is the same meaning as `visualMap[i].dimension: 1`,
+ *     if no dimension name is defined as `"1"`.
+ * + If dim is a not-number-like string, it means the concrete dim name.
+ *   For example, it can be be default name `"x"`, `"y"`, `"z"`, `"lng"`, `"lat"`, `"angle"`, `"radius"`,
+ *   or customized in `dimensions` property of option like `"age"`.
+ *
  * Get dimension name
- * @param {string|number} dim
- *        Dimension can be concrete names like x, y, z, lng, lat, angle, radius
- *        Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
+ * @param {string|number} dim See above.
  * @return {string} Concrete dim name.
  */
 
 listProto.getDimension = function (dim) {
-  if (!isNaN(dim)) {
-    dim = this.dimensions[dim] || dim;
+  if (typeof dim === 'number' // If being a number-like string but not being defined a dimension name.
+  || !isNaN(dim) && !this._dimensionInfos.hasOwnProperty(dim)) {
+    dim = this.dimensions[dim];
   }
 
   return dim;
@@ -850,12 +878,12 @@ listProto.getValues = function (dimensions, idx
 
 listProto.hasValue = function (idx) {
   var dataDimsOnCoord = this._dimensionsSummary.dataDimsOnCoord;
-  var dimensionInfos = this._dimensionInfos;
 
   for (var i = 0, len = dataDimsOnCoord.length; i < len; i++) {
-    if ( // Ordinal type can be string or number
-    dimensionInfos[dataDimsOnCoord[i]].type !== 'ordinal' // FIXME check ordinal when using index?
-    && isNaN(this.get(dataDimsOnCoord[i], idx))) {
+    // Ordinal type originally can be string or number.
+    // But when an ordinal type is used on coord, it can
+    // not be string but only number. So we can also use isNaN.
+    if (isNaN(this.get(dataDimsOnCoord[i], idx))) {
       return false;
     }
   }
@@ -1080,12 +1108,12 @@ listProto.indexOfName = function (name) {
 
 
 listProto.indexOfRawIndex = function (rawIndex) {
-  if (!this._indices) {
-    return rawIndex;
-  }
-
   if (rawIndex >= this._rawCount || rawIndex < 0) {
     return -1;
+  }
+
+  if (!this._indices) {
+    return rawIndex;
   } // Indices are ascending
 
 
@@ -1119,7 +1147,8 @@ listProto.indexOfRawIndex = function (rawIndex) {
  * @param {string} dim
  * @param {number} value
  * @param {number} [maxDistance=Infinity]
- * @return {Array.<number>} Considere multiple points has the same value.
+ * @return {Array.<number>} If and only if multiple indices has
+ *        the same value, they are put to the result.
  */
 
 
@@ -1136,29 +1165,34 @@ listProto.indicesOfNearest = function (dim, value, maxDistance) {
     maxDistance = Infinity;
   }
 
-  var minDist = Number.MAX_VALUE;
+  var minDist = Infinity;
   var minDiff = -1;
+  var nearestIndicesLen = 0; // Check the test case of `test/ut/spec/data/List.js`.
 
   for (var i = 0, len = this.count(); i < len; i++) {
-    var diff = value - this.get(dim, i
-    /*, stack */
-    );
+    var diff = value - this.get(dim, i);
     var dist = Math.abs(diff);
 
-    if (diff <= maxDistance && dist <= minDist) {
-      // For the case of two data are same on xAxis, which has sequence data.
-      // Show the nearest index
-      // https://github.com/ecomfe/echarts/issues/2869
-      if (dist < minDist || diff >= 0 && minDiff < 0) {
+    if (dist <= maxDistance) {
+      // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`,
+      // we'd better not push both of them to `nearestIndices`, otherwise it is easy to
+      // get more than one item in `nearestIndices` (more specifically, in `tooltip`).
+      // So we chose the one that `diff >= 0` in this csae.
+      // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them
+      // should be push to `nearestIndices`.
+      if (dist < minDist || dist === minDist && diff >= 0 && minDiff < 0) {
         minDist = dist;
         minDiff = diff;
-        nearestIndices.length = 0;
+        nearestIndicesLen = 0;
       }
 
-      nearestIndices.push(i);
+      if (diff === minDiff) {
+        nearestIndices[nearestIndicesLen++] = i;
+      }
     }
   }
 
+  nearestIndices.length = nearestIndicesLen;
   return nearestIndices;
 };
 /**
diff --git a/builder/src/echarts/data/Tree.js b/builder/src/echarts/data/Tree.js
index 84d1680..867b208 100644
--- a/builder/src/echarts/data/Tree.js
+++ b/builder/src/echarts/data/Tree.js
@@ -482,7 +482,7 @@ Tree.prototype = {
  * @return module:echarts/data/Tree
  */
 
-Tree.createTree = function (dataRoot, hostModel, treeOptions) {
+Tree.createTree = function (dataRoot, hostModel, treeOptions, beforeLink) {
   var tree = new Tree(hostModel, treeOptions.levels, treeOptions.leaves);
   var listData = [];
   var dimMax = 1;
@@ -519,6 +519,7 @@ Tree.createTree = function (dataRoot, hostModel, treeOptions) {
     structAttr: 'tree'
   });
   tree.update();
+  beforeLink && beforeLink(list);
   return tree;
 };
 /**
diff --git a/builder/src/echarts/data/helper/completeDimensions.js b/builder/src/echarts/data/helper/completeDimensions.js
index cacb09e..cc385b5 100644
--- a/builder/src/echarts/data/helper/completeDimensions.js
+++ b/builder/src/echarts/data/helper/completeDimensions.js
@@ -23,14 +23,19 @@
  */
 import { createHashMap, each, isString, defaults, extend, isObject, clone } from 'zrender/src/core/util';
 import { normalizeToArray } from '../../util/model';
-import { guessOrdinal } from './sourceHelper';
+import { guessOrdinal, BE_ORDINAL } from './sourceHelper';
 import Source from '../Source';
 import { OTHER_DIMENSIONS } from './dimensionHelper';
+import DataDimensionInfo from '../DataDimensionInfo';
 /**
  * @see {module:echarts/test/ut/spec/data/completeDimensions}
  *
- * Complete the dimensions array, by user defined `dimension` and `encode`,
- * and guessing from the data structure.
+ * This method builds the relationship between:
+ * + "what the coord sys or series requires (see `sysDims`)",
+ * + "what the user defines (in `encode` and `dimensions`, see `opt.dimsDef` and `opt.encodeDef`)"
+ * + "what the data source provids (see `source`)".
+ *
+ * Some guess strategy will be adapted if user does not define something.
  * If no 'value' dimension specified, the first no-named dimension will be
  * named as 'value'.
  *
@@ -46,32 +51,20 @@ import { OTHER_DIMENSIONS } from './dimensionHelper';
  * @param {Array.<Object|string>} [opt.dimsDef] option.series.dimensions User defined dimensions
  *      For example: ['asdf', {name, type}, ...].
  * @param {Object|HashMap} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3}
+ * @param {Function} [opt.encodeDefaulter] Called if no `opt.encodeDef` exists.
+ *      If not specified, auto find the next available data dim.
+ *      param source {module:data/Source}
+ *      param dimCount {number}
+ *      return {Object} encode Never be `null/undefined`.
  * @param {string} [opt.generateCoord] Generate coord dim with the given name.
- *                 If not specified, extra dim names will be:
- *                 'value', 'value0', 'value1', ...
+ *      If not specified, extra dim names will be:
+ *      'value', 'value0', 'value1', ...
  * @param {number} [opt.generateCoordCount] By default, the generated dim name is `generateCoord`.
- *                 If `generateCoordCount` specified, the generated dim names will be:
- *                 `generateCoord` + 0, `generateCoord` + 1, ...
- *                 can be Infinity, indicate that use all of the remain columns.
+ *      If `generateCoordCount` specified, the generated dim names will be:
+ *      `generateCoord` + 0, `generateCoord` + 1, ...
+ *      can be Infinity, indicate that use all of the remain columns.
  * @param {number} [opt.dimCount] If not specified, guess by the first data item.
- * @param {number} [opt.encodeDefaulter] If not specified, auto find the next available data dim.
- * @return {Array.<Object>} [{
- *      name: string mandatory,
- *      displayName: string, the origin name in dimsDef, see source helper.
... 165926 lines suppressed ...


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