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 2021/04/12 09:23:14 UTC

[echarts] branch release-dev updated (0c1ffeb -> e6d593a)

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

sushuang pushed a change to branch release-dev
in repository https://gitbox.apache.org/repos/asf/echarts.git.


    from 0c1ffeb  release: 5.0.2
     add 2801c17  Feat: dev-fase use esbuild watch mode
     add 51aab9e  chore: use banner and footer to wrap code
     add cf89ecc  Merge pull request #14177 from susiwen8/esbuild-watch
     add 2b55862  fix(showLoading): #14188 text of loading covered by charts
     add 0b33193  Merge pull request #14191 from apache/fix-14188
     add b04772d  Update LegendModel.ts
     add 28bffa0  Merge pull request #14263 from thesiti92/patch-1
     add 03bee99  Merge pull request #14178 from apache/release-dev
     add 52b9ed5  Improve French translation
     add a44926a  Merge pull request #14283 from apache/release
     add 55384ad  fix(type): exporting more necessary types
     add 6a7ac85  Merge pull request #14289 from apache/export-types
     add 2a49feb  This code has been modified in 8c2267d45 (see #11854) and merge into next branch in dd3d83cc4, but in 58dc3f701 the merge was not correct enough (it cause the drillDownIcon displayed repeatedly in some case). So fix it according to 8c2267d45. And add the missing test case.
     add e893d90  Merge pull request #14299 from apache/fix/treemap-expand
     add 27449d3  fix(markLine): fix axis type in markLine data and close #14300
     add a302c0c  Merge pull request #14314 from apache/fix-14300
     add 1c6d63c  fix(markArea): markArea background color disappeared. close #13647
     add 8e8ed75  chore: simplify code
     add 474c759  improve: rename variable and add sort compare func
     add 8b17abb  Merge pull request #14343 from Nick22nd/fix-13647
     add f03dfad  Export union members of option types separately
     add cc8a94a  Merge pull request #14353 from twittwer/feat/export-PiecewiseVisualMapOption
     add 9e647d3  fix(dataZoom):fix dataZoom setting no effect
     add a7ce768  Merge pull request #14388 from apache/fix-14285
     add a1a3fa3  Fix(sankey): sankey label has higher z2
     add 31a6de8  Merge pull request #14417 from susiwen8/14287
     add 13f1f03  fix(series): fix series data type judgment bug. close #14293 (#14413)
     add 64c0bbe  fix file names in license (#14456)
     add cd84535  feat(i18n): added czech translation
     add 773d87e  Merge pull request #14468 from JiriBalcar/czech_translation
     add 0456847  fix(tooltip): fix time axis formatter #14470
     add b9c7e9e  feature: [tooltip] (1) Make component tooltip inherit cascade correct: itemOption.tooltip -> componentOption.tooltip -> globalOption.tooltip (previous incorrect cascade: itemOption.tooltip -> globalOption.tooltip (2) Enable trigger component tooltip by chart.dispatchAction({ type: 'showTip', legendIndex: 0, name: 'some' });
     add 91e8e47  fix: [tooltip] add test case for the last commit.
     add 35d9f60  fix: [tooltip] escape series from component finder.
     add 438f403  fix: [tooltip] keep support tooltip on graphic component.
     add 3dea90f  fix: [tooltip] (1) keep support string tooltip on each component item. (2) some tiny refactor.
     add 88d2ad7  Merge pull request #14473 from apache/fix/component-tooltip
     add a04213d  perf(tooltip): optimize the performance of tooltip.
     add 5751a30  Merge branch 'master' of https://github.com/apache/echarts into perf-tooltip
     add 15fb2a3  Merge branch 'master' of https://github.com/apache/echarts into perf-tooltip
     add 7fe6d4d  fix(tooltip): rename `ieTransform3dSupported` to be `transformSupported`.
     add ce4d237  perf(tooltip): reduce strings.
     add ae6b635  fix(tooltip): fix tooltip position may be incorrect.
     add 6904fc6  fix(tooltip): fix tooltip position issue when using transform.
     add 242c403  fix(tooltip): explicitly use import type.
     add 73a9f6e  fix(tooltip): fix code format and check if dom is supported before `testStyle`.
     add e88b99f  fix(tooltip): fix potential NPE in `toCSSVendorPrefix` function.
     add 07b074a  Merge pull request #14246 from apache/perf-tooltip
     add e3974dd  fix(custom): fix series label on custom series not working properly. close #14092
     add f3471f0  Merge pull request #14254 from Nick22nd/fix-14092
     add c152d91  fix(label): fix labels are not on the top bug.
     add 0910200  revert(sankey): revert the changes made by #14417.
     add 64aa9c5  fix(label): fix the bug that labelLine was mistakenly put into else branch and should keep z unchanged.
     add 17b2ba0  fix(label): optimize z2 calculation of label on group
     add 05ed207  fix(z): use z2 to represent overlay in treemap
     add ab5838eb fix(treemap): ensure breadcrumb is on the top
     add c3a4982  fix: remove legacy usage of transform
     add 28f01ef  Merge pull request #14357 from apache/fix-legacy-code
     add 01e2da5  1) fix: markLine `symbolOffset` doesn't work bug - Resolves #9325 - Resolves #14106 - Resolves #4771 2) feat: `markLine.symbolRotate` can be an array to specify symbol rotation at the two endpoints. - Related #12736, #12392 3) feat: add `markLine.symbolKeepAspect` and fix `symbolKeepAspect` doesn't work bug. 4) feat: `symbolOffset` can be a callback function, close #12495.
     add 93b157c  fix(markLine): remove unexpected dev code.
     add 1c1632d  fix(lint): tweak code format.
     add d5b3f71  fix(symbol): fix `symbolOffset` bug in `effectSymbol`.
     add a328e65  fix(markLine): `0` should be considered as a valid value, so use `retrieve2` instead of `||`.
     add 1fb3d89  test(markLine): add test cases for markLine symbolRotate & symbolOffset.
     add a39c4a1  Merge pull request #14375 from apache/fix/markLine-symbol
     add 1e86a5c  test(lines): add extraneous lines test case
     add 41551fa  fix: discard removed line data points
     add d80deef  Merge pull request #13638 from areo/fix-10228
     add d010376  test(line): add test case for line remove animation.
     add 6e8515a  Merge pull request #14552 from apache/add-test-for-line-extraneous
     add 1fecb51  feat(animation): add animaiton configuration in resize
     add ba3e89b  Merge pull request #14553 from apache/resize-animation
     add f28bd48  fix(Calendar): fix day label drifting. close #11508
     add 5231bbd  improve: set margin as minimal one
     add a7fe5a4  Merge pull request #13902 from Nick22nd/fix-11508
     add da7d797  fix(marker): only use maker component when exists on series
     add 4933a8e  fix(debug): enhance error log when component is missing
     add 68f2a55  test: fix ut
     add af9f776  fix(timeline): remove deprecated usage
     add ac49c2b  fix(option): optimize component missing error
     add b8c6add  test: add missing component ut. fix some warnings
     add 4719d54  chore: enable unit test checking in pull request
     add 839ae77  tweak log content when component missing
     add 78a7e00  chore: always run unit test in action
     add d0860d9  fix(marker): fix typo in marker
     add 13d75a3  chore: disable ut in action temporary
     add 09ddced  Merge pull request #14568 from apache/enhance-missing-components-log
     add 68f5c90  fix(label): fix map label won't update it's position when labelLayout is used
     add cc7001d  fix: tweak
     add 6a22cc6  fix: [geo] clean code and add comment and make interface better.
     add e9af050  fix: [geo] (1) refactor of geoJSON & SVG source loader and management. (2) remove the support of "load multiple geoJSON or SVG in one map name". This feature is never documented and published. And this feature have a inherent problem that it's not easy to normalize the unit among the different SVG. After this commit, one map name can only have one geoJSON or one SVG.
     add 6b5a0e5  fix: [geo] (1) label scale implementation change: user afterUpdate rather than / parentScale. (2) some refactor and clean code.
     add ca58174  feature: [geo] support geo svg named elements have the same behavior as regions of geoJSON
     add 30c861c  feature: [geo] (1) "geoselectchanged" event: add param: allSelected: { geoIndex: number, name: string[] }[] (2) geoSVG resource support: + label + emphasis/select/blur state + "geoselectchanged" event (on geo component) + "selectchanged" event (on map series) (3) some refactor to make those happen: + The original `Region` is migrated to `GeoJSONRegion`. And make `Region` as the base class of `GeoJSONRegion` and `GeoSVGRegion`. + Modify the constructor of `Geo`.
     add f2c35fa  fix: [geo] tweak a little.
     add 86522a1  fix: [geo] modified default item color for geoSVG and some tweak.
     add 886d041  Merge branch 'master' into fix/geo-svg
     add 152ab8e  fix: [geo] (1) fix contain point calculation. (2) remove Geo['_nameCoordMap'], instead, calculate center on demand. (3) fix that some API missing nameProperty and geoJSON should cached not only by mapName but also by nameProperty. (4) do not support nameMap in geoSVG until some real requirements come. (5) svg line polyline use 'region.lineStyle' rather than 'region.itemStyle' (6) svg text tspan image are enabled to trigger tooltip and user event (but not supported to cha [...]
     add 426f371  Merge branch 'master' into fix/geo-svg
     add c35a522  fix: [tooltip] (1) add missing test:visual (2) fix tooltip component default position: should apply `position` on option firstly.
     add c2d7873  fix: [blur] make API trigger emphasis blur correct (should leave blur firstly for other series).
     add 9c2cb8e  fix: tweak the last commit.
     add b0d4a35  feature: [geo] (1) Support component focus blur. The option `emphasis.focus` can be specified to enable this feature. `emphasis.focus` only supports the value `'self'`. The option `emphasis.focusScope` is not supported in component. That is, the focus scope can be only a single component itself. All of the elements in this component will be blurred. Added `Component['focusBlurEnabled']` to enable component blur. (2) Support component hover link when highlight with a give [...]
     add 8235095  featrue: [geo] (1) support name on <g>. (2) some refactor.
     add fc311a0  fix: geoJSON focus-blur
     add 4f47a93  fix: param validation: throw error -> console.error.
     add ad3d433  fix: [geo] fix label z on hover and simplify label code.
     add dfb58ad  fix: label should only apply the translate of this host el.
     add d8ebb5f  fix: [geo] svg fix converter and add test case.
     add fc4ca57  fix: [geo svg] fix viewBox and add test cases.
     add 43e99ef  fix: [geo svg] add test files to echarts folder.
     add 31c7787  fix: [geo svg] make test case better.
     add d56c496  fix(gauge) #14131 Pointer can not display when icon is image
     add 397a253  Merge branch 'master' into fix-14131
     add a4aad8c  Pointer can not display when icon is image
     add bf14323  gauge has decal & the symbolStyle will not be reused
     add 1a1d7c9  pointer don't have scale
     add 4e82112  Merge pull request #14165 from apache/fix-14131
     add 995637a  fix(line): ensure lineWidth is a number before addition in bolder logic, resolves #14591.
     add bfa1f26  Merge pull request #14593 from apache/fix-line-width
     add f72c9e2  Feat(effectScatter): add clip for effectScatter
     add 27c0908  Merge pull request #14574 from susiwen8/effectScatter-clip
     add cd523cd  fix(graph): no symbol when offset is not defined
     add 1320c28  Merge pull request #14600 from apache/fix-symbol
     add ca83c55  Merge branch 'master' into fix/geo-svg
     add 76625ba  test: [geo svg] add visual test.
     add 36dcf1f  test: [geo svg] add test case.
     add b059e22  Merge pull request #14571 from apache/fix/geo-svg
     add dc8f5b5  Merge branch 'master' into fix-map-label
     add f12cb62  fix(map): fix map label not display caused by merge
     add f0eb7ae  Merge pull request #14578 from apache/fix-map-label
     add e7f431a  WIP(legend): merge #12444 and current master
     add 1c93de6  feat(legend): line series default legend and customed style
     add 402f8f5  WIP(legend): reserve emptyCircle
     add bf2529e  WIP(legend): use default style in series
     add 39d4e53  WIP(legend): refactor and use fixed line width
     add 7955fd8  WIP(legend): default symbolSize as 80% itemHeight while it can also inherit
     add 3646296  WIP(legend): style when series is not selected
     add a654399  test(legend): update test cases
     add 635d986  Merge branch 'master' into fix-legend
     add aa7f802  WIP(legend): fix symbolSize
     add ef532ba  WIP(legend): fix inactive legend style
     add e95638a  WIP(legend): add more style attributes
     add 171571b  fix(legend): fix shadow default value
     add dc2282f  WIP(legend): legend icon in series policy
     add 5b10d82  WIP(legend): move default legend icon logic from series to legend
     add c06dfcf  WIP(legend): fix legendSymbol
     add 04ce156  fix(legend): fix bugs of legend style
     add 98e87ee  fix(legend): fix line and radar
     add b083c1e  fix: empty symbol lineWidth 2
     add 64f2cb6  fix(legend): fix radar legend
     add 74eec89  Merge branch 'master' into fix-legend
     add c125b4a  refactor: simplify type definition
     add da6d040  fix(legend): fix line series icon
     add 3966af8  refactor(legend): render legend in legendView when icon is defined
     add 304685d  Merge pull request #14497 from apache/fix-legend
     add 71ec194  fix(visualMap): use itemSymbol as default symbol type and fix #5719
     add fffa912  fix(visualMap): no need to filter square
     add c9e7001  refactor(visualMap): do not make assumption of child class in parent
     add a95ff6a  fix(visualMap): remove unnecessary logic
     add 98ee07d  Merge pull request #14243 from apache/feat-visualMap-itemSymbol
     add 0fdc8bf  Merge branch 'master' into fix-label-z
     add 8da6b3f  fix: not using global z in graphic component
     add 8f48ad2  Merge pull request #14542 from apache/fix-label-z
     add f69c500  Merge pull request #14606 from apache/master
     add 11eb4fc  style: remove unused imports. fix imports from entry
     add b77aecf  Merge pull request #14608 from apache/fix-linting
     add 669209d  fix(map): fix label layout may not update in map
     add 2b2d11d  fix(map): remove unnecessary code
     add d8d0ea6  Merge pull request #14609 from apache/fix-map-label
     add 5ea8147  fix: fix geo center incorrect brought by geo refactor (test case: test/map.html 'main2')
     add 710984f  fix: [geo svg] add notion for the issue of cut label.
     add 7306b7f  fix: [map labelLayout] fix hideOverlap work correct in map series.
     add f76f6f8  fix: [geo svg] fix labelLayout broken by geo refactor.
     add 68a3b73  Merge pull request #14624 from apache/fix/geo-location
     add 515fef0  fix(pie): fix NaN sector and label is still displayed.
     add 7ff75da  test(pie): add test case for switching between NaN value
     add 15a6880  Merge pull request #14630 from apache/fix-pie-display-nan
     add 1a44632  fix(bar): fix bar layout with borderWidth but no borderColor
     add f2df3ed  Merge pull request #14634 from apache/fix-bar-border-layout
     add 8060ab1  fix: (1) fix treemap upperLabel opacity incorrect. (2) enhance TS type of `getVisual`.
     add fc59953  Merge pull request #14638 from apache/fix/treemap-opacity
     add 9bbce3d  fix(sankey): make label in the front of rect, recover the change of #14417.
     add d584916  Merge pull request #14640 from apache/fix-sankey-label
     new e6d593a  release: 5.1.0

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .github/workflows/nodejs.yml                       |    16 +-
 LICENSE                                            |     9 +-
 build/dev-fast.js                                  |    69 +-
 dist/echarts.common.js                             |  3555 ++-
 dist/echarts.common.js.map                         |     2 +-
 dist/echarts.common.min.js                         |     4 +-
 dist/echarts.esm.js                                | 22770 ++++++++++---------
 dist/echarts.esm.js.map                            |     2 +-
 dist/echarts.esm.min.js                            |     4 +-
 dist/echarts.js                                    | 22770 ++++++++++---------
 dist/echarts.js.map                                |     2 +-
 dist/echarts.min.js                                |     4 +-
 dist/echarts.simple.js                             |  2749 ++-
 dist/echarts.simple.js.map                         |     2 +-
 dist/echarts.simple.min.js                         |     4 +-
 i18n/{langEN-obj.js => langCS-obj.js}              |   112 +-
 i18n/langCS.js                                     |   168 +
 i18n/langFR-obj.js                                 |    47 +-
 i18n/langFR.js                                     |    47 +-
 package-lock.json                                  |    60 +-
 package.json                                       |     8 +-
 src/chart/bar/BarView.ts                           |    13 +-
 src/chart/bar/install.ts                           |     8 -
 src/chart/boxplot/boxplotVisual.ts                 |     3 -
 src/chart/candlestick/candlestickVisual.ts         |     2 -
 src/chart/effectScatter/EffectScatterSeries.ts     |     2 +
 src/chart/effectScatter/EffectScatterView.ts       |     8 +-
 src/chart/gauge/GaugeView.ts                       |    24 +-
 src/chart/graph/GraphView.ts                       |     4 +-
 src/chart/helper/EffectSymbol.ts                   |    13 +-
 src/chart/helper/Line.ts                           |    33 +-
 src/chart/helper/Symbol.ts                         |    21 +-
 src/chart/helper/SymbolDraw.ts                     |    14 +-
 src/chart/line/LineSeries.ts                       |    49 +-
 src/chart/line/LineView.ts                         |     7 +-
 src/chart/line/install.ts                          |    16 +
 src/chart/line/lineAnimationDiff.ts                |    27 +-
 src/chart/map/MapSeries.ts                         |    34 +-
 src/chart/map/MapView.ts                           |    12 +-
 src/chart/map/mapSymbolLayout.ts                   |     4 +-
 src/chart/pie/PieView.ts                           |    10 +-
 src/chart/radar/RadarSeries.ts                     |     3 +-
 src/chart/sankey/SankeyView.ts                     |     5 +-
 src/chart/sunburst/SunburstPiece.ts                |    10 +-
 src/chart/tree/TreeSeries.ts                       |     2 +-
 src/chart/tree/TreeView.ts                         |     4 +-
 src/chart/treemap/Breadcrumb.ts                    |     3 +-
 src/chart/treemap/TreemapView.ts                   |    62 +-
 src/component/axis/AxisBuilder.ts                  |    34 +-
 src/component/brush/BrushModel.ts                  |     5 +
 src/component/calendar/CalendarView.ts             |     2 +-
 src/component/dataZoom/SliderZoomView.ts           |     5 +-
 src/component/geo/GeoView.ts                       |    17 +-
 src/component/geo/install.ts                       |    16 +-
 src/component/graphic/install.ts                   |    17 +-
 src/component/helper/MapDraw.ts                    |   744 +-
 src/component/legend/LegendModel.ts                |   141 +-
 src/component/legend/LegendView.ts                 |   340 +-
 src/component/marker/MarkAreaView.ts               |    29 +-
 src/component/marker/MarkLineModel.ts              |    11 +-
 src/component/marker/MarkLineView.ts               |    24 +-
 .../marker/checkMarkerInSeries.ts}                 |    24 +-
 src/component/marker/installMarkArea.ts            |     7 +-
 src/component/marker/installMarkLine.ts            |     7 +-
 src/component/marker/installMarkPoint.ts           |     7 +-
 src/component/radar/install.ts                     |    14 +
 src/component/timeline/SliderTimelineView.ts       |    11 +-
 src/component/toolbox/ToolboxModel.ts              |     3 +-
 src/component/toolbox/ToolboxView.ts               |    28 +-
 src/component/tooltip/TooltipHTMLContent.ts        |   175 +-
 src/component/tooltip/TooltipView.ts               |   236 +-
 src/component/tooltip/helper.ts                    |    44 +
 src/component/visualMap/PiecewiseModel.ts          |     7 +
 src/component/visualMap/VisualMapModel.ts          |    15 +-
 src/component/visualMap/VisualMapView.ts           |     4 -
 src/coord/View.ts                                  |    76 +-
 src/coord/geo/Geo.ts                               |   100 +-
 src/coord/geo/GeoJSONResource.ts                   |   171 +
 src/coord/geo/GeoModel.ts                          |    58 +-
 src/coord/geo/GeoSVGResource.ts                    |   373 +
 src/coord/geo/Region.ts                            |   112 +-
 src/coord/geo/fix/diaoyuIsland.ts                  |     6 +-
 src/coord/geo/fix/geoCoord.ts                      |    16 +-
 src/coord/geo/fix/nanhai.ts                        |     6 +-
 src/coord/geo/fix/textCoord.ts                     |    10 +-
 src/coord/geo/geoCreator.ts                        |    37 +-
 src/coord/geo/geoJSONLoader.ts                     |    99 -
 src/coord/geo/geoSVGLoader.ts                      |   153 -
 src/coord/geo/geoSourceManager.ts                  |   217 +-
 src/coord/geo/geoTypes.ts                          |    25 +
 src/coord/geo/mapDataStorage.ts                    |   158 -
 src/coord/geo/parseGeoJson.ts                      |     8 +-
 src/core/echarts.ts                                |   208 +-
 src/data/List.ts                                   |     6 +-
 src/data/OrdinalMeta.ts                            |     2 +-
 src/data/Tree.ts                                   |     3 +-
 src/echarts.ts                                     |     2 +-
 src/export/core.ts                                 |    12 +-
 src/export/option.ts                               |    27 +-
 src/i18n/langCS.ts                                 |   142 +
 src/i18n/langFR.ts                                 |    48 +-
 src/label/LabelManager.ts                          |     9 +
 src/label/labelStyle.ts                            |    13 +-
 src/loading/default.ts                             |     4 +-
 src/model/Global.ts                                |    91 +-
 src/model/Series.ts                                |    12 +-
 src/model/mixin/lineStyle.ts                       |     2 +-
 src/util/clazz.ts                                  |     2 +-
 src/util/component.ts                              |     4 +-
 src/util/format.ts                                 |     2 +-
 src/util/graphic.ts                                |    57 +-
 src/util/innerStore.ts                             |    21 +-
 src/util/model.ts                                  |    68 +-
 src/util/states.ts                                 |   186 +-
 src/util/styleCompat.ts                            |     2 +-
 src/util/symbol.ts                                 |    30 +-
 src/util/types.ts                                  |    36 +-
 src/view/Component.ts                              |    18 +-
 src/visual/commonVisualTypes.ts                    |     8 +-
 src/visual/style.ts                                |    16 +-
 src/visual/symbol.ts                               |    23 +-
 test/data/svg/Beef_cuts_France.svg                 |  1430 ++
 test/data/svg/MacOdrum-LV5-floorplan-web.svg       |  2694 +++
 test/data/svg/Map_of_Iceland.svg                   |  7211 ++++++
 .../svg/Sicily_prehellenic_topographic_map.svg     |  1303 ++
 test/data/svg/Veins_Medical_Diagram_clip_art.svg   |  1012 +
 test/data/svg/flight-seats.svg                     |  2997 +++
 test/data/svg/ksia-ext-plan-min.svg                |  3698 +++
 test/data/svg/seatmap-example.svg                  |   842 +
 test/gauge-pointer.html                            |    82 +
 test/geo-layout.html                               |   346 +
 test/geo-svg-demo.html                             |   909 +
 test/geo-svg.html                                  |   873 +
 test/hoverFocus2.html                              |    88 +
 test/label-layout.html                             |   117 +
 test/legend-style.html                             |   215 +
 test/line-extraneous.html                          |   274 +
 test/{allZero.html => line-non-continuous.html}    |    46 +-
 test/line-style.html                               |     1 +
 test/loading.html                                  |    46 +
 test/markLine-symbolRotate.html                    |     8 +-
 test/pie-animation.html                            |    76 +-
 test/radar.html                                    |    22 +-
 test/resize-animation.html                         |   117 +
 test/runTest/actions/__meta__.json                 |    11 +-
 test/runTest/actions/geo-svg-demo.json             |     1 +
 test/runTest/actions/geo-svg.json                  |     1 +
 test/runTest/actions/hoverFocus2.json              |     2 +-
 test/runTest/actions/label-layout.json             |     2 +-
 test/runTest/actions/line-extraneous.json          |     1 +
 test/runTest/actions/pie-animation.json            |     2 +-
 test/runTest/actions/resize-animation.json         |     1 +
 test/runTest/actions/tooltip-component.json        |     1 +
 test/runTest/client/index.html                     |     2 +-
 test/symbol3.html                                  |    46 +-
 test/tooltip-component.html                        |   497 +
 test/tree-legend.html                              |     9 +-
 test/treemap-action.html                           |   416 +
 test/ut/core/extendExpect.ts                       |     4 +-
 test/ut/core/utHelper.ts                           |    14 +-
 test/{runTest/runtime/shim.js => ut/index.d.ts}    |    21 +-
 test/ut/spec/component/graphic/setOption.test.ts   |     6 +-
 test/ut/spec/component/visualMap/setOption.test.ts |     8 +-
 test/ut/spec/data/dataTransform.test.ts            |    12 +-
 test/ut/spec/model/Component.test.ts               |   235 -
 test/ut/spec/model/Global.test.ts                  |    56 +-
 test/ut/spec/model/componentDependency.test.ts     |   240 +
 test/ut/spec/model/componentMissing.test.ts        |   138 +
 test/ut/spec/model/timelineMediaOptions.test.ts    |    44 +-
 test/ut/spec/scale/interval.test.ts                |    10 +-
 test/ut/spec/series/custom.test.ts                 |     2 +-
 test/visualMap-scatter-colorAndSymbol.html         |    11 +-
 172 files changed, 58640 insertions(+), 25003 deletions(-)
 copy i18n/{langEN-obj.js => langCS-obj.js} (50%)
 create mode 100644 i18n/langCS.js
 copy src/{util/vendor.ts => component/marker/checkMarkerInSeries.ts} (56%)
 create mode 100644 src/coord/geo/GeoJSONResource.ts
 create mode 100644 src/coord/geo/GeoSVGResource.ts
 delete mode 100644 src/coord/geo/geoJSONLoader.ts
 delete mode 100644 src/coord/geo/geoSVGLoader.ts
 delete mode 100644 src/coord/geo/mapDataStorage.ts
 create mode 100644 src/i18n/langCS.ts
 create mode 100644 test/data/svg/Beef_cuts_France.svg
 create mode 100644 test/data/svg/MacOdrum-LV5-floorplan-web.svg
 create mode 100644 test/data/svg/Map_of_Iceland.svg
 create mode 100644 test/data/svg/Sicily_prehellenic_topographic_map.svg
 create mode 100644 test/data/svg/Veins_Medical_Diagram_clip_art.svg
 create mode 100644 test/data/svg/flight-seats.svg
 create mode 100644 test/data/svg/ksia-ext-plan-min.svg
 create mode 100644 test/data/svg/seatmap-example.svg
 create mode 100644 test/geo-layout.html
 create mode 100644 test/geo-svg-demo.html
 create mode 100644 test/geo-svg.html
 create mode 100644 test/legend-style.html
 create mode 100644 test/line-extraneous.html
 copy test/{allZero.html => line-non-continuous.html} (66%)
 create mode 100644 test/resize-animation.html
 create mode 100644 test/runTest/actions/geo-svg-demo.json
 create mode 100644 test/runTest/actions/geo-svg.json
 create mode 100644 test/runTest/actions/line-extraneous.json
 create mode 100644 test/runTest/actions/resize-animation.json
 create mode 100644 test/runTest/actions/tooltip-component.json
 create mode 100644 test/tooltip-component.html
 create mode 100755 test/treemap-action.html
 copy test/{runTest/runtime/shim.js => ut/index.d.ts} (73%)
 delete mode 100755 test/ut/spec/model/Component.test.ts
 create mode 100755 test/ut/spec/model/componentDependency.test.ts
 create mode 100644 test/ut/spec/model/componentMissing.test.ts

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


[echarts] 01/01: release: 5.1.0

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e6d593a09b991f65dfcf4bb2120e95b6e9ea68da
Author: 100pah <su...@gmail.com>
AuthorDate: Mon Apr 12 17:22:15 2021 +0800

    release: 5.1.0
---
 dist/echarts.common.js                      |  3555 +++-
 dist/echarts.common.js.map                  |     2 +-
 dist/echarts.common.min.js                  |     4 +-
 dist/echarts.esm.js                         | 22770 ++++++++++++++------------
 dist/echarts.esm.js.map                     |     2 +-
 dist/echarts.esm.min.js                     |     4 +-
 dist/echarts.js                             | 22770 ++++++++++++++------------
 dist/echarts.js.map                         |     2 +-
 dist/echarts.min.js                         |     4 +-
 dist/echarts.simple.js                      |  2749 +++-
 dist/echarts.simple.js.map                  |     2 +-
 dist/echarts.simple.min.js                  |     4 +-
 i18n/langCS-obj.js                          |   172 +
 i18n/langCS.js                              |   168 +
 i18n/langFR-obj.js                          |    47 +-
 i18n/langFR.js                              |    47 +-
 package-lock.json                           |     8 +-
 package.json                                |     4 +-
 src/core/echarts.ts                         |     4 +-
 test/ut/index.d.ts                          |    20 +
 test/ut/spec/model/componentMissing.test.ts |    20 +
 21 files changed, 29483 insertions(+), 22875 deletions(-)

diff --git a/dist/echarts.common.js b/dist/echarts.common.js
index 2c5421e..1332c43 100644
--- a/dist/echarts.common.js
+++ b/dist/echarts.common.js
@@ -93,6 +93,8 @@
             this.touchEventsSupported = false;
             this.pointerEventsSupported = false;
             this.domSupported = false;
+            this.transformSupported = false;
+            this.transform3dSupported = false;
         }
         return Env;
     }());
@@ -143,6 +145,14 @@
         env.pointerEventsSupported = 'onpointerdown' in window
             && (browser.edge || (browser.ie && +browser.version >= 11));
         env.domSupported = typeof document !== 'undefined';
+        var style = document.documentElement.style;
+        env.transform3dSupported = ((browser.ie && 'transition' in style)
+            || browser.edge
+            || (('WebKitCSSMatrix' in window) && ('m11' in new WebKitCSSMatrix()))
+            || 'MozPerspective' in style)
+            && !('OTransition' in style);
+        env.transformSupported = env.transform3dSupported
+            || (browser.ie && +browser.version >= 9);
     }
 
     var BUILTIN_OBJECT = {
@@ -2976,7 +2986,7 @@
                             this.interpolable = false;
                         }
                     }
-                    else if (typeof value !== 'number') {
+                    else if (typeof value !== 'number' || isNaN(value)) {
                         this.interpolable = false;
                         return;
                     }
@@ -4595,6 +4605,10 @@
             extend(this.textConfig, cfg);
             this.markRedraw();
         };
+        Element.prototype.removeTextConfig = function () {
+            this.textConfig = null;
+            this.markRedraw();
+        };
         Element.prototype.removeTextContent = function () {
             var textEl = this._textContent;
             if (textEl) {
@@ -6553,7 +6567,7 @@
     function registerPainter(name, Ctor) {
         painterCtors[name] = Ctor;
     }
-    var version = '5.0.4';
+    var version = '5.1.0';
 
     var zrender = /*#__PURE__*/Object.freeze({
         __proto__: null,
@@ -7675,6 +7689,30 @@
      */
 
     function parseFinder(ecModel, finderInput, opt) {
+      var _a = preParseFinder(finderInput, opt),
+          mainTypeSpecified = _a.mainTypeSpecified,
+          queryOptionMap = _a.queryOptionMap,
+          others = _a.others;
+
+      var result = others;
+      var defaultMainType = opt ? opt.defaultMainType : null;
+
+      if (!mainTypeSpecified && defaultMainType) {
+        queryOptionMap.set(defaultMainType, {});
+      }
+
+      queryOptionMap.each(function (queryOption, mainType) {
+        var queryResult = queryReferringComponents(ecModel, mainType, queryOption, {
+          useDefault: defaultMainType === mainType,
+          enableAll: opt && opt.enableAll != null ? opt.enableAll : true,
+          enableNone: opt && opt.enableNone != null ? opt.enableNone : true
+        });
+        result[mainType + 'Models'] = queryResult.models;
+        result[mainType + 'Model'] = queryResult.models[0];
+      });
+      return result;
+    }
+    function preParseFinder(finderInput, opt) {
       var finder;
 
       if (isString(finderInput)) {
@@ -7686,12 +7724,12 @@
       }
 
       var queryOptionMap = createHashMap();
-      var result = {};
+      var others = {};
       var mainTypeSpecified = false;
       each(finder, function (value, key) {
         // Exclude 'dataIndex' and other illgal keys.
         if (key === 'dataIndex' || key === 'dataIndexInside') {
-          result[key] = value;
+          others[key] = value;
           return;
         }
 
@@ -7707,22 +7745,11 @@
         var queryOption = queryOptionMap.get(mainType) || queryOptionMap.set(mainType, {});
         queryOption[queryType] = value;
       });
-      var defaultMainType = opt ? opt.defaultMainType : null;
-
-      if (!mainTypeSpecified && defaultMainType) {
-        queryOptionMap.set(defaultMainType, {});
-      }
-
-      queryOptionMap.each(function (queryOption, mainType) {
-        var queryResult = queryReferringComponents(ecModel, mainType, queryOption, {
-          useDefault: defaultMainType === mainType,
-          enableAll: opt && opt.enableAll != null ? opt.enableAll : true,
-          enableNone: opt && opt.enableNone != null ? opt.enableNone : true
-        });
-        result[mainType + 'Models'] = queryResult.models;
-        result[mainType + 'Model'] = queryResult.models[0];
-      });
-      return result;
+      return {
+        mainTypeSpecified: mainTypeSpecified,
+        queryOptionMap: queryOptionMap,
+        others: others
+      };
     }
     var SINGLE_REFERRING = {
       useDefault: true,
@@ -8063,7 +8090,7 @@
         }
 
         if (throwWhenNotFound && !clz) {
-          throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' not exists. Load it first.');
+          throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' is used but not imported.');
         }
 
         return clz;
@@ -8537,7 +8564,7 @@
             var tokenPadding = tokenStyle.padding;
             var tokenPaddingH = tokenPadding ? tokenPadding[1] + tokenPadding[3] : 0;
             if (tokenStyle.width != null && tokenStyle.width !== 'auto') {
-                var outerWidth_1 = parsePercent$2(tokenStyle.width, wrapInfo.width) + tokenPaddingH;
+                var outerWidth_1 = parsePercent(tokenStyle.width, wrapInfo.width) + tokenPaddingH;
                 if (lines.length > 0) {
                     if (outerWidth_1 + wrapInfo.accumWidth > wrapInfo.width) {
                         strLines = str.split('\n');
@@ -8703,15 +8730,6 @@
             linesWidths: linesWidths
         };
     }
-    function parsePercent$2(value, maxValue) {
-        if (typeof value === 'string') {
-            if (value.lastIndexOf('%') >= 0) {
-                return parseFloat(value) / 100 * maxValue;
-            }
-            return parseFloat(value);
-        }
-        return value;
-    }
 
     var STYLE_MAGIC_KEY = '__zr_style_' + Math.round((Math.random() * 10));
     var DEFAULT_COMMON_STYLE = {
@@ -12197,8 +12215,7 @@
         });
       });
     }
-
-    function toggleSeriesBlurState(targetSeriesIndex, focus, blurScope, api, isBlur) {
+    function blurSeries(targetSeriesIndex, focus, blurScope, api) {
       var ecModel = api.getModel();
       blurScope = blurScope || 'coordinateSystem';
 
@@ -12209,11 +12226,6 @@
         }
       }
 
-      if (!isBlur) {
-        allLeaveBlur(api);
-        return;
-      }
-
       if (targetSeriesIndex == null) {
         return;
       }
@@ -12275,12 +12287,28 @@
         }
       });
     }
-    function toggleSeriesBlurStateFromPayload(seriesModel, payload, api) {
-      if (!isHighDownPayload(payload)) {
+    function blurComponent(componentMainType, componentIndex, api) {
+      if (componentMainType == null || componentIndex == null) {
         return;
       }
 
-      var isHighlight = payload.type === HIGHLIGHT_ACTION_TYPE;
+      var componentModel = api.getModel().getComponent(componentMainType, componentIndex);
+
+      if (!componentModel) {
+        return;
+      }
+
+      var view = api.getViewOfComponentModel(componentModel);
+
+      if (!view || !view.focusBlurEnabled) {
+        return;
+      }
+
+      view.group.traverse(function (child) {
+        singleEnterBlur(child);
+      });
+    }
+    function blurSeriesFromHighlightPayload(seriesModel, payload, api) {
       var seriesIndex = seriesModel.seriesIndex;
       var data = seriesModel.getData(payload.dataType);
       var dataIndex = queryDataIndex(data, payload); // Pick the first one if there is multiple/none exists.
@@ -12299,7 +12327,7 @@
 
       if (el) {
         var ecData = getECData(el);
-        toggleSeriesBlurState(seriesIndex, ecData.focus, ecData.blurScope, api, isHighlight);
+        blurSeries(seriesIndex, ecData.focus, ecData.blurScope, api);
       } else {
         // If there is no element put on the data. Try getting it from raw option
         // TODO Should put it on seriesModel?
@@ -12307,10 +12335,106 @@
         var blurScope = seriesModel.get(['emphasis', 'blurScope']);
 
         if (focus_1 != null) {
-          toggleSeriesBlurState(seriesIndex, focus_1, blurScope, api, isHighlight);
+          blurSeries(seriesIndex, focus_1, blurScope, api);
         }
       }
     }
+    function findComponentHighDownDispatchers(componentMainType, componentIndex, name, api) {
+      var ret = {
+        focusSelf: false,
+        dispatchers: null
+      };
+
+      if (componentMainType == null || componentMainType === 'series' || componentIndex == null || name == null) {
+        return ret;
+      }
+
+      var componentModel = api.getModel().getComponent(componentMainType, componentIndex);
+
+      if (!componentModel) {
+        return ret;
+      }
+
+      var view = api.getViewOfComponentModel(componentModel);
+
+      if (!view || !view.findHighDownDispatchers) {
+        return ret;
+      }
+
+      var dispatchers = view.findHighDownDispatchers(name); // At presnet, the component (like Geo) only blur inside itself.
+      // So we do not use `blurScope` in component.
+
+      var focusSelf;
+
+      for (var i = 0; i < dispatchers.length; i++) {
+        if ("development" !== 'production' && !isHighDownDispatcher(dispatchers[i])) {
+          error('param should be highDownDispatcher');
+        }
+
+        if (getECData(dispatchers[i]).focus === 'self') {
+          focusSelf = true;
+          break;
+        }
+      }
+
+      return {
+        focusSelf: focusSelf,
+        dispatchers: dispatchers
+      };
+    }
+    function handleGlobalMouseOverForHighDown(dispatcher, e, api) {
+      if ("development" !== 'production' && !isHighDownDispatcher(dispatcher)) {
+        error('param should be highDownDispatcher');
+      }
+
+      var ecData = getECData(dispatcher);
+
+      var _a = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api),
+          dispatchers = _a.dispatchers,
+          focusSelf = _a.focusSelf; // If `findHighDownDispatchers` is supported on the component,
+      // highlight/downplay elements with the same name.
+
+
+      if (dispatchers) {
+        if (focusSelf) {
+          blurComponent(ecData.componentMainType, ecData.componentIndex, api);
+        }
+
+        each(dispatchers, function (dispatcher) {
+          return enterEmphasisWhenMouseOver(dispatcher, e);
+        });
+      } else {
+        // Try blur all in the related series. Then emphasis the hoverred.
+        // TODO. progressive mode.
+        blurSeries(ecData.seriesIndex, ecData.focus, ecData.blurScope, api);
+
+        if (ecData.focus === 'self') {
+          blurComponent(ecData.componentMainType, ecData.componentIndex, api);
+        } // Other than series, component that not support `findHighDownDispatcher` will
+        // also use it. But in this case, highlight/downplay are only supported in
+        // mouse hover but not in dispatchAction.
+
+
+        enterEmphasisWhenMouseOver(dispatcher, e);
+      }
+    }
+    function handleGlboalMouseOutForHighDown(dispatcher, e, api) {
+      if ("development" !== 'production' && !isHighDownDispatcher(dispatcher)) {
+        error('param should be highDownDispatcher');
+      }
+
+      allLeaveBlur(api);
+      var ecData = getECData(dispatcher);
+      var dispatchers = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api).dispatchers;
+
+      if (dispatchers) {
+        each(dispatchers, function (dispatcher) {
+          return leaveEmphasisWhenMouseOut(dispatcher, e);
+        });
+      } else {
+        leaveEmphasisWhenMouseOut(dispatcher, e);
+      }
+    }
     function toggleSelectionFromPayload(seriesModel, payload, api) {
       if (!isSelectChangePayload(payload)) {
         return;
@@ -14530,10 +14654,47 @@
 
     function nearZero(val) {
       return val <= 1e-6 && val >= -1e-6;
+    }
+
+    function setTooltipConfig(opt) {
+      var itemTooltipOption = opt.itemTooltipOption;
+      var componentModel = opt.componentModel;
+      var itemName = opt.itemName;
+      var itemTooltipOptionObj = isString(itemTooltipOption) ? {
+        formatter: itemTooltipOption
+      } : itemTooltipOption;
+      var mainType = componentModel.mainType;
+      var componentIndex = componentModel.componentIndex;
+      var formatterParams = {
+        componentType: mainType,
+        name: itemName,
+        $vars: ['name']
+      };
+      formatterParams[mainType + 'Index'] = componentIndex;
+      var formatterParamsExtra = opt.formatterParamsExtra;
+
+      if (formatterParamsExtra) {
+        each(keys(formatterParamsExtra), function (key) {
+          if (!hasOwn(formatterParams, key)) {
+            formatterParams[key] = formatterParamsExtra[key];
+            formatterParams.$vars.push(key);
+          }
+        });
+      }
+
+      var ecData = getECData(opt.el);
+      ecData.componentMainType = mainType;
+      ecData.componentIndex = componentIndex;
+      ecData.tooltipConfig = {
+        name: itemName,
+        option: defaults({
+          content: itemName,
+          formatterParams: formatterParams
+        }, itemTooltipOptionObj)
+      };
     } // Register built-in shapes. These shapes might be overwirtten
     // by users, although we do not recommend that.
 
-
     registerShape('circle', Circle);
     registerShape('ellipse', Ellipse);
     registerShape('sector', Sector);
@@ -14572,6 +14733,7 @@
         createIcon: createIcon,
         linePolygonIntersect: linePolygonIntersect,
         lineLineIntersect: lineLineIntersect,
+        setTooltipConfig: setTooltipConfig,
         Group: Group,
         Image: ZRImage,
         Text: ZRText,
@@ -15433,7 +15595,7 @@
      * Topological travel on Activity Network (Activity On Vertices).
      * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis'].
      * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology.
-     * If there is circle dependencey, Error will be thrown.
+     * If there is circular dependencey, Error will be thrown.
      */
 
     function enableTopologicalTravel(entity, dependencyGetter) {
@@ -15474,7 +15636,7 @@
           var errMsg = '';
 
           if ("development" !== 'production') {
-            errMsg = makePrintable('Circle dependency may exists: ', targetNameSet, targetNameList, fullNameList);
+            errMsg = makePrintable('Circular dependency may exists: ', targetNameSet, targetNameList, fullNameList);
           }
 
           throw new Error(errMsg);
@@ -16216,7 +16378,7 @@
      */
 
     function makeValueReadable(value, valueType, useUTC) {
-      var USER_READABLE_DEFUALT_TIME_PATTERN = 'yyyy-MM-dd hh:mm:ss';
+      var USER_READABLE_DEFUALT_TIME_PATTERN = '{yyyy}-{MM}-{dd} {hh}:{mm}:{ss}';
 
       function stringToUserReadable(str) {
         return str && trim(str) ? str : '-';
@@ -17620,6 +17782,59 @@
     var initBase;
     var OPTION_INNER_KEY = '\0_ec_inner';
     var OPTION_INNER_VALUE = 1;
+    var BUITIN_COMPONENTS_MAP = {
+      grid: 'GridComponent',
+      polar: 'PolarComponent',
+      geo: 'GeoComponent',
+      singleAxis: 'SingleAxisComponent',
+      parallel: 'ParallelComponent',
+      calendar: 'CalendarComponent',
+      graphic: 'GraphicComponent',
+      toolbox: 'ToolboxComponent',
+      tooltip: 'TooltipComponent',
+      axisPointer: 'AxisPointerComponent',
+      brush: 'BrushComponent',
+      title: 'TitleComponent',
+      timeline: 'TimelineComponent',
+      markPoint: 'MarkPointComponent',
+      markLine: 'MarkLineComponent',
+      markArea: 'MarkAreaComponent',
+      legend: 'LegendComponent',
+      dataZoom: 'DataZoomComponent',
+      visualMap: 'VisualMapComponent',
+      // aria: 'AriaComponent',
+      // dataset: 'DatasetComponent',
+      // Dependencies
+      xAxis: 'GridComponent',
+      yAxis: 'GridComponent',
+      angleAxis: 'PolarComponent',
+      radiusAxis: 'PolarComponent'
+    };
+    var BUILTIN_CHARTS_MAP = {
+      line: 'LineChart',
+      bar: 'BarChart',
+      pie: 'PieChart',
+      scatter: 'ScatterChart',
+      radar: 'RadarChart',
+      map: 'MapChart',
+      tree: 'TreeChart',
+      treemap: 'TreemapChart',
+      graph: 'GraphChart',
+      gauge: 'GaugeChart',
+      funnel: 'FunnelChart',
+      parallel: 'ParallelChart',
+      sankey: 'SankeyChart',
+      boxplot: 'BoxplotChart',
+      candlestick: 'CandlestickChart',
+      effectScatter: 'EffectScatterChart',
+      lines: 'LinesChart',
+      heatmap: 'HeatmapChart',
+      pictorialBar: 'PictorialBarChart',
+      themeRiver: 'ThemeRiverChart',
+      sunburst: 'SunburstChart',
+      custom: 'CustomChart'
+    };
+    var componetsMissingLogPrinted = {};
 
     var GlobalModel =
     /** @class */
@@ -17739,7 +17954,16 @@
           }
 
           if (!ComponentModel.hasClass(mainType)) {
-            // globalSettingTask.dirty();
+            if ("development" !== 'production') {
+              var componentImportName = BUITIN_COMPONENTS_MAP[mainType];
+
+              if (componentImportName && !componetsMissingLogPrinted[componentImportName]) {
+                error("Component " + mainType + " is used but not imported.\nimport { " + componentImportName + " } from 'echarts/components';\necharts.use([" + componentImportName + "]);");
+                componetsMissingLogPrinted[componentImportName] = true;
+              }
+            } // globalSettingTask.dirty();
+
+
             option[mainType] = option[mainType] == null ? clone(componentOption) : merge(option[mainType], componentOption, true);
           } else if (mainType) {
             newCmptTypes.push(mainType);
@@ -17795,7 +18019,28 @@
               // or it has been removed in previous `replaceMerge` and left a "hole" in this component index.
 
             } else {
-              var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, true);
+              var isSeriesType = mainType === 'series';
+              var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, !isSeriesType // Give a more detailed warn later if series don't exists
+              );
+
+              if (!ComponentModelClass) {
+                if ("development" !== 'production') {
+                  var subType = resultItem.keyInfo.subType;
+                  var seriesImportName = BUILTIN_CHARTS_MAP[subType];
+
+                  if (!componetsMissingLogPrinted[subType]) {
+                    componetsMissingLogPrinted[subType] = true;
+
+                    if (seriesImportName) {
+                      error("Series " + subType + " is used but not imported.\nimport { " + seriesImportName + " } from 'echarts/charts';\necharts.use([" + seriesImportName + "]);");
+                    } else {
+                      error("Unkown series " + subType);
+                    }
+                  }
+                }
+
+                return;
+              }
 
               if (componentModel && componentModel.constructor === ComponentModelClass) {
                 componentModel.name = resultItem.keyInfo.name; // componentModel.settingTask && componentModel.settingTask.dirty();
@@ -22290,7 +22535,7 @@
           data.each(function (idx) {
             var rawItem = data.getRawDataItem(idx);
 
-            if (typeof rawItem === 'object' && rawItem.selected) {
+            if (rawItem && rawItem.selected) {
               dataIndices.push(idx);
             }
           });
@@ -22856,15 +23101,23 @@
         var colorKey = getDefaultColorKey(seriesModel, stylePath);
         var color = globalStyle[colorKey]; // TODO style callback
 
-        var colorCallback = isFunction(color) ? color : null; // Get from color palette by default.
+        var colorCallback = isFunction(color) ? color : null;
+        var hasAutoColor = globalStyle.fill === 'auto' || globalStyle.stroke === 'auto'; // Get from color palette by default.
 
-        if (!globalStyle[colorKey] || colorCallback) {
+        if (!globalStyle[colorKey] || colorCallback || hasAutoColor) {
           // Note: if some series has color specified (e.g., by itemStyle.color), we DO NOT
           // make it effect palette. Bacause some scenarios users need to make some series
           // transparent or as background, which should better not effect the palette.
-          globalStyle[colorKey] = seriesModel.getColorFromPalette( // TODO series count changed.
+          var colorPalette = seriesModel.getColorFromPalette( // TODO series count changed.
           seriesModel.name, null, ecModel.getSeriesCount());
-          data.setVisual('colorFromPalette', true);
+
+          if (!globalStyle[colorKey]) {
+            globalStyle[colorKey] = colorPalette;
+            data.setVisual('colorFromPalette', true);
+          }
+
+          globalStyle.fill = globalStyle.fill === 'auto' || typeof globalStyle.fill === 'function' ? colorPalette : globalStyle.fill;
+          globalStyle.stroke = globalStyle.stroke === 'auto' || typeof globalStyle.stroke === 'function' ? colorPalette : globalStyle.stroke;
         }
 
         data.setVisual('style', globalStyle);
@@ -23021,7 +23274,9 @@
           fontWeight: opts.fontWeight,
           fontStyle: opts.fontStyle,
           fontFamily: opts.fontFamily
-        }
+        },
+        zlevel: opts.zlevel,
+        z: 10001
       });
       var labelRect = new Rect({
         style: {
@@ -23868,108 +24123,6 @@
     };
     theme.categoryAxis.splitLine.show = false;
 
-    function parseXML(svg) {
-        if (isString(svg)) {
-            var parser = new DOMParser();
-            svg = parser.parseFromString(svg, 'text/xml');
-        }
-        var svgNode = svg;
-        if (svgNode.nodeType === 9) {
-            svgNode = svgNode.firstChild;
-        }
-        while (svgNode.nodeName.toLowerCase() !== 'svg' || svgNode.nodeType !== 1) {
-            svgNode = svgNode.nextSibling;
-        }
-        return svgNode;
-    }
-
-    var storage = createHashMap();
-    var mapDataStorage = {
-      /**
-       * Compatible with previous `echarts.registerMap`.
-       * @usage
-       * ```js
-       * $.get('USA.json', function (geoJson) {
-       *     echarts.registerMap('USA', geoJson);
-       *     // Or
-       *     echarts.registerMap('USA', {
-       *         geoJson: geoJson,
-       *         specialAreas: {}
-       *     })
-       * });
-       *
-       * $.get('airport.svg', function (svg) {
-       *     echarts.registerMap('airport', {
-       *         svg: svg
-       *     }
-       * });
-       *
-       * echarts.registerMap('eu', [
-       *     {svg: eu-topographic.svg},
-       *     {geoJSON: eu.json}
-       * ])
-       * ```
-       */
-      registerMap: function (mapName, rawDef, rawSpecialAreas) {
-        var records;
-
-        if (isArray(rawDef)) {
-          records = rawDef;
-        } else if (rawDef.svg) {
-          records = [{
-            type: 'svg',
-            source: rawDef.svg,
-            specialAreas: rawDef.specialAreas
-          }];
-        } else {
-          // Backward compatibility.
-          var geoSource = rawDef.geoJson || rawDef.geoJSON;
-
-          if (geoSource && !rawDef.features) {
-            rawSpecialAreas = rawDef.specialAreas;
-            rawDef = geoSource;
-          }
-
-          records = [{
-            type: 'geoJSON',
-            source: rawDef,
-            specialAreas: rawSpecialAreas
-          }];
-        }
-
-        each(records, function (record) {
-          var type = record.type;
-          type === 'geoJson' && (type = record.type = 'geoJSON');
-          var parse = parsers[type];
-
-          if ("development" !== 'production') {
-            assert(parse, 'Illegal map type: ' + type);
-          }
-
-          parse(record);
-        });
-        return storage.set(mapName, records);
-      },
-      retrieveMap: function (mapName) {
-        return storage.get(mapName);
-      }
-    };
-    var parsers = {
-      geoJSON: function (record) {
-        var source = record.source;
-        record.geoJSON = !isString(source) ? source : typeof JSON !== 'undefined' && JSON.parse ? JSON.parse(source) : new Function('return (' + source + ');')();
-      },
-      // Only perform parse to XML object here, which might be time
-      // consiming for large SVG.
-      // Although convert XML to zrender element is also time consiming,
-      // if we do it here, the clone of zrender elements has to be
-      // required. So we do it once for each geo instance, util real
-      // performance issues call for optimizing it.
-      svg: function (record) {
-        record.svgXML = parseXML(record.source);
-      }
-    };
-
     /**
      * Usage of query:
      * `chart.on('click', query, handler);`
@@ -24102,13 +24255,16 @@
         var symbolSize = seriesModel.get('symbolSize');
         var keepAspect = seriesModel.get('symbolKeepAspect');
         var symbolRotate = seriesModel.get('symbolRotate');
+        var symbolOffset = seriesModel.get('symbolOffset');
         var hasSymbolTypeCallback = isFunction(symbolType);
         var hasSymbolSizeCallback = isFunction(symbolSize);
         var hasSymbolRotateCallback = isFunction(symbolRotate);
-        var hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback || hasSymbolRotateCallback;
+        var hasSymbolOffsetCallback = isFunction(symbolOffset);
+        var hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback || hasSymbolRotateCallback || hasSymbolOffsetCallback;
         var seriesSymbol = !hasSymbolTypeCallback && symbolType ? symbolType : seriesModel.defaultSymbol;
         var seriesSymbolSize = !hasSymbolSizeCallback ? symbolSize : null;
         var seriesSymbolRotate = !hasSymbolRotateCallback ? symbolRotate : null;
+        var seriesSymbolOffset = !hasSymbolOffsetCallback ? symbolOffset : null;
         data.setVisual({
           legendSymbol: seriesModel.legendSymbol || seriesSymbol,
           // If seting callback functions on `symbol` or `symbolSize`, for simplicity and avoiding
@@ -24118,7 +24274,8 @@
           symbol: seriesSymbol,
           symbolSize: seriesSymbolSize,
           symbolKeepAspect: keepAspect,
-          symbolRotate: seriesSymbolRotate
+          symbolRotate: seriesSymbolRotate,
+          symbolOffset: seriesSymbolOffset
         }); // Only visible series has each data be visual encoded
 
         if (ecModel.isSeriesFiltered(seriesModel)) {
@@ -24131,6 +24288,7 @@
           hasSymbolTypeCallback && data.setItemVisual(idx, 'symbol', symbolType(rawValue, params));
           hasSymbolSizeCallback && data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params));
           hasSymbolRotateCallback && data.setItemVisual(idx, 'symbolRotate', symbolRotate(rawValue, params));
+          hasSymbolOffsetCallback && data.setItemVisual(idx, 'symbolOffset', symbolOffset(rawValue, params));
         }
 
         return {
@@ -24159,6 +24317,7 @@
           var itemSymbolType = itemModel.getShallow('symbol', true);
           var itemSymbolSize = itemModel.getShallow('symbolSize', true);
           var itemSymbolRotate = itemModel.getShallow('symbolRotate', true);
+          var itemSymbolOffset = itemModel.getShallow('symbolOffset', true);
           var itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true); // If has item symbol
 
           if (itemSymbolType != null) {
@@ -24174,6 +24333,10 @@
             data.setItemVisual(idx, 'symbolRotate', itemSymbolRotate);
           }
 
+          if (itemSymbolOffset != null) {
+            data.setItemVisual(idx, 'symbolOffset', itemSymbolOffset);
+          }
+
           if (itemSymbolKeepAspect != null) {
             data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect);
           }
@@ -25257,6 +25420,8 @@
             labelGuideIgnore: labelGuide && labelGuide.ignore,
             x: dummyTransformable.x,
             y: dummyTransformable.y,
+            scaleX: dummyTransformable.scaleX,
+            scaleY: dummyTransformable.scaleY,
             rotation: dummyTransformable.rotation,
             style: {
               x: labelStyle.x,
@@ -25329,7 +25494,8 @@
 
           layoutOption = layoutOption || {};
           labelItem.computedLayoutOption = layoutOption;
-          var degreeToRadian = Math.PI / 180;
+          var degreeToRadian = Math.PI / 180; // TODO hostEl should always exists.
+          // Or label should not have parent because the x, y is all in global space.
 
           if (hostEl) {
             hostEl.setTextConfig({
@@ -25382,6 +25548,8 @@
           var labelLayoutStore = labelLayoutInnerStore(label);
           labelLayoutStore.needsUpdateLabelLine = needsUpdateLabelLine;
           label.rotation = layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation;
+          label.scaleX = defaultLabelAttr.scaleX;
+          label.scaleY = defaultLabelAttr.scaleY;
 
           for (var k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) {
             var key = LABEL_OPTION_TO_STYLE_KEYS[k];
@@ -25878,9 +26046,7 @@
     // TODO Use function to build symbol path.
 
     var symbolCtors = {
-      // Use small height rect to simulate line.
-      // Avoid using stroke.
-      line: Rect,
+      line: Line,
       rect: Rect,
       roundRect: Rect,
       square: Rect,
@@ -25889,16 +26055,13 @@
       pin: Pin,
       arrow: Arrow,
       triangle: Triangle
-    }; // NOTICE Only use fill. No line!
-
+    };
     var symbolShapeMakers = {
       line: function (x, y, w, h, shape) {
-        var thickness = 2; // A thin line
-
-        shape.x = x;
-        shape.y = y + h / 2 - thickness / 2;
-        shape.width = w;
-        shape.height = thickness;
+        shape.x1 = x;
+        shape.y1 = y + h / 2;
+        shape.x2 = x + w;
+        shape.y2 = y + h / 2;
       },
       rect: function (x, y, w, h, shape) {
         shape.x = x;
@@ -25998,9 +26161,11 @@
 
         if (this.__isEmptyBrush) {
           symbolStyle.stroke = color;
-          symbolStyle.fill = innerColor || '#fff'; // TODO Same width with lineStyle in LineView.
+          symbolStyle.fill = innerColor || '#fff'; // TODO Same width with lineStyle in LineView
 
           symbolStyle.lineWidth = 2;
+        } else if (this.shape.symbolType === 'line') {
+          symbolStyle.stroke = color;
         } else {
           symbolStyle.fill = color;
         }
@@ -26157,7 +26322,8 @@
         var image = createOrUpdateImage(pattern.image, pattern.__image, el);
         if (isImageReady(image)) {
             var canvasPattern = ctx.createPattern(image, pattern.repeat || 'repeat');
-            if (typeof DOMMatrix === 'function') {
+            if (typeof DOMMatrix === 'function'
+                && canvasPattern.setTransform) {
                 var matrix = new DOMMatrix();
                 matrix.rotateSelf(0, 0, (pattern.rotation || 0) / Math.PI * 180);
                 matrix.scaleSelf((pattern.scaleX || 1), (pattern.scaleY || 1));
@@ -26400,7 +26566,8 @@
                 flushPathDrawn(ctx, scope);
                 styleChanged = true;
             }
-            ctx.globalAlpha = style.opacity == null ? DEFAULT_COMMON_STYLE.opacity : style.opacity;
+            var opacity = Math.max(Math.min(style.opacity, 1), 0);
+            ctx.globalAlpha = isNaN(opacity) ? DEFAULT_COMMON_STYLE.opacity : opacity;
         }
         if (forceSetAll || style.blend !== prevStyle.blend) {
             if (!styleChanged) {
@@ -27124,15 +27291,1704 @@
       });
     }
 
+    function parseXML(svg) {
+        if (isString(svg)) {
+            var parser = new DOMParser();
+            svg = parser.parseFromString(svg, 'text/xml');
+        }
+        var svgNode = svg;
+        if (svgNode.nodeType === 9) {
+            svgNode = svgNode.firstChild;
+        }
+        while (svgNode.nodeName.toLowerCase() !== 'svg' || svgNode.nodeType !== 1) {
+            svgNode = svgNode.nextSibling;
+        }
+        return svgNode;
+    }
+
+    var nodeParsers;
+    var INHERITABLE_STYLE_ATTRIBUTES_MAP = {
+        'fill': 'fill',
+        'stroke': 'stroke',
+        'stroke-width': 'lineWidth',
+        'opacity': 'opacity',
+        'fill-opacity': 'fillOpacity',
+        'stroke-opacity': 'strokeOpacity',
+        'stroke-dasharray': 'lineDash',
+        'stroke-dashoffset': 'lineDashOffset',
+        'stroke-linecap': 'lineCap',
+        'stroke-linejoin': 'lineJoin',
+        'stroke-miterlimit': 'miterLimit',
+        'font-family': 'fontFamily',
+        'font-size': 'fontSize',
+        'font-style': 'fontStyle',
+        'font-weight': 'fontWeight',
+        'text-anchor': 'textAlign',
+        'visibility': 'visibility',
+        'display': 'display'
+    };
+    var INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS = keys(INHERITABLE_STYLE_ATTRIBUTES_MAP);
+    var SELF_STYLE_ATTRIBUTES_MAP = {
+        'alignment-baseline': 'textBaseline',
+        'stop-color': 'stopColor'
+    };
+    var SELF_STYLE_ATTRIBUTES_MAP_KEYS = keys(SELF_STYLE_ATTRIBUTES_MAP);
+    var SVGParser = (function () {
+        function SVGParser() {
+            this._defs = {};
+            this._root = null;
+        }
+        SVGParser.prototype.parse = function (xml, opt) {
+            opt = opt || {};
+            var svg = parseXML(xml);
+            if (!svg) {
+                throw new Error('Illegal svg');
+            }
+            this._defsUsePending = [];
+            var root = new Group();
+            this._root = root;
+            var named = [];
+            var viewBox = svg.getAttribute('viewBox') || '';
+            var width = parseFloat((svg.getAttribute('width') || opt.width));
+            var height = parseFloat((svg.getAttribute('height') || opt.height));
+            isNaN(width) && (width = null);
+            isNaN(height) && (height = null);
+            parseAttributes(svg, root, null, true, false);
+            var child = svg.firstChild;
+            while (child) {
+                this._parseNode(child, root, named, null, false, false);
+                child = child.nextSibling;
+            }
+            applyDefs(this._defs, this._defsUsePending);
+            this._defsUsePending = [];
+            var viewBoxRect;
+            var viewBoxTransform;
+            if (viewBox) {
+                var viewBoxArr = splitNumberSequence(viewBox);
+                if (viewBoxArr.length >= 4) {
+                    viewBoxRect = {
+                        x: parseFloat((viewBoxArr[0] || 0)),
+                        y: parseFloat((viewBoxArr[1] || 0)),
+                        width: parseFloat(viewBoxArr[2]),
+                        height: parseFloat(viewBoxArr[3])
+                    };
+                }
+            }
+            if (viewBoxRect && width != null && height != null) {
+                viewBoxTransform = makeViewBoxTransform(viewBoxRect, { x: 0, y: 0, width: width, height: height });
+                if (!opt.ignoreViewBox) {
+                    var elRoot = root;
+                    root = new Group();
+                    root.add(elRoot);
+                    elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale;
+                    elRoot.x = viewBoxTransform.x;
+                    elRoot.y = viewBoxTransform.y;
+                }
+            }
+            if (!opt.ignoreRootClip && width != null && height != null) {
+                root.setClipPath(new Rect({
+                    shape: { x: 0, y: 0, width: width, height: height }
+                }));
+            }
+            return {
+                root: root,
+                width: width,
+                height: height,
+                viewBoxRect: viewBoxRect,
+                viewBoxTransform: viewBoxTransform,
+                named: named
+            };
+        };
+        SVGParser.prototype._parseNode = function (xmlNode, parentGroup, named, namedFrom, isInDefs, isInText) {
+            var nodeName = xmlNode.nodeName.toLowerCase();
+            var el;
+            var namedFromForSub = namedFrom;
+            if (nodeName === 'defs') {
+                isInDefs = true;
+            }
+            if (nodeName === 'text') {
+                isInText = true;
+            }
+            if (nodeName === 'defs' || nodeName === 'switch') {
+                el = parentGroup;
+            }
+            else {
+                if (!isInDefs) {
+                    var parser_1 = nodeParsers[nodeName];
+                    if (parser_1 && hasOwn(nodeParsers, nodeName)) {
+                        el = parser_1.call(this, xmlNode, parentGroup);
+                        var nameAttr = xmlNode.getAttribute('name');
+                        if (nameAttr) {
+                            var newNamed = {
+                                name: nameAttr,
+                                namedFrom: null,
+                                svgNodeTagLower: nodeName,
+                                el: el
+                            };
+                            named.push(newNamed);
+                            if (nodeName === 'g') {
+                                namedFromForSub = newNamed;
+                            }
+                        }
+                        else if (namedFrom) {
+                            named.push({
+                                name: namedFrom.name,
+                                namedFrom: namedFrom,
+                                svgNodeTagLower: nodeName,
+                                el: el
+                            });
+                        }
+                        parentGroup.add(el);
+                    }
+                }
+                var parser = paintServerParsers[nodeName];
+                if (parser && hasOwn(paintServerParsers, nodeName)) {
+                    var def = parser.call(this, xmlNode);
+                    var id = xmlNode.getAttribute('id');
+                    if (id) {
+                        this._defs[id] = def;
+                    }
+                }
+            }
+            if (el && el.isGroup) {
+                var child = xmlNode.firstChild;
+                while (child) {
+                    if (child.nodeType === 1) {
+                        this._parseNode(child, el, named, namedFromForSub, isInDefs, isInText);
+                    }
+                    else if (child.nodeType === 3 && isInText) {
+                        this._parseText(child, el);
+                    }
+                    child = child.nextSibling;
+                }
+            }
+        };
+        SVGParser.prototype._parseText = function (xmlNode, parentGroup) {
+            var text = new TSpan({
+                style: {
+                    text: xmlNode.textContent
+                },
+                silent: true,
+                x: this._textX || 0,
+                y: this._textY || 0
+            });
+            inheritStyle(parentGroup, text);
+            parseAttributes(xmlNode, text, this._defsUsePending, false, false);
+            applyTextAlignment(text, parentGroup);
+            var textStyle = text.style;
+            var fontSize = textStyle.fontSize;
+            if (fontSize && fontSize < 9) {
+                textStyle.fontSize = 9;
+                text.scaleX *= fontSize / 9;
+                text.scaleY *= fontSize / 9;
+            }
+            var font = (textStyle.fontSize || textStyle.fontFamily) && [
+                textStyle.fontStyle,
+                textStyle.fontWeight,
+                (textStyle.fontSize || 12) + 'px',
+                textStyle.fontFamily || 'sans-serif'
+            ].join(' ');
+            textStyle.font = font;
+            var rect = text.getBoundingRect();
+            this._textX += rect.width;
+            parentGroup.add(text);
+            return text;
+        };
+        SVGParser.internalField = (function () {
+            nodeParsers = {
+                'g': function (xmlNode, parentGroup) {
+                    var g = new Group();
+                    inheritStyle(parentGroup, g);
+                    parseAttributes(xmlNode, g, this._defsUsePending, false, false);
+                    return g;
+                },
+                'rect': function (xmlNode, parentGroup) {
+                    var rect = new Rect();
+                    inheritStyle(parentGroup, rect);
+                    parseAttributes(xmlNode, rect, this._defsUsePending, false, false);
+                    rect.setShape({
+                        x: parseFloat(xmlNode.getAttribute('x') || '0'),
+                        y: parseFloat(xmlNode.getAttribute('y') || '0'),
+                        width: parseFloat(xmlNode.getAttribute('width') || '0'),
+                        height: parseFloat(xmlNode.getAttribute('height') || '0')
+                    });
+                    rect.silent = true;
+                    return rect;
+                },
+                'circle': function (xmlNode, parentGroup) {
+                    var circle = new Circle();
+                    inheritStyle(parentGroup, circle);
+                    parseAttributes(xmlNode, circle, this._defsUsePending, false, false);
+                    circle.setShape({
+                        cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
+                        cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
+                        r: parseFloat(xmlNode.getAttribute('r') || '0')
+                    });
+                    circle.silent = true;
+                    return circle;
+                },
+                'line': function (xmlNode, parentGroup) {
+                    var line = new Line();
+                    inheritStyle(parentGroup, line);
+                    parseAttributes(xmlNode, line, this._defsUsePending, false, false);
+                    line.setShape({
+                        x1: parseFloat(xmlNode.getAttribute('x1') || '0'),
+                        y1: parseFloat(xmlNode.getAttribute('y1') || '0'),
+                        x2: parseFloat(xmlNode.getAttribute('x2') || '0'),
+                        y2: parseFloat(xmlNode.getAttribute('y2') || '0')
+                    });
+                    line.silent = true;
+                    return line;
+                },
+                'ellipse': function (xmlNode, parentGroup) {
+                    var ellipse = new Ellipse();
+                    inheritStyle(parentGroup, ellipse);
+                    parseAttributes(xmlNode, ellipse, this._defsUsePending, false, false);
+                    ellipse.setShape({
+                        cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
+                        cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
+                        rx: parseFloat(xmlNode.getAttribute('rx') || '0'),
+                        ry: parseFloat(xmlNode.getAttribute('ry') || '0')
+                    });
+                    ellipse.silent = true;
+                    return ellipse;
+                },
+                'polygon': function (xmlNode, parentGroup) {
+                    var pointsStr = xmlNode.getAttribute('points');
+                    var pointsArr;
+                    if (pointsStr) {
+                        pointsArr = parsePoints(pointsStr);
+                    }
+                    var polygon = new Polygon({
+                        shape: {
+                            points: pointsArr || []
+                        },
+                        silent: true
+                    });
+                    inheritStyle(parentGroup, polygon);
+                    parseAttributes(xmlNode, polygon, this._defsUsePending, false, false);
+                    return polygon;
+                },
+                'polyline': function (xmlNode, parentGroup) {
+                    var pointsStr = xmlNode.getAttribute('points');
+                    var pointsArr;
+                    if (pointsStr) {
+                        pointsArr = parsePoints(pointsStr);
+                    }
+                    var polyline = new Polyline({
+                        shape: {
+                            points: pointsArr || []
+                        },
+                        silent: true
+                    });
+                    inheritStyle(parentGroup, polyline);
+                    parseAttributes(xmlNode, polyline, this._defsUsePending, false, false);
+                    return polyline;
+                },
+                'image': function (xmlNode, parentGroup) {
+                    var img = new ZRImage();
+                    inheritStyle(parentGroup, img);
+                    parseAttributes(xmlNode, img, this._defsUsePending, false, false);
+                    img.setStyle({
+                        image: xmlNode.getAttribute('xlink:href'),
+                        x: +xmlNode.getAttribute('x'),
+                        y: +xmlNode.getAttribute('y'),
+                        width: +xmlNode.getAttribute('width'),
+                        height: +xmlNode.getAttribute('height')
+                    });
+                    img.silent = true;
+                    return img;
+                },
+                'text': function (xmlNode, parentGroup) {
+                    var x = xmlNode.getAttribute('x') || '0';
+                    var y = xmlNode.getAttribute('y') || '0';
+                    var dx = xmlNode.getAttribute('dx') || '0';
+                    var dy = xmlNode.getAttribute('dy') || '0';
+                    this._textX = parseFloat(x) + parseFloat(dx);
+                    this._textY = parseFloat(y) + parseFloat(dy);
+                    var g = new Group();
+                    inheritStyle(parentGroup, g);
+                    parseAttributes(xmlNode, g, this._defsUsePending, false, true);
+                    return g;
+                },
+                'tspan': function (xmlNode, parentGroup) {
+                    var x = xmlNode.getAttribute('x');
+                    var y = xmlNode.getAttribute('y');
+                    if (x != null) {
+                        this._textX = parseFloat(x);
+                    }
+                    if (y != null) {
+                        this._textY = parseFloat(y);
+                    }
+                    var dx = xmlNode.getAttribute('dx') || '0';
+                    var dy = xmlNode.getAttribute('dy') || '0';
+                    var g = new Group();
+                    inheritStyle(parentGroup, g);
+                    parseAttributes(xmlNode, g, this._defsUsePending, false, true);
+                    this._textX += parseFloat(dx);
+                    this._textY += parseFloat(dy);
+                    return g;
+                },
+                'path': function (xmlNode, parentGroup) {
+                    var d = xmlNode.getAttribute('d') || '';
+                    var path = createFromString(d);
+                    inheritStyle(parentGroup, path);
+                    parseAttributes(xmlNode, path, this._defsUsePending, false, false);
+                    path.silent = true;
+                    return path;
+                }
+            };
+        })();
+        return SVGParser;
+    }());
+    var paintServerParsers = {
+        'lineargradient': function (xmlNode) {
+            var x1 = parseInt(xmlNode.getAttribute('x1') || '0', 10);
+            var y1 = parseInt(xmlNode.getAttribute('y1') || '0', 10);
+            var x2 = parseInt(xmlNode.getAttribute('x2') || '10', 10);
+            var y2 = parseInt(xmlNode.getAttribute('y2') || '0', 10);
+            var gradient = new LinearGradient(x1, y1, x2, y2);
+            parsePaintServerUnit(xmlNode, gradient);
+            parseGradientColorStops(xmlNode, gradient);
+            return gradient;
+        },
+        'radialgradient': function (xmlNode) {
+            var cx = parseInt(xmlNode.getAttribute('cx') || '0', 10);
+            var cy = parseInt(xmlNode.getAttribute('cy') || '0', 10);
+            var r = parseInt(xmlNode.getAttribute('r') || '0', 10);
+            var gradient = new RadialGradient(cx, cy, r);
+            parsePaintServerUnit(xmlNode, gradient);
+            parseGradientColorStops(xmlNode, gradient);
+            return gradient;
+        }
+    };
+    function parsePaintServerUnit(xmlNode, gradient) {
+        var gradientUnits = xmlNode.getAttribute('gradientUnits');
+        if (gradientUnits === 'userSpaceOnUse') {
+            gradient.global = true;
+        }
+    }
+    function parseGradientColorStops(xmlNode, gradient) {
+        var stop = xmlNode.firstChild;
+        while (stop) {
+            if (stop.nodeType === 1
+                && stop.nodeName.toLocaleLowerCase() === 'stop') {
+                var offsetStr = stop.getAttribute('offset');
+                var offset = void 0;
+                if (offsetStr && offsetStr.indexOf('%') > 0) {
+                    offset = parseInt(offsetStr, 10) / 100;
+                }
+                else if (offsetStr) {
+                    offset = parseFloat(offsetStr);
+                }
+                else {
+                    offset = 0;
+                }
+                var styleVals = {};
+                parseInlineStyle(stop, styleVals, styleVals);
+                var stopColor = styleVals.stopColor
+                    || stop.getAttribute('stop-color')
+                    || '#000000';
+                gradient.colorStops.push({
+                    offset: offset,
+                    color: stopColor
+                });
+            }
+            stop = stop.nextSibling;
+        }
+    }
+    function inheritStyle(parent, child) {
+        if (parent && parent.__inheritedStyle) {
+            if (!child.__inheritedStyle) {
+                child.__inheritedStyle = {};
+            }
+            defaults(child.__inheritedStyle, parent.__inheritedStyle);
+        }
+    }
+    function parsePoints(pointsString) {
+        var list = splitNumberSequence(pointsString);
+        var points = [];
+        for (var i = 0; i < list.length; i += 2) {
+            var x = parseFloat(list[i]);
+            var y = parseFloat(list[i + 1]);
+            points.push([x, y]);
+        }
+        return points;
+    }
+    function parseAttributes(xmlNode, el, defsUsePending, onlyInlineStyle, isTextGroup) {
+        var disp = el;
+        var inheritedStyle = disp.__inheritedStyle = disp.__inheritedStyle || {};
+        var selfStyle = {};
+        if (xmlNode.nodeType === 1) {
+            parseTransformAttribute(xmlNode, el);
+            parseInlineStyle(xmlNode, inheritedStyle, selfStyle);
+            if (!onlyInlineStyle) {
+                parseAttributeStyle(xmlNode, inheritedStyle, selfStyle);
+            }
+        }
+        disp.style = disp.style || {};
+        if (inheritedStyle.fill != null) {
+            disp.style.fill = getFillStrokeStyle(disp, 'fill', inheritedStyle.fill, defsUsePending);
+        }
+        if (inheritedStyle.stroke != null) {
+            disp.style.stroke = getFillStrokeStyle(disp, 'stroke', inheritedStyle.stroke, defsUsePending);
+        }
+        each([
+            'lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize'
+        ], function (propName) {
+            if (inheritedStyle[propName] != null) {
+                disp.style[propName] = parseFloat(inheritedStyle[propName]);
+            }
+        });
+        each([
+            'lineDashOffset', 'lineCap', 'lineJoin', 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign'
+        ], function (propName) {
+            if (inheritedStyle[propName] != null) {
+                disp.style[propName] = inheritedStyle[propName];
+            }
+        });
+        if (isTextGroup) {
+            disp.__selfStyle = selfStyle;
+        }
+        if (inheritedStyle.lineDash) {
+            disp.style.lineDash = map(splitNumberSequence(inheritedStyle.lineDash), function (str) {
+                return parseFloat(str);
+            });
+        }
+        if (inheritedStyle.visibility === 'hidden' || inheritedStyle.visibility === 'collapse') {
+            disp.invisible = true;
+        }
+        if (inheritedStyle.display === 'none') {
+            disp.ignore = true;
+        }
+        disp.z = -10000;
+        disp.z2 = -1000;
+    }
+    function applyTextAlignment(text, parentGroup) {
+        var parentSelfStyle = parentGroup.__selfStyle;
+        if (parentSelfStyle) {
+            var textBaseline = parentSelfStyle.textBaseline;
+            var zrTextBaseline = textBaseline;
+            if (!textBaseline || textBaseline === 'auto') {
+                zrTextBaseline = 'alphabetic';
+            }
+            else if (textBaseline === 'baseline') {
+                zrTextBaseline = 'alphabetic';
+            }
+            else if (textBaseline === 'before-edge' || textBaseline === 'text-before-edge') {
+                zrTextBaseline = 'top';
+            }
+            else if (textBaseline === 'after-edge' || textBaseline === 'text-after-edge') {
+                zrTextBaseline = 'bottom';
+            }
+            else if (textBaseline === 'central' || textBaseline === 'mathematical') {
+                zrTextBaseline = 'middle';
+            }
+            text.style.textBaseline = zrTextBaseline;
+        }
+        var parentInheritedStyle = parentGroup.__inheritedStyle;
+        if (parentInheritedStyle) {
+            var textAlign = parentInheritedStyle.textAlign;
+            var zrTextAlign = textAlign;
+            if (textAlign) {
+                if (textAlign === 'middle') {
+                    zrTextAlign = 'center';
+                }
+                text.style.textAlign = zrTextAlign;
+            }
+        }
+    }
+    var urlRegex = /^url\(\s*#(.*?)\)/;
+    function getFillStrokeStyle(el, method, str, defsUsePending) {
+        var urlMatch = str && str.match(urlRegex);
+        if (urlMatch) {
+            var url = trim(urlMatch[1]);
+            defsUsePending.push([el, method, url]);
+            return;
+        }
+        if (str === 'none') {
+            str = null;
+        }
+        return str;
+    }
+    function applyDefs(defs, defsUsePending) {
+        for (var i = 0; i < defsUsePending.length; i++) {
+            var item = defsUsePending[i];
+            item[0].style[item[1]] = defs[item[2]];
+        }
+    }
+    var numberReg$1 = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;
+    function splitNumberSequence(rawStr) {
+        return rawStr.match(numberReg$1) || [];
+    }
+    var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.eE,]*)\)/g;
+    function parseTransformAttribute(xmlNode, node) {
+        var transform = xmlNode.getAttribute('transform');
+        if (transform) {
+            transform = transform.replace(/,/g, ' ');
+            var transformOps_1 = [];
+            var mt = null;
+            transform.replace(transformRegex, function (str, type, value) {
+                transformOps_1.push(type, value);
+                return '';
+            });
+            for (var i = transformOps_1.length - 1; i > 0; i -= 2) {
+                var value = transformOps_1[i];
+                var type = transformOps_1[i - 1];
+                var valueArr = void 0;
+                mt = mt || create$1();
+                switch (type) {
+                    case 'translate':
+                        valueArr = splitNumberSequence(value);
+                        translate(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || '0')]);
+                        break;
+                    case 'scale':
+                        valueArr = splitNumberSequence(value);
+                        scale$1(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || valueArr[0])]);
+                        break;
+                    case 'rotate':
+                        valueArr = splitNumberSequence(value);
+                        rotate(mt, mt, -parseFloat(valueArr[0]) / 180 * Math.PI);
+                        break;
+                    case 'skew':
+                        valueArr = splitNumberSequence(value);
+                        console.warn('Skew transform is not supported yet');
+                        break;
+                    case 'matrix':
+                        valueArr = splitNumberSequence(value);
+                        mt[0] = parseFloat(valueArr[0]);
+                        mt[1] = parseFloat(valueArr[1]);
+                        mt[2] = parseFloat(valueArr[2]);
+                        mt[3] = parseFloat(valueArr[3]);
+                        mt[4] = parseFloat(valueArr[4]);
+                        mt[5] = parseFloat(valueArr[5]);
+                        break;
+                }
+            }
+            node.setLocalTransform(mt);
+        }
+    }
+    var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g;
+    function parseInlineStyle(xmlNode, inheritableStyleResult, selfStyleResult) {
+        var style = xmlNode.getAttribute('style');
+        if (!style) {
+            return;
+        }
+        styleRegex.lastIndex = 0;
+        var styleRegResult;
+        while ((styleRegResult = styleRegex.exec(style)) != null) {
+            var svgStlAttr = styleRegResult[1];
+            var zrInheritableStlAttr = hasOwn(INHERITABLE_STYLE_ATTRIBUTES_MAP, svgStlAttr)
+                ? INHERITABLE_STYLE_ATTRIBUTES_MAP[svgStlAttr]
+                : null;
+            if (zrInheritableStlAttr) {
+                inheritableStyleResult[zrInheritableStlAttr] = styleRegResult[2];
+            }
+            var zrSelfStlAttr = hasOwn(SELF_STYLE_ATTRIBUTES_MAP, svgStlAttr)
+                ? SELF_STYLE_ATTRIBUTES_MAP[svgStlAttr]
+                : null;
+            if (zrSelfStlAttr) {
+                selfStyleResult[zrSelfStlAttr] = styleRegResult[2];
+            }
+        }
+    }
+    function parseAttributeStyle(xmlNode, inheritableStyleResult, selfStyleResult) {
+        for (var i = 0; i < INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) {
+            var svgAttrName = INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS[i];
+            var attrValue = xmlNode.getAttribute(svgAttrName);
+            if (attrValue != null) {
+                inheritableStyleResult[INHERITABLE_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue;
+            }
+        }
+        for (var i = 0; i < SELF_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) {
+            var svgAttrName = SELF_STYLE_ATTRIBUTES_MAP_KEYS[i];
+            var attrValue = xmlNode.getAttribute(svgAttrName);
+            if (attrValue != null) {
+                selfStyleResult[SELF_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue;
+            }
+        }
+    }
+    function makeViewBoxTransform(viewBoxRect, boundingRect) {
+        var scaleX = boundingRect.width / viewBoxRect.width;
+        var scaleY = boundingRect.height / viewBoxRect.height;
+        var scale = Math.min(scaleX, scaleY);
+        return {
+            scale: scale,
+            x: -(viewBoxRect.x + viewBoxRect.width / 2) * scale + (boundingRect.x + boundingRect.width / 2),
+            y: -(viewBoxRect.y + viewBoxRect.height / 2) * scale + (boundingRect.y + boundingRect.height / 2)
+        };
+    }
+    function parseSVG(xml, opt) {
+        var parser = new SVGParser();
+        return parser.parse(xml, opt);
+    }
+
+    var EPSILON$3 = 1e-8;
+    function isAroundEqual$1(a, b) {
+        return Math.abs(a - b) < EPSILON$3;
+    }
+    function contain$1(points, x, y) {
+        var w = 0;
+        var p = points[0];
+        if (!p) {
+            return false;
+        }
+        for (var i = 1; i < points.length; i++) {
+            var p2 = points[i];
+            w += windingLine(p[0], p[1], p2[0], p2[1], x, y);
+            p = p2;
+        }
+        var p0 = points[0];
+        if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) {
+            w += windingLine(p[0], p[1], p0[0], p0[1], x, y);
+        }
+        return w !== 0;
+    }
+
+    var TMP_TRANSFORM = [];
+
+    var Region =
+    /** @class */
+    function () {
+      function Region(name) {
+        this.name = name;
+      }
+      /**
+       * Get center point in data unit. That is,
+       * for GeoJSONRegion, the unit is lat/lng,
+       * for GeoSVGRegion, the unit is SVG local coord.
+       */
+
+
+      Region.prototype.getCenter = function () {
+        return;
+      };
+
+      return Region;
+    }();
+
+    var GeoJSONRegion =
+    /** @class */
+    function (_super) {
+      __extends(GeoJSONRegion, _super);
+
+      function GeoJSONRegion(name, geometries, cp) {
+        var _this = _super.call(this, name) || this;
+
+        _this.type = 'geoJSON';
+        _this.geometries = geometries;
+
+        if (!cp) {
+          var rect = _this.getBoundingRect();
+
+          cp = [rect.x + rect.width / 2, rect.y + rect.height / 2];
+        } else {
+          cp = [cp[0], cp[1]];
+        }
+
+        _this._center = cp;
+        return _this;
+      }
+
+      GeoJSONRegion.prototype.getBoundingRect = function () {
+        var rect = this._rect;
+
+        if (rect) {
+          return rect;
+        }
+
+        var MAX_NUMBER = Number.MAX_VALUE;
+        var min$1 = [MAX_NUMBER, MAX_NUMBER];
+        var max$1 = [-MAX_NUMBER, -MAX_NUMBER];
+        var min2 = [];
+        var max2 = [];
+        var geometries = this.geometries;
+        var i = 0;
+
+        for (; i < geometries.length; i++) {
+          // Only support polygon
+          if (geometries[i].type !== 'polygon') {
+            continue;
+          } // Doesn't consider hole
+
+
+          var exterior = geometries[i].exterior;
+          fromPoints(exterior, min2, max2);
+          min(min$1, min$1, min2);
+          max(max$1, max$1, max2);
+        } // No data
+
+
+        if (i === 0) {
+          min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0;
+        }
+
+        return this._rect = new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]);
+      };
+
+      GeoJSONRegion.prototype.contain = function (coord) {
+        var rect = this.getBoundingRect();
+        var geometries = this.geometries;
+
+        if (!rect.contain(coord[0], coord[1])) {
+          return false;
+        }
+
+        loopGeo: for (var i = 0, len = geometries.length; i < len; i++) {
+          // Only support polygon.
+          if (geometries[i].type !== 'polygon') {
+            continue;
+          }
+
+          var exterior = geometries[i].exterior;
+          var interiors = geometries[i].interiors;
+
+          if (contain$1(exterior, coord[0], coord[1])) {
+            // Not in the region if point is in the hole.
+            for (var k = 0; k < (interiors ? interiors.length : 0); k++) {
+              if (contain$1(interiors[k], coord[0], coord[1])) {
+                continue loopGeo;
+              }
+            }
+
+            return true;
+          }
+        }
+
+        return false;
+      };
+
+      GeoJSONRegion.prototype.transformTo = function (x, y, width, height) {
+        var rect = this.getBoundingRect();
+        var aspect = rect.width / rect.height;
+
+        if (!width) {
+          width = aspect * height;
+        } else if (!height) {
+          height = width / aspect;
+        }
+
+        var target = new BoundingRect(x, y, width, height);
+        var transform = rect.calculateTransform(target);
+        var geometries = this.geometries;
+
+        for (var i = 0; i < geometries.length; i++) {
+          // Only support polygon.
+          if (geometries[i].type !== 'polygon') {
+            continue;
+          }
+
+          var exterior = geometries[i].exterior;
+          var interiors = geometries[i].interiors;
+
+          for (var p = 0; p < exterior.length; p++) {
+            applyTransform(exterior[p], exterior[p], transform);
+          }
+
+          for (var h = 0; h < (interiors ? interiors.length : 0); h++) {
+            for (var p = 0; p < interiors[h].length; p++) {
+              applyTransform(interiors[h][p], interiors[h][p], transform);
+            }
+          }
+        }
+
+        rect = this._rect;
+        rect.copy(target); // Update center
+
+        this._center = [rect.x + rect.width / 2, rect.y + rect.height / 2];
+      };
+
+      GeoJSONRegion.prototype.cloneShallow = function (name) {
+        name == null && (name = this.name);
+        var newRegion = new GeoJSONRegion(name, this.geometries, this._center);
+        newRegion._rect = this._rect;
+        newRegion.transformTo = null; // Simply avoid to be called.
+
+        return newRegion;
+      };
+
+      GeoJSONRegion.prototype.getCenter = function () {
+        return this._center;
+      };
+
+      GeoJSONRegion.prototype.setCenter = function (center) {
+        this._center = center;
+      };
+
+      return GeoJSONRegion;
+    }(Region);
+
+    var GeoSVGRegion =
+    /** @class */
+    function (_super) {
+      __extends(GeoSVGRegion, _super);
+
+      function GeoSVGRegion(name, elOnlyForCalculate) {
+        var _this = _super.call(this, name) || this;
+
+        _this.type = 'geoSVG';
+        _this._elOnlyForCalculate = elOnlyForCalculate;
+        return _this;
+      }
+
+      GeoSVGRegion.prototype.getCenter = function () {
+        var center = this._center;
+
+        if (!center) {
+          // In most cases there are no need to calculate this center.
+          // So calculate only when called.
+          center = this._center = this._calculateCenter();
+        }
+
+        return center;
+      };
+
+      GeoSVGRegion.prototype._calculateCenter = function () {
+        var el = this._elOnlyForCalculate;
+        var rect = el.getBoundingRect();
+        var center = [rect.x + rect.width / 2, rect.y + rect.height / 2];
+        var mat = identity(TMP_TRANSFORM);
+        var target = el;
+
+        while (target && !target.isGeoSVGGraphicRoot) {
+          mul$1(mat, target.getLocalTransform(), mat);
+          target = target.parent;
+        }
+
+        invert(mat, mat);
+        applyTransform(center, center, mat);
+        return center;
+      };
+
+      return GeoSVGRegion;
+    }(Region);
+
+    /**
+     * "region available" means that: enable users to set attribute `name="xxx"` on those tags
+     * to make it be a region.
+     * 1. region styles and its label styles can be defined in echarts opton:
+     * ```js
+     * geo: {
+     *     regions: [{
+     *         name: 'xxx',
+     *         itemStyle: { ... },
+     *         label: { ... }
+     *     }, {
+     *         ...
+     *     },
+     *     ...]
+     * };
+     * ```
+     * 2. name can be duplicated in different SVG tag. All of the tags with the same name share
+     * a region option. For exampel if there are two <path> representing two lung lobes. They have
+     * no common parents but both of them need to display label "lung" inside.
+     */
+
+    var REGION_AVAILABLE_SVG_TAG_MAP = createHashMap(['rect', 'circle', 'line', 'ellipse', 'polygon', 'polyline', 'path', // <text> <tspan> are also enabled becuase some SVG might paint text itself,
+    // but still need to trigger events or tooltip.
+    'text', 'tspan', // <g> is also enabled because this case: if multiple tags share one name
+    // and need label displayed, every tags will display the name, which is not
+    // expected. So we can put them into a <g name="xxx">. Thereby only one label
+    // displayed and located based on the bounding rect of the <g>.
+    'g']);
+
+    var GeoSVGResource =
+    /** @class */
+    function () {
+      function GeoSVGResource(mapName, svg) {
+        this.type = 'geoSVG'; // All used graphics. key: hostKey, value: root
+
+        this._usedGraphicMap = createHashMap(); // All unused graphics.
+
+        this._freedGraphics = [];
+        this._mapName = mapName; // Only perform parse to XML object here, which might be time
+        // consiming for large SVG.
+        // Although convert XML to zrender element is also time consiming,
+        // if we do it here, the clone of zrender elements has to be
+        // required. So we do it once for each geo instance, util real
+        // performance issues call for optimizing it.
+
+        this._parsedXML = parseXML(svg);
+      }
+
+      GeoSVGResource.prototype.load = function ()
+      /* nameMap: NameMap */
+      {
+        // In the "load" stage, graphic need to be built to
+        // get boundingRect for geo coordinate system.
+        var firstGraphic = this._firstGraphic; // Create the return data structure only when first graphic created.
+        // Because they will be used in geo coordinate system update stage,
+        // and `regions` will be mounted at `geo` coordinate system,
+        // in which there is no "view" info, so that it should better not to
+        // make references to graphic elements.
+
+        if (!firstGraphic) {
+          firstGraphic = this._firstGraphic = this._buildGraphic(this._parsedXML);
+
+          this._freedGraphics.push(firstGraphic);
+
+          this._boundingRect = this._firstGraphic.boundingRect.clone(); // PENDING: `nameMap` will not be supported until some real requirement come.
+          // if (nameMap) {
+          //     named = applyNameMap(named, nameMap);
+          // }
+
+          var _a = createRegions(firstGraphic.named),
+              regions = _a.regions,
+              regionsMap = _a.regionsMap;
+
+          this._regions = regions;
+          this._regionsMap = regionsMap;
+        }
+
+        return {
+          boundingRect: this._boundingRect,
+          regions: this._regions,
+          regionsMap: this._regionsMap
+        };
+      };
+
+      GeoSVGResource.prototype._buildGraphic = function (svgXML) {
+        var result;
+        var rootFromParse;
+
+        try {
+          result = svgXML && parseSVG(svgXML, {
+            ignoreViewBox: true,
+            ignoreRootClip: true
+          }) || {};
+          rootFromParse = result.root;
+          assert(rootFromParse != null);
+        } catch (e) {
+          throw new Error('Invalid svg format\n' + e.message);
+        } // Note: we keep the covenant that the root has no transform. So always add an extra root.
+
+
+        var root = new Group();
+        root.add(rootFromParse);
+        root.isGeoSVGGraphicRoot = true; // [THE_RULE_OF_VIEWPORT_AND_VIEWBOX]
+        //
+        // Consider: `<svg width="..." height="..." viewBox="...">`
+        // - the `width/height` we call it `svgWidth/svgHeight` for short.
+        // - `(0, 0, svgWidth, svgHeight)` defines the viewport of the SVG, or say,
+        //   "viewport boundingRect", or `boundingRect` for short.
+        // - `viewBox` defines the transform from the real content ot the viewport.
+        //   `viewBox` has the same unit as the content of SVG.
+        //   If `viewBox` exists, a transform is defined, so the unit of `svgWidth/svgHeight` become
+        //   different from the content of SVG. Otherwise, they are the same.
+        //
+        // If both `svgWidth/svgHeight/viewBox` are specified in a SVG file, the transform rule will be:
+        // 0. `boundingRect` is `(0, 0, svgWidth, svgHeight)`. Set it to Geo['_rect'] (View['_rect']).
+        // 1. Make a transform from `viewBox` to `boundingRect`.
+        //    Note: only suport `preserveAspectRatio 'xMidYMid'` here. That is, this transform will preserve
+        //    the aspect ratio.
+        // 2. Make a transform from boundingRect to Geo['_viewRect'] (View['_viewRect'])
+        //    (`Geo`/`View` will do this job).
+        //    Note: this transform might not preserve aspect radio, which depending on how users specify
+        //    viewRect in echarts option (e.g., `geo.left/top/width/height` will not preserve aspect ratio,
+        //    but `geo.layoutCenter/layoutSize` will preserve aspect ratio).
+        //
+        // If `svgWidth/svgHeight` not specified, we use `viewBox` as the `boundingRect` to make the SVG
+        // layout look good.
+        //
+        // If neither `svgWidth/svgHeight` nor `viewBox` are not specified, we calculate the boundingRect
+        // of the SVG content and use them to make SVG layout look good.
+
+        var svgWidth = result.width;
+        var svgHeight = result.height;
+        var viewBoxRect = result.viewBoxRect;
+        var boundingRect = this._boundingRect;
+
+        if (!boundingRect) {
+          var bRectX = void 0;
+          var bRectY = void 0;
+          var bRectWidth = void 0;
+          var bRectHeight = void 0;
+
+          if (svgWidth != null) {
+            bRectX = 0;
+            bRectWidth = svgWidth;
+          } else if (viewBoxRect) {
+            bRectX = viewBoxRect.x;
+            bRectWidth = viewBoxRect.width;
+          }
+
+          if (svgHeight != null) {
+            bRectY = 0;
+            bRectHeight = svgHeight;
+          } else if (viewBoxRect) {
+            bRectY = viewBoxRect.y;
+            bRectHeight = viewBoxRect.height;
+          } // If both viewBox and svgWidth/svgHeight not specified,
+          // we have to determine how to layout those element to make them look good.
+
+
+          if (bRectX == null || bRectY == null) {
+            var calculatedBoundingRect = rootFromParse.getBoundingRect();
+
+            if (bRectX == null) {
+              bRectX = calculatedBoundingRect.x;
+              bRectWidth = calculatedBoundingRect.width;
+            }
+
+            if (bRectY == null) {
+              bRectY = calculatedBoundingRect.y;
+              bRectHeight = calculatedBoundingRect.height;
+            }
+          }
+
+          boundingRect = this._boundingRect = new BoundingRect(bRectX, bRectY, bRectWidth, bRectHeight);
+        }
+
+        if (viewBoxRect) {
+          var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect); // Only support `preserveAspectRatio 'xMidYMid'`
+
+          rootFromParse.scaleX = rootFromParse.scaleY = viewBoxTransform.scale;
+          rootFromParse.x = viewBoxTransform.x;
+          rootFromParse.y = viewBoxTransform.y;
+        } // SVG needs to clip based on `viewBox`. And some SVG files really rely on this feature.
+        // They do not strictly confine all of the content inside a display rect, but deliberately
+        // use a `viewBox` to define a displayable rect.
+        // PENDING:
+        // The drawback of the `setClipPath` here is: the region label (genereted by echarts) near the
+        // edge might also be clipped, because region labels are put as `textContent` of the SVG path.
+
+
+        root.setClipPath(new Rect({
+          shape: boundingRect.plain()
+        }));
+        var named = [];
+        each(result.named, function (namedItem) {
+          if (REGION_AVAILABLE_SVG_TAG_MAP.get(namedItem.svgNodeTagLower) != null) {
+            named.push(namedItem);
+            setSilent(namedItem.el);
+          }
+        });
+        return {
+          root: root,
+          boundingRect: boundingRect,
+          named: named
+        };
+      };
+      /**
+       * Consider:
+       * (1) One graphic element can not be shared by different `geoView` running simultaneously.
+       *     Notice, also need to consider multiple echarts instances share a `mapRecord`.
+       * (2) Converting SVG to graphic elements is time consuming.
+       * (3) In the current architecture, `load` should be called frequently to get boundingRect,
+       *     and it is called without view info.
+       * So we maintain graphic elements in this module, and enables `view` to use/return these
+       * graphics from/to the pool with it's uid.
+       */
+
+
+      GeoSVGResource.prototype.useGraphic = function (hostKey
+      /*, nameMap: NameMap */
+      ) {
+        var usedRootMap = this._usedGraphicMap;
+        var svgGraphic = usedRootMap.get(hostKey);
+
+        if (svgGraphic) {
+          return svgGraphic;
+        }
+
+        svgGraphic = this._freedGraphics.pop() // use the first boundingRect to avoid duplicated boundingRect calculation.
+        || this._buildGraphic(this._parsedXML);
+        usedRootMap.set(hostKey, svgGraphic); // PENDING: `nameMap` will not be supported until some real requirement come.
+        // `nameMap` can only be obtained from echarts option.
+        // The original `named` must not be modified.
+        // if (nameMap) {
+        //     svgGraphic = extend({}, svgGraphic);
+        //     svgGraphic.named = applyNameMap(svgGraphic.named, nameMap);
+        // }
+
+        return svgGraphic;
+      };
+
+      GeoSVGResource.prototype.freeGraphic = function (hostKey) {
+        var usedRootMap = this._usedGraphicMap;
+        var svgGraphic = usedRootMap.get(hostKey);
+
+        if (svgGraphic) {
+          usedRootMap.removeKey(hostKey);
+
+          this._freedGraphics.push(svgGraphic);
+        }
+      };
+
+      return GeoSVGResource;
+    }();
+
+    function setSilent(el) {
+      // Only named element has silent: false, other elements should
+      // act as background and has no user interaction.
+      el.silent = false; // text|tspan will be converted to group.
+
+      if (el.isGroup) {
+        el.traverse(function (child) {
+          child.silent = false;
+        });
+      }
+    }
+
+    function createRegions(named) {
+      var regions = [];
+      var regionsMap = createHashMap(); // Create resions only for the first graphic.
+
+      each(named, function (namedItem) {
+        // Region has feature to calculate center for tooltip or other features.
+        // If there is a <g name="xxx">, the center should be the center of the
+        // bounding rect of the g.
+        if (namedItem.namedFrom != null) {
+          return;
+        }
+
+        var region = new GeoSVGRegion(namedItem.name, namedItem.el); // PENDING: if `nameMap` supported, this region can not be mounted on
+        // `this`, but can only be created each time `load()` called.
+
+        regions.push(region); // PENDING: if multiple tag named with the same name, only one will be
+        // found by `_regionsMap`. `_regionsMap` is used to find a coordinate
+        // by name. We use `region.getCenter()` as the coordinate.
+
+        regionsMap.set(namedItem.name, region);
+      });
+      return {
+        regions: regions,
+        regionsMap: regionsMap
+      };
+    } // PENDING: `nameMap` will not be supported until some real requirement come.
+    // /**
+    //  * Use the alias in geoNameMap.
+    //  * The input `named` must not be modified.
+    //  */
+    // function applyNameMap(
+    //     named: GeoSVGGraphicRecord['named'],
+    //     nameMap: NameMap
+    // ): GeoSVGGraphicRecord['named'] {
+    //     const result = [] as GeoSVGGraphicRecord['named'];
+    //     for (let i = 0; i < named.length; i++) {
+    //         let regionGraphic = named[i];
+    //         const name = regionGraphic.name;
+    //         if (nameMap && nameMap.hasOwnProperty(name)) {
+    //             regionGraphic = extend({}, regionGraphic);
+    //             regionGraphic.name = name;
+    //         }
+    //         result.push(regionGraphic);
+    //     }
+    //     return result;
+    // }
+
+    function decode(json) {
+      if (!json.UTF8Encoding) {
+        return json;
+      }
+
+      var jsonCompressed = json;
+      var encodeScale = jsonCompressed.UTF8Scale;
+
+      if (encodeScale == null) {
+        encodeScale = 1024;
+      }
+
+      var features = jsonCompressed.features;
+
+      for (var f = 0; f < features.length; f++) {
+        var feature = features[f];
+        var geometry = feature.geometry;
+
+        if (geometry.type === 'Polygon') {
+          var coordinates = geometry.coordinates;
+
+          for (var c = 0; c < coordinates.length; c++) {
+            coordinates[c] = decodePolygon(coordinates[c], geometry.encodeOffsets[c], encodeScale);
+          }
+        } else if (geometry.type === 'MultiPolygon') {
+          var coordinates = geometry.coordinates;
+
+          for (var c = 0; c < coordinates.length; c++) {
+            var coordinate = coordinates[c];
+
+            for (var c2 = 0; c2 < coordinate.length; c2++) {
+              coordinate[c2] = decodePolygon(coordinate[c2], geometry.encodeOffsets[c][c2], encodeScale);
+            }
+          }
+        }
+      } // Has been decoded
+
+
+      jsonCompressed.UTF8Encoding = false;
+      return jsonCompressed;
+    }
+
+    function decodePolygon(coordinate, encodeOffsets, encodeScale) {
+      var result = [];
+      var prevX = encodeOffsets[0];
+      var prevY = encodeOffsets[1];
+
+      for (var i = 0; i < coordinate.length; i += 2) {
+        var x = coordinate.charCodeAt(i) - 64;
+        var y = coordinate.charCodeAt(i + 1) - 64; // ZigZag decoding
+
+        x = x >> 1 ^ -(x & 1);
+        y = y >> 1 ^ -(y & 1); // Delta deocding
+
+        x += prevX;
+        y += prevY;
+        prevX = x;
+        prevY = y; // Dequantize
+
+        result.push([x / encodeScale, y / encodeScale]);
+      }
+
+      return result;
+    }
+
+    function parseGeoJSON(geoJson, nameProperty) {
+      geoJson = decode(geoJson);
+      return map(filter(geoJson.features, function (featureObj) {
+        // Output of mapshaper may have geometry null
+        return featureObj.geometry && featureObj.properties && featureObj.geometry.coordinates.length > 0;
+      }), function (featureObj) {
+        var properties = featureObj.properties;
+        var geo = featureObj.geometry;
+        var geometries = [];
+
+        if (geo.type === 'Polygon') {
+          var coordinates = geo.coordinates;
+          geometries.push({
+            type: 'polygon',
+            // According to the GeoJSON specification.
+            // First must be exterior, and the rest are all interior(holes).
+            exterior: coordinates[0],
+            interiors: coordinates.slice(1)
+          });
+        }
+
+        if (geo.type === 'MultiPolygon') {
+          var coordinates = geo.coordinates;
+          each(coordinates, function (item) {
+            if (item[0]) {
+              geometries.push({
+                type: 'polygon',
+                exterior: item[0],
+                interiors: item.slice(1)
+              });
+            }
+          });
+        }
+
+        var region = new GeoJSONRegion(properties[nameProperty || 'name'], geometries, properties.cp);
+        region.properties = properties;
+        return region;
+      });
+    }
+
+    var geoCoord = [126, 25];
+    var points$1 = [[[0, 3.5], [7, 11.2], [15, 11.9], [30, 7], [42, 0.7], [52, 0.7], [56, 7.7], [59, 0.7], [64, 0.7], [64, 0], [5, 0], [0, 3.5]], [[13, 16.1], [19, 14.7], [16, 21.7], [11, 23.1], [13, 16.1]], [[12, 32.2], [14, 38.5], [15, 38.5], [13, 32.2], [12, 32.2]], [[16, 47.6], [12, 53.2], [13, 53.2], [18, 47.6], [16, 47.6]], [[6, 64.4], [8, 70], [9, 70], [8, 64.4], [6, 64.4]], [[23, 82.6], [29, 79.8], [30, 79.8], [25, 82.6], [23, 82.6]], [[37, 70.7], [43, 62.3], [44, 62.3], [39, 70. [...]
+
+    for (var i = 0; i < points$1.length; i++) {
+      for (var k = 0; k < points$1[i].length; k++) {
+        points$1[i][k][0] /= 10.5;
+        points$1[i][k][1] /= -10.5 / 0.75;
+        points$1[i][k][0] += geoCoord[0];
+        points$1[i][k][1] += geoCoord[1];
+      }
+    }
+
+    function fixNanhai(mapType, regions) {
+      if (mapType === 'china') {
+        regions.push(new GeoJSONRegion('南海诸岛', map(points$1, function (exterior) {
+          return {
+            type: 'polygon',
+            exterior: exterior
+          };
+        }), geoCoord));
+      }
+    }
+
+    /*
+    * 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.
+    */
+
+
+    /**
+     * AUTO-GENERATED FILE. DO NOT MODIFY.
+     */
+
+    /*
+    * Licensed to the Apache Software Foundation (ASF) under one
+    * or more contributor license agreements.  See the NOTICE file
+    * distributed with this work for additional information
+    * regarding copyright ownership.  The ASF licenses this file
+    * to you under the Apache License, Version 2.0 (the
+    * "License"); you may not use this file except in compliance
+    * with the License.  You may obtain a copy of the License at
+    *
+    *   http://www.apache.org/licenses/LICENSE-2.0
+    *
+    * Unless required by applicable law or agreed to in writing,
+    * software distributed under the License is distributed on an
+    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    * KIND, either express or implied.  See the License for the
+    * specific language governing permissions and limitations
+    * under the License.
+    */
+    var coordsOffsetMap = {
+      '南海诸岛': [32, 80],
+      // 全国
+      '广东': [0, -10],
+      '香港': [10, 5],
+      '澳门': [-10, 10],
+      //'北京': [-10, 0],
+      '天津': [5, 5]
+    };
+    function fixTextCoords(mapType, region) {
+      if (mapType === 'china') {
+        var coordFix = coordsOffsetMap[region.name];
+
+        if (coordFix) {
+          var cp = region.getCenter();
+          cp[0] += coordFix[0] / 10.5;
+          cp[1] += -coordFix[1] / (10.5 / 0.75);
+          region.setCenter(cp);
+        }
+      }
+    }
+
+    /*
+    * 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.
+    */
+
+
+    /**
+     * AUTO-GENERATED FILE. DO NOT MODIFY.
+     */
+
+    /*
+    * Licensed to the Apache Software Foundation (ASF) under one
+    * or more contributor license agreements.  See the NOTICE file
+    * distributed with this work for additional information
+    * regarding copyright ownership.  The ASF licenses this file
+    * to you under the Apache License, Version 2.0 (the
+    * "License"); you may not use this file except in compliance
+    * with the License.  You may obtain a copy of the License at
+    *
+    *   http://www.apache.org/licenses/LICENSE-2.0
+    *
+    * Unless required by applicable law or agreed to in writing,
+    * software distributed under the License is distributed on an
+    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    * KIND, either express or implied.  See the License for the
+    * specific language governing permissions and limitations
+    * under the License.
+    */
+    var geoCoordMap = {
+      'Russia': [100, 60],
+      'United States': [-99, 38],
+      'United States of America': [-99, 38]
+    };
+    function fixGeoCoords(mapType, region) {
+      if (mapType === 'world') {
+        var geoCoord = geoCoordMap[region.name];
+
+        if (geoCoord) {
+          var cp = [geoCoord[0], geoCoord[1]];
+          region.setCenter(cp);
+        }
+      }
+    }
+
+    /*
+    * 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.
+    */
+
+
+    /**
+     * AUTO-GENERATED FILE. DO NOT MODIFY.
+     */
+
+    /*
+    * 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.
+    */
+    // Fix for 钓鱼岛
+    // let Region = require('../Region');
+    // let zrUtil = require('zrender/lib/core/util');
+    // let geoCoord = [126, 25];
+    var points$2 = [[[123.45165252685547, 25.73527164402261], [123.49731445312499, 25.73527164402261], [123.49731445312499, 25.750734064600884], [123.45165252685547, 25.750734064600884], [123.45165252685547, 25.73527164402261]]];
+    function fixDiaoyuIsland(mapType, region) {
+      if (mapType === 'china' && region.name === '台湾') {
+        region.geometries.push({
+          type: 'polygon',
+          exterior: points$2[0]
+        });
+      }
+    }
+
+    var DEFAULT_NAME_PROPERTY = 'name';
+
+    var GeoJSONResource =
+    /** @class */
+    function () {
+      function GeoJSONResource(mapName, geoJSON, specialAreas) {
+        this.type = 'geoJSON';
+        this._parsedMap = createHashMap();
+        this._mapName = mapName;
+        this._specialAreas = specialAreas; // PENDING: delay the parse to the first usage to rapid up the FMP?
+
+        this._geoJSON = parseInput(geoJSON);
+      }
+      /**
+       * @param nameMap can be null/undefined
+       * @param nameProperty can be null/undefined
+       */
+
+
+      GeoJSONResource.prototype.load = function (nameMap, nameProperty) {
+        nameProperty = nameProperty || DEFAULT_NAME_PROPERTY;
+
+        var parsed = this._parsedMap.get(nameProperty);
+
+        if (!parsed) {
+          var rawRegions = this._parseToRegions(nameProperty);
+
+          parsed = this._parsedMap.set(nameProperty, {
+            regions: rawRegions,
+            boundingRect: calculateBoundingRect(rawRegions)
+          });
+        }
+
+        var regionsMap = createHashMap();
+        var finalRegions = [];
+        each(parsed.regions, function (region) {
+          var regionName = region.name; // Try use the alias in geoNameMap
+
+          if (nameMap && nameMap.hasOwnProperty(regionName)) {
+            region = region.cloneShallow(regionName = nameMap[regionName]);
+          }
+
+          finalRegions.push(region);
+          regionsMap.set(regionName, region);
+        });
+        return {
+          regions: finalRegions,
+          boundingRect: parsed.boundingRect || new BoundingRect(0, 0, 0, 0),
+          regionsMap: regionsMap
+        };
+      };
+
+      GeoJSONResource.prototype._parseToRegions = function (nameProperty) {
+        var mapName = this._mapName;
+        var geoJSON = this._geoJSON;
+        var rawRegions; // https://jsperf.com/try-catch-performance-overhead
+
+        try {
+          rawRegions = geoJSON ? parseGeoJSON(geoJSON, nameProperty) : [];
+        } catch (e) {
+          throw new Error('Invalid geoJson format\n' + e.message);
+        }
+
+        fixNanhai(mapName, rawRegions);
+        each(rawRegions, function (region) {
+          var regionName = region.name;
+          fixTextCoords(mapName, region);
+          fixGeoCoords(mapName, region);
+          fixDiaoyuIsland(mapName, region); // Some area like Alaska in USA map needs to be tansformed
+          // to look better
+
+          var specialArea = this._specialAreas && this._specialAreas[regionName];
+
+          if (specialArea) {
+            region.transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height);
+          }
+        }, this);
+        return rawRegions;
+      };
+      /**
+       * Only for exporting to users.
+       * **MUST NOT** used internally.
+       */
+
+
+      GeoJSONResource.prototype.getMapForUser = function () {
+        return {
+          // For backward compatibility, use geoJson
+          // PENDING: it has been returning them without clone.
+          // do we need to avoid outsite modification?
+          geoJson: this._geoJSON,
+          geoJSON: this._geoJSON,
+          specialAreas: this._specialAreas
+        };
+      };
+
+      return GeoJSONResource;
+    }();
+
+    function calculateBoundingRect(regions) {
+      var rect;
+
+      for (var i = 0; i < regions.length; i++) {
+        var regionRect = regions[i].getBoundingRect();
+        rect = rect || regionRect.clone();
+        rect.union(regionRect);
+      }
+
+      return rect;
+    }
+
+    function parseInput(source) {
+      return !isString(source) ? source : typeof JSON !== 'undefined' && JSON.parse ? JSON.parse(source) : new Function('return (' + source + ');')();
+    }
+
+    var storage = createHashMap();
+    var geoSourceManager = {
+      /**
+       * Compatible with previous `echarts.registerMap`.
+       *
+       * @usage
+       * ```js
+       *
+       * echarts.registerMap('USA', geoJson, specialAreas);
+       *
+       * echarts.registerMap('USA', {
+       *     geoJson: geoJson,
+       *     specialAreas: {...}
+       * });
+       * echarts.registerMap('USA', {
+       *     geoJSON: geoJson,
+       *     specialAreas: {...}
+       * });
+       *
+       * echarts.registerMap('airport', {
+       *     svg: svg
+       * }
+       * ```
+       *
+       * Note:
+       * Do not support that register multiple geoJSON or SVG
+       * one map name. Because different geoJSON and SVG have
+       * different unit. It's not easy to make sure how those
+       * units are mapping/normalize.
+       * If intending to use multiple geoJSON or SVG, we can
+       * use multiple geo coordinate system.
+       */
+      registerMap: function (mapName, rawDef, rawSpecialAreas) {
+        if (rawDef.svg) {
+          var resource = new GeoSVGResource(mapName, rawDef.svg);
+          storage.set(mapName, resource);
+        } else {
+          // Recommend:
+          //     echarts.registerMap('eu', { geoJSON: xxx, specialAreas: xxx });
+          // Backward compatibility:
+          //     echarts.registerMap('eu', geoJSON, specialAreas);
+          //     echarts.registerMap('eu', { geoJson: xxx, specialAreas: xxx });
+          var geoJSON = rawDef.geoJson || rawDef.geoJSON;
+
+          if (geoJSON && !rawDef.features) {
+            rawSpecialAreas = rawDef.specialAreas;
+          } else {
+            geoJSON = rawDef;
+          }
+
+          var resource = new GeoJSONResource(mapName, geoJSON, rawSpecialAreas);
+          storage.set(mapName, resource);
+        }
+      },
+      getGeoResource: function (mapName) {
+        return storage.get(mapName);
+      },
+
+      /**
+       * Only for exporting to users.
+       * **MUST NOT** used internally.
+       */
+      getMapForUser: function (mapName) {
+        var resource = storage.get(mapName); // Do not support return SVG until some real requirement come.
+
+        return resource && resource.type === 'geoJSON' && resource.getMapForUser();
+      },
+      load: function (mapName, nameMap, nameProperty) {
+        var resource = storage.get(mapName);
+
+        if (!resource) {
+          if ("development" !== 'production') {
+            console.error('Map ' + mapName + ' not exists. The GeoJSON of the map must be provided.');
+          }
+
+          return;
+        }
+
+        return resource.load(nameMap, nameProperty);
+      }
+    };
+
     var assert$1 = assert;
     var each$3 = each;
     var isFunction$1 = isFunction;
     var isObject$2 = isObject;
     var indexOf$1 = indexOf;
     var hasWindow = typeof window !== 'undefined';
-    var version$1 = '5.0.2';
+    var version$1 = '5.1.0';
     var dependencies = {
-      zrender: '5.0.4'
+      zrender: '5.1.0'
     };
     var TEST_FRAME_REMAIN_TIME = 1;
     var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
@@ -27939,10 +29795,10 @@
         optionChanged && prepare(this);
         updateMethods.update.call(this, {
           type: 'resize',
-          animation: {
+          animation: extend({
             // Disable animation
             duration: 0
-          }
+          }, opts && opts.animation)
         });
         this[IN_MAIN_PROCESS_KEY] = false;
         flushPendingActions.call(this, silent);
@@ -28217,14 +30073,38 @@
                 excludeSeriesIdMap.set(modelId, true);
               }
             });
+          }
+
+          if (isHighDownPayload(payload)) {
+            allLeaveBlur(ecIns._api);
           } // If dispatchAction before setOption, do nothing.
 
 
           ecModel && ecModel.eachComponent(condition, function (model) {
             if (!excludeSeriesIdMap || excludeSeriesIdMap.get(model.id) == null) {
-              if (isHighDownPayload(payload) && !payload.notBlur) {
+              if (isHighDownPayload(payload)) {
                 if (model instanceof SeriesModel) {
-                  toggleSeriesBlurStateFromPayload(model, payload, ecIns._api);
+                  if (payload.type === HIGHLIGHT_ACTION_TYPE && !payload.notBlur) {
+                    blurSeriesFromHighlightPayload(model, payload, ecIns._api);
+                  }
+                } else {
+                  var _a = findComponentHighDownDispatchers(model.mainType, model.componentIndex, payload.name, ecIns._api),
+                      focusSelf = _a.focusSelf,
+                      dispatchers = _a.dispatchers;
+
+                  if (payload.type === HIGHLIGHT_ACTION_TYPE && focusSelf && !payload.notBlur) {
+                    blurComponent(model.mainType, model.componentIndex, ecIns._api);
+                  } // PENDING:
+                  // Whether to put this "enter emphasis" code in `ComponentView`,
+                  // which will be the same as `ChartView` but might be not necessary
+                  // and will be far from this logic.
+
+
+                  if (dispatchers) {
+                    each$3(dispatchers, function (dispatcher) {
+                      payload.type === HIGHLIGHT_ACTION_TYPE ? enterEmphasis(dispatcher) : leaveEmphasis(dispatcher);
+                    });
+                  }
                 }
               } else if (isSelectChangePayload(payload)) {
                 // TODO geo
@@ -28478,7 +30358,7 @@
           var eventObjBatch = [];
           var eventObj;
           var isSelectChange = isSelectChangePayload(payload);
-          var isStatusChange = isHighDownPayload(payload) || isSelectChange;
+          var isHighDown = isHighDownPayload(payload);
           each$3(payloads, function (batchItem) {
             // Action can specify the event by return it.
             eventObj = actionWrap.action(batchItem, _this._model, _this._api); // Emit event outside
@@ -28488,17 +30368,25 @@
             eventObj.type = actionInfo.event || eventObj.type;
             eventObjBatch.push(eventObj); // light update does not perform data process, layout and visual.
 
-            if (isStatusChange) {
-              // method, payload, mainType, subType
-              updateDirectly(_this, updateMethod, batchItem, 'series'); // Mark status to update
+            if (isHighDown) {
+              var _a = preParseFinder(payload),
+                  queryOptionMap = _a.queryOptionMap,
+                  mainTypeSpecified = _a.mainTypeSpecified;
 
+              var componentMainType = mainTypeSpecified ? queryOptionMap.keys()[0] : 'series';
+              updateDirectly(_this, updateMethod, batchItem, componentMainType);
+              markStatusToUpdate(_this);
+            } else if (isSelectChange) {
+              // At present `dispatchAction({ type: 'select', ... })` is not supported on components.
+              // geo still use 'geoselect'.
+              updateDirectly(_this, updateMethod, batchItem, 'series');
               markStatusToUpdate(_this);
             } else if (cptType) {
               updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub);
             }
           });
 
-          if (updateMethod !== 'none' && !isStatusChange && !cptType) {
+          if (updateMethod !== 'none' && !isHighDown && !isSelectChange && !cptType) {
             // Still dirty
             if (this[OPTION_UPDATED_KEY]) {
               prepare(this);
@@ -28588,11 +30476,7 @@
             var dispatcher = findEventDispatcher(el, isHighDownDispatcher);
 
             if (dispatcher) {
-              var ecData = getECData(dispatcher); // Try blur all in the related series. Then emphasis the hoverred.
-              // TODO. progressive mode.
-
-              toggleSeriesBlurState(ecData.seriesIndex, ecData.focus, ecData.blurScope, ecIns._api, true);
-              enterEmphasisWhenMouseOver(dispatcher, e);
+              handleGlobalMouseOverForHighDown(dispatcher, e, ecIns._api);
               markStatusToUpdate(ecIns);
             }
           }).on('mouseout', function (e) {
@@ -28600,9 +30484,7 @@
             var dispatcher = findEventDispatcher(el, isHighDownDispatcher);
 
             if (dispatcher) {
-              var ecData = getECData(dispatcher);
-              toggleSeriesBlurState(ecData.seriesIndex, ecData.focus, ecData.blurScope, ecIns._api, false);
-              leaveEmphasisWhenMouseOut(dispatcher, e);
+              handleGlboalMouseOutForHighDown(dispatcher, e, ecIns._api);
               markStatusToUpdate(ecIns);
             }
           }).on('click', function (e) {
@@ -28822,38 +30704,54 @@
         function updateZ(model, view) {
           if (model.preventAutoZ) {
             return;
-          }
+          } // Set z and zlevel
 
-          var z = model.get('z');
-          var zlevel = model.get('zlevel'); // Set z and zlevel
 
-          view.group.traverse(function (el) {
-            if (!el.isGroup) {
-              z != null && (el.z = z);
-              zlevel != null && (el.zlevel = zlevel); // TODO if textContent is on group.
+          _updateZ(view.group, model.get('z') || 0, model.get('zlevel') || 0, -Infinity);
+        }
 
-              var label = el.getTextContent();
-              var labelLine = el.getTextGuideLine();
+        function _updateZ(el, z, zlevel, maxZ2) {
+          // Group may also have textContent
+          var label = el.getTextContent();
+          var labelLine = el.getTextGuideLine();
+          var isGroup = el.isGroup;
 
-              if (label) {
-                label.z = el.z;
-                label.zlevel = el.zlevel; // lift z2 of text content
-                // TODO if el.emphasis.z2 is spcefied, what about textContent.
+          if (isGroup) {
+            // set z & zlevel of children elements of Group
+            // el.traverse((childEl: Element) => _updateZ(childEl, z, zlevel));
+            var children = el.childrenRef();
 
-                label.z2 = el.z2 + 2;
-              }
-
-              if (labelLine) {
-                var showAbove = el.textGuideLineConfig && el.textGuideLineConfig.showAbove;
-                labelLine.z = el.z;
-                labelLine.zlevel = el.zlevel;
-                labelLine.z2 = el.z2 + (showAbove ? 1 : -1);
-              }
+            for (var i = 0; i < children.length; i++) {
+              maxZ2 = Math.max(_updateZ(children[i], z, zlevel, maxZ2), maxZ2);
             }
-          });
-        }
+          } else {
+            // not Group
+            el.z = z;
+            el.zlevel = zlevel;
+            maxZ2 = Math.max(el.z2, maxZ2);
+          } // always set z and zlevel if label/labelLine exists
+
+
+          if (label) {
+            label.z = z;
+            label.zlevel = zlevel; // lift z2 of text content
+            // TODO if el.emphasis.z2 is spcefied, what about textContent.
+
+            isFinite(maxZ2) && (label.z2 = maxZ2 + 2);
+          }
+
+          if (labelLine) {
+            var textGuideLineConfig = el.textGuideLineConfig;
+            labelLine.z = z;
+            labelLine.zlevel = zlevel;
+            isFinite(maxZ2) && (labelLine.z2 = maxZ2 + (textGuideLineConfig && textGuideLineConfig.showAbove ? 1 : -1));
+          }
+
+          return maxZ2;
+        } // Clear states without animation.
         // TODO States on component.
 
+
         function clearStates(model, view) {
           view.group.traverse(function (el) {
             // Not applied on removed elements, it may still in fading.
@@ -29439,22 +31337,15 @@
       $override('createCanvas', creator);
     }
     /**
-     * The parameters and usage: see `mapDataStorage.registerMap`.
+     * The parameters and usage: see `geoSourceManager.registerMap`.
      * Compatible with previous `echarts.registerMap`.
      */
 
     function registerMap(mapName, geoJson, specialAreas) {
-      mapDataStorage.registerMap(mapName, geoJson, specialAreas);
+      geoSourceManager.registerMap(mapName, geoJson, specialAreas);
     }
     function getMap(mapName) {
-      // For backward compatibility, only return the first one.
-      var records = mapDataStorage.retrieveMap(mapName); // FIXME support SVG, where return not only records[0].
-
-      return records && records[0] && {
-        // @ts-ignore
-        geoJson: records[0].geoJSON,
-        specialAreas: records[0].specialAreas
-      };
+      return geoSourceManager.getMapForUser(mapName);
     }
     var registerTransform = registerExternalTransform;
     /**
@@ -32765,7 +34656,7 @@
         niceTickExtent[0] = niceTickExtent[1];
       }
     }
-    function contain$1(val, extent) {
+    function contain$2(val, extent) {
       return val >= extent[0] && val <= extent[1];
     }
     function normalize$1(val, extent) {
@@ -32817,7 +34708,7 @@
 
       OrdinalScale.prototype.contain = function (rank) {
         rank = this.parse(rank);
-        return contain$1(rank, this._extent) && this._ordinalMeta.categories[rank] != null;
+        return contain$2(rank, this._extent) && this._ordinalMeta.categories[rank] != null;
       };
       /**
        * Normalize given rank or name to linear [0, 1]
@@ -32994,7 +34885,7 @@
       };
 
       IntervalScale.prototype.contain = function (val) {
-        return contain$1(val, this._extent);
+        return contain$2(val, this._extent);
       };
 
       IntervalScale.prototype.normalize = function (val) {
@@ -33819,7 +35710,7 @@
       };
 
       TimeScale.prototype.contain = function (val) {
-        return contain$1(this.parse(val), this._extent);
+        return contain$2(this.parse(val), this._extent);
       };
 
       TimeScale.prototype.normalize = function (val) {
@@ -34366,7 +36257,7 @@
 
       LogScale.prototype.contain = function (val) {
         val = mathLog(val) / mathLog(this.base);
-        return contain$1(val, this._extent);
+        return contain$2(val, this._extent);
       };
 
       LogScale.prototype.normalize = function (val) {
@@ -35077,270 +36968,6 @@
         enableHoverEmphasis: enableHoverEmphasis
     });
 
-    var EPSILON$3 = 1e-8;
-    function isAroundEqual$1(a, b) {
-        return Math.abs(a - b) < EPSILON$3;
-    }
-    function contain$2(points, x, y) {
-        var w = 0;
-        var p = points[0];
-        if (!p) {
-            return false;
-        }
-        for (var i = 1; i < points.length; i++) {
-            var p2 = points[i];
-            w += windingLine(p[0], p[1], p2[0], p2[1], x, y);
-            p = p2;
-        }
-        var p0 = points[0];
-        if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) {
-            w += windingLine(p[0], p[1], p0[0], p0[1], x, y);
-        }
-        return w !== 0;
-    }
-
-    var Region =
-    /** @class */
-    function () {
-      function Region(name, geometries, cp) {
-        this.name = name;
-        this.geometries = geometries;
-
-        if (!cp) {
-          var rect = this.getBoundingRect();
-          cp = [rect.x + rect.width / 2, rect.y + rect.height / 2];
-        } else {
-          cp = [cp[0], cp[1]];
-        }
-
-        this.center = cp;
-      }
-
-      Region.prototype.getBoundingRect = function () {
-        var rect = this._rect;
-
-        if (rect) {
-          return rect;
-        }
-
-        var MAX_NUMBER = Number.MAX_VALUE;
-        var min$1 = [MAX_NUMBER, MAX_NUMBER];
-        var max$1 = [-MAX_NUMBER, -MAX_NUMBER];
-        var min2 = [];
-        var max2 = [];
-        var geometries = this.geometries;
-        var i = 0;
-
-        for (; i < geometries.length; i++) {
-          // Only support polygon
-          if (geometries[i].type !== 'polygon') {
-            continue;
-          } // Doesn't consider hole
-
-
-          var exterior = geometries[i].exterior;
-          fromPoints(exterior, min2, max2);
-          min(min$1, min$1, min2);
-          max(max$1, max$1, max2);
-        } // No data
-
-
-        if (i === 0) {
-          min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0;
-        }
-
-        return this._rect = new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]);
-      };
-
-      Region.prototype.contain = function (coord) {
-        var rect = this.getBoundingRect();
-        var geometries = this.geometries;
-
-        if (!rect.contain(coord[0], coord[1])) {
-          return false;
-        }
-
-        loopGeo: for (var i = 0, len = geometries.length; i < len; i++) {
-          // Only support polygon.
-          if (geometries[i].type !== 'polygon') {
-            continue;
-          }
-
-          var exterior = geometries[i].exterior;
-          var interiors = geometries[i].interiors;
-
-          if (contain$2(exterior, coord[0], coord[1])) {
-            // Not in the region if point is in the hole.
-            for (var k = 0; k < (interiors ? interiors.length : 0); k++) {
-              if (contain$2(interiors[k], coord[0], coord[1])) {
-                continue loopGeo;
-              }
-            }
-
-            return true;
-          }
-        }
-
-        return false;
-      };
-
-      Region.prototype.transformTo = function (x, y, width, height) {
-        var rect = this.getBoundingRect();
-        var aspect = rect.width / rect.height;
-
-        if (!width) {
-          width = aspect * height;
-        } else if (!height) {
-          height = width / aspect;
-        }
-
-        var target = new BoundingRect(x, y, width, height);
-        var transform = rect.calculateTransform(target);
-        var geometries = this.geometries;
-
-        for (var i = 0; i < geometries.length; i++) {
-          // Only support polygon.
-          if (geometries[i].type !== 'polygon') {
-            continue;
-          }
-
-          var exterior = geometries[i].exterior;
-          var interiors = geometries[i].interiors;
-
-          for (var p = 0; p < exterior.length; p++) {
-            applyTransform(exterior[p], exterior[p], transform);
-          }
-
-          for (var h = 0; h < (interiors ? interiors.length : 0); h++) {
-            for (var p = 0; p < interiors[h].length; p++) {
-              applyTransform(interiors[h][p], interiors[h][p], transform);
-            }
-          }
-        }
-
-        rect = this._rect;
-        rect.copy(target); // Update center
-
-        this.center = [rect.x + rect.width / 2, rect.y + rect.height / 2];
-      };
-
-      Region.prototype.cloneShallow = function (name) {
-        name == null && (name = this.name);
-        var newRegion = new Region(name, this.geometries, this.center);
-        newRegion._rect = this._rect;
-        newRegion.transformTo = null; // Simply avoid to be called.
-
-        return newRegion;
-      };
-
-      return Region;
-    }();
-
-    function decode(json) {
-      if (!json.UTF8Encoding) {
-        return json;
-      }
-
-      var jsonCompressed = json;
-      var encodeScale = jsonCompressed.UTF8Scale;
-
-      if (encodeScale == null) {
-        encodeScale = 1024;
-      }
-
-      var features = jsonCompressed.features;
-
-      for (var f = 0; f < features.length; f++) {
-        var feature = features[f];
-        var geometry = feature.geometry;
-
-        if (geometry.type === 'Polygon') {
-          var coordinates = geometry.coordinates;
-
-          for (var c = 0; c < coordinates.length; c++) {
-            coordinates[c] = decodePolygon(coordinates[c], geometry.encodeOffsets[c], encodeScale);
-          }
-        } else if (geometry.type === 'MultiPolygon') {
-          var coordinates = geometry.coordinates;
-
-          for (var c = 0; c < coordinates.length; c++) {
-            var coordinate = coordinates[c];
-
-            for (var c2 = 0; c2 < coordinate.length; c2++) {
-              coordinate[c2] = decodePolygon(coordinate[c2], geometry.encodeOffsets[c][c2], encodeScale);
-            }
-          }
-        }
-      } // Has been decoded
-
-
-      jsonCompressed.UTF8Encoding = false;
-      return jsonCompressed;
-    }
-
-    function decodePolygon(coordinate, encodeOffsets, encodeScale) {
-      var result = [];
-      var prevX = encodeOffsets[0];
-      var prevY = encodeOffsets[1];
-
-      for (var i = 0; i < coordinate.length; i += 2) {
-        var x = coordinate.charCodeAt(i) - 64;
-        var y = coordinate.charCodeAt(i + 1) - 64; // ZigZag decoding
-
-        x = x >> 1 ^ -(x & 1);
-        y = y >> 1 ^ -(y & 1); // Delta deocding
-
-        x += prevX;
-        y += prevY;
-        prevX = x;
-        prevY = y; // Dequantize
-
-        result.push([x / encodeScale, y / encodeScale]);
-      }
-
-      return result;
-    }
-
-    function parseGeoJSON(geoJson, nameProperty) {
-      geoJson = decode(geoJson);
-      return map(filter(geoJson.features, function (featureObj) {
-        // Output of mapshaper may have geometry null
-        return featureObj.geometry && featureObj.properties && featureObj.geometry.coordinates.length > 0;
-      }), function (featureObj) {
-        var properties = featureObj.properties;
-        var geo = featureObj.geometry;
-        var geometries = [];
-
-        if (geo.type === 'Polygon') {
-          var coordinates = geo.coordinates;
-          geometries.push({
-            type: 'polygon',
-            // According to the GeoJSON specification.
-            // First must be exterior, and the rest are all interior(holes).
-            exterior: coordinates[0],
-            interiors: coordinates.slice(1)
-          });
-        }
-
-        if (geo.type === 'MultiPolygon') {
-          var coordinates = geo.coordinates;
-          each(coordinates, function (item) {
-            if (item[0]) {
-              geometries.push({
-                type: 'polygon',
-                exterior: item[0],
-                interiors: item.slice(1)
-              });
-            }
-          });
-        }
-
-        var region = new Region(properties[nameProperty || 'name'], geometries, properties.cp);
-        region.properties = properties;
-        return region;
-      });
-    }
-
     var number = /*#__PURE__*/Object.freeze({
         __proto__: null,
         linearMap: linearMap,
@@ -37352,36 +38979,6 @@
             shadowManager.removeUnused();
             this._visibleList = newVisibleList;
         };
-        SVGPainter.prototype._getDefs = function (isForceCreating) {
-            var svgRoot = this._svgDom;
-            var defs = svgRoot.getElementsByTagName('defs');
-            if (defs.length === 0) {
-                if (isForceCreating) {
-                    var defs_1 = svgRoot.insertBefore(createElement('defs'), svgRoot.firstChild);
-                    if (!defs_1.contains) {
-                        defs_1.contains = function (el) {
-                            var children = defs_1.children;
-                            if (!children) {
-                                return false;
-                            }
-                            for (var i = children.length - 1; i >= 0; --i) {
-                                if (children[i] === el) {
-                                    return true;
-                                }
-                            }
-                            return false;
-                        };
-                    }
-                    return defs_1;
-                }
-                else {
-                    return null;
-                }
-            }
-            else {
-                return defs[0];
-            }
-        };
         SVGPainter.prototype.resize = function (width, height) {
             var viewport = this._viewport;
             viewport.style.display = 'none';
@@ -38467,7 +40064,6 @@
 
         _this.type = LineSeriesModel.type;
         _this.hasSymbolVisual = true;
-        _this.legendSymbol = 'line';
         return _this;
       }
 
@@ -38485,6 +40081,28 @@
         });
       };
 
+      LineSeriesModel.prototype.getLegendIcon = function (opt) {
+        var group = new Group();
+        var line = createSymbol('line', 0, opt.itemHeight / 2, opt.itemWidth, 0, opt.lineStyle.stroke, false);
+        group.add(line);
+        line.setStyle(opt.lineStyle);
+        var visualType = this.getData().getVisual('symbol');
+        var symbolType = visualType === 'none' ? 'circle' : visualType; // Symbol size is 80% when there is a line
+
+        var size = opt.itemHeight * 0.8;
+        var symbol = createSymbol(symbolType, (opt.itemWidth - size) / 2, (opt.itemHeight - size) / 2, size, size, opt.itemStyle.fill, opt.symbolKeepAspect);
+        group.add(symbol);
+        symbol.setStyle(opt.itemStyle);
+
+        if (symbolType.indexOf('empty') > -1) {
+          symbol.style.stroke = symbol.style.fill;
+          symbol.style.fill = '#fff';
+          symbol.style.lineWidth = 2;
+        }
+
+        return group;
+      };
+
       LineSeriesModel.type = 'series.line';
       LineSeriesModel.dependencies = ['grid', 'polar'];
       LineSeriesModel.defaultOption = {
@@ -38496,6 +40114,8 @@
         label: {
           position: 'top'
         },
+        // itemStyle: {
+        // },
         endLabel: {
           show: false,
           valueAnimation: true,
@@ -38738,7 +40358,6 @@
         var selectItemStyle;
         var focus;
         var blurScope;
-        var symbolOffset;
         var labelStatesModels;
         var hoverScale;
         var cursorStyle;
@@ -38749,7 +40368,6 @@
           selectItemStyle = seriesScope.selectItemStyle;
           focus = seriesScope.focus;
           blurScope = seriesScope.blurScope;
-          symbolOffset = seriesScope.symbolOffset;
           labelStatesModels = seriesScope.labelStatesModels;
           hoverScale = seriesScope.hoverScale;
           cursorStyle = seriesScope.cursorStyle;
@@ -38763,7 +40381,6 @@
           blurItemStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle();
           focus = emphasisModel.get('focus');
           blurScope = emphasisModel.get('blurScope');
-          symbolOffset = itemModel.getShallow('symbolOffset');
           labelStatesModels = getLabelStatesModels(itemModel);
           hoverScale = emphasisModel.getShallow('scale');
           cursorStyle = itemModel.getShallow('cursor');
@@ -38771,10 +40388,15 @@
 
         var symbolRotate = data.getItemVisual(idx, 'symbolRotate');
         symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0);
+        var symbolOffset = data.getItemVisual(idx, 'symbolOffset') || 0;
 
         if (symbolOffset) {
+          if (!isArray(symbolOffset)) {
+            symbolOffset = [symbolOffset, symbolOffset];
+          }
+
           symbolPath.x = parsePercent$1(symbolOffset[0], symbolSize[0]);
-          symbolPath.y = parsePercent$1(symbolOffset[1], symbolSize[1]);
+          symbolPath.y = parsePercent$1(retrieve2(symbolOffset[1], symbolOffset[0]) || 0, symbolSize[1]);
         }
 
         cursorStyle && symbolPath.attr('cursor', cursorStyle);
@@ -38897,7 +40519,7 @@
 
       Symbol.getSymbolSize = function (data, idx) {
         var symbolSize = data.getItemVisual(idx, 'symbolSize');
-        return symbolSize instanceof Array ? symbolSize.slice() : [+symbolSize, +symbolSize];
+        return isArray(symbolSize) ? symbolSize.slice() : [+symbolSize, +symbolSize];
       };
 
       return Symbol;
@@ -38933,8 +40555,6 @@
         selectItemStyle: seriesModel.getModel(['select', 'itemStyle']).getItemStyle(),
         focus: emphasisModel.get('focus'),
         blurScope: emphasisModel.get('blurScope'),
-        symbolRotate: seriesModel.get('symbolRotate'),
-        symbolOffset: seriesModel.get('symbolOffset'),
         hoverScale: emphasisModel.get('scale'),
         labelStatesModels: getLabelStatesModels(seriesModel),
         cursorStyle: seriesModel.get('cursor')
@@ -39270,24 +40890,7 @@
             break;
 
           case '-':
-            var oldIdx = diffItem.idx;
-            var rawIndex = oldData.getRawIndex(oldIdx);
-            var oldDataDimsForPoint = oldDataNewCoordInfo.dataDimsForPoint;
-            oldIdx2 = oldIdx * 2; // Data is replaced. In the case of dynamic data queue
-            // FIXME FIXME FIXME
-
-            if (rawIndex !== oldIdx) {
-              var newPt = newCoordSys.dataToPoint([oldData.get(oldDataDimsForPoint[0], oldIdx), oldData.get(oldDataDimsForPoint[1], oldIdx)]);
-              var newStackedOnPt = getStackedOnPoint(oldDataNewCoordInfo, newCoordSys, oldData, oldIdx);
-              currPoints.push(oldPoints[oldIdx2], oldPoints[oldIdx2 + 1]);
-              nextPoints.push(newPt[0], newPt[1]);
-              currStackedPoints.push(oldStackedOnPoints[oldIdx2], oldStackedOnPoints[oldIdx2 + 1]);
-              nextStackedPoints.push(newStackedOnPt[0], newStackedOnPt[1]);
-              rawIndices.push(rawIndex);
-            } else {
-              pointAdded = false;
-            }
-
+            pointAdded = false;
         } // Original indices
 
 
@@ -40401,7 +42004,7 @@
 
         if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') {
           var emphasisLineStyle = polyline.getState('emphasis').style;
-          emphasisLineStyle.lineWidth = polyline.style.lineWidth + 1;
+          emphasisLineStyle.lineWidth = +polyline.style.lineWidth + 1;
         } // Needs seriesIndex for focus
 
 
@@ -40490,7 +42093,10 @@
             symbol = new Symbol(data, dataIndex);
             symbol.x = x;
             symbol.y = y;
-            symbol.setZ(seriesModel.get('zlevel'), seriesModel.get('z'));
+            symbol.setZ(seriesModel.get('zlevel'), seriesModel.get('z')); // ensure label text of the temporal symbol is on the top of line and area polygon
+
+            var symbolLabel = symbol.getSymbolPath().getTextContent();
+            symbolLabel && (symbolLabel.z2 = this._polyline.z2 + 1);
             symbol.__temp = true;
             data.setItemGraphicEl(dataIndex, symbol); // Stop scale animation
 
@@ -41132,7 +42738,23 @@
     function install$2(registers) {
       registers.registerChartView(LineView);
       registers.registerSeriesModel(LineSeriesModel);
-      registers.registerLayout(pointsLayout('line', true)); // Down sample after filter
+      registers.registerLayout(pointsLayout('line', true));
+      registers.registerVisual({
+        seriesType: 'line',
+        reset: function (seriesModel) {
+          var data = seriesModel.getData(); // Visual coding for legend
+
+          var lineStyle = seriesModel.getModel('lineStyle').getLineStyle();
+
+          if (lineStyle && !lineStyle.stroke) {
+            // Fill in visual should be palette color if
+            // has color callback
+            lineStyle.stroke = data.getVisual('style').fill;
+          }
+
+          data.setVisual('legendLineStyle', lineStyle);
+        }
+      }); // Down sample after filter
 
       registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('line'));
     }
@@ -41345,8 +42967,6 @@
       return SausagePath;
     }(Path);
 
-    var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'borderWidth'];
-    var BAR_BORDER_RADIUS_QUERY = ['itemStyle', 'borderRadius'];
     var _eventPos = [0, 0];
     var mathMax$6 = Math.max;
     var mathMin$6 = Math.min;
@@ -42026,7 +43646,7 @@
       var style = data.getItemVisual(dataIndex, 'style');
 
       if (!isPolar) {
-        el.setShape('r', itemModel.get(BAR_BORDER_RADIUS_QUERY) || 0);
+        el.setShape('r', itemModel.get(['itemStyle', 'borderRadius']) || 0);
       }
 
       el.useStyle(style);
@@ -42067,7 +43687,14 @@
 
 
     function getLineWidth(itemModel, rawLayout) {
-      var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0; // width or height may be NaN for empty data
+      // Has no border.
+      var borderColor = itemModel.get(['itemStyle', 'borderColor']);
+
+      if (!borderColor || borderColor === 'none') {
+        return 0;
+      }
+
+      var lineWidth = itemModel.get(['itemStyle', 'borderWidth']) || 0; // width or height may be NaN for empty data
 
       var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width);
       var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height);
@@ -42258,14 +43885,7 @@
       registers.registerLayout(registers.PRIORITY.VISUAL.LAYOUT, 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`.
 
-      registers.registerLayout(registers.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, largeLayout);
-      registers.registerVisual({
-        seriesType: 'bar',
-        reset: function (seriesModel) {
-          // Visual coding for legend
-          seriesModel.getData().setVisual('legendSymbol', 'roundRect');
-        }
-      }); // Down sample after filter
+      registers.registerLayout(registers.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, largeLayout); // Down sample after filter
 
       registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('bar'));
       /**
@@ -42925,7 +44545,13 @@
         var itemModel = data.getItemModel(idx);
         var emphasisModel = itemModel.getModel('emphasis');
         var layout = data.getItemLayout(idx);
-        var sectorShape = extend(getSectorCornerRadius(itemModel.getModel('itemStyle'), layout) || {}, layout);
+        var sectorShape = extend(getSectorCornerRadius(itemModel.getModel('itemStyle'), layout) || {}, layout); // Ignore NaN data.
+
+        if (isNaN(sectorShape.startAngle)) {
+          // Use NaN shape to avoid drawing shape.
+          sector.setShape(sectorShape);
+          return;
+        }
 
         if (firstCreate) {
           sector.setShape(sectorShape);
@@ -45240,14 +46866,6 @@
         var truncateOpt = axisModel.get('nameTruncate', true) || {};
         var ellipsis = truncateOpt.ellipsis;
         var maxWidth = retrieve(opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth);
-        var tooltipOpt = axisModel.get('tooltip', true);
-        var mainType = axisModel.mainType;
-        var formatterParams = {
-          componentType: mainType,
-          name: name,
-          $vars: ['name']
-        };
-        formatterParams[mainType + 'Index'] = axisModel.componentIndex;
         var textEl = new ZRText({
           x: pos[0],
           y: pos[1],
@@ -45265,13 +46883,11 @@
           }),
           z2: 1
         });
-        textEl.tooltip = tooltipOpt && tooltipOpt.show ? extend({
-          content: name,
-          formatter: function () {
-            return name;
-          },
-          formatterParams: formatterParams
-        }, tooltipOpt) : null;
+        setTooltipConfig({
+          el: textEl,
+          componentModel: axisModel,
+          itemName: name
+        });
         textEl.__fullText = name; // Id for animation
 
         textEl.anid = 'name';
@@ -47814,6 +49430,7 @@
         var _this = _super !== null && _super.apply(this, arguments) || this;
 
         _this.type = GraphicComponentModel.type;
+        _this.preventAutoZ = true;
         return _this;
       }
 
@@ -48039,6 +49656,12 @@
             elInner.__ecGraphicWidthOption = elOption.width;
             elInner.__ecGraphicHeightOption = elOption.height;
             setEventData(el, graphicModel, elOption);
+            setTooltipConfig({
+              el: el,
+              componentModel: graphicModel,
+              itemName: el.name,
+              itemTooltipOption: elOption.tooltip
+            });
           }
         });
       };
@@ -49599,7 +51222,8 @@
         // textStyle: {},
         // feature
         tooltip: {
-          show: false
+          show: false,
+          position: 'bottom'
         }
       };
       return ToolboxModel;
@@ -49806,24 +51430,14 @@
               ignore: true
             });
             path.setTextContent(textContent);
-            var tooltipModel = toolboxModel.getModel('tooltip');
-
-            if (tooltipModel && tooltipModel.get('show')) {
-              path.tooltip = extend({
-                content: titlesMap[iconName],
-                formatter: tooltipModel.get('formatter', true) || function () {
-                  return titlesMap[iconName];
-                },
-                formatterParams: {
-                  componentType: 'toolbox',
-                  name: iconName,
-                  title: titlesMap[iconName],
-                  $vars: ['name', 'title']
-                },
-                position: tooltipModel.get('position', true) || 'bottom'
-              }, tooltipModel.option);
-            } // graphic.enableHoverEmphasis(path);
-
+            setTooltipConfig({
+              el: path,
+              componentModel: toolboxModel,
+              itemName: iconName,
+              formatterParamsExtra: {
+                title: titlesMap[iconName]
+              }
+            }); // graphic.enableHoverEmphasis(path);
 
             path.__title = titlesMap[iconName];
             path.on('mouseover', function () {
@@ -52345,56 +53959,51 @@
       return TooltipModel;
     }(ComponentModel);
 
-    /*
-    * 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.
-    */
-
-
-    /**
-     * AUTO-GENERATED FILE. DO NOT MODIFY.
-     */
+    /* global document */
 
-    /*
-    * 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.
-    */
     function shouldTooltipConfine(tooltipModel) {
       var confineOption = tooltipModel.get('confine');
       return confineOption != null ? !!confineOption // In richText mode, the outside part can not be visible.
       : tooltipModel.get('renderMode') === 'richText';
     }
 
-    var vendors = ['-ms-', '-moz-', '-o-', '-webkit-', ''];
-    var gCssText = 'position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;';
+    function testStyle(styleProps) {
+      if (!env.domSupported) {
+        return;
+      }
+
+      var style = document.documentElement.style;
+
+      for (var i = 0, len = styleProps.length; i < len; i++) {
+        if (styleProps[i] in style) {
+          return styleProps[i];
+        }
+      }
+    }
+
+    var TRANSFORM_VENDOR = testStyle(['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
+    var TRANSITION_VENDOR = testStyle(['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
+    function toCSSVendorPrefix(styleVendor, styleProp) {
+      if (!styleVendor) {
+        return styleProp;
+      }
+
+      styleProp = toCamelCase(styleProp, true);
+      var idx = styleVendor.indexOf(styleProp);
+      styleVendor = idx === -1 ? styleProp : "-" + styleVendor.slice(0, idx) + "-" + styleProp;
+      return styleVendor.toLowerCase();
+    }
+    function getComputedStyle(el, style) {
+      var stl = el.currentStyle || document.defaultView && document.defaultView.getComputedStyle(el);
+      return stl ? style ? stl[style] : stl : null;
+    }
+
+    /* global document, window */
+
+    var CSS_TRANSITION_VENDOR = toCSSVendorPrefix(TRANSITION_VENDOR, 'transition');
+    var CSS_TRANSFORM_VENDOR = toCSSVendorPrefix(TRANSFORM_VENDOR, 'transform'); // eslint-disable-next-line
+
+    var gCssText = "position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;" + (env.transform3dSupported ? 'will-change:transform;' : '');
 
     function mirrorPos(pos) {
       pos = pos === 'left' ? 'right' : pos === 'right' ? 'left' : pos === 'top' ? 'bottom' : 'top';
@@ -52408,35 +54017,55 @@
 
       borderColor = convertToColorString(borderColor);
       var arrowPos = mirrorPos(arrowPosition);
-      var positionStyle = '';
-      var transformStyle = '';
+      var positionStyle = arrowPos + ":-6px;";
+      var transformStyle = CSS_TRANSFORM_VENDOR + ':';
 
       if (indexOf(['left', 'right'], arrowPos) > -1) {
-        positionStyle = arrowPos + ":-6px;top:50%;";
-        transformStyle = "translateY(-50%) rotate(" + (arrowPos === 'left' ? -225 : -45) + "deg)";
+        positionStyle += 'top:50%';
+        transformStyle += "translateY(-50%) rotate(" + (arrowPos === 'left' ? -225 : -45) + "deg)";
       } else {
-        positionStyle = arrowPos + ":-6px;left:50%;";
-        transformStyle = "translateX(-50%) rotate(" + (arrowPos === 'top' ? 225 : 45) + "deg)";
+        positionStyle += 'left:50%';
+        transformStyle += "translateX(-50%) rotate(" + (arrowPos === 'top' ? 225 : 45) + "deg)";
       }
 
-      transformStyle = map(vendors, function (vendorPrefix) {
-        return vendorPrefix + 'transform:' + transformStyle;
-      }).join(';');
-      var styleCss = ['position:absolute;width:10px;height:10px;', "" + positionStyle + transformStyle + ";", "border-bottom: " + borderColor + " solid 1px;", "border-right: " + borderColor + " solid 1px;", "background-color: " + backgroundColor + ";", 'box-shadow: 8px 8px 16px -3px #000;'];
+      var borderStyle = borderColor + " solid 1px;";
+      var styleCss = ['position:absolute;width:10px;height:10px;', positionStyle + ";" + transformStyle + ";", "border-bottom:" + borderStyle, "border-right:" + borderStyle, "background-color:" + backgroundColor + ";", 'box-shadow:8px 8px 16px -3px #000;'];
       return "<div style=\"" + styleCss.join('') + "\"></div>";
     }
 
     function assembleTransition(duration, onlyFade) {
-      var transitionCurve = 'cubic-bezier(0.23, 1, 0.32, 1)';
-      var transitionText = 'opacity ' + duration / 2 + 's ' + transitionCurve + ',' + 'visibility ' + duration / 2 + 's ' + transitionCurve;
+      var transitionCurve = 'cubic-bezier(0.23,1,0.32,1)';
+      var transitionOption = " " + duration / 2 + "s " + transitionCurve;
+      var transitionText = "opacity" + transitionOption + ",visibility" + transitionOption;
 
       if (!onlyFade) {
-        transitionText += ',left ' + duration + 's ' + transitionCurve + ',top ' + duration + 's ' + transitionCurve;
+        transitionOption = " " + duration + "s " + transitionCurve;
+        transitionText += env.transformSupported ? "," + TRANSFORM_VENDOR + transitionOption : ",left" + transitionOption + ",top" + transitionOption;
       }
 
-      return map(vendors, function (vendorPrefix) {
-        return vendorPrefix + 'transition:' + transitionText;
-      }).join(';');
+      return CSS_TRANSITION_VENDOR + ':' + transitionText;
+    }
+
+    function assembleTransform(el, x, y, toString) {
+      // If using float on style, the final width of the dom might
+      // keep changing slightly while mouse move. So `toFixed(0)` them.
+      var x0;
+      var y0; // not support transform, use `left` and `top` instead.
+
+      if (!env.transformSupported) {
+        x0 = x.toFixed(0);
+        y0 = y.toFixed(0);
+        return toString ? "top:" + y0 + "px;left:" + x0 + "px;" : [['top', y0 + "px"], ['left', x0 + "px"]];
+      } // support transform
+      // FIXME: the padding of parent element will affect the position of tooltip
+
+
+      var stl = getComputedStyle(el.parentElement);
+      x0 = (x - parseInt(stl.paddingLeft, 10)).toFixed(0);
+      y0 = (y - parseInt(stl.paddingTop, 10)).toFixed(0);
+      var is3d = env.transform3dSupported;
+      var translate = "translate" + (is3d ? '3d' : '') + "(" + x0 + "px," + y0 + "px" + (is3d ? ',0' : '') + ")";
+      return toString ? CSS_TRANSFORM_VENDOR + ':' + translate + ';' : [[TRANSFORM_VENDOR, translate]];
     }
     /**
      * @param {Object} textStyle
@@ -52482,10 +54111,10 @@
 
       if (backgroundColor) {
         if (env.canvasSupported) {
-          cssText.push('background-Color:' + backgroundColor);
+          cssText.push('background-color:' + backgroundColor);
         } else {
           // for ie
-          cssText.push('background-Color:#' + toHex(backgroundColor));
+          cssText.push('background-color:#' + toHex(backgroundColor));
           cssText.push('filter:alpha(opacity=70)');
         }
       } // Border style
@@ -52561,7 +54190,8 @@
         if (appendToBody) {
           document.body.appendChild(el);
         } else {
-          container.appendChild(el);
+          // PENDING
+          container.prepend(el);
         }
 
         this._container = container; // FIXME
@@ -52617,10 +54247,10 @@
         // FIXME
         // Move this logic to ec main?
         var container = this._container;
-        var stl = container.currentStyle || document.defaultView.getComputedStyle(container);
+        var position = getComputedStyle(container, 'position');
         var domStyle = container.style;
 
-        if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
+        if (domStyle.position !== 'absolute' && position !== 'absolute') {
           domStyle.position = 'relative';
         } // move tooltip if chart resized
 
@@ -52637,20 +54267,21 @@
         clearTimeout(this._hideTimeout);
         clearTimeout(this._longHideTimeout);
         var el = this.el;
+        var style = el.style;
         var styleCoord = this._styleCoord;
-        var offset = el.offsetHeight / 2;
-        nearPointColor = convertToColorString(nearPointColor);
-        el.style.cssText = gCssText + assembleCssText(tooltipModel, !this._firstShow, this._longHide) // 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:' + styleCoord[0] + 'px;top:' + (styleCoord[1] - offset) + 'px;' + ("border-color: " + nearPointColor + ";") + (tooltipModel.get('extraCssText') || '');
-        el.style.display = el.innerHTML ? 'block' : 'none'; // If mouse occasionally move over the tooltip, a mouseout event will be
-        // triggered by canvas, and cause some unexpectable result like dragging
-        // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
-        // it. Although it is not supported by IE8~IE10, fortunately it is a rare
-        // scenario.
-
-        el.style.pointerEvents = this._enterable ? 'auto' : 'none';
+
+        if (!el.innerHTML) {
+          style.display = 'none';
+        } else {
+          style.cssText = gCssText + assembleCssText(tooltipModel, !this._firstShow, this._longHide) // initial transform
+          + assembleTransform(el, styleCoord[0], styleCoord[1], true) + ("border-color:" + convertToColorString(nearPointColor) + ";") + (tooltipModel.get('extraCssText') || '') // If mouse occasionally move over the tooltip, a mouseout event will be
+          // triggered by canvas, and cause some unexpectable result like dragging
+          // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
+          // it. Although it is not supported by IE8~IE10, fortunately it is a rare
+          // scenario.
+          + (";pointer-event:" + (this._enterable ? 'auto' : 'none'));
+        }
+
         this._show = true;
         this._firstShow = false;
         this._longHide = false;
@@ -52699,11 +54330,11 @@
         makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY);
 
         if (styleCoord[0] != null && styleCoord[1] != null) {
-          var style = this.el.style; // If using float on style, the final width of the dom might
-          // keep changing slightly while mouse move. So `toFixed(0)` them.
-
-          style.left = styleCoord[0].toFixed(0) + 'px';
-          style.top = styleCoord[1].toFixed(0) + 'px';
+          var style_1 = this.el.style;
+          var transforms = assembleTransform(this.el, styleCoord[0], styleCoord[1]);
+          each(transforms, function (transform) {
+            style_1[transform[0]] = transform[1];
+          });
         }
       };
       /**
@@ -52723,8 +54354,10 @@
       TooltipHTMLContent.prototype.hide = function () {
         var _this = this;
 
-        this.el.style.visibility = 'hidden';
-        this.el.style.opacity = '0';
+        var style = this.el.style;
+        style.visibility = 'hidden';
+        style.opacity = '0';
+        env.transform3dSupported && (style.willChange = '');
         this._show = false;
         this._longHideTimeout = setTimeout(function () {
           return _this._longHide = true;
@@ -52757,13 +54390,11 @@
         var height = this.el.clientHeight; // Consider browser compatibility.
         // IE8 does not support getComputedStyle.
 
-        if (document.defaultView && document.defaultView.getComputedStyle) {
-          var stl = document.defaultView.getComputedStyle(this.el);
+        var stl = getComputedStyle(this.el);
 
-          if (stl) {
-            width += parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10);
-            height += parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10);
-          }
+        if (stl) {
+          width += parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10);
+          height += parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10);
         }
 
         return {
@@ -52975,7 +54606,7 @@
 
     var bind$2 = bind;
     var each$8 = each;
-    var parsePercent$3 = parsePercent$1;
+    var parsePercent$2 = parsePercent$1;
     var proxyRect = new Rect({
       shape: {
         x: -1,
@@ -53101,13 +54732,30 @@
         this._ticket = ''; // When triggered from axisPointer.
 
         var dataByCoordSys = payload.dataByCoordSys;
+        var cmptRef = findComponentReference(payload, ecModel, api);
+
+        if (cmptRef) {
+          var rect = cmptRef.el.getBoundingRect().clone();
+          rect.applyTransform(cmptRef.el.transform);
 
-        if (payload.tooltip && payload.x != null && payload.y != null) {
+          this._tryShow({
+            offsetX: rect.x + rect.width / 2,
+            offsetY: rect.y + rect.height / 2,
+            target: cmptRef.el,
+            position: payload.position,
+            // When manully trigger, the mouse is not on the el, so we'd better to
+            // position tooltip on the bottom of the el and display arrow is possible.
+            positionDefault: 'bottom'
+          }, dispatchAction);
+        } else if (payload.tooltip && payload.x != null && payload.y != null) {
           var el = proxyRect;
           el.x = payload.x;
           el.y = payload.y;
           el.update();
-          el.tooltip = payload.tooltip; // Manually show tooltip while view is not using zrender elements.
+          getECData(el).tooltipConfig = {
+            name: null,
+            option: payload.tooltip
+          }; // Manually show tooltip while view is not using zrender elements.
 
           this._tryShow({
             offsetX: payload.x,
@@ -53135,8 +54783,11 @@
             this._tryShow({
               offsetX: cx,
               offsetY: cy,
+              target: pointInfo.el,
               position: payload.position,
-              target: pointInfo.el
+              // When manully trigger, the mouse is not on the el, so we'd better to
+              // position tooltip on the bottom of the el and display arrow is possible.
+              positionDefault: 'bottom'
             }, dispatchAction);
           }
         } else if (payload.x != null && payload.y != null) {
@@ -53191,7 +54842,7 @@
         }
 
         var data = seriesModel.getData();
-        var tooltipCascadedModel = buildTooltipModel([data.getItemModel(dataIndex), seriesModel, (seriesModel.coordinateSystem || {}).model, tooltipModel]);
+        var tooltipCascadedModel = buildTooltipModel([data.getItemModel(dataIndex), seriesModel, (seriesModel.coordinateSystem || {}).model], this._tooltipModel);
 
         if (tooltipCascadedModel.get('trigger') !== 'axis') {
           return;
@@ -53221,23 +54872,36 @@
 
         if (dataByCoordSys && dataByCoordSys.length) {
           this._showAxisTooltip(dataByCoordSys, e);
-        } // Always show item tooltip if mouse is on the element with dataIndex
-        else if (el && findEventDispatcher(el, function (target) {
-            return getECData(target).dataIndex != null;
-          }, true)) {
-            this._lastDataByCoordSys = null;
-
-            this._showSeriesItemTooltip(e, el, dispatchAction);
-          } // Tooltip provided directly. Like legend.
-          else if (el && el.tooltip) {
-              this._lastDataByCoordSys = null;
-
-              this._showComponentItemTooltip(e, el, dispatchAction);
-            } else {
-              this._lastDataByCoordSys = null;
+        } else if (el) {
+          this._lastDataByCoordSys = null;
+          var seriesDispatcher_1;
+          var cmptDispatcher_1;
+          findEventDispatcher(el, function (target) {
+            // Always show item tooltip if mouse is on the element with dataIndex
+            if (getECData(target).dataIndex != null) {
+              seriesDispatcher_1 = target;
+              return true;
+            } // Tooltip provided directly. Like legend.
+
+
+            if (getECData(target).tooltipConfig != null) {
+              cmptDispatcher_1 = target;
+              return true;
+            }
+          }, true);
+
+          if (seriesDispatcher_1) {
+            this._showSeriesItemTooltip(e, seriesDispatcher_1, dispatchAction);
+          } else if (cmptDispatcher_1) {
+            this._showComponentItemTooltip(e, cmptDispatcher_1, dispatchAction);
+          } else {
+            this._hide(dispatchAction);
+          }
+        } else {
+          this._lastDataByCoordSys = null;
 
-              this._hide(dispatchAction);
-            }
+          this._hide(dispatchAction);
+        }
       };
 
       TooltipView.prototype._showOrMove = function (tooltipModel, cb) {
@@ -53255,7 +54919,7 @@
         var ecModel = this._ecModel;
         var globalTooltipModel = this._tooltipModel;
         var point = [e.offsetX, e.offsetY];
-        var singleTooltipModel = buildTooltipModel([e.tooltipOption, globalTooltipModel]);
+        var singleTooltipModel = buildTooltipModel([e.tooltipOption], globalTooltipModel);
         var renderMode = this._renderMode;
         var cbParamsList = [];
         var articleMarkup = createTooltipMarkup('section', {
@@ -53333,10 +54997,7 @@
 
       };
 
-      TooltipView.prototype._showSeriesItemTooltip = function (e, el, dispatchAction) {
-        var dispatcher = findEventDispatcher(el, function (target) {
-          return getECData(target).dataIndex != null;
-        }, true);
+      TooltipView.prototype._showSeriesItemTooltip = function (e, dispatcher, dispatchAction) {
         var ecModel = this._ecModel;
         var ecData = getECData(dispatcher); // Use dataModel in element if possible
         // Used when mouseover on a element like markPoint or edge
@@ -53350,7 +55011,10 @@
         var dataType = ecData.dataType;
         var data = dataModel.getData(dataType);
         var renderMode = this._renderMode;
-        var tooltipModel = buildTooltipModel([data.getItemModel(dataIndex), dataModel, seriesModel && (seriesModel.coordinateSystem || {}).model, this._tooltipModel]);
+        var positionDefault = e.positionDefault;
+        var tooltipModel = buildTooltipModel([data.getItemModel(dataIndex), dataModel, seriesModel && (seriesModel.coordinateSystem || {}).model], this._tooltipModel, positionDefault ? {
+          position: positionDefault
+        } : null);
         var tooltipTrigger = tooltipModel.get('trigger');
 
         if (tooltipTrigger != null && tooltipTrigger !== 'item') {
@@ -53383,7 +55047,9 @@
       };
 
       TooltipView.prototype._showComponentItemTooltip = function (e, el, dispatchAction) {
-        var tooltipOpt = el.tooltip;
+        var ecData = getECData(el);
+        var tooltipConfig = ecData.tooltipConfig;
+        var tooltipOpt = tooltipConfig.option;
 
         if (isString(tooltipOpt)) {
           var content = tooltipOpt;
@@ -53394,7 +55060,18 @@
           };
         }
 
-        var subTooltipModel = new Model(tooltipOpt, this._tooltipModel, this._ecModel);
+        var tooltipModelCascade = [tooltipOpt];
+
+        var cmpt = this._ecModel.getComponent(ecData.componentMainType, ecData.componentIndex);
+
+        if (cmpt) {
+          tooltipModelCascade.push(cmpt);
+        }
+
+        var positionDefault = e.positionDefault;
+        var subTooltipModel = buildTooltipModel(tooltipModelCascade, this._tooltipModel, positionDefault ? {
+          position: positionDefault
+        } : null);
         var defaultHtml = subTooltipModel.get('content');
         var asyncTicket = Math.random() + ''; // PENDING: this case do not support richText style yet.
 
@@ -53403,8 +55080,11 @@
         // that requires setting `trigger` nothing on component yet.
 
         this._showOrMove(subTooltipModel, function () {
-          this._showTooltipContent( // Use formatterParams from element defined in component
-          subTooltipModel, defaultHtml, subTooltipModel.get('formatterParams') || {}, asyncTicket, e.offsetX, e.offsetY, e.position, el, markupStyleCreator);
+          // Use formatterParams from element defined in component
+          // Avoid users modify it.
+          var formatterParams = clone(subTooltipModel.get('formatterParams') || {});
+
+          this._showTooltipContent(subTooltipModel, defaultHtml, formatterParams, asyncTicket, e.offsetX, e.offsetY, e.position, el, markupStyleCreator);
         }); // If not dispatch showTip, tip may be hide triggered by axis.
 
 
@@ -53431,6 +55111,8 @@
 
         var nearPoint = this._getNearestPoint([x, y], params, tooltipModel.get('trigger'), tooltipModel.get('borderColor'));
 
+        var nearPointColor = nearPoint.color;
+
         if (formatter && isString(formatter)) {
           var useUTC = tooltipModel.ecModel.get('useUTC');
           var params0 = isArray(params) ? params[0] : params;
@@ -53445,7 +55127,7 @@
         } else if (isFunction(formatter)) {
           var callback = bind$2(function (cbTicket, html) {
             if (cbTicket === this._ticket) {
-              tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPoint.color, positionExpr);
+              tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr);
 
               this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el);
             }
@@ -53454,8 +55136,8 @@
           html = formatter(params, asyncTicket, callback);
         }
 
-        tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPoint.color, positionExpr);
-        tooltipContent.show(tooltipModel, nearPoint.color);
+        tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr);
+        tooltipContent.show(tooltipModel, nearPointColor);
 
         this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el);
       };
@@ -53497,8 +55179,8 @@
         }
 
         if (isArray(positionExpr)) {
-          x = parsePercent$3(positionExpr[0], viewWidth);
-          y = parsePercent$3(positionExpr[1], viewHeight);
+          x = parsePercent$2(positionExpr[0], viewWidth);
+          y = parsePercent$2(positionExpr[1], viewHeight);
         } else if (isObject(positionExpr)) {
           var boxLayoutPosition = positionExpr;
           boxLayoutPosition.width = contentSize[0];
@@ -53591,12 +55273,20 @@
      */
 
 
-    function buildTooltipModel(modelCascade) {
+    function buildTooltipModel(modelCascade, globalTooltipModel, defaultTooltipOption) {
       // Last is always tooltip model.
-      var resultModel = modelCascade.pop();
+      var ecModel = globalTooltipModel.ecModel;
+      var resultModel;
 
-      while (modelCascade.length) {
-        var tooltipOpt = modelCascade.pop();
+      if (defaultTooltipOption) {
+        resultModel = new Model(defaultTooltipOption, ecModel, ecModel);
+        resultModel = new Model(globalTooltipModel.option, resultModel, ecModel);
+      } else {
+        resultModel = globalTooltipModel;
+      }
+
+      for (var i = modelCascade.length - 1; i >= 0; i--) {
+        var tooltipOpt = modelCascade[i];
 
         if (tooltipOpt) {
           if (tooltipOpt instanceof Model) {
@@ -53614,7 +55304,9 @@
             };
           }
 
-          resultModel = new Model(tooltipOpt, resultModel, resultModel.ecModel);
+          if (tooltipOpt) {
+            resultModel = new Model(tooltipOpt, resultModel, ecModel);
+          }
         }
       }
 
@@ -53706,6 +55398,57 @@
     function isCenterAlign(align) {
       return align === 'center' || align === 'middle';
     }
+    /**
+     * Find target component by payload like:
+     * ```js
+     * { legendId: 'some_id', name: 'xxx' }
+     * { toolboxIndex: 1, name: 'xxx' }
+     * { geoName: 'some_name', name: 'xxx' }
+     * ```
+     * PENDING: at present only
+     *
+     * If not found, return null/undefined.
+     */
+
+
+    function findComponentReference(payload, ecModel, api) {
+      var queryOptionMap = preParseFinder(payload).queryOptionMap;
+      var componentMainType = queryOptionMap.keys()[0];
+
+      if (!componentMainType || componentMainType === 'series') {
+        return;
+      }
+
+      var queryResult = queryReferringComponents(ecModel, componentMainType, queryOptionMap.get(componentMainType), {
+        useDefault: false,
+        enableAll: false,
+        enableNone: false
+      });
+      var model = queryResult.models[0];
+
+      if (!model) {
+        return;
+      }
+
+      var view = api.getViewOfComponentModel(model);
+      var el;
+      view.group.traverse(function (subEl) {
+        var tooltipConfig = getECData(subEl).tooltipConfig;
+
+        if (tooltipConfig && tooltipConfig.name === payload.name) {
+          el = subEl;
+          return true; // stop
+        }
+      });
+
+      if (el) {
+        return {
+          componentMainType: componentMainType,
+          componentIndex: model.componentIndex,
+          el: el
+        };
+      }
+    }
 
     function install$c(registers) {
       use(install$7);
@@ -53931,6 +55674,22 @@
       registers.registerComponentView(TitleView);
     }
 
+    function checkMarkerInSeries(seriesOpts, markerType) {
+      if (!seriesOpts) {
+        return false;
+      }
+
+      var seriesOptArr = isArray(seriesOpts) ? seriesOpts : [seriesOpts];
+
+      for (var idx = 0; idx < seriesOptArr.length; idx++) {
+        if (seriesOptArr[idx] && seriesOptArr[idx][markerType]) {
+          return true;
+        }
+      }
+
+      return false;
+    }
+
     function fillLabel(opt) {
       defaultEmphasis(opt, 'label', ['show']);
     } // { [componentType]: MarkerModel }
@@ -54508,8 +56267,10 @@
       registers.registerComponentModel(MarkPointModel);
       registers.registerComponentView(MarkPointView);
       registers.registerPreprocessor(function (opt) {
-        // Make sure markPoint component is enabled
-        opt.markPoint = opt.markPoint || {};
+        if (checkMarkerInSeries(opt.series, 'markPoint')) {
+          // Make sure markPoint component is enabled
+          opt.markPoint = opt.markPoint || {};
+        }
       });
     }
 
@@ -54536,6 +56297,7 @@
         symbol: ['circle', 'arrow'],
         symbolSize: [8, 16],
         //symbolRotate: 0,
+        symbolOffset: 0,
         precision: 2,
         tooltip: {
           trigger: 'item'
@@ -54663,8 +56425,13 @@
 
       var symbolSize = lineData.getItemVisual(idx, name + 'Size');
       var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate');
+      var symbolOffset = lineData.getItemVisual(idx, name + 'Offset') || 0;
+      var symbolKeepAspect = lineData.getItemVisual(idx, name + 'KeepAspect');
       var symbolSizeArr = isArray(symbolSize) ? symbolSize : [symbolSize, symbolSize];
-      var symbolPath = createSymbol(symbolType, -symbolSizeArr[0] / 2, -symbolSizeArr[1] / 2, symbolSizeArr[0], symbolSizeArr[1]);
+      var symbolOffsetArr = isArray(symbolOffset) ? symbolOffset : [symbolOffset, symbolOffset];
+      symbolOffsetArr[0] = parsePercent$1(symbolOffsetArr[0], symbolSizeArr[0]);
+      symbolOffsetArr[1] = parsePercent$1(retrieve2(symbolOffsetArr[1], symbolOffsetArr[0]), symbolSizeArr[1]);
+      var symbolPath = createSymbol(symbolType, -symbolSizeArr[0] / 2 + symbolOffsetArr[0], -symbolSizeArr[1] / 2 + symbolOffsetArr[1], symbolSizeArr[0], symbolSizeArr[1], null, symbolKeepAspect);
       symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate) ? void 0 : +symbolRotate * Math.PI / 180 || 0;
       symbolPath.name = name;
       return symbolPath;
@@ -55390,6 +57157,8 @@
         mlModel.setData(lineData);
         var symbolType = mlModel.get('symbol');
         var symbolSize = mlModel.get('symbolSize');
+        var symbolRotate = mlModel.get('symbolRotate');
+        var symbolOffset = mlModel.get('symbolOffset');
 
         if (!isArray(symbolType)) {
           symbolType = [symbolType, symbolType];
@@ -55397,6 +57166,14 @@
 
         if (!isArray(symbolSize)) {
           symbolSize = [symbolSize, symbolSize];
+        }
+
+        if (!isArray(symbolRotate)) {
+          symbolRotate = [symbolRotate, symbolRotate];
+        }
+
+        if (!isArray(symbolOffset)) {
+          symbolOffset = [symbolOffset, symbolOffset];
         } // Update visual and layout of from symbol and to symbol
 
 
@@ -55417,9 +57194,13 @@
           }
 
           lineData.setItemVisual(idx, {
+            fromSymbolKeepAspect: fromData.getItemVisual(idx, 'symbolKeepAspect'),
+            fromSymbolOffset: fromData.getItemVisual(idx, 'symbolOffset'),
             fromSymbolRotate: fromData.getItemVisual(idx, 'symbolRotate'),
             fromSymbolSize: fromData.getItemVisual(idx, 'symbolSize'),
             fromSymbol: fromData.getItemVisual(idx, 'symbol'),
+            toSymbolKeepAspect: toData.getItemVisual(idx, 'symbolKeepAspect'),
+            toSymbolOffset: toData.getItemVisual(idx, 'symbolOffset'),
             toSymbolRotate: toData.getItemVisual(idx, 'symbolRotate'),
             toSymbolSize: toData.getItemVisual(idx, 'symbolSize'),
             toSymbol: toData.getItemVisual(idx, 'symbol'),
@@ -55445,9 +57226,12 @@
           }
 
           data.setItemVisual(idx, {
-            symbolRotate: itemModel.get('symbolRotate'),
-            symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
-            symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
+            symbolKeepAspect: itemModel.get('symbolKeepAspect'),
+            // `0` should be considered as a valid value, so use `retrieve2` instead of `||`
+            symbolOffset: retrieve2(itemModel.get('symbolOffset'), symbolOffset[isFrom ? 0 : 1]),
+            symbolRotate: retrieve2(itemModel.get('symbolRotate', true), symbolRotate[isFrom ? 0 : 1]),
+            symbolSize: retrieve2(itemModel.get('symbolSize'), symbolSize[isFrom ? 0 : 1]),
+            symbol: retrieve2(itemModel.get('symbol', true), symbolType[isFrom ? 0 : 1]),
             style: style
           });
         }
@@ -55512,8 +57296,10 @@
       registers.registerComponentModel(MarkLineModel);
       registers.registerComponentView(MarkLineView);
       registers.registerPreprocessor(function (opt) {
-        // Make sure markLine component is enabled
-        opt.markLine = opt.markLine || {};
+        if (checkMarkerInSeries(opt.series, 'markLine')) {
+          // Make sure markLine component is enabled
+          opt.markLine = opt.markLine || {};
+        }
       });
     }
 
@@ -55723,22 +57509,19 @@
           // Layout
           var points = map(dimPermutations, function (dim) {
             return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
-          }); // If none of the area is inside coordSys, allClipped is set to be true
+          });
+          var xAxisScale = coordSys.getAxis('x').scale;
+          var yAxisScale = coordSys.getAxis('y').scale;
+          var xAxisExtent = xAxisScale.getExtent();
+          var yAxisExtent = yAxisScale.getExtent();
+          var xPointExtent = [xAxisScale.parse(areaData.get('x0', idx)), xAxisScale.parse(areaData.get('x1', idx))];
+          var yPointExtent = [yAxisScale.parse(areaData.get('y0', idx)), yAxisScale.parse(areaData.get('y1', idx))];
+          asc(xPointExtent);
+          asc(yPointExtent);
+          var overlapped = !(xAxisExtent[0] > xPointExtent[1] || xAxisExtent[1] < xPointExtent[0] || yAxisExtent[0] > yPointExtent[1] || yAxisExtent[1] < yPointExtent[0]); // If none of the area is inside coordSys, allClipped is set to be true
           // in layout so that label will not be displayed. See #12591
 
-          var allClipped = true;
-          each(dimPermutations, function (dim) {
-            if (!allClipped) {
-              return;
-            }
-
-            var xValue = areaData.get(dim[0], idx);
-            var yValue = areaData.get(dim[1], idx); // If is infinity, the axis should be considered not clipped
-
-            if ((isInifinity$1(xValue) || coordSys.getAxis('x').containData(xValue)) && (isInifinity$1(yValue) || coordSys.getAxis('y').containData(yValue))) {
-              allClipped = false;
-            }
-          });
+          var allClipped = !overlapped;
           areaData.setItemLayout(idx, {
             points: points,
             allClipped: allClipped
@@ -55872,8 +57655,10 @@
       registers.registerComponentModel(MarkAreaModel);
       registers.registerComponentView(MarkAreaView);
       registers.registerPreprocessor(function (opt) {
-        // Make sure markArea component is enabled
-        opt.markArea = opt.markArea || {};
+        if (checkMarkerInSeries(opt.series, 'markArea')) {
+          // Make sure markArea component is enabled
+          opt.markArea = opt.markArea || {};
+        }
       });
     }
 
@@ -56116,10 +57901,40 @@
         itemGap: 10,
         itemWidth: 25,
         itemHeight: 14,
+        symbolSize: 'auto',
         inactiveColor: '#ccc',
         inactiveBorderColor: '#ccc',
+        inactiveBorderWidth: 'auto',
         itemStyle: {
-          borderWidth: 0
+          color: 'inherit',
+          opacity: 'inherit',
+          decal: 'inherit',
+          shadowBlur: 0,
+          shadowColor: null,
+          shadowOffsetX: 0,
+          shadowOffsetY: 0,
+          borderColor: 'inherit',
+          borderWidth: 'auto',
+          borderCap: 'inherit',
+          borderJoin: 'inherit',
+          borderDashOffset: 'inherit',
+          borderMiterLimit: 'inherit'
+        },
+        lineStyle: {
+          width: 'auto',
+          color: 'inherit',
+          inactiveColor: '#ccc',
+          inactiveWidth: 2,
+          opacity: 'inherit',
+          type: 'inherit',
+          cap: 'inherit',
+          join: 'inherit',
+          dashOffset: 'inherit',
+          miterLimit: 'inherit',
+          shadowBlur: 0,
+          shadowColor: null,
+          shadowOffsetX: 0,
+          shadowOffsetY: 0
         },
         textStyle: {
           color: '#333'
@@ -56256,8 +58071,8 @@
         ecModel.eachRawSeries(function (seriesModel) {
           !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id);
         });
-        each$9(legendModel.getData(), function (itemModel, dataIndex) {
-          var name = itemModel.get('name'); // Use empty string or \n as a newline string
+        each$9(legendModel.getData(), function (legendItemModel, dataIndex) {
+          var name = legendItemModel.get('name'); // Use empty string or \n as a newline string
 
           if (!this.newlineDisabled && (name === '' || name === '\n')) {
             var g = new Group$1(); // @ts-ignore
@@ -56278,15 +58093,17 @@
 
           if (seriesModel) {
             var data = seriesModel.getData();
-            var style = data.getVisual('style');
-            var color = style[data.getVisual('drawType')] || style.fill;
-            var borderColor = style.stroke;
-            var decal = style.decal; // Using rect symbol defaultly
+            var lineVisualStyle = data.getVisual('legendLineStyle') || {};
+            var symbolType = data.getVisual('legendSymbol');
+            /**
+             * `data.getVisual('style')` may be the color from the register
+             * in series. For example, for line series,
+             */
 
-            var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect';
-            var symbolType = data.getVisual('symbol');
+            var style = data.getVisual('style');
+            data.getVisual('symbolSize');
 
-            var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, borderColor, decal, selectMode);
+            var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, style, symbolType, selectMode);
 
             itemGroup.on('click', curry$1(dispatchSelectAction, name, null, api, excludeSeriesId)).on('mouseover', curry$1(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry$1(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));
             legendDrawnMap.set(name, true);
@@ -56307,21 +58124,17 @@
 
                 var idx = provider.indexOfName(name);
                 var style = provider.getItemVisual(idx, 'style');
-                var borderColor = style.stroke;
-                var decal = style.decal;
-                var color = style.fill;
+                var symbolType = provider.getItemVisual(idx, 'legendSymbol');
                 var colorArr = parse(style.fill); // Color may be set to transparent in visualMap when data is out of range.
                 // Do not show nothing.
 
                 if (colorArr && colorArr[3] === 0) {
                   colorArr[3] = 0.2; // TODO color is set to 0, 0, 0, 0. Should show correct RGBA
 
-                  color = stringify(colorArr, 'rgba');
+                  style.fill = stringify(colorArr, 'rgba');
                 }
 
-                var legendSymbolType = 'roundRect';
-
-                var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, null, itemAlign, color, borderColor, decal, selectMode); // FIXME: consider different series has items with the same name.
+                var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, {}, style, symbolType, selectMode); // FIXME: consider different series has items with the same name.
 
 
                 itemGroup.on('click', curry$1(dispatchSelectAction, null, name, api, excludeSeriesId)) // Should not specify the series name, consider legend controls
@@ -56374,38 +58187,39 @@
         });
       };
 
-      LegendView.prototype._createItem = function (name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, borderColor, decal, selectMode) {
+      LegendView.prototype._createItem = function (seriesModel, name, dataIndex, itemModel, legendModel, itemAlign, lineVisualStyle, itemVisualStyle, symbolType, selectMode) {
+        var drawType = seriesModel.visualDrawType;
         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 symbolKeepAspect = itemModel.get('symbolKeepAspect');
+        var legendIconType = itemModel.get('icon');
+        symbolType = legendIconType || symbolType || 'roundRect';
+        var legendLineStyle = legendModel.getModel('lineStyle');
+        var style = getLegendStyle(symbolType, itemModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected);
         var itemGroup = new Group$1();
         var textStyleModel = itemModel.getModel('textStyle');
-        var itemIcon = itemModel.get('icon');
-        var tooltipModel = itemModel.getModel('tooltip');
-        var legendGlobalTooltipModel = tooltipModel.parentModel; // Use user given icon first
-
-        legendSymbolType = itemIcon || legendSymbolType;
-        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, decal, isSelected)); // Compose symbols
-        // PENDING
-
-        if (!itemIcon && symbolType // At least show one symbol, can't be all none
-        && (symbolType !== legendSymbolType || symbolType === 'none')) {
-          var size = itemHeight * 0.8;
 
-          if (symbolType === 'none') {
-            symbolType = 'circle';
-          }
-
-          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(setSymbolStyle(legendSymbolCenter, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, decal, isSelected));
+        if (typeof seriesModel.getLegendIcon === 'function' && !legendIconType) {
+          // Series has specific way to define legend icon
+          itemGroup.add(seriesModel.getLegendIcon({
+            itemWidth: itemWidth,
+            itemHeight: itemHeight,
+            symbolType: symbolType,
+            symbolKeepAspect: symbolKeepAspect,
+            itemStyle: style.itemStyle,
+            lineStyle: style.lineStyle
+          }));
+        } else {
+          // Use default legend icon policy for most series
+          itemGroup.add(getDefaultLegendIcon({
+            itemWidth: itemWidth,
+            itemHeight: itemHeight,
+            symbolType: symbolType,
+            symbolKeepAspect: symbolKeepAspect,
+            itemStyle: style.itemStyle,
+            lineStyle: style.lineStyle
+          }));
         }
 
         var textX = itemAlign === 'left' ? itemWidth + 5 : -5;
@@ -56419,6 +58233,7 @@
           content = formatter(name);
         }
 
+        var inactiveColor = itemModel.get('inactiveColor');
         itemGroup.add(new ZRText({
           style: createTextStyle(textStyleModel, {
             text: content,
@@ -56434,22 +58249,15 @@
           shape: itemGroup.getBoundingRect(),
           invisible: true
         });
+        var tooltipModel = itemModel.getModel('tooltip');
 
         if (tooltipModel.get('show')) {
-          var formatterParams = {
-            componentType: 'legend',
-            legendIndex: legendModel.componentIndex,
-            name: name,
-            $vars: ['name']
-          };
-          hitRect.tooltip = extend({
-            content: name,
-            // Defaul formatter
-            formatter: legendGlobalTooltipModel.get('formatter', true) || function (params) {
-              return params.name;
-            },
-            formatterParams: formatterParams
-          }, tooltipModel.option);
+          setTooltipConfig({
+            el: hitRect,
+            componentModel: legendModel,
+            itemName: name,
+            itemTooltipOption: tooltipModel.option
+          });
         }
 
         itemGroup.add(hitRect);
@@ -56526,22 +58334,115 @@
       return LegendView;
     }(ComponentView);
 
-    function setSymbolStyle(symbol, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, decal, isSelected) {
-      var itemStyle;
+    function getLegendStyle(symbolType, legendModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected) {
+      /**
+       * Use series style if is inherit;
+       * elsewise, use legend style
+       */
+      // itemStyle
+      var legendItemModel = legendModel.getModel('itemStyle');
+      var itemProperties = ITEM_STYLE_KEY_MAP.concat([['decal']]);
+      var itemStyle = {};
+
+      for (var i = 0; i < itemProperties.length; ++i) {
+        var propName = itemProperties[i][itemProperties[i].length - 1];
+        var visualName = itemProperties[i][0];
+        var value = legendItemModel.getShallow(propName);
+
+        if (value === 'inherit') {
+          switch (visualName) {
+            case 'fill':
+              /**
+               * Series with visualDrawType as 'stroke' should have
+               * series stroke as legend fill
+               */
+              itemStyle.fill = itemVisualStyle[drawType];
+              break;
+
+            case 'stroke':
+              /**
+               * symbol type with "emptyXXX" should use fill color
+               * in visual style
+               */
+              itemStyle.stroke = itemVisualStyle[symbolType.startsWith('empty') ? 'fill' : 'stroke'];
+              break;
 
-      if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) {
-        itemStyle = legendModelItemStyle.getItemStyle();
-        symbol.style.stroke = borderColor;
-        symbol.style.decal = decal;
+            case 'opacity':
+              /**
+               * Use lineStyle.opacity if drawType is stroke
+               */
+              itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
+              break;
 
-        if (!isSelected) {
-          itemStyle.stroke = inactiveBorderColor;
+            default:
+              itemStyle[visualName] = itemVisualStyle[visualName];
+          }
+        } else if (value === 'auto' && visualName === 'lineWidth') {
+          // If lineStyle.width is 'auto', it is set to be 2 if series has border
+          itemStyle.lineWidth = itemVisualStyle.lineWidth > 0 ? 2 : 0;
+        } else {
+          itemStyle[visualName] = value;
         }
-      } else {
-        itemStyle = legendModelItemStyle.getItemStyle(['borderWidth', 'borderColor']);
+      } // lineStyle
+
+
+      var legendLineModel = legendModel.getModel('lineStyle');
+      var lineProperties = LINE_STYLE_KEY_MAP.concat([['inactiveColor'], ['inactiveWidth']]);
+      var lineStyle = {};
+
+      for (var i = 0; i < lineProperties.length; ++i) {
+        var propName = lineProperties[i][1];
+        var visualName = lineProperties[i][0];
+        var value = legendLineModel.getShallow(propName);
+
+        if (value === 'inherit') {
+          lineStyle[visualName] = lineVisualStyle[visualName];
+        } else if (value === 'auto' && visualName === 'lineWidth') {
+          // If lineStyle.width is 'auto', it is set to be 2 if series has border
+          lineStyle.lineWidth = lineVisualStyle.lineWidth > 0 ? 2 : 0;
+        } else {
+          lineStyle[visualName] = value;
+        }
+      } // Fix auto color to real color
+
+
+      itemStyle.fill === 'auto' && (itemStyle.fill = itemVisualStyle.fill);
+      itemStyle.stroke === 'auto' && (itemStyle.stroke = itemVisualStyle.fill);
+      lineStyle.stroke === 'auto' && (lineStyle.stroke = itemVisualStyle.fill);
+
+      if (!isSelected) {
+        var borderWidth = legendModel.get('inactiveBorderWidth');
+        /**
+         * Since stroke is set to be inactiveBorderColor, it may occur that
+         * there is no border in series but border in legend, so we need to
+         * use border only when series has border if is set to be auto
+         */
+
+        var visualHasBorder = itemStyle[symbolType.indexOf('empty') > -1 ? 'fill' : 'stroke'];
+        itemStyle.lineWidth = borderWidth === 'auto' ? itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0 : itemStyle.lineWidth;
+        itemStyle.fill = legendModel.get('inactiveColor');
+        itemStyle.stroke = legendModel.get('inactiveBorderColor');
+        lineStyle.stroke = legendLineStyle.get('inactiveColor');
+        lineStyle.lineWidth = legendLineStyle.get('inactiveWidth');
+      }
+
+      return {
+        itemStyle: itemStyle,
+        lineStyle: lineStyle
+      };
+    }
+
+    function getDefaultLegendIcon(opt) {
+      var symboType = opt.symbolType || 'roundRect';
+      var symbol = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
+      symbol.setStyle(opt.itemStyle);
+
+      if (symboType.indexOf('empty') > -1) {
+        symbol.style.stroke = symbol.style.fill;
+        symbol.style.fill = '#fff';
+        symbol.style.lineWidth = 2;
       }
 
-      symbol.setStyle(itemStyle);
       return symbol;
     }
 
@@ -58437,7 +60338,7 @@
           thisGroup.add(handleLabels[handleIndex] = new ZRText({
             silent: true,
             invisible: true,
-            style: {
+            style: createTextStyle(textStyleModel, {
               x: 0,
               y: 0,
               text: '',
@@ -58445,7 +60346,7 @@
               align: 'center',
               fill: textStyleModel.getTextColor(),
               font: textStyleModel.getFont()
-            },
+            }),
             z2: 10
           }));
         }, this); // Handle to move. Only visible when brushSelect is set true.
diff --git a/dist/echarts.common.js.map b/dist/echarts.common.js.map
index bbb2668..0914d45 100644
--- a/dist/echarts.common.js.map
+++ b/dist/echarts.common.js.map
@@ -1 +1 @@
-{"version":3,"file":"echarts.common.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/ [...]
\ No newline at end of file
+{"version":3,"file":"echarts.common.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/ [...]
\ No newline at end of file
diff --git a/dist/echarts.common.min.js b/dist/echarts.common.min.js
index ad10d31..1ab19bc 100644
--- a/dist/echarts.common.min.js
+++ b/dist/echarts.common.min.js
@@ -32,7 +32,7 @@
     LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
     OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     PERFORMANCE OF THIS SOFTWARE.
-    ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var i=function(){return(i=Object.assign||function(t){for(var e,n=1,i=argument [...]
+    ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var i=function(){return(i=Object.assign||function(t){for(var e,n=1,i=argument [...]
 /*!
     * ZRender, a high performance 2d drawing library.
     *
@@ -42,4 +42,4 @@
     * LICENSE
     * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
     */
-var Li=!a.canvasSupported,Pi={},Oi={};var Ri=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new hi,o=n.renderer||"canvas";if(Li)throw new Error("IE8 support has been dropped since 5.0");if(Pi[o]||(o=E(Pi)[0]),!Pi[o])throw new Error("Renderer '"+o+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
+var Li=!a.canvasSupported,Pi={},Oi={};var Ri=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new hi,o=n.renderer||"canvas";if(Li)throw new Error("IE8 support has been dropped since 5.0");if(Pi[o]||(o=E(Pi)[0]),!Pi[o])throw new Error("Renderer '"+o+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
diff --git a/dist/echarts.esm.js b/dist/echarts.esm.js
index d72c093..2ff84cb 100644
--- a/dist/echarts.esm.js
+++ b/dist/echarts.esm.js
@@ -87,6 +87,8 @@ var Env = (function () {
         this.touchEventsSupported = false;
         this.pointerEventsSupported = false;
         this.domSupported = false;
+        this.transformSupported = false;
+        this.transform3dSupported = false;
     }
     return Env;
 }());
@@ -137,6 +139,14 @@ function detect(ua, env) {
     env.pointerEventsSupported = 'onpointerdown' in window
         && (browser.edge || (browser.ie && +browser.version >= 11));
     env.domSupported = typeof document !== 'undefined';
+    var style = document.documentElement.style;
+    env.transform3dSupported = ((browser.ie && 'transition' in style)
+        || browser.edge
+        || (('WebKitCSSMatrix' in window) && ('m11' in new WebKitCSSMatrix()))
+        || 'MozPerspective' in style)
+        && !('OTransition' in style);
+    env.transformSupported = env.transform3dSupported
+        || (browser.ie && +browser.version >= 9);
 }
 
 var BUILTIN_OBJECT = {
@@ -2970,7 +2980,7 @@ var Track = (function () {
                         this.interpolable = false;
                     }
                 }
-                else if (typeof value !== 'number') {
+                else if (typeof value !== 'number' || isNaN(value)) {
                     this.interpolable = false;
                     return;
                 }
@@ -4589,6 +4599,10 @@ var Element = (function () {
         extend(this.textConfig, cfg);
         this.markRedraw();
     };
+    Element.prototype.removeTextConfig = function () {
+        this.textConfig = null;
+        this.markRedraw();
+    };
     Element.prototype.removeTextContent = function () {
         var textEl = this._textContent;
         if (textEl) {
@@ -6547,7 +6561,7 @@ function getInstance(id) {
 function registerPainter(name, Ctor) {
     painterCtors[name] = Ctor;
 }
-var version = '5.0.4';
+var version = '5.1.0';
 
 var zrender = /*#__PURE__*/Object.freeze({
     __proto__: null,
@@ -7729,6 +7743,30 @@ var innerUniqueIndex = getRandomIdBase();
  */
 
 function parseFinder(ecModel, finderInput, opt) {
+  var _a = preParseFinder(finderInput, opt),
+      mainTypeSpecified = _a.mainTypeSpecified,
+      queryOptionMap = _a.queryOptionMap,
+      others = _a.others;
+
+  var result = others;
+  var defaultMainType = opt ? opt.defaultMainType : null;
+
+  if (!mainTypeSpecified && defaultMainType) {
+    queryOptionMap.set(defaultMainType, {});
+  }
+
+  queryOptionMap.each(function (queryOption, mainType) {
+    var queryResult = queryReferringComponents(ecModel, mainType, queryOption, {
+      useDefault: defaultMainType === mainType,
+      enableAll: opt && opt.enableAll != null ? opt.enableAll : true,
+      enableNone: opt && opt.enableNone != null ? opt.enableNone : true
+    });
+    result[mainType + 'Models'] = queryResult.models;
+    result[mainType + 'Model'] = queryResult.models[0];
+  });
+  return result;
+}
+function preParseFinder(finderInput, opt) {
   var finder;
 
   if (isString(finderInput)) {
@@ -7740,12 +7778,12 @@ function parseFinder(ecModel, finderInput, opt) {
   }
 
   var queryOptionMap = createHashMap();
-  var result = {};
+  var others = {};
   var mainTypeSpecified = false;
   each(finder, function (value, key) {
     // Exclude 'dataIndex' and other illgal keys.
     if (key === 'dataIndex' || key === 'dataIndexInside') {
-      result[key] = value;
+      others[key] = value;
       return;
     }
 
@@ -7761,22 +7799,11 @@ function parseFinder(ecModel, finderInput, opt) {
     var queryOption = queryOptionMap.get(mainType) || queryOptionMap.set(mainType, {});
     queryOption[queryType] = value;
   });
-  var defaultMainType = opt ? opt.defaultMainType : null;
-
-  if (!mainTypeSpecified && defaultMainType) {
-    queryOptionMap.set(defaultMainType, {});
-  }
-
-  queryOptionMap.each(function (queryOption, mainType) {
-    var queryResult = queryReferringComponents(ecModel, mainType, queryOption, {
-      useDefault: defaultMainType === mainType,
-      enableAll: opt && opt.enableAll != null ? opt.enableAll : true,
-      enableNone: opt && opt.enableNone != null ? opt.enableNone : true
-    });
-    result[mainType + 'Models'] = queryResult.models;
-    result[mainType + 'Model'] = queryResult.models[0];
-  });
-  return result;
+  return {
+    mainTypeSpecified: mainTypeSpecified,
+    queryOptionMap: queryOptionMap,
+    others: others
+  };
 }
 var SINGLE_REFERRING = {
   useDefault: true,
@@ -8134,7 +8161,7 @@ function enableClassManagement(target) {
     }
 
     if (throwWhenNotFound && !clz) {
-      throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' not exists. Load it first.');
+      throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' is used but not imported.');
     }
 
     return clz;
@@ -8608,7 +8635,7 @@ function pushTokens(block, str, style, wrapInfo, styleName) {
         var tokenPadding = tokenStyle.padding;
         var tokenPaddingH = tokenPadding ? tokenPadding[1] + tokenPadding[3] : 0;
         if (tokenStyle.width != null && tokenStyle.width !== 'auto') {
-            var outerWidth_1 = parsePercent$2(tokenStyle.width, wrapInfo.width) + tokenPaddingH;
+            var outerWidth_1 = parsePercent(tokenStyle.width, wrapInfo.width) + tokenPaddingH;
             if (lines.length > 0) {
                 if (outerWidth_1 + wrapInfo.accumWidth > wrapInfo.width) {
                     strLines = str.split('\n');
@@ -8774,15 +8801,6 @@ function wrapText(text, font, lineWidth, isBreakAll, lastAccumWidth) {
         linesWidths: linesWidths
     };
 }
-function parsePercent$2(value, maxValue) {
-    if (typeof value === 'string') {
-        if (value.lastIndexOf('%') >= 0) {
-            return parseFloat(value) / 100 * maxValue;
-        }
-        return parseFloat(value);
-    }
-    return value;
-}
 
 var STYLE_MAGIC_KEY = '__zr_style_' + Math.round((Math.random() * 10));
 var DEFAULT_COMMON_STYLE = {
@@ -12268,8 +12286,7 @@ function allLeaveBlur(api) {
     });
   });
 }
-
-function toggleSeriesBlurState(targetSeriesIndex, focus, blurScope, api, isBlur) {
+function blurSeries(targetSeriesIndex, focus, blurScope, api) {
   var ecModel = api.getModel();
   blurScope = blurScope || 'coordinateSystem';
 
@@ -12280,11 +12297,6 @@ function toggleSeriesBlurState(targetSeriesIndex, focus, blurScope, api, isBlur)
     }
   }
 
-  if (!isBlur) {
-    allLeaveBlur(api);
-    return;
-  }
-
   if (targetSeriesIndex == null) {
     return;
   }
@@ -12346,12 +12358,28 @@ function toggleSeriesBlurState(targetSeriesIndex, focus, blurScope, api, isBlur)
     }
   });
 }
-function toggleSeriesBlurStateFromPayload(seriesModel, payload, api) {
-  if (!isHighDownPayload(payload)) {
+function blurComponent(componentMainType, componentIndex, api) {
+  if (componentMainType == null || componentIndex == null) {
+    return;
+  }
+
+  var componentModel = api.getModel().getComponent(componentMainType, componentIndex);
+
+  if (!componentModel) {
+    return;
+  }
+
+  var view = api.getViewOfComponentModel(componentModel);
+
+  if (!view || !view.focusBlurEnabled) {
     return;
   }
 
-  var isHighlight = payload.type === HIGHLIGHT_ACTION_TYPE;
+  view.group.traverse(function (child) {
+    singleEnterBlur(child);
+  });
+}
+function blurSeriesFromHighlightPayload(seriesModel, payload, api) {
   var seriesIndex = seriesModel.seriesIndex;
   var data = seriesModel.getData(payload.dataType);
   var dataIndex = queryDataIndex(data, payload); // Pick the first one if there is multiple/none exists.
@@ -12370,7 +12398,7 @@ function toggleSeriesBlurStateFromPayload(seriesModel, payload, api) {
 
   if (el) {
     var ecData = getECData(el);
-    toggleSeriesBlurState(seriesIndex, ecData.focus, ecData.blurScope, api, isHighlight);
+    blurSeries(seriesIndex, ecData.focus, ecData.blurScope, api);
   } else {
     // If there is no element put on the data. Try getting it from raw option
     // TODO Should put it on seriesModel?
@@ -12378,8 +12406,104 @@ function toggleSeriesBlurStateFromPayload(seriesModel, payload, api) {
     var blurScope = seriesModel.get(['emphasis', 'blurScope']);
 
     if (focus_1 != null) {
-      toggleSeriesBlurState(seriesIndex, focus_1, blurScope, api, isHighlight);
+      blurSeries(seriesIndex, focus_1, blurScope, api);
+    }
+  }
+}
+function findComponentHighDownDispatchers(componentMainType, componentIndex, name, api) {
+  var ret = {
+    focusSelf: false,
+    dispatchers: null
+  };
+
+  if (componentMainType == null || componentMainType === 'series' || componentIndex == null || name == null) {
+    return ret;
+  }
+
+  var componentModel = api.getModel().getComponent(componentMainType, componentIndex);
+
+  if (!componentModel) {
+    return ret;
+  }
+
+  var view = api.getViewOfComponentModel(componentModel);
+
+  if (!view || !view.findHighDownDispatchers) {
+    return ret;
+  }
+
+  var dispatchers = view.findHighDownDispatchers(name); // At presnet, the component (like Geo) only blur inside itself.
+  // So we do not use `blurScope` in component.
+
+  var focusSelf;
+
+  for (var i = 0; i < dispatchers.length; i++) {
+    if ("development" !== 'production' && !isHighDownDispatcher(dispatchers[i])) {
+      error('param should be highDownDispatcher');
     }
+
+    if (getECData(dispatchers[i]).focus === 'self') {
+      focusSelf = true;
+      break;
+    }
+  }
+
+  return {
+    focusSelf: focusSelf,
+    dispatchers: dispatchers
+  };
+}
+function handleGlobalMouseOverForHighDown(dispatcher, e, api) {
+  if ("development" !== 'production' && !isHighDownDispatcher(dispatcher)) {
+    error('param should be highDownDispatcher');
+  }
+
+  var ecData = getECData(dispatcher);
+
+  var _a = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api),
+      dispatchers = _a.dispatchers,
+      focusSelf = _a.focusSelf; // If `findHighDownDispatchers` is supported on the component,
+  // highlight/downplay elements with the same name.
+
+
+  if (dispatchers) {
+    if (focusSelf) {
+      blurComponent(ecData.componentMainType, ecData.componentIndex, api);
+    }
+
+    each(dispatchers, function (dispatcher) {
+      return enterEmphasisWhenMouseOver(dispatcher, e);
+    });
+  } else {
+    // Try blur all in the related series. Then emphasis the hoverred.
+    // TODO. progressive mode.
+    blurSeries(ecData.seriesIndex, ecData.focus, ecData.blurScope, api);
+
+    if (ecData.focus === 'self') {
+      blurComponent(ecData.componentMainType, ecData.componentIndex, api);
+    } // Other than series, component that not support `findHighDownDispatcher` will
+    // also use it. But in this case, highlight/downplay are only supported in
+    // mouse hover but not in dispatchAction.
+
+
+    enterEmphasisWhenMouseOver(dispatcher, e);
+  }
+}
+function handleGlboalMouseOutForHighDown(dispatcher, e, api) {
+  if ("development" !== 'production' && !isHighDownDispatcher(dispatcher)) {
+    error('param should be highDownDispatcher');
+  }
+
+  allLeaveBlur(api);
+  var ecData = getECData(dispatcher);
+  var dispatchers = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api).dispatchers;
+
+  if (dispatchers) {
+    each(dispatchers, function (dispatcher) {
+      return leaveEmphasisWhenMouseOut(dispatcher, e);
+    });
+  } else {
+    leaveEmphasisWhenMouseOut(dispatcher, e);
   }
 }
 function toggleSelectionFromPayload(seriesModel, payload, api) {
@@ -12522,6 +12646,18 @@ function isHighDownDispatcher(el) {
   return !!(el && el.__highDownDispatcher);
 }
 /**
+ * Enable component highlight/downplay features:
+ * + hover link (within the same name)
+ * + focus blur in component
+ */
+
+function enableComponentHighDownFeatures(el, componentModel, componentHighDownName) {
+  var ecData = getECData(el);
+  ecData.componentMainType = componentModel.mainType;
+  ecData.componentIndex = componentModel.componentIndex;
+  ecData.componentHighDownName = componentHighDownName;
+}
+/**
  * Support hightlight/downplay record on each elements.
  * For the case: hover highlight/downplay (legend, visualMap, ...) and
  * user triggerred hightlight/downplay should not conflict.
@@ -14601,10 +14737,47 @@ function crossProduct2d(x1, y1, x2, y2) {
 
 function nearZero(val) {
   return val <= 1e-6 && val >= -1e-6;
+}
+
+function setTooltipConfig(opt) {
+  var itemTooltipOption = opt.itemTooltipOption;
+  var componentModel = opt.componentModel;
+  var itemName = opt.itemName;
+  var itemTooltipOptionObj = isString(itemTooltipOption) ? {
+    formatter: itemTooltipOption
+  } : itemTooltipOption;
+  var mainType = componentModel.mainType;
+  var componentIndex = componentModel.componentIndex;
+  var formatterParams = {
+    componentType: mainType,
+    name: itemName,
+    $vars: ['name']
+  };
+  formatterParams[mainType + 'Index'] = componentIndex;
+  var formatterParamsExtra = opt.formatterParamsExtra;
+
+  if (formatterParamsExtra) {
+    each(keys(formatterParamsExtra), function (key) {
+      if (!hasOwn(formatterParams, key)) {
+        formatterParams[key] = formatterParamsExtra[key];
+        formatterParams.$vars.push(key);
+      }
+    });
+  }
+
+  var ecData = getECData(opt.el);
+  ecData.componentMainType = mainType;
+  ecData.componentIndex = componentIndex;
+  ecData.tooltipConfig = {
+    name: itemName,
+    option: defaults({
+      content: itemName,
+      formatterParams: formatterParams
+    }, itemTooltipOptionObj)
+  };
 } // Register built-in shapes. These shapes might be overwirtten
 // by users, although we do not recommend that.
 
-
 registerShape('circle', Circle);
 registerShape('ellipse', Ellipse);
 registerShape('sector', Sector);
@@ -14643,6 +14816,7 @@ var graphic = /*#__PURE__*/Object.freeze({
     createIcon: createIcon,
     linePolygonIntersect: linePolygonIntersect,
     lineLineIntersect: lineLineIntersect,
+    setTooltipConfig: setTooltipConfig,
     Group: Group,
     Image: ZRImage,
     Text: ZRText,
@@ -15179,6 +15353,10 @@ function animateLabelValue(textEl, dataIndex, data, animatableModel, labelFetche
 
   (currValue == null ? initProps : updateProps)(textEl, {}, animatableModel, dataIndex, null, during);
 }
+function enableLayoutLayoutFeatures(el, dataIndex, dataType) {
+  getECData(el).dataIndex = dataIndex;
+  getECData(el).dataType = dataType;
+}
 
 var PATH_COLOR = ['textStyle', 'color']; // TODO Performance improvement?
 
@@ -15504,7 +15682,7 @@ function enableSubTypeDefaulter(target) {
  * Topological travel on Activity Network (Activity On Vertices).
  * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis'].
  * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology.
- * If there is circle dependencey, Error will be thrown.
+ * If there is circular dependencey, Error will be thrown.
  */
 
 function enableTopologicalTravel(entity, dependencyGetter) {
@@ -15545,7 +15723,7 @@ function enableTopologicalTravel(entity, dependencyGetter) {
       var errMsg = '';
 
       if ("development" !== 'production') {
-        errMsg = makePrintable('Circle dependency may exists: ', targetNameSet, targetNameList, fullNameList);
+        errMsg = makePrintable('Circular dependency may exists: ', targetNameSet, targetNameList, fullNameList);
       }
 
       throw new Error(errMsg);
@@ -16287,7 +16465,7 @@ function encodeHTML(source) {
  */
 
 function makeValueReadable(value, valueType, useUTC) {
-  var USER_READABLE_DEFUALT_TIME_PATTERN = 'yyyy-MM-dd hh:mm:ss';
+  var USER_READABLE_DEFUALT_TIME_PATTERN = '{yyyy}-{MM}-{dd} {hh}:{mm}:{ss}';
 
   function stringToUserReadable(str) {
     return str && trim(str) ? str : '-';
@@ -17733,6 +17911,59 @@ var assertSeriesInitialized;
 var initBase;
 var OPTION_INNER_KEY = '\0_ec_inner';
 var OPTION_INNER_VALUE = 1;
+var BUITIN_COMPONENTS_MAP = {
+  grid: 'GridComponent',
+  polar: 'PolarComponent',
+  geo: 'GeoComponent',
+  singleAxis: 'SingleAxisComponent',
+  parallel: 'ParallelComponent',
+  calendar: 'CalendarComponent',
+  graphic: 'GraphicComponent',
+  toolbox: 'ToolboxComponent',
+  tooltip: 'TooltipComponent',
+  axisPointer: 'AxisPointerComponent',
+  brush: 'BrushComponent',
+  title: 'TitleComponent',
+  timeline: 'TimelineComponent',
+  markPoint: 'MarkPointComponent',
+  markLine: 'MarkLineComponent',
+  markArea: 'MarkAreaComponent',
+  legend: 'LegendComponent',
+  dataZoom: 'DataZoomComponent',
+  visualMap: 'VisualMapComponent',
+  // aria: 'AriaComponent',
+  // dataset: 'DatasetComponent',
+  // Dependencies
+  xAxis: 'GridComponent',
+  yAxis: 'GridComponent',
+  angleAxis: 'PolarComponent',
+  radiusAxis: 'PolarComponent'
+};
+var BUILTIN_CHARTS_MAP = {
+  line: 'LineChart',
+  bar: 'BarChart',
+  pie: 'PieChart',
+  scatter: 'ScatterChart',
+  radar: 'RadarChart',
+  map: 'MapChart',
+  tree: 'TreeChart',
+  treemap: 'TreemapChart',
+  graph: 'GraphChart',
+  gauge: 'GaugeChart',
+  funnel: 'FunnelChart',
+  parallel: 'ParallelChart',
+  sankey: 'SankeyChart',
+  boxplot: 'BoxplotChart',
+  candlestick: 'CandlestickChart',
+  effectScatter: 'EffectScatterChart',
+  lines: 'LinesChart',
+  heatmap: 'HeatmapChart',
+  pictorialBar: 'PictorialBarChart',
+  themeRiver: 'ThemeRiverChart',
+  sunburst: 'SunburstChart',
+  custom: 'CustomChart'
+};
+var componetsMissingLogPrinted = {};
 
 var GlobalModel =
 /** @class */
@@ -17852,7 +18083,16 @@ function (_super) {
       }
 
       if (!ComponentModel.hasClass(mainType)) {
-        // globalSettingTask.dirty();
+        if ("development" !== 'production') {
+          var componentImportName = BUITIN_COMPONENTS_MAP[mainType];
+
+          if (componentImportName && !componetsMissingLogPrinted[componentImportName]) {
+            error("Component " + mainType + " is used but not imported.\nimport { " + componentImportName + " } from 'echarts/components';\necharts.use([" + componentImportName + "]);");
+            componetsMissingLogPrinted[componentImportName] = true;
+          }
+        } // globalSettingTask.dirty();
+
+
         option[mainType] = option[mainType] == null ? clone(componentOption) : merge(option[mainType], componentOption, true);
       } else if (mainType) {
         newCmptTypes.push(mainType);
@@ -17908,7 +18148,28 @@ function (_super) {
           // or it has been removed in previous `replaceMerge` and left a "hole" in this component index.
 
         } else {
-          var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, true);
+          var isSeriesType = mainType === 'series';
+          var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, !isSeriesType // Give a more detailed warn later if series don't exists
+          );
+
+          if (!ComponentModelClass) {
+            if ("development" !== 'production') {
+              var subType = resultItem.keyInfo.subType;
+              var seriesImportName = BUILTIN_CHARTS_MAP[subType];
+
+              if (!componetsMissingLogPrinted[subType]) {
+                componetsMissingLogPrinted[subType] = true;
+
+                if (seriesImportName) {
+                  error("Series " + subType + " is used but not imported.\nimport { " + seriesImportName + " } from 'echarts/charts';\necharts.use([" + seriesImportName + "]);");
+                } else {
+                  error("Unkown series " + subType);
+                }
+              }
+            }
+
+            return;
+          }
 
           if (componentModel && componentModel.constructor === ComponentModelClass) {
             componentModel.name = resultItem.keyInfo.name; // componentModel.settingTask && componentModel.settingTask.dirty();
@@ -22521,7 +22782,7 @@ function (_super) {
       data.each(function (idx) {
         var rawItem = data.getRawDataItem(idx);
 
-        if (typeof rawItem === 'object' && rawItem.selected) {
+        if (rawItem && rawItem.selected) {
           dataIndices.push(idx);
         }
       });
@@ -23087,15 +23348,23 @@ var seriesStyleTask = {
     var colorKey = getDefaultColorKey(seriesModel, stylePath);
     var color = globalStyle[colorKey]; // TODO style callback
 
-    var colorCallback = isFunction(color) ? color : null; // Get from color palette by default.
+    var colorCallback = isFunction(color) ? color : null;
+    var hasAutoColor = globalStyle.fill === 'auto' || globalStyle.stroke === 'auto'; // Get from color palette by default.
 
-    if (!globalStyle[colorKey] || colorCallback) {
+    if (!globalStyle[colorKey] || colorCallback || hasAutoColor) {
       // Note: if some series has color specified (e.g., by itemStyle.color), we DO NOT
       // make it effect palette. Bacause some scenarios users need to make some series
       // transparent or as background, which should better not effect the palette.
-      globalStyle[colorKey] = seriesModel.getColorFromPalette( // TODO series count changed.
+      var colorPalette = seriesModel.getColorFromPalette( // TODO series count changed.
       seriesModel.name, null, ecModel.getSeriesCount());
-      data.setVisual('colorFromPalette', true);
+
+      if (!globalStyle[colorKey]) {
+        globalStyle[colorKey] = colorPalette;
+        data.setVisual('colorFromPalette', true);
+      }
+
+      globalStyle.fill = globalStyle.fill === 'auto' || typeof globalStyle.fill === 'function' ? colorPalette : globalStyle.fill;
+      globalStyle.stroke = globalStyle.stroke === 'auto' || typeof globalStyle.stroke === 'function' ? colorPalette : globalStyle.stroke;
     }
 
     data.setVisual('style', globalStyle);
@@ -23252,7 +23521,9 @@ function defaultLoading(api, opts) {
       fontWeight: opts.fontWeight,
       fontStyle: opts.fontStyle,
       fontFamily: opts.fontFamily
-    }
+    },
+    zlevel: opts.zlevel,
+    z: 10001
   });
   var labelRect = new Rect({
     style: {
@@ -24099,108 +24370,6 @@ var theme = {
 };
 theme.categoryAxis.splitLine.show = false;
 
-function parseXML(svg) {
-    if (isString(svg)) {
-        var parser = new DOMParser();
-        svg = parser.parseFromString(svg, 'text/xml');
-    }
-    var svgNode = svg;
-    if (svgNode.nodeType === 9) {
-        svgNode = svgNode.firstChild;
-    }
-    while (svgNode.nodeName.toLowerCase() !== 'svg' || svgNode.nodeType !== 1) {
-        svgNode = svgNode.nextSibling;
-    }
-    return svgNode;
-}
-
-var storage = createHashMap();
-var mapDataStorage = {
-  /**
-   * Compatible with previous `echarts.registerMap`.
-   * @usage
-   * ```js
-   * $.get('USA.json', function (geoJson) {
-   *     echarts.registerMap('USA', geoJson);
-   *     // Or
-   *     echarts.registerMap('USA', {
-   *         geoJson: geoJson,
-   *         specialAreas: {}
-   *     })
-   * });
-   *
-   * $.get('airport.svg', function (svg) {
-   *     echarts.registerMap('airport', {
-   *         svg: svg
-   *     }
-   * });
-   *
-   * echarts.registerMap('eu', [
-   *     {svg: eu-topographic.svg},
-   *     {geoJSON: eu.json}
-   * ])
-   * ```
-   */
-  registerMap: function (mapName, rawDef, rawSpecialAreas) {
-    var records;
-
-    if (isArray(rawDef)) {
-      records = rawDef;
-    } else if (rawDef.svg) {
-      records = [{
-        type: 'svg',
-        source: rawDef.svg,
-        specialAreas: rawDef.specialAreas
-      }];
-    } else {
-      // Backward compatibility.
-      var geoSource = rawDef.geoJson || rawDef.geoJSON;
-
-      if (geoSource && !rawDef.features) {
-        rawSpecialAreas = rawDef.specialAreas;
-        rawDef = geoSource;
-      }
-
-      records = [{
-        type: 'geoJSON',
-        source: rawDef,
-        specialAreas: rawSpecialAreas
-      }];
-    }
-
-    each(records, function (record) {
-      var type = record.type;
-      type === 'geoJson' && (type = record.type = 'geoJSON');
-      var parse = parsers[type];
-
-      if ("development" !== 'production') {
-        assert(parse, 'Illegal map type: ' + type);
-      }
-
-      parse(record);
-    });
-    return storage.set(mapName, records);
-  },
-  retrieveMap: function (mapName) {
-    return storage.get(mapName);
-  }
-};
-var parsers = {
-  geoJSON: function (record) {
-    var source = record.source;
-    record.geoJSON = !isString(source) ? source : typeof JSON !== 'undefined' && JSON.parse ? JSON.parse(source) : new Function('return (' + source + ');')();
-  },
-  // Only perform parse to XML object here, which might be time
-  // consiming for large SVG.
-  // Although convert XML to zrender element is also time consiming,
-  // if we do it here, the clone of zrender elements has to be
-  // required. So we do it once for each geo instance, util real
-  // performance issues call for optimizing it.
-  svg: function (record) {
-    record.svgXML = parseXML(record.source);
-  }
-};
-
 /**
  * Usage of query:
  * `chart.on('click', query, handler);`
@@ -24333,13 +24502,16 @@ var seriesSymbolTask = {
     var symbolSize = seriesModel.get('symbolSize');
     var keepAspect = seriesModel.get('symbolKeepAspect');
     var symbolRotate = seriesModel.get('symbolRotate');
+    var symbolOffset = seriesModel.get('symbolOffset');
     var hasSymbolTypeCallback = isFunction(symbolType);
     var hasSymbolSizeCallback = isFunction(symbolSize);
     var hasSymbolRotateCallback = isFunction(symbolRotate);
-    var hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback || hasSymbolRotateCallback;
+    var hasSymbolOffsetCallback = isFunction(symbolOffset);
+    var hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback || hasSymbolRotateCallback || hasSymbolOffsetCallback;
     var seriesSymbol = !hasSymbolTypeCallback && symbolType ? symbolType : seriesModel.defaultSymbol;
     var seriesSymbolSize = !hasSymbolSizeCallback ? symbolSize : null;
     var seriesSymbolRotate = !hasSymbolRotateCallback ? symbolRotate : null;
+    var seriesSymbolOffset = !hasSymbolOffsetCallback ? symbolOffset : null;
     data.setVisual({
       legendSymbol: seriesModel.legendSymbol || seriesSymbol,
       // If seting callback functions on `symbol` or `symbolSize`, for simplicity and avoiding
@@ -24349,7 +24521,8 @@ var seriesSymbolTask = {
       symbol: seriesSymbol,
       symbolSize: seriesSymbolSize,
       symbolKeepAspect: keepAspect,
-      symbolRotate: seriesSymbolRotate
+      symbolRotate: seriesSymbolRotate,
+      symbolOffset: seriesSymbolOffset
     }); // Only visible series has each data be visual encoded
 
     if (ecModel.isSeriesFiltered(seriesModel)) {
@@ -24362,6 +24535,7 @@ var seriesSymbolTask = {
       hasSymbolTypeCallback && data.setItemVisual(idx, 'symbol', symbolType(rawValue, params));
       hasSymbolSizeCallback && data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params));
       hasSymbolRotateCallback && data.setItemVisual(idx, 'symbolRotate', symbolRotate(rawValue, params));
+      hasSymbolOffsetCallback && data.setItemVisual(idx, 'symbolOffset', symbolOffset(rawValue, params));
     }
 
     return {
@@ -24390,6 +24564,7 @@ var dataSymbolTask = {
       var itemSymbolType = itemModel.getShallow('symbol', true);
       var itemSymbolSize = itemModel.getShallow('symbolSize', true);
       var itemSymbolRotate = itemModel.getShallow('symbolRotate', true);
+      var itemSymbolOffset = itemModel.getShallow('symbolOffset', true);
       var itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true); // If has item symbol
 
       if (itemSymbolType != null) {
@@ -24405,6 +24580,10 @@ var dataSymbolTask = {
         data.setItemVisual(idx, 'symbolRotate', itemSymbolRotate);
       }
 
+      if (itemSymbolOffset != null) {
+        data.setItemVisual(idx, 'symbolOffset', itemSymbolOffset);
+      }
+
       if (itemSymbolKeepAspect != null) {
         data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect);
       }
@@ -25515,6 +25694,8 @@ function () {
         labelGuideIgnore: labelGuide && labelGuide.ignore,
         x: dummyTransformable.x,
         y: dummyTransformable.y,
+        scaleX: dummyTransformable.scaleX,
+        scaleY: dummyTransformable.scaleY,
         rotation: dummyTransformable.rotation,
         style: {
           x: labelStyle.x,
@@ -25587,7 +25768,8 @@ function () {
 
       layoutOption = layoutOption || {};
       labelItem.computedLayoutOption = layoutOption;
-      var degreeToRadian = Math.PI / 180;
+      var degreeToRadian = Math.PI / 180; // TODO hostEl should always exists.
+      // Or label should not have parent because the x, y is all in global space.
 
       if (hostEl) {
         hostEl.setTextConfig({
@@ -25640,6 +25822,8 @@ function () {
       var labelLayoutStore = labelLayoutInnerStore(label);
       labelLayoutStore.needsUpdateLabelLine = needsUpdateLabelLine;
       label.rotation = layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation;
+      label.scaleX = defaultLabelAttr.scaleX;
+      label.scaleY = defaultLabelAttr.scaleY;
 
       for (var k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) {
         var key = LABEL_OPTION_TO_STYLE_KEYS[k];
@@ -26136,9 +26320,7 @@ var Arrow = Path.extend({
 // TODO Use function to build symbol path.
 
 var symbolCtors = {
-  // Use small height rect to simulate line.
-  // Avoid using stroke.
-  line: Rect,
+  line: Line,
   rect: Rect,
   roundRect: Rect,
   square: Rect,
@@ -26147,16 +26329,13 @@ var symbolCtors = {
   pin: Pin,
   arrow: Arrow,
   triangle: Triangle
-}; // NOTICE Only use fill. No line!
-
+};
 var symbolShapeMakers = {
   line: function (x, y, w, h, shape) {
-    var thickness = 2; // A thin line
-
-    shape.x = x;
-    shape.y = y + h / 2 - thickness / 2;
-    shape.width = w;
-    shape.height = thickness;
+    shape.x1 = x;
+    shape.y1 = y + h / 2;
+    shape.x2 = x + w;
+    shape.y2 = y + h / 2;
   },
   rect: function (x, y, w, h, shape) {
     shape.x = x;
@@ -26256,9 +26435,11 @@ function symbolPathSetColor(color, innerColor) {
 
     if (this.__isEmptyBrush) {
       symbolStyle.stroke = color;
-      symbolStyle.fill = innerColor || '#fff'; // TODO Same width with lineStyle in LineView.
+      symbolStyle.fill = innerColor || '#fff'; // TODO Same width with lineStyle in LineView
 
       symbolStyle.lineWidth = 2;
+    } else if (this.shape.symbolType === 'line') {
+      symbolStyle.stroke = color;
     } else {
       symbolStyle.fill = color;
     }
@@ -26415,7 +26596,8 @@ function createCanvasPattern(ctx, pattern, el) {
     var image = createOrUpdateImage(pattern.image, pattern.__image, el);
     if (isImageReady(image)) {
         var canvasPattern = ctx.createPattern(image, pattern.repeat || 'repeat');
-        if (typeof DOMMatrix === 'function') {
+        if (typeof DOMMatrix === 'function'
+            && canvasPattern.setTransform) {
             var matrix = new DOMMatrix();
             matrix.rotateSelf(0, 0, (pattern.rotation || 0) / Math.PI * 180);
             matrix.scaleSelf((pattern.scaleX || 1), (pattern.scaleY || 1));
@@ -26658,7 +26840,8 @@ function bindCommonProps(ctx, style, prevStyle, forceSetAll, scope) {
             flushPathDrawn(ctx, scope);
             styleChanged = true;
         }
-        ctx.globalAlpha = style.opacity == null ? DEFAULT_COMMON_STYLE.opacity : style.opacity;
+        var opacity = Math.max(Math.min(style.opacity, 1), 0);
+        ctx.globalAlpha = isNaN(opacity) ? DEFAULT_COMMON_STYLE.opacity : opacity;
     }
     if (forceSetAll || style.blend !== prevStyle.blend) {
         if (!styleChanged) {
@@ -27382,9134 +27565,10594 @@ function decalVisual(ecModel, api) {
   });
 }
 
-var assert$1 = assert;
-var each$3 = each;
-var isFunction$1 = isFunction;
-var isObject$2 = isObject;
-var indexOf$1 = indexOf;
-var hasWindow = typeof window !== 'undefined';
-var version$1 = '5.0.2';
-var dependencies = {
-  zrender: '5.0.4'
-};
-var TEST_FRAME_REMAIN_TIME = 1;
-var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
-// So data stack stage should be in front of data processing stage.
-
-var PRIORITY_PROCESSOR_DATASTACK = 900; // "Data filter" will block the stream, so it should be
-// put at the begining of data processing.
-
-var PRIORITY_PROCESSOR_FILTER = 1000;
-var PRIORITY_PROCESSOR_DEFAULT = 2000;
-var PRIORITY_PROCESSOR_STATISTIC = 5000;
-var PRIORITY_VISUAL_LAYOUT = 1000;
-var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100;
-var PRIORITY_VISUAL_GLOBAL = 2000;
-var PRIORITY_VISUAL_CHART = 3000;
-var PRIORITY_VISUAL_COMPONENT = 4000; // Visual property in data. Greater than `PRIORITY_VISUAL_COMPONENT` to enable to
-// overwrite the viusal result of component (like `visualMap`)
-// using data item specific setting (like itemStyle.xxx on data item)
-
-var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500; // Greater than `PRIORITY_VISUAL_CHART_DATA_CUSTOM` to enable to layout based on
-// visual result like `symbolSize`.
-
-var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600;
-var PRIORITY_VISUAL_BRUSH = 5000;
-var PRIORITY_VISUAL_ARIA = 6000;
-var PRIORITY_VISUAL_DECAL = 7000;
-var PRIORITY = {
-  PROCESSOR: {
-    FILTER: PRIORITY_PROCESSOR_FILTER,
-    SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER,
-    STATISTIC: PRIORITY_PROCESSOR_STATISTIC
-  },
-  VISUAL: {
-    LAYOUT: PRIORITY_VISUAL_LAYOUT,
-    PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT,
-    GLOBAL: PRIORITY_VISUAL_GLOBAL,
-    CHART: PRIORITY_VISUAL_CHART,
-    POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT,
-    COMPONENT: PRIORITY_VISUAL_COMPONENT,
-    BRUSH: PRIORITY_VISUAL_BRUSH,
-    CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM,
-    ARIA: PRIORITY_VISUAL_ARIA,
-    DECAL: PRIORITY_VISUAL_DECAL
-  }
-}; // Main process have three entries: `setOption`, `dispatchAction` and `resize`,
-// where they must not be invoked nestedly, except the only case: invoke
-// dispatchAction with updateMethod "none" in main process.
-// This flag is used to carry out this rule.
-// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
-
-var IN_MAIN_PROCESS_KEY = '__flagInMainProcess';
-var OPTION_UPDATED_KEY = '__optionUpdated';
-var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus';
-var ACTION_REG = /^[a-zA-Z0-9_]+$/;
-var CONNECT_STATUS_KEY = '__connectUpdateStatus';
-var CONNECT_STATUS_PENDING = 0;
-var CONNECT_STATUS_UPDATING = 1;
-var CONNECT_STATUS_UPDATED = 2;
-
-function createRegisterEventWithLowercaseECharts(method) {
-  return function () {
-    var args = [];
-
-    for (var _i = 0; _i < arguments.length; _i++) {
-      args[_i] = arguments[_i];
+function parseXML(svg) {
+    if (isString(svg)) {
+        var parser = new DOMParser();
+        svg = parser.parseFromString(svg, 'text/xml');
     }
-
-    if (this.isDisposed()) {
-      disposedWarning(this.id);
-      return;
+    var svgNode = svg;
+    if (svgNode.nodeType === 9) {
+        svgNode = svgNode.firstChild;
     }
-
-    return toLowercaseNameAndCallEventful(this, method, args);
-  };
-}
-
-function createRegisterEventWithLowercaseMessageCenter(method) {
-  return function () {
-    var args = [];
-
-    for (var _i = 0; _i < arguments.length; _i++) {
-      args[_i] = arguments[_i];
+    while (svgNode.nodeName.toLowerCase() !== 'svg' || svgNode.nodeType !== 1) {
+        svgNode = svgNode.nextSibling;
     }
-
-    return toLowercaseNameAndCallEventful(this, method, args);
-  };
-}
-
-function toLowercaseNameAndCallEventful(host, method, args) {
-  // `args[0]` is event name. Event name is all lowercase.
-  args[0] = args[0] && args[0].toLowerCase();
-  return Eventful.prototype[method].apply(host, args);
+    return svgNode;
 }
 
-var MessageCenter =
-/** @class */
-function (_super) {
-  __extends(MessageCenter, _super);
-
-  function MessageCenter() {
-    return _super !== null && _super.apply(this, arguments) || this;
-  }
-
-  return MessageCenter;
-}(Eventful);
-
-var messageCenterProto = MessageCenter.prototype;
-messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on');
-messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off'); // ---------------------------------------
-// Internal method names for class ECharts
-// ---------------------------------------
-
-var prepare;
-var prepareView;
-var updateDirectly;
-var updateMethods;
-var doConvertPixel;
-var updateStreamModes;
-var doDispatchAction;
-var flushPendingActions;
-var triggerUpdatedEvent;
-var bindRenderedEvent;
-var bindMouseEvent;
-var clearColorPalette;
-var render;
-var renderComponents;
-var renderSeries;
-var performPostUpdateFuncs;
-var createExtensionAPI;
-var enableConnect;
-var setTransitionOpt;
-var markStatusToUpdate;
-var applyChangedStates;
-
-var ECharts =
-/** @class */
-function (_super) {
-  __extends(ECharts, _super);
-
-  function ECharts(dom, // Theme name or themeOption.
-  theme, opts) {
-    var _this = _super.call(this, new ECEventProcessor()) || this;
-
-    _this._chartsViews = [];
-    _this._chartsMap = {};
-    _this._componentsViews = [];
-    _this._componentsMap = {}; // Can't dispatch action during rendering procedure
-
-    _this._pendingActions = [];
-    opts = opts || {}; // Get theme by name
-
-    if (typeof theme === 'string') {
-      theme = themeStorage[theme];
-    }
-
-    _this._dom = dom;
-    var defaultRenderer = 'canvas';
-    var defaultUseDirtyRect = false;
-
-    if ("development" !== 'production') {
-      var root =
-      /* eslint-disable-next-line */
-      hasWindow ? window : global;
-      defaultRenderer = root.__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer;
-      var devUseDirtyRect = root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__;
-      defaultUseDirtyRect = devUseDirtyRect == null ? defaultUseDirtyRect : devUseDirtyRect;
-    }
-
-    var zr = _this._zr = init(dom, {
-      renderer: opts.renderer || defaultRenderer,
-      devicePixelRatio: opts.devicePixelRatio,
-      width: opts.width,
-      height: opts.height,
-      useDirtyRect: opts.useDirtyRect == null ? defaultUseDirtyRect : opts.useDirtyRect
-    }); // Expect 60 fps.
-
-    _this._throttledZrFlush = throttle(bind(zr.flush, zr), 17);
-    theme = clone(theme);
-    theme && globalBackwardCompat(theme, true);
-    _this._theme = theme;
-    _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG);
-    _this._coordSysMgr = new CoordinateSystemManager();
-    var api = _this._api = createExtensionAPI(_this); // Sort on demand
-
-    function prioritySortFunc(a, b) {
-      return a.__prio - b.__prio;
-    }
-
-    sort(visualFuncs, prioritySortFunc);
-    sort(dataProcessorFuncs, prioritySortFunc);
-    _this._scheduler = new Scheduler(_this, api, dataProcessorFuncs, visualFuncs);
-    _this._messageCenter = new MessageCenter();
-    _this._labelManager = new LabelManager(); // Init mouse events
-
-    _this._initEvents(); // In case some people write `window.onresize = chart.resize`
-
-
-    _this.resize = bind(_this.resize, _this);
-    zr.animation.on('frame', _this._onframe, _this);
-    bindRenderedEvent(zr, _this);
-    bindMouseEvent(zr, _this); // ECharts instance can be used as value.
-
-    setAsPrimitive(_this);
-    return _this;
-  }
-
-  ECharts.prototype._onframe = function () {
-    if (this._disposed) {
-      return;
+var nodeParsers;
+var INHERITABLE_STYLE_ATTRIBUTES_MAP = {
+    'fill': 'fill',
+    'stroke': 'stroke',
+    'stroke-width': 'lineWidth',
+    'opacity': 'opacity',
+    'fill-opacity': 'fillOpacity',
+    'stroke-opacity': 'strokeOpacity',
+    'stroke-dasharray': 'lineDash',
+    'stroke-dashoffset': 'lineDashOffset',
+    'stroke-linecap': 'lineCap',
+    'stroke-linejoin': 'lineJoin',
+    'stroke-miterlimit': 'miterLimit',
+    'font-family': 'fontFamily',
+    'font-size': 'fontSize',
+    'font-style': 'fontStyle',
+    'font-weight': 'fontWeight',
+    'text-anchor': 'textAlign',
+    'visibility': 'visibility',
+    'display': 'display'
+};
+var INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS = keys(INHERITABLE_STYLE_ATTRIBUTES_MAP);
+var SELF_STYLE_ATTRIBUTES_MAP = {
+    'alignment-baseline': 'textBaseline',
+    'stop-color': 'stopColor'
+};
+var SELF_STYLE_ATTRIBUTES_MAP_KEYS = keys(SELF_STYLE_ATTRIBUTES_MAP);
+var SVGParser = (function () {
+    function SVGParser() {
+        this._defs = {};
+        this._root = null;
     }
-
-    applyChangedStates(this);
-    var scheduler = this._scheduler; // Lazy update
-
-    if (this[OPTION_UPDATED_KEY]) {
-      var silent = this[OPTION_UPDATED_KEY].silent;
-      this[IN_MAIN_PROCESS_KEY] = true;
-      prepare(this);
-      updateMethods.update.call(this); // At present, in each frame, zrender performs:
-      //   (1) animation step forward.
-      //   (2) trigger('frame') (where this `_onframe` is called)
-      //   (3) zrender flush (render).
-      // If we do nothing here, since we use `setToFinal: true`, the step (3) above
-      // will render the final state of the elements before the real animation started.
-
-      this._zr.flush();
-
-      this[IN_MAIN_PROCESS_KEY] = false;
-      this[OPTION_UPDATED_KEY] = false;
-      flushPendingActions.call(this, silent);
-      triggerUpdatedEvent.call(this, silent);
-    } // Avoid do both lazy update and progress in one frame.
-    else if (scheduler.unfinished) {
-        // Stream progress.
-        var remainTime = TEST_FRAME_REMAIN_TIME;
-        var ecModel = this._model;
-        var api = this._api;
-        scheduler.unfinished = false;
-
-        do {
-          var startTime = +new Date();
-          scheduler.performSeriesTasks(ecModel); // Currently dataProcessorFuncs do not check threshold.
-
-          scheduler.performDataProcessorTasks(ecModel);
-          updateStreamModes(this, ecModel); // Do not update coordinate system here. Because that coord system update in
-          // each frame is not a good user experience. So we follow the rule that
-          // the extent of the coordinate system is determin in the first frame (the
-          // frame is executed immedietely after task reset.
-          // this._coordSysMgr.update(ecModel, api);
-          // console.log('--- ec frame visual ---', remainTime);
-
-          scheduler.performVisualTasks(ecModel);
-          renderSeries(this, this._model, api, 'remain');
-          remainTime -= +new Date() - startTime;
-        } while (remainTime > 0 && scheduler.unfinished); // Call flush explicitly for trigger finished event.
-
-
-        if (!scheduler.unfinished) {
-          this._zr.flush();
-        } // Else, zr flushing be ensue within the same frame,
-        // because zr flushing is after onframe event.
-
-      }
-  };
-
-  ECharts.prototype.getDom = function () {
-    return this._dom;
-  };
-
-  ECharts.prototype.getId = function () {
-    return this.id;
-  };
-
-  ECharts.prototype.getZr = function () {
-    return this._zr;
-  };
-  /* eslint-disable-next-line */
-
-
-  ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) {
-    if ("development" !== 'production') {
-      assert$1(!this[IN_MAIN_PROCESS_KEY], '`setOption` should not be called during main process.');
+    SVGParser.prototype.parse = function (xml, opt) {
+        opt = opt || {};
+        var svg = parseXML(xml);
+        if (!svg) {
+            throw new Error('Illegal svg');
+        }
+        this._defsUsePending = [];
+        var root = new Group();
+        this._root = root;
+        var named = [];
+        var viewBox = svg.getAttribute('viewBox') || '';
+        var width = parseFloat((svg.getAttribute('width') || opt.width));
+        var height = parseFloat((svg.getAttribute('height') || opt.height));
+        isNaN(width) && (width = null);
+        isNaN(height) && (height = null);
+        parseAttributes(svg, root, null, true, false);
+        var child = svg.firstChild;
+        while (child) {
+            this._parseNode(child, root, named, null, false, false);
+            child = child.nextSibling;
+        }
+        applyDefs(this._defs, this._defsUsePending);
+        this._defsUsePending = [];
+        var viewBoxRect;
+        var viewBoxTransform;
+        if (viewBox) {
+            var viewBoxArr = splitNumberSequence(viewBox);
+            if (viewBoxArr.length >= 4) {
+                viewBoxRect = {
+                    x: parseFloat((viewBoxArr[0] || 0)),
+                    y: parseFloat((viewBoxArr[1] || 0)),
+                    width: parseFloat(viewBoxArr[2]),
+                    height: parseFloat(viewBoxArr[3])
+                };
+            }
+        }
+        if (viewBoxRect && width != null && height != null) {
+            viewBoxTransform = makeViewBoxTransform(viewBoxRect, { x: 0, y: 0, width: width, height: height });
+            if (!opt.ignoreViewBox) {
+                var elRoot = root;
+                root = new Group();
+                root.add(elRoot);
+                elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale;
+                elRoot.x = viewBoxTransform.x;
+                elRoot.y = viewBoxTransform.y;
+            }
+        }
+        if (!opt.ignoreRootClip && width != null && height != null) {
+            root.setClipPath(new Rect({
+                shape: { x: 0, y: 0, width: width, height: height }
+            }));
+        }
+        return {
+            root: root,
+            width: width,
+            height: height,
+            viewBoxRect: viewBoxRect,
+            viewBoxTransform: viewBoxTransform,
+            named: named
+        };
+    };
+    SVGParser.prototype._parseNode = function (xmlNode, parentGroup, named, namedFrom, isInDefs, isInText) {
+        var nodeName = xmlNode.nodeName.toLowerCase();
+        var el;
+        var namedFromForSub = namedFrom;
+        if (nodeName === 'defs') {
+            isInDefs = true;
+        }
+        if (nodeName === 'text') {
+            isInText = true;
+        }
+        if (nodeName === 'defs' || nodeName === 'switch') {
+            el = parentGroup;
+        }
+        else {
+            if (!isInDefs) {
+                var parser_1 = nodeParsers[nodeName];
+                if (parser_1 && hasOwn(nodeParsers, nodeName)) {
+                    el = parser_1.call(this, xmlNode, parentGroup);
+                    var nameAttr = xmlNode.getAttribute('name');
+                    if (nameAttr) {
+                        var newNamed = {
+                            name: nameAttr,
+                            namedFrom: null,
+                            svgNodeTagLower: nodeName,
+                            el: el
+                        };
+                        named.push(newNamed);
+                        if (nodeName === 'g') {
+                            namedFromForSub = newNamed;
+                        }
+                    }
+                    else if (namedFrom) {
+                        named.push({
+                            name: namedFrom.name,
+                            namedFrom: namedFrom,
+                            svgNodeTagLower: nodeName,
+                            el: el
+                        });
+                    }
+                    parentGroup.add(el);
+                }
+            }
+            var parser = paintServerParsers[nodeName];
+            if (parser && hasOwn(paintServerParsers, nodeName)) {
+                var def = parser.call(this, xmlNode);
+                var id = xmlNode.getAttribute('id');
+                if (id) {
+                    this._defs[id] = def;
+                }
+            }
+        }
+        if (el && el.isGroup) {
+            var child = xmlNode.firstChild;
+            while (child) {
+                if (child.nodeType === 1) {
+                    this._parseNode(child, el, named, namedFromForSub, isInDefs, isInText);
+                }
+                else if (child.nodeType === 3 && isInText) {
+                    this._parseText(child, el);
+                }
+                child = child.nextSibling;
+            }
+        }
+    };
+    SVGParser.prototype._parseText = function (xmlNode, parentGroup) {
+        var text = new TSpan({
+            style: {
+                text: xmlNode.textContent
+            },
+            silent: true,
+            x: this._textX || 0,
+            y: this._textY || 0
+        });
+        inheritStyle(parentGroup, text);
+        parseAttributes(xmlNode, text, this._defsUsePending, false, false);
+        applyTextAlignment(text, parentGroup);
+        var textStyle = text.style;
+        var fontSize = textStyle.fontSize;
+        if (fontSize && fontSize < 9) {
+            textStyle.fontSize = 9;
+            text.scaleX *= fontSize / 9;
+            text.scaleY *= fontSize / 9;
+        }
+        var font = (textStyle.fontSize || textStyle.fontFamily) && [
+            textStyle.fontStyle,
+            textStyle.fontWeight,
+            (textStyle.fontSize || 12) + 'px',
+            textStyle.fontFamily || 'sans-serif'
+        ].join(' ');
+        textStyle.font = font;
+        var rect = text.getBoundingRect();
+        this._textX += rect.width;
+        parentGroup.add(text);
+        return text;
+    };
+    SVGParser.internalField = (function () {
+        nodeParsers = {
+            'g': function (xmlNode, parentGroup) {
+                var g = new Group();
+                inheritStyle(parentGroup, g);
+                parseAttributes(xmlNode, g, this._defsUsePending, false, false);
+                return g;
+            },
+            'rect': function (xmlNode, parentGroup) {
+                var rect = new Rect();
+                inheritStyle(parentGroup, rect);
+                parseAttributes(xmlNode, rect, this._defsUsePending, false, false);
+                rect.setShape({
+                    x: parseFloat(xmlNode.getAttribute('x') || '0'),
+                    y: parseFloat(xmlNode.getAttribute('y') || '0'),
+                    width: parseFloat(xmlNode.getAttribute('width') || '0'),
+                    height: parseFloat(xmlNode.getAttribute('height') || '0')
+                });
+                rect.silent = true;
+                return rect;
+            },
+            'circle': function (xmlNode, parentGroup) {
+                var circle = new Circle();
+                inheritStyle(parentGroup, circle);
+                parseAttributes(xmlNode, circle, this._defsUsePending, false, false);
+                circle.setShape({
+                    cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
+                    cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
+                    r: parseFloat(xmlNode.getAttribute('r') || '0')
+                });
+                circle.silent = true;
+                return circle;
+            },
+            'line': function (xmlNode, parentGroup) {
+                var line = new Line();
+                inheritStyle(parentGroup, line);
+                parseAttributes(xmlNode, line, this._defsUsePending, false, false);
+                line.setShape({
+                    x1: parseFloat(xmlNode.getAttribute('x1') || '0'),
+                    y1: parseFloat(xmlNode.getAttribute('y1') || '0'),
+                    x2: parseFloat(xmlNode.getAttribute('x2') || '0'),
+                    y2: parseFloat(xmlNode.getAttribute('y2') || '0')
+                });
+                line.silent = true;
+                return line;
+            },
+            'ellipse': function (xmlNode, parentGroup) {
+                var ellipse = new Ellipse();
+                inheritStyle(parentGroup, ellipse);
+                parseAttributes(xmlNode, ellipse, this._defsUsePending, false, false);
+                ellipse.setShape({
+                    cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
+                    cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
+                    rx: parseFloat(xmlNode.getAttribute('rx') || '0'),
+                    ry: parseFloat(xmlNode.getAttribute('ry') || '0')
+                });
+                ellipse.silent = true;
+                return ellipse;
+            },
+            'polygon': function (xmlNode, parentGroup) {
+                var pointsStr = xmlNode.getAttribute('points');
+                var pointsArr;
+                if (pointsStr) {
+                    pointsArr = parsePoints(pointsStr);
+                }
+                var polygon = new Polygon({
+                    shape: {
+                        points: pointsArr || []
+                    },
+                    silent: true
+                });
+                inheritStyle(parentGroup, polygon);
+                parseAttributes(xmlNode, polygon, this._defsUsePending, false, false);
+                return polygon;
+            },
+            'polyline': function (xmlNode, parentGroup) {
+                var pointsStr = xmlNode.getAttribute('points');
+                var pointsArr;
+                if (pointsStr) {
+                    pointsArr = parsePoints(pointsStr);
+                }
+                var polyline = new Polyline({
+                    shape: {
+                        points: pointsArr || []
+                    },
+                    silent: true
+                });
+                inheritStyle(parentGroup, polyline);
+                parseAttributes(xmlNode, polyline, this._defsUsePending, false, false);
+                return polyline;
+            },
+            'image': function (xmlNode, parentGroup) {
+                var img = new ZRImage();
+                inheritStyle(parentGroup, img);
+                parseAttributes(xmlNode, img, this._defsUsePending, false, false);
+                img.setStyle({
+                    image: xmlNode.getAttribute('xlink:href'),
+                    x: +xmlNode.getAttribute('x'),
+                    y: +xmlNode.getAttribute('y'),
+                    width: +xmlNode.getAttribute('width'),
+                    height: +xmlNode.getAttribute('height')
+                });
+                img.silent = true;
+                return img;
+            },
+            'text': function (xmlNode, parentGroup) {
+                var x = xmlNode.getAttribute('x') || '0';
+                var y = xmlNode.getAttribute('y') || '0';
+                var dx = xmlNode.getAttribute('dx') || '0';
+                var dy = xmlNode.getAttribute('dy') || '0';
+                this._textX = parseFloat(x) + parseFloat(dx);
+                this._textY = parseFloat(y) + parseFloat(dy);
+                var g = new Group();
+                inheritStyle(parentGroup, g);
+                parseAttributes(xmlNode, g, this._defsUsePending, false, true);
+                return g;
+            },
+            'tspan': function (xmlNode, parentGroup) {
+                var x = xmlNode.getAttribute('x');
+                var y = xmlNode.getAttribute('y');
+                if (x != null) {
+                    this._textX = parseFloat(x);
+                }
+                if (y != null) {
+                    this._textY = parseFloat(y);
+                }
+                var dx = xmlNode.getAttribute('dx') || '0';
+                var dy = xmlNode.getAttribute('dy') || '0';
+                var g = new Group();
+                inheritStyle(parentGroup, g);
+                parseAttributes(xmlNode, g, this._defsUsePending, false, true);
+                this._textX += parseFloat(dx);
+                this._textY += parseFloat(dy);
+                return g;
+            },
+            'path': function (xmlNode, parentGroup) {
+                var d = xmlNode.getAttribute('d') || '';
+                var path = createFromString(d);
+                inheritStyle(parentGroup, path);
+                parseAttributes(xmlNode, path, this._defsUsePending, false, false);
+                path.silent = true;
+                return path;
+            }
+        };
+    })();
+    return SVGParser;
+}());
+var paintServerParsers = {
+    'lineargradient': function (xmlNode) {
+        var x1 = parseInt(xmlNode.getAttribute('x1') || '0', 10);
+        var y1 = parseInt(xmlNode.getAttribute('y1') || '0', 10);
+        var x2 = parseInt(xmlNode.getAttribute('x2') || '10', 10);
+        var y2 = parseInt(xmlNode.getAttribute('y2') || '0', 10);
+        var gradient = new LinearGradient(x1, y1, x2, y2);
+        parsePaintServerUnit(xmlNode, gradient);
+        parseGradientColorStops(xmlNode, gradient);
+        return gradient;
+    },
+    'radialgradient': function (xmlNode) {
+        var cx = parseInt(xmlNode.getAttribute('cx') || '0', 10);
+        var cy = parseInt(xmlNode.getAttribute('cy') || '0', 10);
+        var r = parseInt(xmlNode.getAttribute('r') || '0', 10);
+        var gradient = new RadialGradient(cx, cy, r);
+        parsePaintServerUnit(xmlNode, gradient);
+        parseGradientColorStops(xmlNode, gradient);
+        return gradient;
     }
-
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
+};
+function parsePaintServerUnit(xmlNode, gradient) {
+    var gradientUnits = xmlNode.getAttribute('gradientUnits');
+    if (gradientUnits === 'userSpaceOnUse') {
+        gradient.global = true;
     }
-
-    var silent;
-    var replaceMerge;
-    var transitionOpt;
-
-    if (isObject$2(notMerge)) {
-      lazyUpdate = notMerge.lazyUpdate;
-      silent = notMerge.silent;
-      replaceMerge = notMerge.replaceMerge;
-      transitionOpt = notMerge.transition;
-      notMerge = notMerge.notMerge;
+}
+function parseGradientColorStops(xmlNode, gradient) {
+    var stop = xmlNode.firstChild;
+    while (stop) {
+        if (stop.nodeType === 1
+            && stop.nodeName.toLocaleLowerCase() === 'stop') {
+            var offsetStr = stop.getAttribute('offset');
+            var offset = void 0;
+            if (offsetStr && offsetStr.indexOf('%') > 0) {
+                offset = parseInt(offsetStr, 10) / 100;
+            }
+            else if (offsetStr) {
+                offset = parseFloat(offsetStr);
+            }
+            else {
+                offset = 0;
+            }
+            var styleVals = {};
+            parseInlineStyle(stop, styleVals, styleVals);
+            var stopColor = styleVals.stopColor
+                || stop.getAttribute('stop-color')
+                || '#000000';
+            gradient.colorStops.push({
+                offset: offset,
+                color: stopColor
+            });
+        }
+        stop = stop.nextSibling;
     }
-
-    this[IN_MAIN_PROCESS_KEY] = true;
-
-    if (!this._model || notMerge) {
-      var optionManager = new OptionManager(this._api);
-      var theme = this._theme;
-      var ecModel = this._model = new GlobalModel();
-      ecModel.scheduler = this._scheduler;
-      ecModel.init(null, null, null, theme, this._locale, optionManager);
+}
+function inheritStyle(parent, child) {
+    if (parent && parent.__inheritedStyle) {
+        if (!child.__inheritedStyle) {
+            child.__inheritedStyle = {};
+        }
+        defaults(child.__inheritedStyle, parent.__inheritedStyle);
     }
+}
+function parsePoints(pointsString) {
+    var list = splitNumberSequence(pointsString);
+    var points = [];
+    for (var i = 0; i < list.length; i += 2) {
+        var x = parseFloat(list[i]);
+        var y = parseFloat(list[i + 1]);
+        points.push([x, y]);
+    }
+    return points;
+}
+function parseAttributes(xmlNode, el, defsUsePending, onlyInlineStyle, isTextGroup) {
+    var disp = el;
+    var inheritedStyle = disp.__inheritedStyle = disp.__inheritedStyle || {};
+    var selfStyle = {};
+    if (xmlNode.nodeType === 1) {
+        parseTransformAttribute(xmlNode, el);
+        parseInlineStyle(xmlNode, inheritedStyle, selfStyle);
+        if (!onlyInlineStyle) {
+            parseAttributeStyle(xmlNode, inheritedStyle, selfStyle);
+        }
+    }
+    disp.style = disp.style || {};
+    if (inheritedStyle.fill != null) {
+        disp.style.fill = getFillStrokeStyle(disp, 'fill', inheritedStyle.fill, defsUsePending);
+    }
+    if (inheritedStyle.stroke != null) {
+        disp.style.stroke = getFillStrokeStyle(disp, 'stroke', inheritedStyle.stroke, defsUsePending);
+    }
+    each([
+        'lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize'
+    ], function (propName) {
+        if (inheritedStyle[propName] != null) {
+            disp.style[propName] = parseFloat(inheritedStyle[propName]);
+        }
+    });
+    each([
+        'lineDashOffset', 'lineCap', 'lineJoin', 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign'
+    ], function (propName) {
+        if (inheritedStyle[propName] != null) {
+            disp.style[propName] = inheritedStyle[propName];
+        }
+    });
+    if (isTextGroup) {
+        disp.__selfStyle = selfStyle;
+    }
+    if (inheritedStyle.lineDash) {
+        disp.style.lineDash = map(splitNumberSequence(inheritedStyle.lineDash), function (str) {
+            return parseFloat(str);
+        });
+    }
+    if (inheritedStyle.visibility === 'hidden' || inheritedStyle.visibility === 'collapse') {
+        disp.invisible = true;
+    }
+    if (inheritedStyle.display === 'none') {
+        disp.ignore = true;
+    }
+    disp.z = -10000;
+    disp.z2 = -1000;
+}
+function applyTextAlignment(text, parentGroup) {
+    var parentSelfStyle = parentGroup.__selfStyle;
+    if (parentSelfStyle) {
+        var textBaseline = parentSelfStyle.textBaseline;
+        var zrTextBaseline = textBaseline;
+        if (!textBaseline || textBaseline === 'auto') {
+            zrTextBaseline = 'alphabetic';
+        }
+        else if (textBaseline === 'baseline') {
+            zrTextBaseline = 'alphabetic';
+        }
+        else if (textBaseline === 'before-edge' || textBaseline === 'text-before-edge') {
+            zrTextBaseline = 'top';
+        }
+        else if (textBaseline === 'after-edge' || textBaseline === 'text-after-edge') {
+            zrTextBaseline = 'bottom';
+        }
+        else if (textBaseline === 'central' || textBaseline === 'mathematical') {
+            zrTextBaseline = 'middle';
+        }
+        text.style.textBaseline = zrTextBaseline;
+    }
+    var parentInheritedStyle = parentGroup.__inheritedStyle;
+    if (parentInheritedStyle) {
+        var textAlign = parentInheritedStyle.textAlign;
+        var zrTextAlign = textAlign;
+        if (textAlign) {
+            if (textAlign === 'middle') {
+                zrTextAlign = 'center';
+            }
+            text.style.textAlign = zrTextAlign;
+        }
+    }
+}
+var urlRegex = /^url\(\s*#(.*?)\)/;
+function getFillStrokeStyle(el, method, str, defsUsePending) {
+    var urlMatch = str && str.match(urlRegex);
+    if (urlMatch) {
+        var url = trim(urlMatch[1]);
+        defsUsePending.push([el, method, url]);
+        return;
+    }
+    if (str === 'none') {
+        str = null;
+    }
+    return str;
+}
+function applyDefs(defs, defsUsePending) {
+    for (var i = 0; i < defsUsePending.length; i++) {
+        var item = defsUsePending[i];
+        item[0].style[item[1]] = defs[item[2]];
+    }
+}
+var numberReg$1 = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;
+function splitNumberSequence(rawStr) {
+    return rawStr.match(numberReg$1) || [];
+}
+var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.eE,]*)\)/g;
+function parseTransformAttribute(xmlNode, node) {
+    var transform = xmlNode.getAttribute('transform');
+    if (transform) {
+        transform = transform.replace(/,/g, ' ');
+        var transformOps_1 = [];
+        var mt = null;
+        transform.replace(transformRegex, function (str, type, value) {
+            transformOps_1.push(type, value);
+            return '';
+        });
+        for (var i = transformOps_1.length - 1; i > 0; i -= 2) {
+            var value = transformOps_1[i];
+            var type = transformOps_1[i - 1];
+            var valueArr = void 0;
+            mt = mt || create$1();
+            switch (type) {
+                case 'translate':
+                    valueArr = splitNumberSequence(value);
+                    translate(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || '0')]);
+                    break;
+                case 'scale':
+                    valueArr = splitNumberSequence(value);
+                    scale$1(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || valueArr[0])]);
+                    break;
+                case 'rotate':
+                    valueArr = splitNumberSequence(value);
+                    rotate(mt, mt, -parseFloat(valueArr[0]) / 180 * Math.PI);
+                    break;
+                case 'skew':
+                    valueArr = splitNumberSequence(value);
+                    console.warn('Skew transform is not supported yet');
+                    break;
+                case 'matrix':
+                    valueArr = splitNumberSequence(value);
+                    mt[0] = parseFloat(valueArr[0]);
+                    mt[1] = parseFloat(valueArr[1]);
+                    mt[2] = parseFloat(valueArr[2]);
+                    mt[3] = parseFloat(valueArr[3]);
+                    mt[4] = parseFloat(valueArr[4]);
+                    mt[5] = parseFloat(valueArr[5]);
+                    break;
+            }
+        }
+        node.setLocalTransform(mt);
+    }
+}
+var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g;
+function parseInlineStyle(xmlNode, inheritableStyleResult, selfStyleResult) {
+    var style = xmlNode.getAttribute('style');
+    if (!style) {
+        return;
+    }
+    styleRegex.lastIndex = 0;
+    var styleRegResult;
+    while ((styleRegResult = styleRegex.exec(style)) != null) {
+        var svgStlAttr = styleRegResult[1];
+        var zrInheritableStlAttr = hasOwn(INHERITABLE_STYLE_ATTRIBUTES_MAP, svgStlAttr)
+            ? INHERITABLE_STYLE_ATTRIBUTES_MAP[svgStlAttr]
+            : null;
+        if (zrInheritableStlAttr) {
+            inheritableStyleResult[zrInheritableStlAttr] = styleRegResult[2];
+        }
+        var zrSelfStlAttr = hasOwn(SELF_STYLE_ATTRIBUTES_MAP, svgStlAttr)
+            ? SELF_STYLE_ATTRIBUTES_MAP[svgStlAttr]
+            : null;
+        if (zrSelfStlAttr) {
+            selfStyleResult[zrSelfStlAttr] = styleRegResult[2];
+        }
+    }
+}
+function parseAttributeStyle(xmlNode, inheritableStyleResult, selfStyleResult) {
+    for (var i = 0; i < INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) {
+        var svgAttrName = INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS[i];
+        var attrValue = xmlNode.getAttribute(svgAttrName);
+        if (attrValue != null) {
+            inheritableStyleResult[INHERITABLE_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue;
+        }
+    }
+    for (var i = 0; i < SELF_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) {
+        var svgAttrName = SELF_STYLE_ATTRIBUTES_MAP_KEYS[i];
+        var attrValue = xmlNode.getAttribute(svgAttrName);
+        if (attrValue != null) {
+            selfStyleResult[SELF_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue;
+        }
+    }
+}
+function makeViewBoxTransform(viewBoxRect, boundingRect) {
+    var scaleX = boundingRect.width / viewBoxRect.width;
+    var scaleY = boundingRect.height / viewBoxRect.height;
+    var scale = Math.min(scaleX, scaleY);
+    return {
+        scale: scale,
+        x: -(viewBoxRect.x + viewBoxRect.width / 2) * scale + (boundingRect.x + boundingRect.width / 2),
+        y: -(viewBoxRect.y + viewBoxRect.height / 2) * scale + (boundingRect.y + boundingRect.height / 2)
+    };
+}
+function parseSVG(xml, opt) {
+    var parser = new SVGParser();
+    return parser.parse(xml, opt);
+}
 
-    this._model.setOption(option, {
-      replaceMerge: replaceMerge
-    }, optionPreprocessorFuncs);
-
-    setTransitionOpt(this, transitionOpt);
-
-    if (lazyUpdate) {
-      this[OPTION_UPDATED_KEY] = {
-        silent: silent
-      };
-      this[IN_MAIN_PROCESS_KEY] = false; // `setOption(option, {lazyMode: true})` may be called when zrender has been slept.
-      // It should wake it up to make sure zrender start to render at the next frame.
-
-      this.getZr().wakeUp();
-    } else {
-      prepare(this);
-      updateMethods.update.call(this); // Ensure zr refresh sychronously, and then pixel in canvas can be
-      // fetched after `setOption`.
+var EPSILON$3 = 1e-8;
+function isAroundEqual$1(a, b) {
+    return Math.abs(a - b) < EPSILON$3;
+}
+function contain$1(points, x, y) {
+    var w = 0;
+    var p = points[0];
+    if (!p) {
+        return false;
+    }
+    for (var i = 1; i < points.length; i++) {
+        var p2 = points[i];
+        w += windingLine(p[0], p[1], p2[0], p2[1], x, y);
+        p = p2;
+    }
+    var p0 = points[0];
+    if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) {
+        w += windingLine(p[0], p[1], p0[0], p0[1], x, y);
+    }
+    return w !== 0;
+}
 
-      this._zr.flush();
+var TMP_TRANSFORM = [];
 
-      this[OPTION_UPDATED_KEY] = false;
-      this[IN_MAIN_PROCESS_KEY] = false;
-      flushPendingActions.call(this, silent);
-      triggerUpdatedEvent.call(this, silent);
-    }
-  };
+var Region =
+/** @class */
+function () {
+  function Region(name) {
+    this.name = name;
+  }
   /**
-   * @DEPRECATED
+   * Get center point in data unit. That is,
+   * for GeoJSONRegion, the unit is lat/lng,
+   * for GeoSVGRegion, the unit is SVG local coord.
    */
 
 
-  ECharts.prototype.setTheme = function () {
-    console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
-  }; // We don't want developers to use getModel directly.
+  Region.prototype.getCenter = function () {
+    return;
+  };
 
+  return Region;
+}();
 
-  ECharts.prototype.getModel = function () {
-    return this._model;
-  };
+var GeoJSONRegion =
+/** @class */
+function (_super) {
+  __extends(GeoJSONRegion, _super);
 
-  ECharts.prototype.getOption = function () {
-    return this._model && this._model.getOption();
-  };
+  function GeoJSONRegion(name, geometries, cp) {
+    var _this = _super.call(this, name) || this;
 
-  ECharts.prototype.getWidth = function () {
-    return this._zr.getWidth();
-  };
+    _this.type = 'geoJSON';
+    _this.geometries = geometries;
 
-  ECharts.prototype.getHeight = function () {
-    return this._zr.getHeight();
-  };
+    if (!cp) {
+      var rect = _this.getBoundingRect();
 
-  ECharts.prototype.getDevicePixelRatio = function () {
-    return this._zr.painter.dpr
-    /* eslint-disable-next-line */
-    || hasWindow && window.devicePixelRatio || 1;
-  };
-  /**
-   * Get canvas which has all thing rendered
-   */
+      cp = [rect.x + rect.width / 2, rect.y + rect.height / 2];
+    } else {
+      cp = [cp[0], cp[1]];
+    }
+
+    _this._center = cp;
+    return _this;
+  }
 
+  GeoJSONRegion.prototype.getBoundingRect = function () {
+    var rect = this._rect;
 
-  ECharts.prototype.getRenderedCanvas = function (opts) {
-    if (!env.canvasSupported) {
-      return;
+    if (rect) {
+      return rect;
     }
 
-    opts = extend({}, opts || {});
-    opts.pixelRatio = opts.pixelRatio || this.getDevicePixelRatio();
-    opts.backgroundColor = opts.backgroundColor || this._model.get('backgroundColor');
-    var zr = this._zr; // let list = zr.storage.getDisplayList();
-    // Stop animations
-    // Never works before in init animation, so remove it.
-    // zrUtil.each(list, function (el) {
-    //     el.stopAnimation(true);
-    // });
+    var MAX_NUMBER = Number.MAX_VALUE;
+    var min$1 = [MAX_NUMBER, MAX_NUMBER];
+    var max$1 = [-MAX_NUMBER, -MAX_NUMBER];
+    var min2 = [];
+    var max2 = [];
+    var geometries = this.geometries;
+    var i = 0;
 
-    return zr.painter.getRenderedCanvas(opts);
-  };
-  /**
-   * Get svg data url
-   */
+    for (; i < geometries.length; i++) {
+      // Only support polygon
+      if (geometries[i].type !== 'polygon') {
+        continue;
+      } // Doesn't consider hole
 
 
-  ECharts.prototype.getSvgDataURL = function () {
-    if (!env.svgSupported) {
-      return;
-    }
+      var exterior = geometries[i].exterior;
+      fromPoints(exterior, min2, max2);
+      min(min$1, min$1, min2);
+      max(max$1, max$1, max2);
+    } // No data
 
-    var zr = this._zr;
-    var list = zr.storage.getDisplayList(); // Stop animations
 
-    each(list, function (el) {
-      el.stopAnimation(null, true);
-    });
-    return zr.painter.toDataURL();
+    if (i === 0) {
+      min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0;
+    }
+
+    return this._rect = new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]);
   };
 
-  ECharts.prototype.getDataURL = function (opts) {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
+  GeoJSONRegion.prototype.contain = function (coord) {
+    var rect = this.getBoundingRect();
+    var geometries = this.geometries;
+
+    if (!rect.contain(coord[0], coord[1])) {
+      return false;
     }
 
-    opts = opts || {};
-    var excludeComponents = opts.excludeComponents;
-    var ecModel = this._model;
-    var excludesComponentViews = [];
-    var self = this;
-    each$3(excludeComponents, function (componentType) {
-      ecModel.eachComponent({
-        mainType: componentType
-      }, function (component) {
-        var view = self._componentsMap[component.__viewId];
+    loopGeo: for (var i = 0, len = geometries.length; i < len; i++) {
+      // Only support polygon.
+      if (geometries[i].type !== 'polygon') {
+        continue;
+      }
 
-        if (!view.group.ignore) {
-          excludesComponentViews.push(view);
-          view.group.ignore = true;
+      var exterior = geometries[i].exterior;
+      var interiors = geometries[i].interiors;
+
+      if (contain$1(exterior, coord[0], coord[1])) {
+        // Not in the region if point is in the hole.
+        for (var k = 0; k < (interiors ? interiors.length : 0); k++) {
+          if (contain$1(interiors[k], coord[0], coord[1])) {
+            continue loopGeo;
+          }
         }
-      });
-    });
-    var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.getRenderedCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png'));
-    each$3(excludesComponentViews, function (view) {
-      view.group.ignore = false;
-    });
-    return url;
-  };
 
-  ECharts.prototype.getConnectedDataURL = function (opts) {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
+        return true;
+      }
     }
 
-    if (!env.canvasSupported) {
-      return;
+    return false;
+  };
+
+  GeoJSONRegion.prototype.transformTo = function (x, y, width, height) {
+    var rect = this.getBoundingRect();
+    var aspect = rect.width / rect.height;
+
+    if (!width) {
+      width = aspect * height;
+    } else if (!height) {
+      height = width / aspect;
     }
 
-    var isSvg = opts.type === 'svg';
-    var groupId = this.group;
-    var mathMin = Math.min;
-    var mathMax = Math.max;
-    var MAX_NUMBER = Infinity;
+    var target = new BoundingRect(x, y, width, height);
+    var transform = rect.calculateTransform(target);
+    var geometries = this.geometries;
 
-    if (connectedGroups[groupId]) {
-      var left_1 = MAX_NUMBER;
-      var top_1 = MAX_NUMBER;
-      var right_1 = -MAX_NUMBER;
-      var bottom_1 = -MAX_NUMBER;
-      var canvasList_1 = [];
-      var dpr_1 = opts && opts.pixelRatio || this.getDevicePixelRatio();
-      each(instances$1, function (chart, id) {
-        if (chart.group === groupId) {
-          var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.getRenderedCanvas(clone(opts));
-          var boundingRect = chart.getDom().getBoundingClientRect();
-          left_1 = mathMin(boundingRect.left, left_1);
-          top_1 = mathMin(boundingRect.top, top_1);
-          right_1 = mathMax(boundingRect.right, right_1);
-          bottom_1 = mathMax(boundingRect.bottom, bottom_1);
-          canvasList_1.push({
-            dom: canvas,
-            left: boundingRect.left,
-            top: boundingRect.top
-          });
-        }
-      });
-      left_1 *= dpr_1;
-      top_1 *= dpr_1;
-      right_1 *= dpr_1;
-      bottom_1 *= dpr_1;
-      var width = right_1 - left_1;
-      var height = bottom_1 - top_1;
-      var targetCanvas = createCanvas();
-      var zr_1 = init(targetCanvas, {
-        renderer: isSvg ? 'svg' : 'canvas'
-      });
-      zr_1.resize({
-        width: width,
-        height: height
-      });
+    for (var i = 0; i < geometries.length; i++) {
+      // Only support polygon.
+      if (geometries[i].type !== 'polygon') {
+        continue;
+      }
 
-      if (isSvg) {
-        var content_1 = '';
-        each$3(canvasList_1, function (item) {
-          var x = item.left - left_1;
-          var y = item.top - top_1;
-          content_1 += '<g transform="translate(' + x + ',' + y + ')">' + item.dom + '</g>';
-        });
-        zr_1.painter.getSvgRoot().innerHTML = content_1;
+      var exterior = geometries[i].exterior;
+      var interiors = geometries[i].interiors;
 
-        if (opts.connectedBackgroundColor) {
-          zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor);
-        }
+      for (var p = 0; p < exterior.length; p++) {
+        applyTransform(exterior[p], exterior[p], transform);
+      }
 
-        zr_1.refreshImmediately();
-        return zr_1.painter.toDataURL();
-      } else {
-        // Background between the charts
-        if (opts.connectedBackgroundColor) {
-          zr_1.add(new Rect({
-            shape: {
-              x: 0,
-              y: 0,
-              width: width,
-              height: height
-            },
-            style: {
-              fill: opts.connectedBackgroundColor
-            }
-          }));
+      for (var h = 0; h < (interiors ? interiors.length : 0); h++) {
+        for (var p = 0; p < interiors[h].length; p++) {
+          applyTransform(interiors[h][p], interiors[h][p], transform);
         }
-
-        each$3(canvasList_1, function (item) {
-          var img = new ZRImage({
-            style: {
-              x: item.left * dpr_1 - left_1,
-              y: item.top * dpr_1 - top_1,
-              image: item.dom
-            }
-          });
-          zr_1.add(img);
-        });
-        zr_1.refreshImmediately();
-        return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
       }
-    } else {
-      return this.getDataURL(opts);
     }
-  };
 
-  ECharts.prototype.convertToPixel = function (finder, value) {
-    return doConvertPixel(this, 'convertToPixel', finder, value);
+    rect = this._rect;
+    rect.copy(target); // Update center
+
+    this._center = [rect.x + rect.width / 2, rect.y + rect.height / 2];
   };
 
-  ECharts.prototype.convertFromPixel = function (finder, value) {
-    return doConvertPixel(this, 'convertFromPixel', finder, value);
+  GeoJSONRegion.prototype.cloneShallow = function (name) {
+    name == null && (name = this.name);
+    var newRegion = new GeoJSONRegion(name, this.geometries, this._center);
+    newRegion._rect = this._rect;
+    newRegion.transformTo = null; // Simply avoid to be called.
+
+    return newRegion;
   };
-  /**
-   * Is the specified coordinate systems or components contain the given pixel point.
-   * @param {Array|number} value
-   * @return {boolean} result
-   */
 
+  GeoJSONRegion.prototype.getCenter = function () {
+    return this._center;
+  };
 
-  ECharts.prototype.containPixel = function (finder, value) {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
-    }
+  GeoJSONRegion.prototype.setCenter = function (center) {
+    this._center = center;
+  };
 
-    var ecModel = this._model;
-    var result;
-    var findResult = parseFinder(ecModel, finder);
-    each(findResult, function (models, key) {
-      key.indexOf('Models') >= 0 && each(models, function (model) {
-        var coordSys = model.coordinateSystem;
+  return GeoJSONRegion;
+}(Region);
 
-        if (coordSys && coordSys.containPoint) {
-          result = result || !!coordSys.containPoint(value);
-        } else if (key === 'seriesModels') {
-          var view = this._chartsMap[model.__viewId];
+var GeoSVGRegion =
+/** @class */
+function (_super) {
+  __extends(GeoSVGRegion, _super);
 
-          if (view && view.containPoint) {
-            result = result || view.containPoint(value, model);
-          } else {
-            if ("development" !== 'production') {
-              console.warn(key + ': ' + (view ? 'The found component do not support containPoint.' : 'No view mapping to the found component.'));
-            }
-          }
-        } else {
-          if ("development" !== 'production') {
-            console.warn(key + ': containPoint is not supported');
-          }
-        }
-      }, this);
-    }, this);
-    return !!result;
-  };
-  /**
-   * Get visual from series or data.
-   * @param finder
-   *        If string, e.g., 'series', means {seriesIndex: 0}.
-   *        If Object, could contain some of these properties below:
-   *        {
-   *            seriesIndex / seriesId / seriesName,
-   *            dataIndex / dataIndexInside
-   *        }
-   *        If dataIndex is not specified, series visual will be fetched,
-   *        but not data item visual.
-   *        If all of seriesIndex, seriesId, seriesName are not specified,
-   *        visual will be fetched from first series.
-   * @param visualType 'color', 'symbol', 'symbolSize'
-   */
+  function GeoSVGRegion(name, elOnlyForCalculate) {
+    var _this = _super.call(this, name) || this;
 
+    _this.type = 'geoSVG';
+    _this._elOnlyForCalculate = elOnlyForCalculate;
+    return _this;
+  }
 
-  ECharts.prototype.getVisual = function (finder, visualType) {
-    var ecModel = this._model;
-    var parsedFinder = parseFinder(ecModel, finder, {
-      defaultMainType: 'series'
-    });
-    var seriesModel = parsedFinder.seriesModel;
+  GeoSVGRegion.prototype.getCenter = function () {
+    var center = this._center;
 
-    if ("development" !== 'production') {
-      if (!seriesModel) {
-        console.warn('There is no specified seires model');
-      }
+    if (!center) {
+      // In most cases there are no need to calculate this center.
+      // So calculate only when called.
+      center = this._center = this._calculateCenter();
     }
 
-    var data = seriesModel.getData();
-    var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null;
-    return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType);
+    return center;
   };
-  /**
-   * Get view of corresponding component model
-   */
 
+  GeoSVGRegion.prototype._calculateCenter = function () {
+    var el = this._elOnlyForCalculate;
+    var rect = el.getBoundingRect();
+    var center = [rect.x + rect.width / 2, rect.y + rect.height / 2];
+    var mat = identity(TMP_TRANSFORM);
+    var target = el;
 
-  ECharts.prototype.getViewOfComponentModel = function (componentModel) {
-    return this._componentsMap[componentModel.__viewId];
+    while (target && !target.isGeoSVGGraphicRoot) {
+      mul$1(mat, target.getLocalTransform(), mat);
+      target = target.parent;
+    }
+
+    invert(mat, mat);
+    applyTransform(center, center, mat);
+    return center;
   };
-  /**
-   * Get view of corresponding series model
-   */
 
+  return GeoSVGRegion;
+}(Region);
 
-  ECharts.prototype.getViewOfSeriesModel = function (seriesModel) {
-    return this._chartsMap[seriesModel.__viewId];
-  };
+/**
+ * "region available" means that: enable users to set attribute `name="xxx"` on those tags
+ * to make it be a region.
+ * 1. region styles and its label styles can be defined in echarts opton:
+ * ```js
+ * geo: {
+ *     regions: [{
+ *         name: 'xxx',
+ *         itemStyle: { ... },
+ *         label: { ... }
+ *     }, {
+ *         ...
+ *     },
+ *     ...]
+ * };
+ * ```
+ * 2. name can be duplicated in different SVG tag. All of the tags with the same name share
+ * a region option. For exampel if there are two <path> representing two lung lobes. They have
+ * no common parents but both of them need to display label "lung" inside.
+ */
 
-  ECharts.prototype._initEvents = function () {
-    var _this = this;
+var REGION_AVAILABLE_SVG_TAG_MAP = createHashMap(['rect', 'circle', 'line', 'ellipse', 'polygon', 'polyline', 'path', // <text> <tspan> are also enabled becuase some SVG might paint text itself,
+// but still need to trigger events or tooltip.
+'text', 'tspan', // <g> is also enabled because this case: if multiple tags share one name
+// and need label displayed, every tags will display the name, which is not
+// expected. So we can put them into a <g name="xxx">. Thereby only one label
+// displayed and located based on the bounding rect of the <g>.
+'g']);
 
-    each$3(MOUSE_EVENT_NAMES, function (eveName) {
-      var handler = function (e) {
-        var ecModel = _this.getModel();
+var GeoSVGResource =
+/** @class */
+function () {
+  function GeoSVGResource(mapName, svg) {
+    this.type = 'geoSVG'; // All used graphics. key: hostKey, value: root
 
-        var el = e.target;
-        var params;
-        var isGlobalOut = eveName === 'globalout'; // no e.target when 'globalout'.
+    this._usedGraphicMap = createHashMap(); // All unused graphics.
 
-        if (isGlobalOut) {
-          params = {};
-        } else {
-          el && findEventDispatcher(el, function (parent) {
-            var ecData = getECData(parent);
+    this._freedGraphics = [];
+    this._mapName = mapName; // Only perform parse to XML object here, which might be time
+    // consiming for large SVG.
+    // Although convert XML to zrender element is also time consiming,
+    // if we do it here, the clone of zrender elements has to be
+    // required. So we do it once for each geo instance, util real
+    // performance issues call for optimizing it.
 
-            if (ecData && ecData.dataIndex != null) {
-              var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex);
-              params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType) || {};
-              return true;
-            } // If element has custom eventData of components
-            else if (ecData.eventData) {
-                params = extend({}, ecData.eventData);
-                return true;
-              }
-          }, true);
-        } // Contract: if params prepared in mouse event,
-        // these properties must be specified:
-        // {
-        //    componentType: string (component main type)
-        //    componentIndex: number
-        // }
-        // Otherwise event query can not work.
+    this._parsedXML = parseXML(svg);
+  }
 
+  GeoSVGResource.prototype.load = function ()
+  /* nameMap: NameMap */
+  {
+    // In the "load" stage, graphic need to be built to
+    // get boundingRect for geo coordinate system.
+    var firstGraphic = this._firstGraphic; // Create the return data structure only when first graphic created.
+    // Because they will be used in geo coordinate system update stage,
+    // and `regions` will be mounted at `geo` coordinate system,
+    // in which there is no "view" info, so that it should better not to
+    // make references to graphic elements.
 
-        if (params) {
-          var componentType = params.componentType;
-          var componentIndex = params.componentIndex; // Special handling for historic reason: when trigger by
-          // markLine/markPoint/markArea, the componentType is
-          // 'markLine'/'markPoint'/'markArea', but we should better
-          // enable them to be queried by seriesIndex, since their
-          // option is set in each series.
+    if (!firstGraphic) {
+      firstGraphic = this._firstGraphic = this._buildGraphic(this._parsedXML);
 
-          if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') {
-            componentType = 'series';
-            componentIndex = params.seriesIndex;
-          }
+      this._freedGraphics.push(firstGraphic);
 
-          var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex);
-          var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId];
+      this._boundingRect = this._firstGraphic.boundingRect.clone(); // PENDING: `nameMap` will not be supported until some real requirement come.
+      // if (nameMap) {
+      //     named = applyNameMap(named, nameMap);
+      // }
 
-          if ("development" !== 'production') {
-            // `event.componentType` and `event[componentTpype + 'Index']` must not
-            // be missed, otherwise there is no way to distinguish source component.
-            // See `dataFormat.getDataParams`.
-            if (!isGlobalOut && !(model && view)) {
-              console.warn('model or view can not be found by params');
-            }
-          }
+      var _a = createRegions(firstGraphic.named),
+          regions = _a.regions,
+          regionsMap = _a.regionsMap;
 
-          params.event = e;
-          params.type = eveName;
-          _this._$eventProcessor.eventInfo = {
-            targetEl: el,
-            packedEvent: params,
-            model: model,
-            view: view
-          };
+      this._regions = regions;
+      this._regionsMap = regionsMap;
+    }
 
-          _this.trigger(eveName, params);
-        }
-      }; // Consider that some component (like tooltip, brush, ...)
-      // register zr event handler, but user event handler might
-      // do anything, such as call `setOption` or `dispatchAction`,
-      // which probably update any of the content and probably
-      // cause problem if it is called previous other inner handlers.
+    return {
+      boundingRect: this._boundingRect,
+      regions: this._regions,
+      regionsMap: this._regionsMap
+    };
+  };
+
+  GeoSVGResource.prototype._buildGraphic = function (svgXML) {
+    var result;
+    var rootFromParse;
 
+    try {
+      result = svgXML && parseSVG(svgXML, {
+        ignoreViewBox: true,
+        ignoreRootClip: true
+      }) || {};
+      rootFromParse = result.root;
+      assert(rootFromParse != null);
+    } catch (e) {
+      throw new Error('Invalid svg format\n' + e.message);
+    } // Note: we keep the covenant that the root has no transform. So always add an extra root.
 
-      handler.zrEventfulCallAtLast = true;
 
-      _this._zr.on(eveName, handler, _this);
-    });
-    each$3(eventActionMap, function (actionType, eventType) {
-      _this._messageCenter.on(eventType, function (event) {
-        this.trigger(eventType, event);
-      }, _this);
-    }); // Extra events
-    // TODO register?
+    var root = new Group();
+    root.add(rootFromParse);
+    root.isGeoSVGGraphicRoot = true; // [THE_RULE_OF_VIEWPORT_AND_VIEWBOX]
+    //
+    // Consider: `<svg width="..." height="..." viewBox="...">`
+    // - the `width/height` we call it `svgWidth/svgHeight` for short.
+    // - `(0, 0, svgWidth, svgHeight)` defines the viewport of the SVG, or say,
+    //   "viewport boundingRect", or `boundingRect` for short.
+    // - `viewBox` defines the transform from the real content ot the viewport.
+    //   `viewBox` has the same unit as the content of SVG.
+    //   If `viewBox` exists, a transform is defined, so the unit of `svgWidth/svgHeight` become
+    //   different from the content of SVG. Otherwise, they are the same.
+    //
+    // If both `svgWidth/svgHeight/viewBox` are specified in a SVG file, the transform rule will be:
+    // 0. `boundingRect` is `(0, 0, svgWidth, svgHeight)`. Set it to Geo['_rect'] (View['_rect']).
+    // 1. Make a transform from `viewBox` to `boundingRect`.
+    //    Note: only suport `preserveAspectRatio 'xMidYMid'` here. That is, this transform will preserve
+    //    the aspect ratio.
+    // 2. Make a transform from boundingRect to Geo['_viewRect'] (View['_viewRect'])
+    //    (`Geo`/`View` will do this job).
+    //    Note: this transform might not preserve aspect radio, which depending on how users specify
+    //    viewRect in echarts option (e.g., `geo.left/top/width/height` will not preserve aspect ratio,
+    //    but `geo.layoutCenter/layoutSize` will preserve aspect ratio).
+    //
+    // If `svgWidth/svgHeight` not specified, we use `viewBox` as the `boundingRect` to make the SVG
+    // layout look good.
+    //
+    // If neither `svgWidth/svgHeight` nor `viewBox` are not specified, we calculate the boundingRect
+    // of the SVG content and use them to make SVG layout look good.
 
-    each$3(['selectchanged'], function (eventType) {
-      _this._messageCenter.on(eventType, function (event) {
-        this.trigger(eventType, event);
-      }, _this);
-    });
-    handleLegacySelectEvents(this._messageCenter, this, this._api);
-  };
+    var svgWidth = result.width;
+    var svgHeight = result.height;
+    var viewBoxRect = result.viewBoxRect;
+    var boundingRect = this._boundingRect;
 
-  ECharts.prototype.isDisposed = function () {
-    return this._disposed;
-  };
+    if (!boundingRect) {
+      var bRectX = void 0;
+      var bRectY = void 0;
+      var bRectWidth = void 0;
+      var bRectHeight = void 0;
 
-  ECharts.prototype.clear = function () {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
-    }
+      if (svgWidth != null) {
+        bRectX = 0;
+        bRectWidth = svgWidth;
+      } else if (viewBoxRect) {
+        bRectX = viewBoxRect.x;
+        bRectWidth = viewBoxRect.width;
+      }
 
-    this.setOption({
-      series: []
-    }, true);
-  };
+      if (svgHeight != null) {
+        bRectY = 0;
+        bRectHeight = svgHeight;
+      } else if (viewBoxRect) {
+        bRectY = viewBoxRect.y;
+        bRectHeight = viewBoxRect.height;
+      } // If both viewBox and svgWidth/svgHeight not specified,
+      // we have to determine how to layout those element to make them look good.
 
-  ECharts.prototype.dispose = function () {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
+
+      if (bRectX == null || bRectY == null) {
+        var calculatedBoundingRect = rootFromParse.getBoundingRect();
+
+        if (bRectX == null) {
+          bRectX = calculatedBoundingRect.x;
+          bRectWidth = calculatedBoundingRect.width;
+        }
+
+        if (bRectY == null) {
+          bRectY = calculatedBoundingRect.y;
+          bRectHeight = calculatedBoundingRect.height;
+        }
+      }
+
+      boundingRect = this._boundingRect = new BoundingRect(bRectX, bRectY, bRectWidth, bRectHeight);
     }
 
-    this._disposed = true;
-    setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
-    var api = this._api;
-    var ecModel = this._model;
-    each$3(this._componentsViews, function (component) {
-      component.dispose(ecModel, api);
-    });
-    each$3(this._chartsViews, function (chart) {
-      chart.dispose(ecModel, api);
-    }); // Dispose after all views disposed
+    if (viewBoxRect) {
+      var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect); // Only support `preserveAspectRatio 'xMidYMid'`
 
-    this._zr.dispose();
+      rootFromParse.scaleX = rootFromParse.scaleY = viewBoxTransform.scale;
+      rootFromParse.x = viewBoxTransform.x;
+      rootFromParse.y = viewBoxTransform.y;
+    } // SVG needs to clip based on `viewBox`. And some SVG files really rely on this feature.
+    // They do not strictly confine all of the content inside a display rect, but deliberately
+    // use a `viewBox` to define a displayable rect.
+    // PENDING:
+    // The drawback of the `setClipPath` here is: the region label (genereted by echarts) near the
+    // edge might also be clipped, because region labels are put as `textContent` of the SVG path.
 
-    delete instances$1[this.id];
+
+    root.setClipPath(new Rect({
+      shape: boundingRect.plain()
+    }));
+    var named = [];
+    each(result.named, function (namedItem) {
+      if (REGION_AVAILABLE_SVG_TAG_MAP.get(namedItem.svgNodeTagLower) != null) {
+        named.push(namedItem);
+        setSilent(namedItem.el);
+      }
+    });
+    return {
+      root: root,
+      boundingRect: boundingRect,
+      named: named
+    };
   };
   /**
-   * Resize the chart
+   * Consider:
+   * (1) One graphic element can not be shared by different `geoView` running simultaneously.
+   *     Notice, also need to consider multiple echarts instances share a `mapRecord`.
+   * (2) Converting SVG to graphic elements is time consuming.
+   * (3) In the current architecture, `load` should be called frequently to get boundingRect,
+   *     and it is called without view info.
+   * So we maintain graphic elements in this module, and enables `view` to use/return these
+   * graphics from/to the pool with it's uid.
    */
 
 
-  ECharts.prototype.resize = function (opts) {
-    if ("development" !== 'production') {
-      assert$1(!this[IN_MAIN_PROCESS_KEY], '`resize` should not be called during main process.');
-    }
+  GeoSVGResource.prototype.useGraphic = function (hostKey
+  /*, nameMap: NameMap */
+  ) {
+    var usedRootMap = this._usedGraphicMap;
+    var svgGraphic = usedRootMap.get(hostKey);
 
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
+    if (svgGraphic) {
+      return svgGraphic;
     }
 
-    this._zr.resize(opts);
+    svgGraphic = this._freedGraphics.pop() // use the first boundingRect to avoid duplicated boundingRect calculation.
+    || this._buildGraphic(this._parsedXML);
+    usedRootMap.set(hostKey, svgGraphic); // PENDING: `nameMap` will not be supported until some real requirement come.
+    // `nameMap` can only be obtained from echarts option.
+    // The original `named` must not be modified.
+    // if (nameMap) {
+    //     svgGraphic = extend({}, svgGraphic);
+    //     svgGraphic.named = applyNameMap(svgGraphic.named, nameMap);
+    // }
 
-    var ecModel = this._model; // Resize loading effect
+    return svgGraphic;
+  };
 
-    this._loadingFX && this._loadingFX.resize();
+  GeoSVGResource.prototype.freeGraphic = function (hostKey) {
+    var usedRootMap = this._usedGraphicMap;
+    var svgGraphic = usedRootMap.get(hostKey);
 
-    if (!ecModel) {
-      return;
-    }
+    if (svgGraphic) {
+      usedRootMap.removeKey(hostKey);
 
-    var optionChanged = ecModel.resetOption('media');
-    var silent = opts && opts.silent;
-    this[IN_MAIN_PROCESS_KEY] = true;
-    optionChanged && prepare(this);
-    updateMethods.update.call(this, {
-      type: 'resize',
-      animation: {
-        // Disable animation
-        duration: 0
-      }
-    });
-    this[IN_MAIN_PROCESS_KEY] = false;
-    flushPendingActions.call(this, silent);
-    triggerUpdatedEvent.call(this, silent);
+      this._freedGraphics.push(svgGraphic);
+    }
   };
 
-  ECharts.prototype.showLoading = function (name, cfg) {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
-    }
+  return GeoSVGResource;
+}();
 
-    if (isObject$2(name)) {
-      cfg = name;
-      name = '';
-    }
+function setSilent(el) {
+  // Only named element has silent: false, other elements should
+  // act as background and has no user interaction.
+  el.silent = false; // text|tspan will be converted to group.
 
-    name = name || 'default';
-    this.hideLoading();
+  if (el.isGroup) {
+    el.traverse(function (child) {
+      child.silent = false;
+    });
+  }
+}
 
-    if (!loadingEffects[name]) {
-      if ("development" !== 'production') {
-        console.warn('Loading effects ' + name + ' not exists.');
-      }
+function createRegions(named) {
+  var regions = [];
+  var regionsMap = createHashMap(); // Create resions only for the first graphic.
 
+  each(named, function (namedItem) {
+    // Region has feature to calculate center for tooltip or other features.
+    // If there is a <g name="xxx">, the center should be the center of the
+    // bounding rect of the g.
+    if (namedItem.namedFrom != null) {
       return;
     }
 
-    var el = loadingEffects[name](this._api, cfg);
-    var zr = this._zr;
-    this._loadingFX = el;
-    zr.add(el);
-  };
-  /**
-   * Hide loading effect
-   */
+    var region = new GeoSVGRegion(namedItem.name, namedItem.el); // PENDING: if `nameMap` supported, this region can not be mounted on
+    // `this`, but can only be created each time `load()` called.
 
+    regions.push(region); // PENDING: if multiple tag named with the same name, only one will be
+    // found by `_regionsMap`. `_regionsMap` is used to find a coordinate
+    // by name. We use `region.getCenter()` as the coordinate.
 
-  ECharts.prototype.hideLoading = function () {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
-    }
-
-    this._loadingFX && this._zr.remove(this._loadingFX);
-    this._loadingFX = null;
-  };
-
-  ECharts.prototype.makeActionFromEvent = function (eventObj) {
-    var payload = extend({}, eventObj);
-    payload.type = eventActionMap[eventObj.type];
-    return payload;
+    regionsMap.set(namedItem.name, region);
+  });
+  return {
+    regions: regions,
+    regionsMap: regionsMap
   };
-  /**
-   * @param opt If pass boolean, means opt.silent
-   * @param opt.silent Default `false`. Whether trigger events.
-   * @param opt.flush Default `undefined`.
-   *        true: Flush immediately, and then pixel in canvas can be fetched
-   *            immediately. Caution: it might affect performance.
-   *        false: Not flush.
-   *        undefined: Auto decide whether perform flush.
-   */
+} // PENDING: `nameMap` will not be supported until some real requirement come.
+// /**
+//  * Use the alias in geoNameMap.
+//  * The input `named` must not be modified.
+//  */
+// function applyNameMap(
+//     named: GeoSVGGraphicRecord['named'],
+//     nameMap: NameMap
+// ): GeoSVGGraphicRecord['named'] {
+//     const result = [] as GeoSVGGraphicRecord['named'];
+//     for (let i = 0; i < named.length; i++) {
+//         let regionGraphic = named[i];
+//         const name = regionGraphic.name;
+//         if (nameMap && nameMap.hasOwnProperty(name)) {
+//             regionGraphic = extend({}, regionGraphic);
+//             regionGraphic.name = name;
+//         }
+//         result.push(regionGraphic);
+//     }
+//     return result;
+// }
 
+function decode(json) {
+  if (!json.UTF8Encoding) {
+    return json;
+  }
 
-  ECharts.prototype.dispatchAction = function (payload, opt) {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
-    }
+  var jsonCompressed = json;
+  var encodeScale = jsonCompressed.UTF8Scale;
 
-    if (!isObject$2(opt)) {
-      opt = {
-        silent: !!opt
-      };
-    }
+  if (encodeScale == null) {
+    encodeScale = 1024;
+  }
 
-    if (!actions[payload.type]) {
-      return;
-    } // Avoid dispatch action before setOption. Especially in `connect`.
+  var features = jsonCompressed.features;
 
+  for (var f = 0; f < features.length; f++) {
+    var feature = features[f];
+    var geometry = feature.geometry;
 
-    if (!this._model) {
-      return;
-    } // May dispatchAction in rendering procedure
+    if (geometry.type === 'Polygon') {
+      var coordinates = geometry.coordinates;
 
+      for (var c = 0; c < coordinates.length; c++) {
+        coordinates[c] = decodePolygon(coordinates[c], geometry.encodeOffsets[c], encodeScale);
+      }
+    } else if (geometry.type === 'MultiPolygon') {
+      var coordinates = geometry.coordinates;
 
-    if (this[IN_MAIN_PROCESS_KEY]) {
-      this._pendingActions.push(payload);
+      for (var c = 0; c < coordinates.length; c++) {
+        var coordinate = coordinates[c];
 
-      return;
+        for (var c2 = 0; c2 < coordinate.length; c2++) {
+          coordinate[c2] = decodePolygon(coordinate[c2], geometry.encodeOffsets[c][c2], encodeScale);
+        }
+      }
     }
+  } // Has been decoded
 
-    var silent = opt.silent;
-    doDispatchAction.call(this, payload, silent);
-    var flush = opt.flush;
 
-    if (flush) {
-      this._zr.flush();
-    } else if (flush !== false && env.browser.weChat) {
-      // In WeChat embeded browser, `requestAnimationFrame` and `setInterval`
-      // hang when sliding page (on touch event), which cause that zr does not
-      // refresh util user interaction finished, which is not expected.
-      // But `dispatchAction` may be called too frequently when pan on touch
-      // screen, which impacts performance if do not throttle them.
-      this._throttledZrFlush();
-    }
+  jsonCompressed.UTF8Encoding = false;
+  return jsonCompressed;
+}
 
-    flushPendingActions.call(this, silent);
-    triggerUpdatedEvent.call(this, silent);
-  };
+function decodePolygon(coordinate, encodeOffsets, encodeScale) {
+  var result = [];
+  var prevX = encodeOffsets[0];
+  var prevY = encodeOffsets[1];
 
-  ECharts.prototype.updateLabelLayout = function () {
-    var labelManager = this._labelManager;
-    labelManager.updateLayoutConfig(this._api);
-    labelManager.layout(this._api);
-    labelManager.processLabelsOverall();
-  };
+  for (var i = 0; i < coordinate.length; i += 2) {
+    var x = coordinate.charCodeAt(i) - 64;
+    var y = coordinate.charCodeAt(i + 1) - 64; // ZigZag decoding
 
-  ECharts.prototype.appendData = function (params) {
-    if (this._disposed) {
-      disposedWarning(this.id);
-      return;
-    }
+    x = x >> 1 ^ -(x & 1);
+    y = y >> 1 ^ -(y & 1); // Delta deocding
 
-    var seriesIndex = params.seriesIndex;
-    var ecModel = this.getModel();
-    var seriesModel = ecModel.getSeriesByIndex(seriesIndex);
+    x += prevX;
+    y += prevY;
+    prevX = x;
+    prevY = y; // Dequantize
 
-    if ("development" !== 'production') {
-      assert$1(params.data && seriesModel);
+    result.push([x / encodeScale, y / encodeScale]);
+  }
+
+  return result;
+}
+
+function parseGeoJSON(geoJson, nameProperty) {
+  geoJson = decode(geoJson);
+  return map(filter(geoJson.features, function (featureObj) {
+    // Output of mapshaper may have geometry null
+    return featureObj.geometry && featureObj.properties && featureObj.geometry.coordinates.length > 0;
+  }), function (featureObj) {
+    var properties = featureObj.properties;
+    var geo = featureObj.geometry;
+    var geometries = [];
+
+    if (geo.type === 'Polygon') {
+      var coordinates = geo.coordinates;
+      geometries.push({
+        type: 'polygon',
+        // According to the GeoJSON specification.
+        // First must be exterior, and the rest are all interior(holes).
+        exterior: coordinates[0],
+        interiors: coordinates.slice(1)
+      });
     }
 
-    seriesModel.appendData(params); // Note: `appendData` does not support that update extent of coordinate
-    // system, util some scenario require that. In the expected usage of
-    // `appendData`, the initial extent of coordinate system should better
-    // be fixed by axis `min`/`max` setting or initial data, otherwise if
-    // the extent changed while `appendData`, the location of the painted
-    // graphic elements have to be changed, which make the usage of
-    // `appendData` meaningless.
+    if (geo.type === 'MultiPolygon') {
+      var coordinates = geo.coordinates;
+      each(coordinates, function (item) {
+        if (item[0]) {
+          geometries.push({
+            type: 'polygon',
+            exterior: item[0],
+            interiors: item.slice(1)
+          });
+        }
+      });
+    }
 
-    this._scheduler.unfinished = true;
-    this.getZr().wakeUp();
-  }; // A work around for no `internal` modifier in ts yet but
-  // need to strictly hide private methods to JS users.
+    var region = new GeoJSONRegion(properties[nameProperty || 'name'], geometries, properties.cp);
+    region.properties = properties;
+    return region;
+  });
+}
 
+var geoCoord = [126, 25];
+var points$1 = [[[0, 3.5], [7, 11.2], [15, 11.9], [30, 7], [42, 0.7], [52, 0.7], [56, 7.7], [59, 0.7], [64, 0.7], [64, 0], [5, 0], [0, 3.5]], [[13, 16.1], [19, 14.7], [16, 21.7], [11, 23.1], [13, 16.1]], [[12, 32.2], [14, 38.5], [15, 38.5], [13, 32.2], [12, 32.2]], [[16, 47.6], [12, 53.2], [13, 53.2], [18, 47.6], [16, 47.6]], [[6, 64.4], [8, 70], [9, 70], [8, 64.4], [6, 64.4]], [[23, 82.6], [29, 79.8], [30, 79.8], [25, 82.6], [23, 82.6]], [[37, 70.7], [43, 62.3], [44, 62.3], [39, 70.7],  [...]
 
-  ECharts.internalField = function () {
-    prepare = function (ecIns) {
-      var scheduler = ecIns._scheduler;
-      scheduler.restorePipelines(ecIns._model);
-      scheduler.prepareStageTasks();
-      prepareView(ecIns, true);
-      prepareView(ecIns, false);
-      scheduler.plan();
-    };
-    /**
-     * Prepare view instances of charts and components
-     */
+for (var i = 0; i < points$1.length; i++) {
+  for (var k = 0; k < points$1[i].length; k++) {
+    points$1[i][k][0] /= 10.5;
+    points$1[i][k][1] /= -10.5 / 0.75;
+    points$1[i][k][0] += geoCoord[0];
+    points$1[i][k][1] += geoCoord[1];
+  }
+}
 
+function fixNanhai(mapType, regions) {
+  if (mapType === 'china') {
+    regions.push(new GeoJSONRegion('南海诸岛', map(points$1, function (exterior) {
+      return {
+        type: 'polygon',
+        exterior: exterior
+      };
+    }), geoCoord));
+  }
+}
 
-    prepareView = function (ecIns, isComponent) {
-      var ecModel = ecIns._model;
-      var scheduler = ecIns._scheduler;
-      var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews;
-      var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap;
-      var zr = ecIns._zr;
-      var api = ecIns._api;
+/*
+* 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.
+*/
 
-      for (var i = 0; i < viewList.length; i++) {
-        viewList[i].__alive = false;
-      }
 
-      isComponent ? ecModel.eachComponent(function (componentType, model) {
-        componentType !== 'series' && doPrepare(model);
-      }) : ecModel.eachSeries(doPrepare);
+/**
+ * AUTO-GENERATED FILE. DO NOT MODIFY.
+ */
 
-      function doPrepare(model) {
-        // By defaut view will be reused if possible for the case that `setOption` with "notMerge"
-        // mode and need to enable transition animation. (Usually, when they have the same id, or
-        // especially no id but have the same type & name & index. See the `model.id` generation
-        // rule in `makeIdAndName` and `viewId` generation rule here).
-        // But in `replaceMerge` mode, this feature should be able to disabled when it is clear that
-        // the new model has nothing to do with the old model.
-        var requireNewView = model.__requireNewView; // This command should not work twice.
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+var coordsOffsetMap = {
+  '南海诸岛': [32, 80],
+  // 全国
+  '广东': [0, -10],
+  '香港': [10, 5],
+  '澳门': [-10, 10],
+  //'北京': [-10, 0],
+  '天津': [5, 5]
+};
+function fixTextCoords(mapType, region) {
+  if (mapType === 'china') {
+    var coordFix = coordsOffsetMap[region.name];
 
-        model.__requireNewView = false; // Consider: id same and type changed.
+    if (coordFix) {
+      var cp = region.getCenter();
+      cp[0] += coordFix[0] / 10.5;
+      cp[1] += -coordFix[1] / (10.5 / 0.75);
+      region.setCenter(cp);
+    }
+  }
+}
 
-        var viewId = '_ec_' + model.id + '_' + model.type;
-        var view = !requireNewView && viewMap[viewId];
+/*
+* 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.
+*/
 
-        if (!view) {
-          var classType = parseClassType(model.type);
-          var Clazz = isComponent ? ComponentView.getClass(classType.main, classType.sub) : // FIXME:TS
-          // (ChartView as ChartViewConstructor).getClass('series', classType.sub)
-          // For backward compat, still support a chart type declared as only subType
-          // like "liquidfill", but recommend "series.liquidfill"
-          // But need a base class to make a type series.
-          ChartView.getClass(classType.sub);
 
-          if ("development" !== 'production') {
-            assert$1(Clazz, classType.sub + ' does not exist.');
-          }
+/**
+ * AUTO-GENERATED FILE. DO NOT MODIFY.
+ */
 
-          view = new Clazz();
-          view.init(ecModel, api);
-          viewMap[viewId] = view;
-          viewList.push(view);
-          zr.add(view.group);
-        }
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+var geoCoordMap = {
+  'Russia': [100, 60],
+  'United States': [-99, 38],
+  'United States of America': [-99, 38]
+};
+function fixGeoCoords(mapType, region) {
+  if (mapType === 'world') {
+    var geoCoord = geoCoordMap[region.name];
 
-        model.__viewId = view.__id = viewId;
-        view.__alive = true;
-        view.__model = model;
-        view.group.__ecComponentInfo = {
-          mainType: model.mainType,
-          index: model.componentIndex
-        };
-        !isComponent && scheduler.prepareView(view, model, ecModel, api);
-      }
+    if (geoCoord) {
+      var cp = [geoCoord[0], geoCoord[1]];
+      region.setCenter(cp);
+    }
+  }
+}
 
-      for (var i = 0; i < viewList.length;) {
-        var view = viewList[i];
+/*
+* 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.
+*/
 
-        if (!view.__alive) {
-          !isComponent && view.renderTask.dispose();
-          zr.remove(view.group);
-          view.dispose(ecModel, api);
-          viewList.splice(i, 1);
 
-          if (viewMap[view.__id] === view) {
-            delete viewMap[view.__id];
-          }
+/**
+ * AUTO-GENERATED FILE. DO NOT MODIFY.
+ */
 
-          view.__id = view.group.__ecComponentInfo = null;
-        } else {
-          i++;
-        }
-      }
-    };
+/*
+* 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.
+*/
+// Fix for 钓鱼岛
+// let Region = require('../Region');
+// let zrUtil = require('zrender/lib/core/util');
+// let geoCoord = [126, 25];
+var points$2 = [[[123.45165252685547, 25.73527164402261], [123.49731445312499, 25.73527164402261], [123.49731445312499, 25.750734064600884], [123.45165252685547, 25.750734064600884], [123.45165252685547, 25.73527164402261]]];
+function fixDiaoyuIsland(mapType, region) {
+  if (mapType === 'china' && region.name === '台湾') {
+    region.geometries.push({
+      type: 'polygon',
+      exterior: points$2[0]
+    });
+  }
+}
 
-    updateDirectly = function (ecIns, method, payload, mainType, subType) {
-      var ecModel = ecIns._model;
-      ecModel.setUpdatePayload(payload); // broadcast
+var DEFAULT_NAME_PROPERTY = 'name';
 
-      if (!mainType) {
-        // FIXME
-        // Chart will not be update directly here, except set dirty.
-        // But there is no such scenario now.
-        each$3([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView);
-        return;
-      }
+var GeoJSONResource =
+/** @class */
+function () {
+  function GeoJSONResource(mapName, geoJSON, specialAreas) {
+    this.type = 'geoJSON';
+    this._parsedMap = createHashMap();
+    this._mapName = mapName;
+    this._specialAreas = specialAreas; // PENDING: delay the parse to the first usage to rapid up the FMP?
 
-      var query = {};
-      query[mainType + 'Id'] = payload[mainType + 'Id'];
-      query[mainType + 'Index'] = payload[mainType + 'Index'];
-      query[mainType + 'Name'] = payload[mainType + 'Name'];
-      var condition = {
-        mainType: mainType,
-        query: query
-      };
-      subType && (condition.subType = subType); // subType may be '' by parseClassType;
+    this._geoJSON = parseInput(geoJSON);
+  }
+  /**
+   * @param nameMap can be null/undefined
+   * @param nameProperty can be null/undefined
+   */
 
-      var excludeSeriesId = payload.excludeSeriesId;
-      var excludeSeriesIdMap;
 
-      if (excludeSeriesId != null) {
-        excludeSeriesIdMap = createHashMap();
-        each$3(normalizeToArray(excludeSeriesId), function (id) {
-          var modelId = convertOptionIdName(id, null);
+  GeoJSONResource.prototype.load = function (nameMap, nameProperty) {
+    nameProperty = nameProperty || DEFAULT_NAME_PROPERTY;
 
-          if (modelId != null) {
-            excludeSeriesIdMap.set(modelId, true);
-          }
-        });
-      } // If dispatchAction before setOption, do nothing.
+    var parsed = this._parsedMap.get(nameProperty);
 
+    if (!parsed) {
+      var rawRegions = this._parseToRegions(nameProperty);
 
-      ecModel && ecModel.eachComponent(condition, function (model) {
-        if (!excludeSeriesIdMap || excludeSeriesIdMap.get(model.id) == null) {
-          if (isHighDownPayload(payload) && !payload.notBlur) {
-            if (model instanceof SeriesModel) {
-              toggleSeriesBlurStateFromPayload(model, payload, ecIns._api);
-            }
-          } else if (isSelectChangePayload(payload)) {
-            // TODO geo
-            if (model instanceof SeriesModel) {
-              toggleSelectionFromPayload(model, payload, ecIns._api);
-              updateSeriesElementSelection(model);
-              markStatusToUpdate(ecIns);
-            }
-          }
+      parsed = this._parsedMap.set(nameProperty, {
+        regions: rawRegions,
+        boundingRect: calculateBoundingRect(rawRegions)
+      });
+    }
 
-          callView(ecIns[mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]);
-        }
-      }, ecIns);
+    var regionsMap = createHashMap();
+    var finalRegions = [];
+    each(parsed.regions, function (region) {
+      var regionName = region.name; // Try use the alias in geoNameMap
 
-      function callView(view) {
-        view && view.__alive && view[method] && view[method](view.__model, ecModel, ecIns._api, payload);
+      if (nameMap && nameMap.hasOwnProperty(regionName)) {
+        region = region.cloneShallow(regionName = nameMap[regionName]);
       }
+
+      finalRegions.push(region);
+      regionsMap.set(regionName, region);
+    });
+    return {
+      regions: finalRegions,
+      boundingRect: parsed.boundingRect || new BoundingRect(0, 0, 0, 0),
+      regionsMap: regionsMap
     };
+  };
 
-    updateMethods = {
-      prepareAndUpdate: function (payload) {
-        prepare(this);
-        updateMethods.update.call(this, payload);
-      },
-      update: function (payload) {
-        // console.profile && console.profile('update');
-        var ecModel = this._model;
-        var api = this._api;
-        var zr = this._zr;
-        var coordSysMgr = this._coordSysMgr;
-        var scheduler = this._scheduler; // update before setOption
+  GeoJSONResource.prototype._parseToRegions = function (nameProperty) {
+    var mapName = this._mapName;
+    var geoJSON = this._geoJSON;
+    var rawRegions; // https://jsperf.com/try-catch-performance-overhead
 
-        if (!ecModel) {
-          return;
-        }
+    try {
+      rawRegions = geoJSON ? parseGeoJSON(geoJSON, nameProperty) : [];
+    } catch (e) {
+      throw new Error('Invalid geoJson format\n' + e.message);
+    }
 
-        ecModel.setUpdatePayload(payload);
-        scheduler.restoreData(ecModel, payload);
-        scheduler.performSeriesTasks(ecModel); // TODO
-        // Save total ecModel here for undo/redo (after restoring data and before processing data).
-        // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.
-        // Create new coordinate system each update
-        // In LineView may save the old coordinate system and use it to get the orignal point
+    fixNanhai(mapName, rawRegions);
+    each(rawRegions, function (region) {
+      var regionName = region.name;
+      fixTextCoords(mapName, region);
+      fixGeoCoords(mapName, region);
+      fixDiaoyuIsland(mapName, region); // Some area like Alaska in USA map needs to be tansformed
+      // to look better
 
-        coordSysMgr.create(ecModel, api);
-        scheduler.performDataProcessorTasks(ecModel, payload); // Current stream render is not supported in data process. So we can update
-        // stream modes after data processing, where the filtered data is used to
-        // deteming whether use progressive rendering.
+      var specialArea = this._specialAreas && this._specialAreas[regionName];
 
-        updateStreamModes(this, ecModel); // We update stream modes before coordinate system updated, then the modes info
-        // can be fetched when coord sys updating (consider the barGrid extent fix). But
-        // the drawback is the full coord info can not be fetched. Fortunately this full
-        // coord is not requied in stream mode updater currently.
+      if (specialArea) {
+        region.transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height);
+      }
+    }, this);
+    return rawRegions;
+  };
+  /**
+   * Only for exporting to users.
+   * **MUST NOT** used internally.
+   */
 
-        coordSysMgr.update(ecModel, api);
-        clearColorPalette(ecModel);
-        scheduler.performVisualTasks(ecModel, payload);
-        render(this, ecModel, api, payload); // Set background
 
-        var backgroundColor = ecModel.get('backgroundColor') || 'transparent';
-        var darkMode = ecModel.get('darkMode'); // In IE8
+  GeoJSONResource.prototype.getMapForUser = function () {
+    return {
+      // For backward compatibility, use geoJson
+      // PENDING: it has been returning them without clone.
+      // do we need to avoid outsite modification?
+      geoJson: this._geoJSON,
+      geoJSON: this._geoJSON,
+      specialAreas: this._specialAreas
+    };
+  };
 
-        if (!env.canvasSupported) {
-          var colorArr = parse(backgroundColor);
-          backgroundColor = stringify(colorArr, 'rgb');
+  return GeoJSONResource;
+}();
 
-          if (colorArr[3] === 0) {
-            backgroundColor = 'transparent';
-          }
-        } else {
-          zr.setBackgroundColor(backgroundColor); // Force set dark mode.
+function calculateBoundingRect(regions) {
+  var rect;
 
-          if (darkMode != null && darkMode !== 'auto') {
-            zr.setDarkMode(darkMode);
-          }
-        }
+  for (var i = 0; i < regions.length; i++) {
+    var regionRect = regions[i].getBoundingRect();
+    rect = rect || regionRect.clone();
+    rect.union(regionRect);
+  }
 
-        performPostUpdateFuncs(ecModel, api); // console.profile && console.profileEnd('update');
-      },
-      updateTransform: function (payload) {
-        var _this = this;
+  return rect;
+}
 
-        var ecModel = this._model;
-        var api = this._api; // update before setOption
+function parseInput(source) {
+  return !isString(source) ? source : typeof JSON !== 'undefined' && JSON.parse ? JSON.parse(source) : new Function('return (' + source + ');')();
+}
 
-        if (!ecModel) {
-          return;
-        }
+var storage = createHashMap();
+var geoSourceManager = {
+  /**
+   * Compatible with previous `echarts.registerMap`.
+   *
+   * @usage
+   * ```js
+   *
+   * echarts.registerMap('USA', geoJson, specialAreas);
+   *
+   * echarts.registerMap('USA', {
+   *     geoJson: geoJson,
+   *     specialAreas: {...}
+   * });
+   * echarts.registerMap('USA', {
+   *     geoJSON: geoJson,
+   *     specialAreas: {...}
+   * });
+   *
+   * echarts.registerMap('airport', {
+   *     svg: svg
+   * }
+   * ```
+   *
+   * Note:
+   * Do not support that register multiple geoJSON or SVG
+   * one map name. Because different geoJSON and SVG have
+   * different unit. It's not easy to make sure how those
+   * units are mapping/normalize.
+   * If intending to use multiple geoJSON or SVG, we can
+   * use multiple geo coordinate system.
+   */
+  registerMap: function (mapName, rawDef, rawSpecialAreas) {
+    if (rawDef.svg) {
+      var resource = new GeoSVGResource(mapName, rawDef.svg);
+      storage.set(mapName, resource);
+    } else {
+      // Recommend:
+      //     echarts.registerMap('eu', { geoJSON: xxx, specialAreas: xxx });
+      // Backward compatibility:
+      //     echarts.registerMap('eu', geoJSON, specialAreas);
+      //     echarts.registerMap('eu', { geoJson: xxx, specialAreas: xxx });
+      var geoJSON = rawDef.geoJson || rawDef.geoJSON;
+
+      if (geoJSON && !rawDef.features) {
+        rawSpecialAreas = rawDef.specialAreas;
+      } else {
+        geoJSON = rawDef;
+      }
 
-        ecModel.setUpdatePayload(payload); // ChartView.markUpdateMethod(payload, 'updateTransform');
+      var resource = new GeoJSONResource(mapName, geoJSON, rawSpecialAreas);
+      storage.set(mapName, resource);
+    }
+  },
+  getGeoResource: function (mapName) {
+    return storage.get(mapName);
+  },
 
-        var componentDirtyList = [];
-        ecModel.eachComponent(function (componentType, componentModel) {
-          if (componentType === 'series') {
-            return;
-          }
+  /**
+   * Only for exporting to users.
+   * **MUST NOT** used internally.
+   */
+  getMapForUser: function (mapName) {
+    var resource = storage.get(mapName); // Do not support return SVG until some real requirement come.
 
-          var componentView = _this.getViewOfComponentModel(componentModel);
+    return resource && resource.type === 'geoJSON' && resource.getMapForUser();
+  },
+  load: function (mapName, nameMap, nameProperty) {
+    var resource = storage.get(mapName);
 
-          if (componentView && componentView.__alive) {
-            if (componentView.updateTransform) {
-              var result = componentView.updateTransform(componentModel, ecModel, api, payload);
-              result && result.update && componentDirtyList.push(componentView);
-            } else {
-              componentDirtyList.push(componentView);
-            }
-          }
-        });
-        var seriesDirtyMap = createHashMap();
-        ecModel.eachSeries(function (seriesModel) {
-          var chartView = _this._chartsMap[seriesModel.__viewId];
+    if (!resource) {
+      if ("development" !== 'production') {
+        console.error('Map ' + mapName + ' not exists. The GeoJSON of the map must be provided.');
+      }
 
-          if (chartView.updateTransform) {
-            var result = chartView.updateTransform(seriesModel, ecModel, api, payload);
-            result && result.update && seriesDirtyMap.set(seriesModel.uid, 1);
-          } else {
-            seriesDirtyMap.set(seriesModel.uid, 1);
-          }
-        });
-        clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
-        // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);
+      return;
+    }
 
-        this._scheduler.performVisualTasks(ecModel, payload, {
-          setDirty: true,
-          dirtyMap: seriesDirtyMap
-        }); // Currently, not call render of components. Geo render cost a lot.
-        // renderComponents(ecIns, ecModel, api, payload, componentDirtyList);
+    return resource.load(nameMap, nameProperty);
+  }
+};
 
+var assert$1 = assert;
+var each$3 = each;
+var isFunction$1 = isFunction;
+var isObject$2 = isObject;
+var indexOf$1 = indexOf;
+var hasWindow = typeof window !== 'undefined';
+var version$1 = '5.1.0';
+var dependencies = {
+  zrender: '5.1.0'
+};
+var TEST_FRAME_REMAIN_TIME = 1;
+var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
+// So data stack stage should be in front of data processing stage.
 
-        renderSeries(this, ecModel, api, payload, seriesDirtyMap);
-        performPostUpdateFuncs(ecModel, this._api);
-      },
-      updateView: function (payload) {
-        var ecModel = this._model; // update before setOption
+var PRIORITY_PROCESSOR_DATASTACK = 900; // "Data filter" will block the stream, so it should be
+// put at the begining of data processing.
 
-        if (!ecModel) {
-          return;
-        }
+var PRIORITY_PROCESSOR_FILTER = 1000;
+var PRIORITY_PROCESSOR_DEFAULT = 2000;
+var PRIORITY_PROCESSOR_STATISTIC = 5000;
+var PRIORITY_VISUAL_LAYOUT = 1000;
+var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100;
+var PRIORITY_VISUAL_GLOBAL = 2000;
+var PRIORITY_VISUAL_CHART = 3000;
+var PRIORITY_VISUAL_COMPONENT = 4000; // Visual property in data. Greater than `PRIORITY_VISUAL_COMPONENT` to enable to
+// overwrite the viusal result of component (like `visualMap`)
+// using data item specific setting (like itemStyle.xxx on data item)
 
-        ecModel.setUpdatePayload(payload);
-        ChartView.markUpdateMethod(payload, 'updateView');
-        clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
+var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500; // Greater than `PRIORITY_VISUAL_CHART_DATA_CUSTOM` to enable to layout based on
+// visual result like `symbolSize`.
 
-        this._scheduler.performVisualTasks(ecModel, payload, {
-          setDirty: true
-        });
+var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600;
+var PRIORITY_VISUAL_BRUSH = 5000;
+var PRIORITY_VISUAL_ARIA = 6000;
+var PRIORITY_VISUAL_DECAL = 7000;
+var PRIORITY = {
+  PROCESSOR: {
+    FILTER: PRIORITY_PROCESSOR_FILTER,
+    SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER,
+    STATISTIC: PRIORITY_PROCESSOR_STATISTIC
+  },
+  VISUAL: {
+    LAYOUT: PRIORITY_VISUAL_LAYOUT,
+    PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT,
+    GLOBAL: PRIORITY_VISUAL_GLOBAL,
+    CHART: PRIORITY_VISUAL_CHART,
+    POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT,
+    COMPONENT: PRIORITY_VISUAL_COMPONENT,
+    BRUSH: PRIORITY_VISUAL_BRUSH,
+    CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM,
+    ARIA: PRIORITY_VISUAL_ARIA,
+    DECAL: PRIORITY_VISUAL_DECAL
+  }
+}; // Main process have three entries: `setOption`, `dispatchAction` and `resize`,
+// where they must not be invoked nestedly, except the only case: invoke
+// dispatchAction with updateMethod "none" in main process.
+// This flag is used to carry out this rule.
+// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
 
-        render(this, this._model, this._api, payload);
-        performPostUpdateFuncs(ecModel, this._api);
-      },
-      updateVisual: function (payload) {
-        // updateMethods.update.call(this, payload);
-        var _this = this;
+var IN_MAIN_PROCESS_KEY = '__flagInMainProcess';
+var OPTION_UPDATED_KEY = '__optionUpdated';
+var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus';
+var ACTION_REG = /^[a-zA-Z0-9_]+$/;
+var CONNECT_STATUS_KEY = '__connectUpdateStatus';
+var CONNECT_STATUS_PENDING = 0;
+var CONNECT_STATUS_UPDATING = 1;
+var CONNECT_STATUS_UPDATED = 2;
 
-        var ecModel = this._model; // update before setOption
+function createRegisterEventWithLowercaseECharts(method) {
+  return function () {
+    var args = [];
 
-        if (!ecModel) {
-          return;
-        }
+    for (var _i = 0; _i < arguments.length; _i++) {
+      args[_i] = arguments[_i];
+    }
 
-        ecModel.setUpdatePayload(payload); // clear all visual
+    if (this.isDisposed()) {
+      disposedWarning(this.id);
+      return;
+    }
 
-        ecModel.eachSeries(function (seriesModel) {
-          seriesModel.getData().clearAllVisual();
-        }); // Perform visual
+    return toLowercaseNameAndCallEventful(this, method, args);
+  };
+}
 
-        ChartView.markUpdateMethod(payload, 'updateVisual');
-        clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
+function createRegisterEventWithLowercaseMessageCenter(method) {
+  return function () {
+    var args = [];
 
-        this._scheduler.performVisualTasks(ecModel, payload, {
-          visualType: 'visual',
-          setDirty: true
-        });
+    for (var _i = 0; _i < arguments.length; _i++) {
+      args[_i] = arguments[_i];
+    }
 
-        ecModel.eachComponent(function (componentType, componentModel) {
-          if (componentType !== 'series') {
-            var componentView = _this.getViewOfComponentModel(componentModel);
+    return toLowercaseNameAndCallEventful(this, method, args);
+  };
+}
 
-            componentView && componentView.__alive && componentView.updateVisual(componentModel, ecModel, _this._api, payload);
-          }
-        });
-        ecModel.eachSeries(function (seriesModel) {
-          var chartView = _this._chartsMap[seriesModel.__viewId];
-          chartView.updateVisual(seriesModel, ecModel, _this._api, payload);
-        });
-        performPostUpdateFuncs(ecModel, this._api);
-      },
-      updateLayout: function (payload) {
-        updateMethods.update.call(this, payload);
-      }
-    };
+function toLowercaseNameAndCallEventful(host, method, args) {
+  // `args[0]` is event name. Event name is all lowercase.
+  args[0] = args[0] && args[0].toLowerCase();
+  return Eventful.prototype[method].apply(host, args);
+}
 
-    doConvertPixel = function (ecIns, methodName, finder, value) {
-      if (ecIns._disposed) {
-        disposedWarning(ecIns.id);
-        return;
-      }
+var MessageCenter =
+/** @class */
+function (_super) {
+  __extends(MessageCenter, _super);
 
-      var ecModel = ecIns._model;
+  function MessageCenter() {
+    return _super !== null && _super.apply(this, arguments) || this;
+  }
 
-      var coordSysList = ecIns._coordSysMgr.getCoordinateSystems();
+  return MessageCenter;
+}(Eventful);
 
-      var result;
-      var parsedFinder = parseFinder(ecModel, finder);
+var messageCenterProto = MessageCenter.prototype;
+messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on');
+messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off'); // ---------------------------------------
+// Internal method names for class ECharts
+// ---------------------------------------
 
-      for (var i = 0; i < coordSysList.length; i++) {
-        var coordSys = coordSysList[i];
+var prepare;
+var prepareView;
+var updateDirectly;
+var updateMethods;
+var doConvertPixel;
+var updateStreamModes;
+var doDispatchAction;
+var flushPendingActions;
+var triggerUpdatedEvent;
+var bindRenderedEvent;
+var bindMouseEvent;
+var clearColorPalette;
+var render;
+var renderComponents;
+var renderSeries;
+var performPostUpdateFuncs;
+var createExtensionAPI;
+var enableConnect;
+var setTransitionOpt;
+var markStatusToUpdate;
+var applyChangedStates;
 
-        if (coordSys[methodName] && (result = coordSys[methodName](ecModel, parsedFinder, value)) != null) {
-          return result;
-        }
-      }
+var ECharts =
+/** @class */
+function (_super) {
+  __extends(ECharts, _super);
 
-      if ("development" !== 'production') {
-        console.warn('No coordinate system that supports ' + methodName + ' found by the given finder.');
-      }
-    };
+  function ECharts(dom, // Theme name or themeOption.
+  theme, opts) {
+    var _this = _super.call(this, new ECEventProcessor()) || this;
 
-    updateStreamModes = function (ecIns, ecModel) {
-      var chartsMap = ecIns._chartsMap;
-      var scheduler = ecIns._scheduler;
-      ecModel.eachSeries(function (seriesModel) {
-        scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]);
-      });
-    };
+    _this._chartsViews = [];
+    _this._chartsMap = {};
+    _this._componentsViews = [];
+    _this._componentsMap = {}; // Can't dispatch action during rendering procedure
 
-    doDispatchAction = function (payload, silent) {
-      var _this = this;
+    _this._pendingActions = [];
+    opts = opts || {}; // Get theme by name
 
-      var ecModel = this.getModel();
-      var payloadType = payload.type;
-      var escapeConnect = payload.escapeConnect;
-      var actionWrap = actions[payloadType];
-      var actionInfo = actionWrap.actionInfo;
-      var cptTypeTmp = (actionInfo.update || 'update').split(':');
-      var updateMethod = cptTypeTmp.pop();
-      var cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]);
-      this[IN_MAIN_PROCESS_KEY] = true;
-      var payloads = [payload];
-      var batched = false; // Batch action
+    if (typeof theme === 'string') {
+      theme = themeStorage[theme];
+    }
 
-      if (payload.batch) {
-        batched = true;
-        payloads = map(payload.batch, function (item) {
-          item = defaults(extend({}, item), payload);
-          item.batch = null;
-          return item;
-        });
-      }
+    _this._dom = dom;
+    var defaultRenderer = 'canvas';
+    var defaultUseDirtyRect = false;
 
-      var eventObjBatch = [];
-      var eventObj;
-      var isSelectChange = isSelectChangePayload(payload);
-      var isStatusChange = isHighDownPayload(payload) || isSelectChange;
-      each$3(payloads, function (batchItem) {
-        // Action can specify the event by return it.
-        eventObj = actionWrap.action(batchItem, _this._model, _this._api); // Emit event outside
+    if ("development" !== 'production') {
+      var root =
+      /* eslint-disable-next-line */
+      hasWindow ? window : global;
+      defaultRenderer = root.__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer;
+      var devUseDirtyRect = root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__;
+      defaultUseDirtyRect = devUseDirtyRect == null ? defaultUseDirtyRect : devUseDirtyRect;
+    }
 
-        eventObj = eventObj || extend({}, batchItem); // Convert type to eventType
+    var zr = _this._zr = init(dom, {
+      renderer: opts.renderer || defaultRenderer,
+      devicePixelRatio: opts.devicePixelRatio,
+      width: opts.width,
+      height: opts.height,
+      useDirtyRect: opts.useDirtyRect == null ? defaultUseDirtyRect : opts.useDirtyRect
+    }); // Expect 60 fps.
 
-        eventObj.type = actionInfo.event || eventObj.type;
-        eventObjBatch.push(eventObj); // light update does not perform data process, layout and visual.
+    _this._throttledZrFlush = throttle(bind(zr.flush, zr), 17);
+    theme = clone(theme);
+    theme && globalBackwardCompat(theme, true);
+    _this._theme = theme;
+    _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG);
+    _this._coordSysMgr = new CoordinateSystemManager();
+    var api = _this._api = createExtensionAPI(_this); // Sort on demand
 
-        if (isStatusChange) {
-          // method, payload, mainType, subType
-          updateDirectly(_this, updateMethod, batchItem, 'series'); // Mark status to update
+    function prioritySortFunc(a, b) {
+      return a.__prio - b.__prio;
+    }
 
-          markStatusToUpdate(_this);
-        } else if (cptType) {
-          updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub);
-        }
-      });
+    sort(visualFuncs, prioritySortFunc);
+    sort(dataProcessorFuncs, prioritySortFunc);
+    _this._scheduler = new Scheduler(_this, api, dataProcessorFuncs, visualFuncs);
+    _this._messageCenter = new MessageCenter();
+    _this._labelManager = new LabelManager(); // Init mouse events
 
-      if (updateMethod !== 'none' && !isStatusChange && !cptType) {
-        // Still dirty
-        if (this[OPTION_UPDATED_KEY]) {
-          prepare(this);
-          updateMethods.update.call(this, payload);
-          this[OPTION_UPDATED_KEY] = false;
-        } else {
-          updateMethods[updateMethod].call(this, payload);
-        }
-      } // Follow the rule of action batch
+    _this._initEvents(); // In case some people write `window.onresize = chart.resize`
 
 
-      if (batched) {
-        eventObj = {
-          type: actionInfo.event || payloadType,
-          escapeConnect: escapeConnect,
-          batch: eventObjBatch
-        };
-      } else {
-        eventObj = eventObjBatch[0];
-      }
+    _this.resize = bind(_this.resize, _this);
+    zr.animation.on('frame', _this._onframe, _this);
+    bindRenderedEvent(zr, _this);
+    bindMouseEvent(zr, _this); // ECharts instance can be used as value.
 
-      this[IN_MAIN_PROCESS_KEY] = false;
+    setAsPrimitive(_this);
+    return _this;
+  }
 
-      if (!silent) {
-        var messageCenter = this._messageCenter;
-        messageCenter.trigger(eventObj.type, eventObj); // Extra triggered 'selectchanged' event
+  ECharts.prototype._onframe = function () {
+    if (this._disposed) {
+      return;
+    }
 
-        if (isSelectChange) {
-          var newObj = {
-            type: 'selectchanged',
-            escapeConnect: escapeConnect,
-            selected: getAllSelectedIndices(ecModel),
-            isFromClick: payload.isFromClick || false,
-            fromAction: payload.type,
-            fromActionPayload: payload
-          };
-          messageCenter.trigger(newObj.type, newObj);
-        }
-      }
-    };
+    applyChangedStates(this);
+    var scheduler = this._scheduler; // Lazy update
 
-    flushPendingActions = function (silent) {
-      var pendingActions = this._pendingActions;
+    if (this[OPTION_UPDATED_KEY]) {
+      var silent = this[OPTION_UPDATED_KEY].silent;
+      this[IN_MAIN_PROCESS_KEY] = true;
+      prepare(this);
+      updateMethods.update.call(this); // At present, in each frame, zrender performs:
+      //   (1) animation step forward.
+      //   (2) trigger('frame') (where this `_onframe` is called)
+      //   (3) zrender flush (render).
+      // If we do nothing here, since we use `setToFinal: true`, the step (3) above
+      // will render the final state of the elements before the real animation started.
 
-      while (pendingActions.length) {
-        var payload = pendingActions.shift();
-        doDispatchAction.call(this, payload, silent);
-      }
-    };
+      this._zr.flush();
 
-    triggerUpdatedEvent = function (silent) {
-      !silent && this.trigger('updated');
-    };
-    /**
-     * Event `rendered` is triggered when zr
-     * rendered. It is useful for realtime
-     * snapshot (reflect animation).
-     *
-     * Event `finished` is triggered when:
-     * (1) zrender rendering finished.
-     * (2) initial animation finished.
-     * (3) progressive rendering finished.
-     * (4) no pending action.
-     * (5) no delayed setOption needs to be processed.
-     */
+      this[IN_MAIN_PROCESS_KEY] = false;
+      this[OPTION_UPDATED_KEY] = false;
+      flushPendingActions.call(this, silent);
+      triggerUpdatedEvent.call(this, silent);
+    } // Avoid do both lazy update and progress in one frame.
+    else if (scheduler.unfinished) {
+        // Stream progress.
+        var remainTime = TEST_FRAME_REMAIN_TIME;
+        var ecModel = this._model;
+        var api = this._api;
+        scheduler.unfinished = false;
 
+        do {
+          var startTime = +new Date();
+          scheduler.performSeriesTasks(ecModel); // Currently dataProcessorFuncs do not check threshold.
 
-    bindRenderedEvent = function (zr, ecIns) {
-      zr.on('rendered', function (params) {
-        ecIns.trigger('rendered', params); // The `finished` event should not be triggered repeatly,
-        // so it should only be triggered when rendering indeed happend
-        // in zrender. (Consider the case that dipatchAction is keep
-        // triggering when mouse move).
-
-        if ( // Although zr is dirty if initial animation is not finished
-        // and this checking is called on frame, we also check
-        // animation finished for robustness.
-        zr.animation.isFinished() && !ecIns[OPTION_UPDATED_KEY] && !ecIns._scheduler.unfinished && !ecIns._pendingActions.length) {
-          ecIns.trigger('finished');
-        }
-      });
-    };
+          scheduler.performDataProcessorTasks(ecModel);
+          updateStreamModes(this, ecModel); // Do not update coordinate system here. Because that coord system update in
+          // each frame is not a good user experience. So we follow the rule that
+          // the extent of the coordinate system is determin in the first frame (the
+          // frame is executed immedietely after task reset.
+          // this._coordSysMgr.update(ecModel, api);
+          // console.log('--- ec frame visual ---', remainTime);
 
-    bindMouseEvent = function (zr, ecIns) {
-      zr.on('mouseover', function (e) {
-        var el = e.target;
-        var dispatcher = findEventDispatcher(el, isHighDownDispatcher);
+          scheduler.performVisualTasks(ecModel);
+          renderSeries(this, this._model, api, 'remain');
+          remainTime -= +new Date() - startTime;
+        } while (remainTime > 0 && scheduler.unfinished); // Call flush explicitly for trigger finished event.
 
-        if (dispatcher) {
-          var ecData = getECData(dispatcher); // Try blur all in the related series. Then emphasis the hoverred.
-          // TODO. progressive mode.
 
-          toggleSeriesBlurState(ecData.seriesIndex, ecData.focus, ecData.blurScope, ecIns._api, true);
-          enterEmphasisWhenMouseOver(dispatcher, e);
-          markStatusToUpdate(ecIns);
-        }
-      }).on('mouseout', function (e) {
-        var el = e.target;
-        var dispatcher = findEventDispatcher(el, isHighDownDispatcher);
+        if (!scheduler.unfinished) {
+          this._zr.flush();
+        } // Else, zr flushing be ensue within the same frame,
+        // because zr flushing is after onframe event.
 
-        if (dispatcher) {
-          var ecData = getECData(dispatcher);
-          toggleSeriesBlurState(ecData.seriesIndex, ecData.focus, ecData.blurScope, ecIns._api, false);
-          leaveEmphasisWhenMouseOut(dispatcher, e);
-          markStatusToUpdate(ecIns);
-        }
-      }).on('click', function (e) {
-        var el = e.target;
-        var dispatcher = findEventDispatcher(el, function (target) {
-          return getECData(target).dataIndex != null;
-        }, true);
+      }
+  };
 
-        if (dispatcher) {
-          var actionType = dispatcher.selected ? 'unselect' : 'select';
-          var ecData = getECData(dispatcher);
+  ECharts.prototype.getDom = function () {
+    return this._dom;
+  };
 
-          ecIns._api.dispatchAction({
-            type: actionType,
-            dataType: ecData.dataType,
-            dataIndexInside: ecData.dataIndex,
-            seriesIndex: ecData.seriesIndex,
-            isFromClick: true
-          });
-        }
-      });
-    };
+  ECharts.prototype.getId = function () {
+    return this.id;
+  };
 
-    clearColorPalette = function (ecModel) {
-      ecModel.clearColorPalette();
-      ecModel.eachSeries(function (seriesModel) {
-        seriesModel.clearColorPalette();
-      });
-    };
+  ECharts.prototype.getZr = function () {
+    return this._zr;
+  };
+  /* eslint-disable-next-line */
 
-    render = function (ecIns, ecModel, api, payload) {
-      renderComponents(ecIns, ecModel, api, payload);
-      each$3(ecIns._chartsViews, function (chart) {
-        chart.__alive = false;
-      });
-      renderSeries(ecIns, ecModel, api, payload); // Remove groups of unrendered charts
 
-      each$3(ecIns._chartsViews, function (chart) {
-        if (!chart.__alive) {
-          chart.remove(ecModel, api);
-        }
-      });
-    };
+  ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) {
+    if ("development" !== 'production') {
+      assert$1(!this[IN_MAIN_PROCESS_KEY], '`setOption` should not be called during main process.');
+    }
 
-    renderComponents = function (ecIns, ecModel, api, payload, dirtyList) {
-      each$3(dirtyList || ecIns._componentsViews, function (componentView) {
-        var componentModel = componentView.__model;
-        clearStates(componentModel, componentView);
-        componentView.render(componentModel, ecModel, api, payload);
-        updateZ(componentModel, componentView);
-        updateStates(componentModel, componentView);
-      });
-    };
-    /**
-     * Render each chart and component
-     */
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
+    }
 
+    var silent;
+    var replaceMerge;
+    var transitionOpt;
 
-    renderSeries = function (ecIns, ecModel, api, payload, dirtyMap) {
-      // Render all charts
-      var scheduler = ecIns._scheduler;
-      var labelManager = ecIns._labelManager;
-      labelManager.clearLabels();
-      var unfinished = false;
-      ecModel.eachSeries(function (seriesModel) {
-        var chartView = ecIns._chartsMap[seriesModel.__viewId];
-        chartView.__alive = true;
-        var renderTask = chartView.renderTask;
-        scheduler.updatePayload(renderTask, payload); // TODO states on marker.
+    if (isObject$2(notMerge)) {
+      lazyUpdate = notMerge.lazyUpdate;
+      silent = notMerge.silent;
+      replaceMerge = notMerge.replaceMerge;
+      transitionOpt = notMerge.transition;
+      notMerge = notMerge.notMerge;
+    }
 
-        clearStates(seriesModel, chartView);
+    this[IN_MAIN_PROCESS_KEY] = true;
 
-        if (dirtyMap && dirtyMap.get(seriesModel.uid)) {
-          renderTask.dirty();
-        }
+    if (!this._model || notMerge) {
+      var optionManager = new OptionManager(this._api);
+      var theme = this._theme;
+      var ecModel = this._model = new GlobalModel();
+      ecModel.scheduler = this._scheduler;
+      ecModel.init(null, null, null, theme, this._locale, optionManager);
+    }
 
-        if (renderTask.perform(scheduler.getPerformArgs(renderTask))) {
-          unfinished = true;
-        }
+    this._model.setOption(option, {
+      replaceMerge: replaceMerge
+    }, optionPreprocessorFuncs);
 
-        seriesModel.__transientTransitionOpt = null;
-        chartView.group.silent = !!seriesModel.get('silent'); // Should not call markRedraw on group, because it will disable zrender
-        // increamental render (alway render from the __startIndex each frame)
-        // chartView.group.markRedraw();
+    setTransitionOpt(this, transitionOpt);
 
-        updateBlend(seriesModel, chartView);
-        updateSeriesElementSelection(seriesModel); // Add labels.
+    if (lazyUpdate) {
+      this[OPTION_UPDATED_KEY] = {
+        silent: silent
+      };
+      this[IN_MAIN_PROCESS_KEY] = false; // `setOption(option, {lazyMode: true})` may be called when zrender has been slept.
+      // It should wake it up to make sure zrender start to render at the next frame.
 
-        labelManager.addLabelsOfSeries(chartView);
-      });
-      scheduler.unfinished = unfinished || scheduler.unfinished;
-      labelManager.updateLayoutConfig(api);
-      labelManager.layout(api);
-      labelManager.processLabelsOverall();
-      ecModel.eachSeries(function (seriesModel) {
-        var chartView = ecIns._chartsMap[seriesModel.__viewId]; // Update Z after labels updated. Before applying states.
+      this.getZr().wakeUp();
+    } else {
+      prepare(this);
+      updateMethods.update.call(this); // Ensure zr refresh sychronously, and then pixel in canvas can be
+      // fetched after `setOption`.
 
-        updateZ(seriesModel, chartView); // NOTE: Update states after label is updated.
-        // label should be in normal status when layouting.
+      this._zr.flush();
 
-        updateStates(seriesModel, chartView);
-      }); // If use hover layer
+      this[OPTION_UPDATED_KEY] = false;
+      this[IN_MAIN_PROCESS_KEY] = false;
+      flushPendingActions.call(this, silent);
+      triggerUpdatedEvent.call(this, silent);
+    }
+  };
+  /**
+   * @DEPRECATED
+   */
 
-      updateHoverLayerStatus(ecIns, ecModel);
-    };
 
-    performPostUpdateFuncs = function (ecModel, api) {
-      each$3(postUpdateFuncs, function (func) {
-        func(ecModel, api);
-      });
-    };
+  ECharts.prototype.setTheme = function () {
+    console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
+  }; // We don't want developers to use getModel directly.
 
-    markStatusToUpdate = function (ecIns) {
-      ecIns[STATUS_NEEDS_UPDATE_KEY] = true; // Wake up zrender if it's sleep. Let it update states in the next frame.
 
-      ecIns.getZr().wakeUp();
-    };
+  ECharts.prototype.getModel = function () {
+    return this._model;
+  };
 
-    applyChangedStates = function (ecIns) {
-      if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) {
-        return;
-      }
+  ECharts.prototype.getOption = function () {
+    return this._model && this._model.getOption();
+  };
 
-      ecIns.getZr().storage.traverse(function (el) {
-        // Not applied on removed elements, it may still in fading.
-        if (isElementRemoved(el)) {
-          return;
-        }
+  ECharts.prototype.getWidth = function () {
+    return this._zr.getWidth();
+  };
 
-        applyElementStates(el);
-      });
-      ecIns[STATUS_NEEDS_UPDATE_KEY] = false;
-    };
+  ECharts.prototype.getHeight = function () {
+    return this._zr.getHeight();
+  };
 
-    function applyElementStates(el) {
-      var newStates = [];
-      var oldStates = el.currentStates; // Keep other states.
+  ECharts.prototype.getDevicePixelRatio = function () {
+    return this._zr.painter.dpr
+    /* eslint-disable-next-line */
+    || hasWindow && window.devicePixelRatio || 1;
+  };
+  /**
+   * Get canvas which has all thing rendered
+   */
 
-      for (var i = 0; i < oldStates.length; i++) {
-        var stateName = oldStates[i];
 
-        if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) {
-          newStates.push(stateName);
-        }
-      } // Only use states when it's exists.
+  ECharts.prototype.getRenderedCanvas = function (opts) {
+    if (!env.canvasSupported) {
+      return;
+    }
 
+    opts = extend({}, opts || {});
+    opts.pixelRatio = opts.pixelRatio || this.getDevicePixelRatio();
+    opts.backgroundColor = opts.backgroundColor || this._model.get('backgroundColor');
+    var zr = this._zr; // let list = zr.storage.getDisplayList();
+    // Stop animations
+    // Never works before in init animation, so remove it.
+    // zrUtil.each(list, function (el) {
+    //     el.stopAnimation(true);
+    // });
 
-      if (el.selected && el.states.select) {
-        newStates.push('select');
-      }
+    return zr.painter.getRenderedCanvas(opts);
+  };
+  /**
+   * Get svg data url
+   */
 
-      if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) {
-        newStates.push('emphasis');
-      } else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) {
-        newStates.push('blur');
-      }
 
-      el.useStates(newStates);
+  ECharts.prototype.getSvgDataURL = function () {
+    if (!env.svgSupported) {
+      return;
     }
 
-    function updateHoverLayerStatus(ecIns, ecModel) {
-      var zr = ecIns._zr;
-      var storage = zr.storage;
-      var elCount = 0;
-      storage.traverse(function (el) {
-        if (!el.isGroup) {
-          elCount++;
-        }
-      });
-
-      if (elCount > ecModel.get('hoverLayerThreshold') && !env.node && !env.worker) {
-        ecModel.eachSeries(function (seriesModel) {
-          if (seriesModel.preventUsingHoverLayer) {
-            return;
-          }
+    var zr = this._zr;
+    var list = zr.storage.getDisplayList(); // Stop animations
 
-          var chartView = ecIns._chartsMap[seriesModel.__viewId];
+    each(list, function (el) {
+      el.stopAnimation(null, true);
+    });
+    return zr.painter.toDataURL();
+  };
 
-          if (chartView.__alive) {
-            chartView.group.traverse(function (el) {
-              if (el.states.emphasis) {
-                el.states.emphasis.hoverLayer = true;
-              }
-            });
-          }
-        });
-      }
+  ECharts.prototype.getDataURL = function (opts) {
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
     }
-    /**
-     * Update chart and blend.
-     */
-
-    function updateBlend(seriesModel, chartView) {
-      var blendMode = seriesModel.get('blendMode') || null;
-
-      if ("development" !== 'production') {
-        if (!env.canvasSupported && blendMode && blendMode !== 'source-over') {
-          console.warn('Only canvas support blendMode');
-        }
-      }
 
-      chartView.group.traverse(function (el) {
-        // FIXME marker and other components
-        if (!el.isGroup) {
-          // DONT mark the element dirty. In case element is incremental and don't wan't to rerender.
-          el.style.blend = blendMode;
-        }
+    opts = opts || {};
+    var excludeComponents = opts.excludeComponents;
+    var ecModel = this._model;
+    var excludesComponentViews = [];
+    var self = this;
+    each$3(excludeComponents, function (componentType) {
+      ecModel.eachComponent({
+        mainType: componentType
+      }, function (component) {
+        var view = self._componentsMap[component.__viewId];
 
-        if (el.eachPendingDisplayable) {
-          el.eachPendingDisplayable(function (displayable) {
-            displayable.style.blend = blendMode;
-          });
+        if (!view.group.ignore) {
+          excludesComponentViews.push(view);
+          view.group.ignore = true;
         }
       });
-    }
-
-    function updateZ(model, view) {
-      if (model.preventAutoZ) {
-        return;
-      }
-
-      var z = model.get('z');
-      var zlevel = model.get('zlevel'); // Set z and zlevel
-
-      view.group.traverse(function (el) {
-        if (!el.isGroup) {
-          z != null && (el.z = z);
-          zlevel != null && (el.zlevel = zlevel); // TODO if textContent is on group.
+    });
+    var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.getRenderedCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png'));
+    each$3(excludesComponentViews, function (view) {
+      view.group.ignore = false;
+    });
+    return url;
+  };
 
-          var label = el.getTextContent();
-          var labelLine = el.getTextGuideLine();
+  ECharts.prototype.getConnectedDataURL = function (opts) {
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
+    }
 
-          if (label) {
-            label.z = el.z;
-            label.zlevel = el.zlevel; // lift z2 of text content
-            // TODO if el.emphasis.z2 is spcefied, what about textContent.
+    if (!env.canvasSupported) {
+      return;
+    }
 
-            label.z2 = el.z2 + 2;
-          }
+    var isSvg = opts.type === 'svg';
+    var groupId = this.group;
+    var mathMin = Math.min;
+    var mathMax = Math.max;
+    var MAX_NUMBER = Infinity;
 
-          if (labelLine) {
-            var showAbove = el.textGuideLineConfig && el.textGuideLineConfig.showAbove;
-            labelLine.z = el.z;
-            labelLine.zlevel = el.zlevel;
-            labelLine.z2 = el.z2 + (showAbove ? 1 : -1);
-          }
+    if (connectedGroups[groupId]) {
+      var left_1 = MAX_NUMBER;
+      var top_1 = MAX_NUMBER;
+      var right_1 = -MAX_NUMBER;
+      var bottom_1 = -MAX_NUMBER;
+      var canvasList_1 = [];
+      var dpr_1 = opts && opts.pixelRatio || this.getDevicePixelRatio();
+      each(instances$1, function (chart, id) {
+        if (chart.group === groupId) {
+          var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.getRenderedCanvas(clone(opts));
+          var boundingRect = chart.getDom().getBoundingClientRect();
+          left_1 = mathMin(boundingRect.left, left_1);
+          top_1 = mathMin(boundingRect.top, top_1);
+          right_1 = mathMax(boundingRect.right, right_1);
+          bottom_1 = mathMax(boundingRect.bottom, bottom_1);
+          canvasList_1.push({
+            dom: canvas,
+            left: boundingRect.left,
+            top: boundingRect.top
+          });
         }
       });
-    }
-    // TODO States on component.
-
-    function clearStates(model, view) {
-      view.group.traverse(function (el) {
-        // Not applied on removed elements, it may still in fading.
-        if (isElementRemoved(el)) {
-          return;
-        }
+      left_1 *= dpr_1;
+      top_1 *= dpr_1;
+      right_1 *= dpr_1;
+      bottom_1 *= dpr_1;
+      var width = right_1 - left_1;
+      var height = bottom_1 - top_1;
+      var targetCanvas = createCanvas();
+      var zr_1 = init(targetCanvas, {
+        renderer: isSvg ? 'svg' : 'canvas'
+      });
+      zr_1.resize({
+        width: width,
+        height: height
+      });
 
-        var textContent = el.getTextContent();
-        var textGuide = el.getTextGuideLine();
+      if (isSvg) {
+        var content_1 = '';
+        each$3(canvasList_1, function (item) {
+          var x = item.left - left_1;
+          var y = item.top - top_1;
+          content_1 += '<g transform="translate(' + x + ',' + y + ')">' + item.dom + '</g>';
+        });
+        zr_1.painter.getSvgRoot().innerHTML = content_1;
 
-        if (el.stateTransition) {
-          el.stateTransition = null;
+        if (opts.connectedBackgroundColor) {
+          zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor);
         }
 
-        if (textContent && textContent.stateTransition) {
-          textContent.stateTransition = null;
+        zr_1.refreshImmediately();
+        return zr_1.painter.toDataURL();
+      } else {
+        // Background between the charts
+        if (opts.connectedBackgroundColor) {
+          zr_1.add(new Rect({
+            shape: {
+              x: 0,
+              y: 0,
+              width: width,
+              height: height
+            },
+            style: {
+              fill: opts.connectedBackgroundColor
+            }
+          }));
         }
 
-        if (textGuide && textGuide.stateTransition) {
-          textGuide.stateTransition = null;
-        } // TODO If el is incremental.
-
-
-        if (el.hasState()) {
-          el.prevStates = el.currentStates;
-          el.clearStates();
-        } else if (el.prevStates) {
-          el.prevStates = null;
-        }
-      });
+        each$3(canvasList_1, function (item) {
+          var img = new ZRImage({
+            style: {
+              x: item.left * dpr_1 - left_1,
+              y: item.top * dpr_1 - top_1,
+              image: item.dom
+            }
+          });
+          zr_1.add(img);
+        });
+        zr_1.refreshImmediately();
+        return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
+      }
+    } else {
+      return this.getDataURL(opts);
     }
+  };
 
-    function updateStates(model, view) {
-      var stateAnimationModel = model.getModel('stateAnimation');
-      var enableAnimation = model.isAnimationEnabled();
-      var duration = stateAnimationModel.get('duration');
-      var stateTransition = duration > 0 ? {
-        duration: duration,
-        delay: stateAnimationModel.get('delay'),
-        easing: stateAnimationModel.get('easing') // additive: stateAnimationModel.get('additive')
-
-      } : null;
-      view.group.traverse(function (el) {
-        if (el.states && el.states.emphasis) {
-          // Not applied on removed elements, it may still in fading.
-          if (isElementRemoved(el)) {
-            return;
-          }
+  ECharts.prototype.convertToPixel = function (finder, value) {
+    return doConvertPixel(this, 'convertToPixel', finder, value);
+  };
 
-          if (el instanceof Path) {
-            savePathStates(el);
-          } // Only updated on changed element. In case element is incremental and don't wan't to rerender.
-          // TODO, a more proper way?
+  ECharts.prototype.convertFromPixel = function (finder, value) {
+    return doConvertPixel(this, 'convertFromPixel', finder, value);
+  };
+  /**
+   * Is the specified coordinate systems or components contain the given pixel point.
+   * @param {Array|number} value
+   * @return {boolean} result
+   */
 
 
-          if (el.__dirty) {
-            var prevStates = el.prevStates; // Restore states without animation
-
-            if (prevStates) {
-              el.useStates(prevStates);
-            }
-          } // Update state transition and enable animation again.
+  ECharts.prototype.containPixel = function (finder, value) {
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
+    }
 
+    var ecModel = this._model;
+    var result;
+    var findResult = parseFinder(ecModel, finder);
+    each(findResult, function (models, key) {
+      key.indexOf('Models') >= 0 && each(models, function (model) {
+        var coordSys = model.coordinateSystem;
 
-          if (enableAnimation) {
-            el.stateTransition = stateTransition;
-            var textContent = el.getTextContent();
-            var textGuide = el.getTextGuideLine(); // TODO Is it necessary to animate label?
+        if (coordSys && coordSys.containPoint) {
+          result = result || !!coordSys.containPoint(value);
+        } else if (key === 'seriesModels') {
+          var view = this._chartsMap[model.__viewId];
 
-            if (textContent) {
-              textContent.stateTransition = stateTransition;
+          if (view && view.containPoint) {
+            result = result || view.containPoint(value, model);
+          } else {
+            if ("development" !== 'production') {
+              console.warn(key + ': ' + (view ? 'The found component do not support containPoint.' : 'No view mapping to the found component.'));
             }
+          }
+        } else {
+          if ("development" !== 'production') {
+            console.warn(key + ': containPoint is not supported');
+          }
+        }
+      }, this);
+    }, this);
+    return !!result;
+  };
+  /**
+   * Get visual from series or data.
+   * @param finder
+   *        If string, e.g., 'series', means {seriesIndex: 0}.
+   *        If Object, could contain some of these properties below:
+   *        {
+   *            seriesIndex / seriesId / seriesName,
+   *            dataIndex / dataIndexInside
+   *        }
+   *        If dataIndex is not specified, series visual will be fetched,
+   *        but not data item visual.
+   *        If all of seriesIndex, seriesId, seriesName are not specified,
+   *        visual will be fetched from first series.
+   * @param visualType 'color', 'symbol', 'symbolSize'
+   */
 
-            if (textGuide) {
-              textGuide.stateTransition = stateTransition;
-            }
-          } // The use higlighted and selected flag to toggle states.
 
+  ECharts.prototype.getVisual = function (finder, visualType) {
+    var ecModel = this._model;
+    var parsedFinder = parseFinder(ecModel, finder, {
+      defaultMainType: 'series'
+    });
+    var seriesModel = parsedFinder.seriesModel;
 
-          if (el.__dirty) {
-            applyElementStates(el);
-          }
-        }
-      });
+    if ("development" !== 'production') {
+      if (!seriesModel) {
+        console.warn('There is no specified seires model');
+      }
     }
 
-    createExtensionAPI = function (ecIns) {
-      return new (
-      /** @class */
-      function (_super) {
-        __extends(class_1, _super);
+    var data = seriesModel.getData();
+    var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null;
+    return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType);
+  };
+  /**
+   * Get view of corresponding component model
+   */
 
-        function class_1() {
-          return _super !== null && _super.apply(this, arguments) || this;
-        }
 
-        class_1.prototype.getCoordinateSystems = function () {
-          return ecIns._coordSysMgr.getCoordinateSystems();
-        };
+  ECharts.prototype.getViewOfComponentModel = function (componentModel) {
+    return this._componentsMap[componentModel.__viewId];
+  };
+  /**
+   * Get view of corresponding series model
+   */
 
-        class_1.prototype.getComponentByElement = function (el) {
-          while (el) {
-            var modelInfo = el.__ecComponentInfo;
 
-            if (modelInfo != null) {
-              return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index);
-            }
+  ECharts.prototype.getViewOfSeriesModel = function (seriesModel) {
+    return this._chartsMap[seriesModel.__viewId];
+  };
 
-            el = el.parent;
-          }
-        };
+  ECharts.prototype._initEvents = function () {
+    var _this = this;
 
-        class_1.prototype.enterEmphasis = function (el, highlightDigit) {
-          enterEmphasis(el, highlightDigit);
-          markStatusToUpdate(ecIns);
-        };
+    each$3(MOUSE_EVENT_NAMES, function (eveName) {
+      var handler = function (e) {
+        var ecModel = _this.getModel();
 
-        class_1.prototype.leaveEmphasis = function (el, highlightDigit) {
-          leaveEmphasis(el, highlightDigit);
-          markStatusToUpdate(ecIns);
-        };
+        var el = e.target;
+        var params;
+        var isGlobalOut = eveName === 'globalout'; // no e.target when 'globalout'.
 
-        class_1.prototype.enterBlur = function (el) {
-          enterBlur(el);
-          markStatusToUpdate(ecIns);
-        };
+        if (isGlobalOut) {
+          params = {};
+        } else {
+          el && findEventDispatcher(el, function (parent) {
+            var ecData = getECData(parent);
 
-        class_1.prototype.leaveBlur = function (el) {
-          leaveBlur(el);
-          markStatusToUpdate(ecIns);
-        };
+            if (ecData && ecData.dataIndex != null) {
+              var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex);
+              params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType) || {};
+              return true;
+            } // If element has custom eventData of components
+            else if (ecData.eventData) {
+                params = extend({}, ecData.eventData);
+                return true;
+              }
+          }, true);
+        } // Contract: if params prepared in mouse event,
+        // these properties must be specified:
+        // {
+        //    componentType: string (component main type)
+        //    componentIndex: number
+        // }
+        // Otherwise event query can not work.
 
-        class_1.prototype.enterSelect = function (el) {
-          enterSelect(el);
-          markStatusToUpdate(ecIns);
-        };
 
-        class_1.prototype.leaveSelect = function (el) {
-          leaveSelect(el);
-          markStatusToUpdate(ecIns);
-        };
+        if (params) {
+          var componentType = params.componentType;
+          var componentIndex = params.componentIndex; // Special handling for historic reason: when trigger by
+          // markLine/markPoint/markArea, the componentType is
+          // 'markLine'/'markPoint'/'markArea', but we should better
+          // enable them to be queried by seriesIndex, since their
+          // option is set in each series.
 
-        class_1.prototype.getModel = function () {
-          return ecIns.getModel();
-        };
+          if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') {
+            componentType = 'series';
+            componentIndex = params.seriesIndex;
+          }
 
-        class_1.prototype.getViewOfComponentModel = function (componentModel) {
-          return ecIns.getViewOfComponentModel(componentModel);
-        };
+          var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex);
+          var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId];
 
-        class_1.prototype.getViewOfSeriesModel = function (seriesModel) {
-          return ecIns.getViewOfSeriesModel(seriesModel);
-        };
+          if ("development" !== 'production') {
+            // `event.componentType` and `event[componentTpype + 'Index']` must not
+            // be missed, otherwise there is no way to distinguish source component.
+            // See `dataFormat.getDataParams`.
+            if (!isGlobalOut && !(model && view)) {
+              console.warn('model or view can not be found by params');
+            }
+          }
 
-        return class_1;
-      }(ExtensionAPI))(ecIns);
-    };
+          params.event = e;
+          params.type = eveName;
+          _this._$eventProcessor.eventInfo = {
+            targetEl: el,
+            packedEvent: params,
+            model: model,
+            view: view
+          };
 
-    enableConnect = function (chart) {
-      function updateConnectedChartsStatus(charts, status) {
-        for (var i = 0; i < charts.length; i++) {
-          var otherChart = charts[i];
-          otherChart[CONNECT_STATUS_KEY] = status;
+          _this.trigger(eveName, params);
         }
-      }
+      }; // Consider that some component (like tooltip, brush, ...)
+      // register zr event handler, but user event handler might
+      // do anything, such as call `setOption` or `dispatchAction`,
+      // which probably update any of the content and probably
+      // cause problem if it is called previous other inner handlers.
 
-      each$3(eventActionMap, function (actionType, eventType) {
-        chart._messageCenter.on(eventType, function (event) {
-          if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) {
-            if (event && event.escapeConnect) {
-              return;
-            }
 
-            var action_1 = chart.makeActionFromEvent(event);
-            var otherCharts_1 = [];
-            each$3(instances$1, function (otherChart) {
-              if (otherChart !== chart && otherChart.group === chart.group) {
-                otherCharts_1.push(otherChart);
-              }
-            });
-            updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_PENDING);
-            each$3(otherCharts_1, function (otherChart) {
-              if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) {
-                otherChart.dispatchAction(action_1);
-              }
-            });
-            updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_UPDATED);
-          }
-        });
-      });
-    };
+      handler.zrEventfulCallAtLast = true;
 
-    setTransitionOpt = function (chart, transitionOpt) {
-      var ecModel = chart._model;
-      each(normalizeToArray(transitionOpt), function (transOpt) {
-        var errMsg;
-        var fromOpt = transOpt.from;
-        var toOpt = transOpt.to;
+      _this._zr.on(eveName, handler, _this);
+    });
+    each$3(eventActionMap, function (actionType, eventType) {
+      _this._messageCenter.on(eventType, function (event) {
+        this.trigger(eventType, event);
+      }, _this);
+    }); // Extra events
+    // TODO register?
 
-        if (toOpt == null) {
-          if ("development" !== 'production') {
-            errMsg = '`transition.to` must be specified.';
-          }
+    each$3(['selectchanged'], function (eventType) {
+      _this._messageCenter.on(eventType, function (event) {
+        this.trigger(eventType, event);
+      }, _this);
+    });
+    handleLegacySelectEvents(this._messageCenter, this, this._api);
+  };
 
-          throwError(errMsg);
-        }
+  ECharts.prototype.isDisposed = function () {
+    return this._disposed;
+  };
 
-        var finderOpt = {
-          includeMainTypes: ['series'],
-          enableAll: false,
-          enableNone: false
-        };
-        var fromResult = fromOpt ? parseFinder(ecModel, fromOpt, finderOpt) : null;
-        var toResult = parseFinder(ecModel, toOpt, finderOpt);
-        var toSeries = toResult.seriesModel;
+  ECharts.prototype.clear = function () {
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
+    }
 
-        if (toSeries == null) {
-          errMsg = '';
+    this.setOption({
+      series: []
+    }, true);
+  };
 
-          if ("development" !== 'production') {
-            errMsg = '`transition` is only supported on series.';
-          }
-        }
+  ECharts.prototype.dispose = function () {
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
+    }
 
-        if (fromResult && fromResult.seriesModel !== toSeries) {
-          errMsg = '';
+    this._disposed = true;
+    setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
+    var api = this._api;
+    var ecModel = this._model;
+    each$3(this._componentsViews, function (component) {
+      component.dispose(ecModel, api);
+    });
+    each$3(this._chartsViews, function (chart) {
+      chart.dispose(ecModel, api);
+    }); // Dispose after all views disposed
 
-          if ("development" !== 'production') {
-            errMsg = '`transition.from` and `transition.to` must be specified to the same series.';
-          }
-        }
+    this._zr.dispose();
 
-        if (errMsg != null) {
-          throwError(errMsg);
-        } // Just a temp solution: mount them on series.
+    delete instances$1[this.id];
+  };
+  /**
+   * Resize the chart
+   */
 
 
-        toSeries.__transientTransitionOpt = {
-          from: fromOpt ? fromOpt.dimension : null,
-          to: toOpt.dimension,
-          dividingMethod: transOpt.dividingMethod
-        };
-      });
-    };
-  }();
+  ECharts.prototype.resize = function (opts) {
+    if ("development" !== 'production') {
+      assert$1(!this[IN_MAIN_PROCESS_KEY], '`resize` should not be called during main process.');
+    }
 
-  return ECharts;
-}(Eventful);
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
+    }
 
-var echartsProto = ECharts.prototype;
-echartsProto.on = createRegisterEventWithLowercaseECharts('on');
-echartsProto.off = createRegisterEventWithLowercaseECharts('off');
-/**
- * @deprecated
- */
-// @ts-ignore
+    this._zr.resize(opts);
 
-echartsProto.one = function (eventName, cb, ctx) {
-  var self = this;
-  deprecateLog('ECharts#one is deprecated.');
+    var ecModel = this._model; // Resize loading effect
 
-  function wrapped() {
-    var args2 = [];
+    this._loadingFX && this._loadingFX.resize();
 
-    for (var _i = 0; _i < arguments.length; _i++) {
-      args2[_i] = arguments[_i];
+    if (!ecModel) {
+      return;
     }
 
-    cb && cb.apply && cb.apply(this, args2); // @ts-ignore
+    var optionChanged = ecModel.resetOption('media');
+    var silent = opts && opts.silent;
+    this[IN_MAIN_PROCESS_KEY] = true;
+    optionChanged && prepare(this);
+    updateMethods.update.call(this, {
+      type: 'resize',
+      animation: extend({
+        // Disable animation
+        duration: 0
+      }, opts && opts.animation)
+    });
+    this[IN_MAIN_PROCESS_KEY] = false;
+    flushPendingActions.call(this, silent);
+    triggerUpdatedEvent.call(this, silent);
+  };
 
-    self.off(eventName, wrapped);
-  }
+  ECharts.prototype.showLoading = function (name, cfg) {
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
+    }
 
-  this.on.call(this, eventName, wrapped, ctx);
-}; // /**
-//  * Encode visual infomation from data after data processing
-//  *
-//  * @param {module:echarts/model/Global} ecModel
-//  * @param {object} layout
-//  * @param {boolean} [layoutFilter] `true`: only layout,
-//  *                                 `false`: only not layout,
-//  *                                 `null`/`undefined`: all.
-//  * @param {string} taskBaseTag
-//  * @private
-//  */
-// function startVisualEncoding(ecIns, ecModel, api, payload, layoutFilter) {
-//     each(visualFuncs, function (visual, index) {
-//         let isLayout = visual.isLayout;
-//         if (layoutFilter == null
-//             || (layoutFilter === false && !isLayout)
-//             || (layoutFilter === true && isLayout)
-//         ) {
-//             visual.func(ecModel, api, payload);
-//         }
-//     });
-// }
+    if (isObject$2(name)) {
+      cfg = name;
+      name = '';
+    }
 
+    name = name || 'default';
+    this.hideLoading();
 
-var MOUSE_EVENT_NAMES = ['click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu'];
+    if (!loadingEffects[name]) {
+      if ("development" !== 'production') {
+        console.warn('Loading effects ' + name + ' not exists.');
+      }
 
-function disposedWarning(id) {
-  if ("development" !== 'production') {
-    console.warn('Instance ' + id + ' has been disposed');
-  }
-}
+      return;
+    }
 
-var actions = {};
-/**
- * Map eventType to actionType
- */
+    var el = loadingEffects[name](this._api, cfg);
+    var zr = this._zr;
+    this._loadingFX = el;
+    zr.add(el);
+  };
+  /**
+   * Hide loading effect
+   */
 
-var eventActionMap = {};
-var dataProcessorFuncs = [];
-var optionPreprocessorFuncs = [];
-var postInitFuncs = [];
-var postUpdateFuncs = [];
-var visualFuncs = [];
-var themeStorage = {};
-var loadingEffects = {};
-var instances$1 = {};
-var connectedGroups = {};
-var idBase = +new Date() - 0;
-var groupIdBase = +new Date() - 0;
-var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
-/**
- * @param opts.devicePixelRatio Use window.devicePixelRatio by default
- * @param opts.renderer Can choose 'canvas' or 'svg' to render the chart.
- * @param opts.width Use clientWidth of the input `dom` by default.
- *        Can be 'auto' (the same as null/undefined)
- * @param opts.height Use clientHeight of the input `dom` by default.
- *        Can be 'auto' (the same as null/undefined)
- */
 
-function init$1(dom, theme, opts) {
-  if ("development" !== 'production') {
-    if (!dom) {
-      throw new Error('Initialize failed: invalid dom.');
+  ECharts.prototype.hideLoading = function () {
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
     }
-  }
 
-  var existInstance = getInstanceByDom(dom);
+    this._loadingFX && this._zr.remove(this._loadingFX);
+    this._loadingFX = null;
+  };
 
-  if (existInstance) {
-    if ("development" !== 'production') {
-      console.warn('There is a chart instance already initialized on the dom.');
-    }
+  ECharts.prototype.makeActionFromEvent = function (eventObj) {
+    var payload = extend({}, eventObj);
+    payload.type = eventActionMap[eventObj.type];
+    return payload;
+  };
+  /**
+   * @param opt If pass boolean, means opt.silent
+   * @param opt.silent Default `false`. Whether trigger events.
+   * @param opt.flush Default `undefined`.
+   *        true: Flush immediately, and then pixel in canvas can be fetched
+   *            immediately. Caution: it might affect performance.
+   *        false: Not flush.
+   *        undefined: Auto decide whether perform flush.
+   */
 
-    return existInstance;
-  }
 
-  if ("development" !== 'production') {
-    if (isDom(dom) && dom.nodeName.toUpperCase() !== 'CANVAS' && (!dom.clientWidth && (!opts || opts.width == null) || !dom.clientHeight && (!opts || opts.height == null))) {
-      console.warn('Can\'t get DOM width or height. Please check ' + 'dom.clientWidth and dom.clientHeight. They should not be 0.' + 'For example, you may need to call this in the callback ' + 'of window.onload.');
+  ECharts.prototype.dispatchAction = function (payload, opt) {
+    if (this._disposed) {
+      disposedWarning(this.id);
+      return;
     }
-  }
 
-  var chart = new ECharts(dom, theme, opts);
-  chart.id = 'ec_' + idBase++;
-  instances$1[chart.id] = chart;
-  setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);
-  enableConnect(chart);
-  each$3(postInitFuncs, function (postInitFunc) {
-    postInitFunc(chart);
-  });
-  return chart;
-}
-/**
- * @usage
- * (A)
- * ```js
- * let chart1 = echarts.init(dom1);
- * let chart2 = echarts.init(dom2);
- * chart1.group = 'xxx';
- * chart2.group = 'xxx';
- * echarts.connect('xxx');
- * ```
- * (B)
- * ```js
- * let chart1 = echarts.init(dom1);
- * let chart2 = echarts.init(dom2);
- * echarts.connect('xxx', [chart1, chart2]);
- * ```
- */
+    if (!isObject$2(opt)) {
+      opt = {
+        silent: !!opt
+      };
+    }
 
-function connect(groupId) {
-  // Is array of charts
-  if (isArray(groupId)) {
-    var charts = groupId;
-    groupId = null; // If any chart has group
+    if (!actions[payload.type]) {
+      return;
+    } // Avoid dispatch action before setOption. Especially in `connect`.
 
-    each$3(charts, function (chart) {
-      if (chart.group != null) {
-        groupId = chart.group;
-      }
-    });
-    groupId = groupId || 'g_' + groupIdBase++;
-    each$3(charts, function (chart) {
-      chart.group = groupId;
-    });
-  }
 
-  connectedGroups[groupId] = true;
-  return groupId;
-}
-/**
- * @deprecated
- */
+    if (!this._model) {
+      return;
+    } // May dispatchAction in rendering procedure
 
-function disConnect(groupId) {
-  connectedGroups[groupId] = false;
-}
-/**
- * Alias and backword compat
- */
 
-var disconnect = disConnect;
-/**
- * Dispose a chart instance
- */
+    if (this[IN_MAIN_PROCESS_KEY]) {
+      this._pendingActions.push(payload);
 
-function dispose$1(chart) {
-  if (typeof chart === 'string') {
-    chart = instances$1[chart];
-  } else if (!(chart instanceof ECharts)) {
-    // Try to treat as dom
-    chart = getInstanceByDom(chart);
-  }
+      return;
+    }
 
-  if (chart instanceof ECharts && !chart.isDisposed()) {
-    chart.dispose();
-  }
-}
-function getInstanceByDom(dom) {
-  return instances$1[getAttribute(dom, DOM_ATTRIBUTE_KEY)];
-}
-function getInstanceById(key) {
-  return instances$1[key];
-}
-/**
- * Register theme
- */
+    var silent = opt.silent;
+    doDispatchAction.call(this, payload, silent);
+    var flush = opt.flush;
 
-function registerTheme(name, theme) {
-  themeStorage[name] = theme;
-}
-/**
- * Register option preprocessor
- */
+    if (flush) {
+      this._zr.flush();
+    } else if (flush !== false && env.browser.weChat) {
+      // In WeChat embeded browser, `requestAnimationFrame` and `setInterval`
+      // hang when sliding page (on touch event), which cause that zr does not
+      // refresh util user interaction finished, which is not expected.
+      // But `dispatchAction` may be called too frequently when pan on touch
+      // screen, which impacts performance if do not throttle them.
+      this._throttledZrFlush();
+    }
 
-function registerPreprocessor(preprocessorFunc) {
-  if (indexOf$1(optionPreprocessorFuncs, preprocessorFunc) < 0) {
-    optionPreprocessorFuncs.push(preprocessorFunc);
-  }
-}
-function registerProcessor(priority, processor) {
-  normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT);
-}
-/**
- * Register postIniter
- * @param {Function} postInitFunc
- */
+    flushPendingActions.call(this, silent);
+    triggerUpdatedEvent.call(this, silent);
+  };
 
-function registerPostInit(postInitFunc) {
-  if (indexOf$1(postInitFuncs, postInitFunc) < 0) {
-    postInitFunc && postInitFuncs.push(postInitFunc);
-  }
-}
-/**
- * Register postUpdater
- * @param {Function} postUpdateFunc
- */
+  ECharts.prototype.updateLabelLayout = function () {
+    var labelManager = this._labelManager;
+    labelManager.updateLayoutConfig(this._api);
+    labelManager.layout(this._api);
+    labelManager.processLabelsOverall();
+  };
 
-function registerPostUpdate(postUpdateFunc) {
-  if (indexOf$1(postUpdateFuncs, postUpdateFunc) < 0) {
-    postUpdateFunc && postUpdateFuncs.push(postUpdateFunc);
-  }
-}
-function registerAction(actionInfo, eventName, action) {
-  if (typeof eventName === 'function') {
-    action = eventName;
-    eventName = '';
-  }
+  ECharts.prototype.appendData = function (params) {
+    if (this._disposed) {
... 52415 lines suppressed ...

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