Merge pull request #17237 from jiawulin001/issue#17228

fix: sliderZoom in candlestick dataset error
diff --git a/.github/workflows/nightly-next.yml b/.github/workflows/nightly-next.yml
index a8f1f2a..b8c7978 100644
--- a/.github/workflows/nightly-next.yml
+++ b/.github/workflows/nightly-next.yml
@@ -11,6 +11,7 @@
 jobs:
   build:
     runs-on: ubuntu-latest
+    if: ${{ github.repository_owner == 'apache' }}
 
     strategy:
       matrix:
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 030044b..5f4a302 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -11,6 +11,7 @@
 jobs:
   build:
     runs-on: ubuntu-latest
+    if: ${{ github.repository_owner == 'apache' }}
 
     strategy:
       matrix:
diff --git a/.github/workflows/source-release.yml b/.github/workflows/source-release.yml
index db4c7e2..c98ba72 100644
--- a/.github/workflows/source-release.yml
+++ b/.github/workflows/source-release.yml
@@ -7,6 +7,7 @@
 jobs:
   materials:
     runs-on: ubuntu-latest
+    if: ${{ github.repository_owner == 'apache' }}
 
     strategy:
       matrix:
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 7f1420b..2c293e7 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -11,9 +11,10 @@
 jobs:
   stale:
     runs-on: ubuntu-latest
+    if: ${{ github.repository_owner == 'apache' }}
     steps:
       - name: Close Stale Issues
-        uses: actions/stale@v4
+        uses: actions/stale@v5
         with:
           days-before-stale: 730
           days-before-close: 7
@@ -21,6 +22,7 @@
           stale-pr-label: stale
           stale-issue-message: 'This issue has been automatically marked as stale because it did not have recent activity. It will be closed in 7 days if no further activity occurs. If you wish not to mark it as stale, please leave a comment in this issue.'
           close-issue-message: 'This issue has been automatically closed because it did not have recent activity. If this remains to be a problem with the latest version of Apache ECharts, please open a new issue and link this to it. Thanks!'
+          close-issue-reason: 'not_planned'
           stale-pr-message: 'This PR has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. If you wish not to mark it as stale, please leave a comment in this PR. We are sorry for this but 2 years is a long time and the code base has been changed a lot. Thanks for your contribution anyway.'
           close-pr-message: 'This PR has been automatically closed because it has not had recent activity. Sorry for that and we are looking forward to your next contribution.'
           exempt-issue-labels: 'FAQ,priority: high'
diff --git a/package-lock.json b/package-lock.json
index 4259502..004f091 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1457,6 +1457,64 @@
         "node": ">=8"
       }
     },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+      "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/source-map": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+      "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.14",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+      "dev": true
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.14",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
+      "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.0.3",
+        "@jridgewell/sourcemap-codec": "^1.4.10"
+      }
+    },
     "node_modules/@lang/rollup-plugin-dts": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/@lang/rollup-plugin-dts/-/rollup-plugin-dts-2.0.2.tgz",
@@ -11737,9 +11795,9 @@
       }
     },
     "node_modules/source-map-support": {
-      "version": "0.5.19",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
-      "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
       "dev": true,
       "dependencies": {
         "buffer-from": "^1.0.0",
@@ -12281,14 +12339,15 @@
       }
     },
     "node_modules/terser": {
-      "version": "5.3.8",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.8.tgz",
-      "integrity": "sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ==",
+      "version": "5.14.2",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
+      "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
       "dev": true,
       "dependencies": {
+        "@jridgewell/source-map": "^0.3.2",
+        "acorn": "^8.5.0",
         "commander": "^2.20.0",
-        "source-map": "~0.7.2",
-        "source-map-support": "~0.5.19"
+        "source-map-support": "~0.5.20"
       },
       "bin": {
         "terser": "bin/terser"
@@ -12297,21 +12356,24 @@
         "node": ">=10"
       }
     },
+    "node_modules/terser/node_modules/acorn": {
+      "version": "8.7.1",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
+      "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
+      "dev": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/terser/node_modules/commander": {
       "version": "2.20.3",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
       "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
       "dev": true
     },
-    "node_modules/terser/node_modules/source-map": {
-      "version": "0.7.3",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
-      "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
     "node_modules/test-exclude": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
@@ -14580,6 +14642,55 @@
         }
       }
     },
+    "@jridgewell/gen-mapping": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+      "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+      "dev": true,
+      "requires": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "@jridgewell/resolve-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+      "dev": true
+    },
+    "@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+      "dev": true
+    },
+    "@jridgewell/source-map": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+      "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+      "dev": true,
+      "requires": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "@jridgewell/sourcemap-codec": {
+      "version": "1.4.14",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+      "dev": true
+    },
+    "@jridgewell/trace-mapping": {
+      "version": "0.3.14",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
+      "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
+      "dev": true,
+      "requires": {
+        "@jridgewell/resolve-uri": "^3.0.3",
+        "@jridgewell/sourcemap-codec": "^1.4.10"
+      }
+    },
     "@lang/rollup-plugin-dts": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/@lang/rollup-plugin-dts/-/rollup-plugin-dts-2.0.2.tgz",
@@ -22933,9 +23044,9 @@
       }
     },
     "source-map-support": {
-      "version": "0.5.19",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
-      "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
       "dev": true,
       "requires": {
         "buffer-from": "^1.0.0",
@@ -23379,27 +23490,28 @@
       }
     },
     "terser": {
-      "version": "5.3.8",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.8.tgz",
-      "integrity": "sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ==",
+      "version": "5.14.2",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
+      "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
       "dev": true,
       "requires": {
+        "@jridgewell/source-map": "^0.3.2",
+        "acorn": "^8.5.0",
         "commander": "^2.20.0",
-        "source-map": "~0.7.2",
-        "source-map-support": "~0.5.19"
+        "source-map-support": "~0.5.20"
       },
       "dependencies": {
+        "acorn": {
+          "version": "8.7.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
+          "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
+          "dev": true
+        },
         "commander": {
           "version": "2.20.3",
           "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
           "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
           "dev": true
-        },
-        "source-map": {
-          "version": "0.7.3",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
-          "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
-          "dev": true
         }
       }
     },
diff --git a/src/action/roamHelper.ts b/src/action/roamHelper.ts
index d1721a9..f14c8cc 100644
--- a/src/action/roamHelper.ts
+++ b/src/action/roamHelper.ts
@@ -22,7 +22,7 @@
 import type ExtensionAPI from '../core/ExtensionAPI';
 import type { Payload } from '../util/types';
 
-export interface RoamPaylod extends Payload {
+export interface RoamPayload extends Payload {
     dx: number
     dy: number
     zoom: number
@@ -39,7 +39,7 @@
 
 export function updateCenterAndZoom(
     view: View,
-    payload: RoamPaylod,
+    payload: RoamPayload,
     zoomLimit?: {
         min?: number,
         max?: number
diff --git a/src/animation/customGraphicKeyframeAnimation.ts b/src/animation/customGraphicKeyframeAnimation.ts
index 196c5fc..36dd9ec 100644
--- a/src/animation/customGraphicKeyframeAnimation.ts
+++ b/src/animation/customGraphicKeyframeAnimation.ts
@@ -22,7 +22,7 @@
 import { keys, filter, each, isArray, indexOf } from 'zrender/src/core/util';
 import { ELEMENT_ANIMATABLE_PROPS } from './customGraphicTransition';
 import { AnimationOption, AnimationOptionMixin, Dictionary } from '../util/types';
-import { Model } from '../echarts.all';
+import type Model from '../model/Model';
 import { getAnimationConfig } from './basicTransition';
 import { warn } from '../util/log';
 import { makeInner } from '../util/model';
@@ -159,4 +159,4 @@
             .duration(duration)
             .start(animationOpts.easing);
     });
-}
\ No newline at end of file
+}
diff --git a/src/chart/custom/CustomView.ts b/src/chart/custom/CustomView.ts
index 49fad96..e0ad444 100644
--- a/src/chart/custom/CustomView.ts
+++ b/src/chart/custom/CustomView.ts
@@ -99,6 +99,7 @@
     applyKeyframeAnimation,
     stopPreviousKeyframeAnimationAndRestore
 } from '../../animation/customGraphicKeyframeAnimation';
+import type SeriesModel from '../../model/Series';
 
 const EMPHASIS = 'emphasis' as const;
 const NORMAL = 'normal' as const;
@@ -228,7 +229,7 @@
             })
             .remove(function (oldIdx) {
                 const el = oldData.getItemGraphicEl(oldIdx);
-                applyLeaveTransition(el, customInnerStore(el).option, customSeries);
+                el && applyLeaveTransition(el, customInnerStore(el).option, customSeries);
             })
             .update(function (newIdx, oldIdx) {
                 const oldEl = oldData.getItemGraphicEl(oldIdx);
@@ -1264,16 +1265,21 @@
 
 
 // Usage:
-// (1) By default, `elOption.$mergeChildren` is `'byIndex'`, which indicates that
-//     the existing children will not be removed, and enables the feature that
-//     update some of the props of some of the children simply by construct
+// (1) By default, `elOption.$mergeChildren` is `'byIndex'`, which indicates
+//     that the existing children will not be removed, and enables the feature
+//     that update some of the props of some of the children simply by construct
 //     the returned children of `renderItem` like:
 //     `var children = group.children = []; children[3] = {opacity: 0.5};`
 // (2) If `elOption.$mergeChildren` is `'byName'`, add/update/remove children
 //     by child.name. But that might be lower performance.
 // (3) If `elOption.$mergeChildren` is `false`, the existing children will be
 //     replaced totally.
-// (4) If `!elOption.children`, following the "merge" principle, nothing will happen.
+// (4) If `!elOption.children`, following the "merge" principle, nothing will
+//     happen.
+// (5) If `elOption.$mergeChildren` is not `false` neither `'byName'` and the
+//     `el` is a group, and if any of the new child is null, it means to remove
+//     the element at the same index, if exists. On the other hand, if the new
+//     child is and empty object `{}`, it means to keep the element not changed.
 //
 // For implementation simpleness, do not provide a direct way to remove sinlge
 // child (otherwise the total indicies of the children array have to be modified).
@@ -1316,24 +1322,59 @@
     // might be better performance.
     let index = 0;
     for (; index < newLen; index++) {
-        newChildren[index] && doCreateOrUpdateEl(
-            api,
-            el.childAt(index),
-            dataIndex,
-            newChildren[index] as CustomElementOption,
-            seriesModel,
-            el
-        );
+        const newChild = newChildren[index];
+        const oldChild = el.childAt(index);
+        if (newChild) {
+            if (newChild.ignore == null) {
+                // The old child is set to be ignored if null (see comments
+                // below). So we need to set ignore to be false back.
+                newChild.ignore = false;
+            }
+            doCreateOrUpdateEl(
+                api,
+                oldChild,
+                dataIndex,
+                newChild as CustomElementOption,
+                seriesModel,
+                el
+            );
+        }
+        else {
+            if (__DEV__) {
+                assert(
+                    oldChild,
+                    'renderItem should not return a group containing elements'
+                    + ' as null/undefined/{} if they do not exist before.'
+                );
+            }
+            // If the new element option is null, it means to remove the old
+            // element. But we cannot really remove the element from the group
+            // directly, because the element order may not be stable when this
+            // element is added back. So we set the element to be ignored.
+            oldChild.ignore = true;
+        }
     }
     for (let i = el.childCount() - 1; i >= index; i--) {
-        // Do not supprot leave elements that are not mentioned in the latest
-        // `renderItem` return. Otherwise users may not have a clear and simple
-        // concept that how to contorl all of the elements.
         const child = el.childAt(i);
-        applyLeaveTransition(child, customInnerStore(el).option, seriesModel);
+        removeChildFromGroup(el, child, seriesModel);
     }
 }
 
+function removeChildFromGroup(
+    group: graphicUtil.Group,
+    child: Element,
+    seriesModel: SeriesModel
+) {
+    // Do not support leave elements that are not mentioned in the latest
+    // `renderItem` return. Otherwise users may not have a clear and simple
+    // concept that how to control all of the elements.
+    child && applyLeaveTransition(
+        child,
+        customInnerStore(group).option,
+        seriesModel
+    );
+}
+
 type DiffGroupContext = {
     api: ExtensionAPI;
     oldChildren: Element[];
@@ -1383,7 +1424,7 @@
 function processRemove(this: DataDiffer<DiffGroupContext>, oldIndex: number): void {
     const context = this.context;
     const child = context.oldChildren[oldIndex];
-    applyLeaveTransition(child, customInnerStore(child).option, context.seriesModel);
+    child && applyLeaveTransition(child, customInnerStore(child).option, context.seriesModel);
 }
 
 /**
diff --git a/src/chart/gauge/GaugeSeries.ts b/src/chart/gauge/GaugeSeries.ts
index 07bfcc4..7ffb508 100644
--- a/src/chart/gauge/GaugeSeries.ts
+++ b/src/chart/gauge/GaugeSeries.ts
@@ -170,8 +170,9 @@
         lineStyle?: LineStyleOption
     }
 
-    axisLabel?: LabelOption & {
+    axisLabel?: Omit<LabelOption, 'rotate'> & {
         formatter?: LabelFormatter | string
+        rotate?: 'tangential' | 'radial' | number
     }
 
     pointer?: PointerOption
@@ -265,7 +266,8 @@
             distance: 15,
             // formatter: null,
             color: '#464646',
-            fontSize: 12
+            fontSize: 12,
+            rotate: 0
         },
         pointer: {
             icon: null,
@@ -321,4 +323,4 @@
 }
 
 
-export default GaugeSeriesModel;
\ No newline at end of file
+export default GaugeSeriesModel;
diff --git a/src/chart/gauge/GaugeView.ts b/src/chart/gauge/GaugeView.ts
index b646607..a03243e 100644
--- a/src/chart/gauge/GaugeView.ts
+++ b/src/chart/gauge/GaugeView.ts
@@ -31,7 +31,7 @@
 import Sausage from '../../util/shape/sausage';
 import {createSymbol} from '../../util/symbol';
 import ZRImage from 'zrender/src/graphic/Image';
-import {extend, isFunction, isString} from 'zrender/src/core/util';
+import {extend, isFunction, isString, isNumber} from 'zrender/src/core/util';
 import {setCommonECData} from '../../util/innerStore';
 import { normalizeArcAngles } from 'zrender/src/core/PathProxy';
 
@@ -272,19 +272,55 @@
                     labelModel.get('formatter')
                 );
                 const autoColor = getColor(i / splitNumber);
+                const textStyleX = unitX * (r - splitLineLen - distance) + cx;
+                const textStyleY = unitY * (r - splitLineLen - distance) + cy;
 
-                group.add(new graphic.Text({
-                    style: createTextStyle(labelModel, {
-                        text: label,
-                        x: unitX * (r - splitLineLen - distance) + cx,
-                        y: unitY * (r - splitLineLen - distance) + cy,
-                        verticalAlign: unitY < -0.8 ? 'top' : (unitY > 0.8 ? 'bottom' : 'middle'),
-                        align: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center')
-                    }, {
-                        inheritColor: autoColor
-                    }),
-                    silent: true
-                }));
+                const rotateType = labelModel.get('rotate');
+                let rotate = 0;
+                if (rotateType === 'radial') {
+                    rotate = -angle + 2 * Math.PI;
+                    if (rotate > Math.PI / 2) {
+                        rotate += Math.PI;
+                    }
+                }
+                else if (rotateType === 'tangential') {
+                    rotate = -angle - Math.PI / 2;
+                }
+                else if (isNumber(rotateType)) {
+                    rotate = rotateType * Math.PI / 180;
+                }
+
+                if (rotate === 0) {
+                    group.add(new graphic.Text({
+                        style: createTextStyle(labelModel, {
+                            text: label,
+                            x: textStyleX,
+                            y: textStyleY,
+                            verticalAlign: unitY < -0.8 ? 'top' : (unitY > 0.8 ? 'bottom' : 'middle'),
+                            align: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center')
+                        }, {
+                            inheritColor: autoColor
+                        }),
+                        silent: true
+                    }));
+                }
+                else {
+                    group.add(new graphic.Text({
+                        style: createTextStyle(labelModel, {
+                            text: label,
+                            x: textStyleX,
+                            y: textStyleY,
+                            verticalAlign: 'middle',
+                            align: 'center'
+                        }, {
+                            inheritColor: autoColor
+                        }),
+                        silent: true,
+                        originX: textStyleX,
+                        originY: textStyleY,
+                        rotation: rotate
+                    }));
+                }
             }
 
             // Axis tick
diff --git a/src/chart/graph/GraphSeries.ts b/src/chart/graph/GraphSeries.ts
index 299b9a4..e1b85be 100644
--- a/src/chart/graph/GraphSeries.ts
+++ b/src/chart/graph/GraphSeries.ts
@@ -184,7 +184,7 @@
 
     emphasis?: {
         focus?: Exclude<GraphNodeItemOption['emphasis'], undefined>['focus']
-        scale?: boolean
+        scale?: boolean | number
         label?: SeriesLabelOption
         edgeLabel?: SeriesLabelOption
         itemStyle?: ItemStyleOption
@@ -513,4 +513,4 @@
     };
 }
 
-export default GraphSeriesModel;
\ No newline at end of file
+export default GraphSeriesModel;
diff --git a/src/chart/graph/install.ts b/src/chart/graph/install.ts
index b917be0..2ffec7b 100644
--- a/src/chart/graph/install.ts
+++ b/src/chart/graph/install.ts
@@ -29,7 +29,7 @@
 import View from '../../coord/View';
 import GraphView from './GraphView';
 import GraphSeriesModel from './GraphSeries';
-import { RoamPaylod, updateCenterAndZoom } from '../../action/roamHelper';
+import { RoamPayload, updateCenterAndZoom } from '../../action/roamHelper';
 import GlobalModel from '../../model/Global';
 import { noop } from 'zrender/src/core/util';
 import type ExtensionAPI from '../../core/ExtensionAPI';
@@ -73,7 +73,7 @@
     }, noop);
 
     // Register roam action.
-    registers.registerAction(actionInfo, function (payload: RoamPaylod, ecModel: GlobalModel, api: ExtensionAPI) {
+    registers.registerAction(actionInfo, function (payload: RoamPayload, ecModel: GlobalModel, api: ExtensionAPI) {
         ecModel.eachComponent({
             mainType: 'series', query: payload
         }, function (seriesModel: GraphSeriesModel) {
diff --git a/src/chart/helper/Symbol.ts b/src/chart/helper/Symbol.ts
index c31e9b1..58ddc36 100644
--- a/src/chart/helper/Symbol.ts
+++ b/src/chart/helper/Symbol.ts
@@ -27,7 +27,7 @@
 import SeriesModel from '../../model/Series';
 import { PathProps } from 'zrender/src/graphic/Path';
 import { SymbolDrawSeriesScope, SymbolDrawItemModelOption } from './SymbolDraw';
-import { extend, isNumber } from 'zrender/src/core/util';
+import { extend } from 'zrender/src/core/util';
 import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';
 import ZRImage from 'zrender/src/graphic/Image';
 import { saveOldStyle } from '../../animation/basicTransition';
@@ -336,11 +336,19 @@
         symbolPath.ensureState('select').style = selectItemStyle;
         symbolPath.ensureState('blur').style = blurItemStyle;
 
-        if (hoverScale) {
-            const scaleRatio = Math.max(isNumber(hoverScale) ? hoverScale : 1.1, 3 / this._sizeY);
-            emphasisState.scaleX = this._sizeX * scaleRatio;
-            emphasisState.scaleY = this._sizeY * scaleRatio;
-        }
+        // null / undefined / true means to use default strategy.
+        // 0 / false / negative number / NaN / Infinity means no scale.
+        const scaleRatio =
+            hoverScale == null || hoverScale === true
+                ? Math.max(1.1, 3 / this._sizeY)
+                // PENDING: restrict hoverScale > 1? It seems unreasonable to scale down
+                : isFinite(hoverScale as number) && hoverScale > 0
+                    ? +hoverScale
+                    : 1;
+        // always set scale to allow resetting
+        emphasisState.scaleX = this._sizeX * scaleRatio;
+        emphasisState.scaleY = this._sizeY * scaleRatio;
+
         this.setSymbolScale(1);
 
         toggleHoverEmphasis(this, focus, blurScope, emphasisDisabled);
diff --git a/src/chart/line/LineSeries.ts b/src/chart/line/LineSeries.ts
index d46640b..9faf5c5 100644
--- a/src/chart/line/LineSeries.ts
+++ b/src/chart/line/LineSeries.ts
@@ -48,7 +48,7 @@
 interface LineStateOptionMixin {
     emphasis?: {
         focus?: DefaultEmphasisFocus
-        scale?: boolean
+        scale?: boolean | number
     }
 }
 
diff --git a/src/chart/line/LineView.ts b/src/chart/line/LineView.ts
index 493c17d..45414fb 100644
--- a/src/chart/line/LineView.ts
+++ b/src/chart/line/LineView.ts
@@ -947,8 +947,8 @@
                 if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(x, y)) {
                     return;
                 }
-                const zlevel = seriesModel.get('zlevel');
-                const z = seriesModel.get('z');
+                const zlevel = seriesModel.get('zlevel') || 0;
+                const z = seriesModel.get('z') || 0;
                 symbol = new SymbolClz(data, dataIndex);
                 symbol.x = x;
                 symbol.y = y;
diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts
index f306faf..fc22425 100644
--- a/src/chart/pie/PieSeries.ts
+++ b/src/chart/pie/PieSeries.ts
@@ -20,7 +20,7 @@
 import createSeriesDataSimply from '../helper/createSeriesDataSimply';
 import * as zrUtil from 'zrender/src/core/util';
 import * as modelUtil from '../../util/model';
-import { getPercentWithPrecision } from '../../util/number';
+import { getPercentSeats } from '../../util/number';
 import { makeSeriesEncodeForNameBased } from '../../data/helper/sourceHelper';
 import LegendVisualProvider from '../../visual/LegendVisualProvider';
 import SeriesModel from '../../model/Series';
@@ -133,6 +133,8 @@
 
     static type = 'series.pie' as const;
 
+    seats: number[];
+
     /**
      * @overwrite
      */
@@ -159,31 +161,25 @@
      * @overwrite
      */
     getInitialData(this: PieSeriesModel): SeriesData {
-        return createSeriesDataSimply(this, {
+        const data = createSeriesDataSimply(this, {
             coordDimensions: ['value'],
             encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this)
         });
+        const valueList:number[] = [];
+        data.each(data.mapDimension('value'), function (value: number) {
+            valueList.push(value);
+        });
+
+        this.seats = getPercentSeats(valueList, data.hostModel.get('percentPrecision'));
+        return data;
     }
 
     /**
      * @overwrite
      */
     getDataParams(dataIndex: number): PieCallbackDataParams {
-        const data = this.getData();
         const params = super.getDataParams(dataIndex) as PieCallbackDataParams;
-        // FIXME toFixed?
-
-        const valueList: number[] = [];
-        data.each(data.mapDimension('value'), function (value: number) {
-            valueList.push(value);
-        });
-
-        params.percent = getPercentWithPrecision(
-            valueList,
-            dataIndex,
-            data.hostModel.get('percentPrecision')
-        );
-
+        params.percent = this.seats[dataIndex];
         params.$vars.push('percent');
         return params;
     }
diff --git a/src/chart/pie/labelLayout.ts b/src/chart/pie/labelLayout.ts
index 9aaf1bf..0c90908 100644
--- a/src/chart/pie/labelLayout.ts
+++ b/src/chart/pie/labelLayout.ts
@@ -394,7 +394,8 @@
 
         if (Math.abs(sectorShape.endAngle - sectorShape.startAngle) < minShowLabelRadian) {
             each(label.states, setNotShow);
-            label.ignore = true;
+            each(labelLine.states, setNotShow);
+            label.ignore = labelLine.ignore = true;
             return;
         }
 
diff --git a/src/chart/scatter/ScatterSeries.ts b/src/chart/scatter/ScatterSeries.ts
index 129b88c..5e2995e 100644
--- a/src/chart/scatter/ScatterSeries.ts
+++ b/src/chart/scatter/ScatterSeries.ts
@@ -50,7 +50,7 @@
 interface ScatterStatesOptionMixin {
     emphasis?: {
         focus?: DefaultEmphasisFocus
-        scale?: boolean
+        scale?: boolean | number
     }
 }
 
@@ -163,4 +163,4 @@
 
 }
 
-export default ScatterSeriesModel;
\ No newline at end of file
+export default ScatterSeriesModel;
diff --git a/src/chart/tree/treeAction.ts b/src/chart/tree/treeAction.ts
index 2589d3e..3587799 100644
--- a/src/chart/tree/treeAction.ts
+++ b/src/chart/tree/treeAction.ts
@@ -17,7 +17,7 @@
 * under the License.
 */
 
-import {updateCenterAndZoom, RoamPaylod} from '../../action/roamHelper';
+import {updateCenterAndZoom, RoamPayload} from '../../action/roamHelper';
 import { Payload } from '../../util/types';
 import TreeSeriesModel from './TreeSeries';
 import GlobalModel from '../../model/Global';
@@ -52,7 +52,7 @@
         // the layout. So don't need to go through the whole update process, such
         // as 'dataPrcocess', 'coordSystemUpdate', 'layout' and so on.
         update: 'none'
-    }, function (payload: RoamPaylod, ecModel: GlobalModel, api: ExtensionAPI) {
+    }, function (payload: RoamPayload, ecModel: GlobalModel, api: ExtensionAPI) {
         ecModel.eachComponent({
             mainType: 'series', subType: 'tree', query: payload
         }, function (seriesModel: TreeSeriesModel) {
@@ -67,4 +67,4 @@
         });
     });
 
-}
\ No newline at end of file
+}
diff --git a/src/chart/treemap/Breadcrumb.ts b/src/chart/treemap/Breadcrumb.ts
index 6dd35c5..0875c4a 100644
--- a/src/chart/treemap/Breadcrumb.ts
+++ b/src/chart/treemap/Breadcrumb.ts
@@ -29,7 +29,8 @@
 import Element from 'zrender/src/Element';
 import Model from '../../model/Model';
 import { convertOptionIdName } from '../../util/model';
-import { Z2_EMPHASIS_LIFT } from '../../util/states';
+import { toggleHoverEmphasis, Z2_EMPHASIS_LIFT } from '../../util/states';
+import { createTextStyle } from '../../label/labelStyle';
 
 const TEXT_PADDING = 8;
 const ITEM_GAP = 8;
@@ -55,6 +56,7 @@
 }
 
 type BreadcrumbItemStyleModel = Model<TreemapSeriesOption['breadcrumb']['itemStyle']>;
+type BreadcrumbEmphasisItemStyleModel = Model<TreemapSeriesOption['breadcrumb']['emphasis']>;
 type BreadcrumbTextStyleModel = Model<TreemapSeriesOption['breadcrumb']['itemStyle']['textStyle']>;
 
 class Breadcrumb {
@@ -81,8 +83,9 @@
         }
 
         const normalStyleModel = model.getModel('itemStyle');
-        // let emphasisStyleModel = model.getModel('emphasis.itemStyle');
+        const emphasisModel = model.getModel('emphasis');
         const textStyleModel = normalStyleModel.getModel('textStyle');
+        const emphasisTextStyleModel = emphasisModel.getModel(['itemStyle', 'textStyle']);
 
         const layoutParam: LayoutParam = {
             pos: {
@@ -101,7 +104,10 @@
         };
 
         this._prepare(targetNode, layoutParam, textStyleModel);
-        this._renderContent(seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect);
+        this._renderContent(
+            seriesModel, layoutParam, normalStyleModel,
+            emphasisModel, textStyleModel, emphasisTextStyleModel, onSelect
+        );
 
         layout.positionElement(thisGroup, layoutParam.pos, layoutParam.box);
     }
@@ -134,7 +140,9 @@
         seriesModel: TreemapSeriesModel,
         layoutParam: LayoutParam,
         normalStyleModel: BreadcrumbItemStyleModel,
+        emphasisModel: BreadcrumbEmphasisItemStyleModel,
         textStyleModel: BreadcrumbTextStyleModel,
+        emphasisTextStyleModel: BreadcrumbTextStyleModel,
         onSelect: OnSelectCallback
     ) {
         // Start rendering.
@@ -144,6 +152,7 @@
         const availableSize = layout.getAvailableSize(layoutParam.pos, layoutParam.box);
         let totalWidth = layoutParam.totalWidth;
         const renderList = layoutParam.renderList;
+        const emphasisItemStyle = emphasisModel.getModel('itemStyle').getItemStyle();
 
         for (let i = renderList.length - 1; i >= 0; i--) {
             const item = renderList[i];
@@ -172,11 +181,7 @@
                     }
                 ),
                 textContent: new graphic.Text({
-                    style: {
-                        text,
-                        fill: textStyleModel.getTextColor(),
-                        font: textStyleModel.getFont()
-                    }
+                    style: createTextStyle(textStyleModel, { text })
                 }),
                 textConfig: {
                     position: 'inside'
@@ -185,7 +190,11 @@
                 onclick: curry(onSelect, itemNode)
             });
             (el as ECElement).disableLabelAnimation = true;
-
+            el.getTextContent().ensureState('emphasis').style = createTextStyle(emphasisTextStyleModel, { text });
+            el.ensureState('emphasis').style = emphasisItemStyle;
+            toggleHoverEmphasis(
+                el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')
+            );
             this.group.add(el);
 
             packEventData(el, seriesModel, itemNode);
diff --git a/src/chart/treemap/TreemapSeries.ts b/src/chart/treemap/TreemapSeries.ts
index 15c0a5e..2e5f228 100644
--- a/src/chart/treemap/TreemapSeries.ts
+++ b/src/chart/treemap/TreemapSeries.ts
@@ -36,7 +36,8 @@
     DecalObject,
     SeriesLabelOption,
     DefaultEmphasisFocus,
-    AriaOptionMixin
+    AriaOptionMixin,
+    BlurScope
 } from '../../util/types';
 import GlobalModel from '../../model/Global';
 import { LayoutRect } from '../../util/layout';
@@ -202,6 +203,9 @@
         itemStyle?: BreadcrumbItemStyleOption
 
         emphasis?: {
+            disabled?: boolean
+            focus?: DefaultEmphasisFocus
+            blurScope?: BlurScope
             itemStyle?: BreadcrumbItemStyleOption
         }
     }
@@ -265,6 +269,11 @@
                 textStyle: {
                     color: '#fff'
                 }
+            },
+            emphasis: {
+                itemStyle: {
+                    color: 'rgba(0,0,0,0.9)' //'#5793f3',
+                }
             }
         },
         label: {
diff --git a/src/component/axis/AxisBuilder.ts b/src/component/axis/AxisBuilder.ts
index 5ed1ed3..b0e31e0 100644
--- a/src/component/axis/AxisBuilder.ts
+++ b/src/component/axis/AxisBuilder.ts
@@ -255,6 +255,7 @@
         const matrix = transformGroup.transform;
         const pt1 = [extent[0], 0];
         const pt2 = [extent[1], 0];
+        const inverse = pt1[0] > pt2[0];
         if (matrix) {
             v2ApplyTransform(pt1, pt1, matrix);
             v2ApplyTransform(pt2, pt2, matrix);
@@ -327,10 +328,11 @@
                     // Calculate arrow position with offset
                     const r = point.r + point.offset;
 
+                    const pt = inverse ? pt2 : pt1;
                     symbol.attr({
                         rotation: point.rotate,
-                        x: pt1[0] + r * Math.cos(opt.rotation),
-                        y: pt1[1] - r * Math.sin(opt.rotation),
+                        x: pt[0] + r * Math.cos(opt.rotation),
+                        y: pt[1] - r * Math.sin(opt.rotation),
                         silent: true,
                         z2: 11
                     });
diff --git a/src/component/geo/install.ts b/src/component/geo/install.ts
index d18aa18..3bf9e3e 100644
--- a/src/component/geo/install.ts
+++ b/src/component/geo/install.ts
@@ -23,7 +23,7 @@
 import { ActionInfo } from '../../util/types';
 import { each } from 'zrender/src/core/util';
 import GlobalModel from '../../model/Global';
-import { updateCenterAndZoom, RoamPaylod } from '../../action/roamHelper';
+import { updateCenterAndZoom, RoamPayload } from '../../action/roamHelper';
 import MapSeries from '../../chart/map/MapSeries';
 import GeoView from './GeoView';
 import geoSourceManager from '../../coord/geo/geoSourceManager';
@@ -115,7 +115,7 @@
         type: 'geoRoam',
         event: 'geoRoam',
         update: 'updateTransform'
-    }, function (payload: RoamPaylod, ecModel: GlobalModel, api: ExtensionAPI) {
+    }, function (payload: RoamPayload, ecModel: GlobalModel, api: ExtensionAPI) {
         const componentType = payload.componentType || 'series';
 
         ecModel.eachComponent(
@@ -147,4 +147,4 @@
             }
         );
     });
-}
\ No newline at end of file
+}
diff --git a/src/component/helper/MapDraw.ts b/src/component/helper/MapDraw.ts
index 5915619..5296014 100644
--- a/src/component/helper/MapDraw.ts
+++ b/src/component/helper/MapDraw.ts
@@ -820,7 +820,7 @@
     dataIdx: number
 ): void {
     // setItemGraphicEl, setHoverStyle after all polygons and labels
-    // are added to the rigionGroup
+    // are added to the regionGroup
     if (viewBuildCtx.data) {
         // FIXME: when series-map use a SVG map, and there are duplicated name specified
         // on different SVG elements, after `data.setItemGraphicEl(...)`:
@@ -832,7 +832,7 @@
         viewBuildCtx.data.setItemGraphicEl(dataIdx, eventTrigger);
     }
     // series-map will not trigger "geoselectchange" no matter it is
-    // based on a declared geo component. Becuause series-map will
+    // based on a declared geo component. Because series-map will
     // trigger "selectchange". If it trigger both the two events,
     // If users call `chart.dispatchAction({type: 'toggleSelect'})`,
     // it not easy to also fire event "geoselectchanged".
diff --git a/src/component/marker/MarkAreaView.ts b/src/component/marker/MarkAreaView.ts
index dcaa4b1..785d107 100644
--- a/src/component/marker/MarkAreaView.ts
+++ b/src/component/marker/MarkAreaView.ts
@@ -91,7 +91,7 @@
     return result;
 };
 
-function isInifinity(val: ScaleDataValue) {
+function isInfinity(val: ScaleDataValue) {
     return !isNaN(val as number) && !isFinite(val as number);
 }
 
@@ -103,7 +103,7 @@
     coordSys: CoordinateSystem
 ) {
     const otherDimIndex = 1 - dimIndex;
-    return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex]);
+    return isInfinity(fromCoord[otherDimIndex]) && isInfinity(toCoord[otherDimIndex]);
 }
 
 function markAreaFilter(coordSys: CoordinateSystem, item: MarkAreaMergedItemOption) {
@@ -164,7 +164,7 @@
     else {
         // Chart like bar may have there own marker positioning logic
         if (seriesModel.getMarkerPosition) {
-            // Use the getMarkerPoisition
+            // Use the getMarkerPosition
             point = seriesModel.getMarkerPosition(
                 data.getValues(dims, idx)
             );
@@ -182,10 +182,10 @@
             const yAxis = coordSys.getAxis('y') as Axis2D;
             const x = data.get(dims[0], idx) as number;
             const y = data.get(dims[1], idx) as number;
-            if (isInifinity(x)) {
+            if (isInfinity(x)) {
                 point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]);
             }
-            else if (isInifinity(y)) {
+            else if (isInfinity(y)) {
                 point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]);
             }
         }
diff --git a/src/component/marker/MarkLineView.ts b/src/component/marker/MarkLineView.ts
index d3d6a66..2c6d5e5 100644
--- a/src/component/marker/MarkLineView.ts
+++ b/src/component/marker/MarkLineView.ts
@@ -154,7 +154,7 @@
     return normalizedItem;
 };
 
-function isInifinity(val: ScaleDataValue) {
+function isInfinity(val: ScaleDataValue) {
     return !isNaN(val as number) && !isFinite(val as number);
 }
 
@@ -167,7 +167,7 @@
 ) {
     const otherDimIndex = 1 - dimIndex;
     const dimName = coordSys.dimensions[dimIndex];
-    return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex])
+    return isInfinity(fromCoord[otherDimIndex]) && isInfinity(toCoord[otherDimIndex])
         && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]);
 }
 
@@ -215,7 +215,7 @@
     else {
         // Chart like bar may have there own marker positioning logic
         if (seriesModel.getMarkerPosition) {
-            // Use the getMarkerPoisition
+            // Use the getMarkerPosition
             point = seriesModel.getMarkerPosition(
                 data.getValues(data.dimensions, idx)
             );
@@ -240,10 +240,10 @@
             const xAxis = coordSys.getAxis('x') as Axis2D;
             const yAxis = coordSys.getAxis('y') as Axis2D;
             const dims = coordSys.dimensions;
-            if (isInifinity(data.get(dims[0], idx))) {
+            if (isInfinity(data.get(dims[0], idx))) {
                 point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]);
             }
-            else if (isInifinity(data.get(dims[1], idx))) {
+            else if (isInfinity(data.get(dims[1], idx))) {
                 point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]);
             }
         }
diff --git a/src/component/marker/MarkPointView.ts b/src/component/marker/MarkPointView.ts
index d5e4fc1..3e4499c 100644
--- a/src/component/marker/MarkPointView.ts
+++ b/src/component/marker/MarkPointView.ts
@@ -51,7 +51,7 @@
         }
         // Chart like bar may have there own marker positioning logic
         else if (seriesModel.getMarkerPosition) {
-            // Use the getMarkerPoisition
+            // Use the getMarkerPosition
             point = seriesModel.getMarkerPosition(
                 mpData.getValues(mpData.dimensions, idx)
             );
diff --git a/src/component/marker/markerHelper.ts b/src/component/marker/markerHelper.ts
index 480a034..1616df4 100644
--- a/src/component/marker/markerHelper.ts
+++ b/src/component/marker/markerHelper.ts
@@ -191,7 +191,7 @@
     },
     item: MarkerPositionOption
 ) {
-    // Alwalys return true if there is no coordSys
+    // Always return true if there is no coordSys
     return (coordSys && coordSys.containData && item.coord && !hasXOrY(item))
         ? coordSys.containData(item.coord) : true;
 }
@@ -204,7 +204,7 @@
     item1: MarkerPositionOption,
     item2: MarkerPositionOption
 ) {
-    // Alwalys return true if there is no coordSys
+    // Always return true if there is no coordSys
     return (coordSys && coordSys.containZone && item1.coord && item2.coord && !hasXOrY(item1) && !hasXOrY(item2))
         ? coordSys.containZone(item1.coord, item2.coord) : true;
 }
diff --git a/src/component/visualMap/ContinuousView.ts b/src/component/visualMap/ContinuousView.ts
index ac31cd0..9886945 100644
--- a/src/component/visualMap/ContinuousView.ts
+++ b/src/component/visualMap/ContinuousView.ts
@@ -37,8 +37,9 @@
 import { setAsHighDownDispatcher } from '../../util/states';
 import { createSymbol } from '../../util/symbol';
 import ZRImage from 'zrender/src/graphic/Image';
-import { getECData } from '../../util/innerStore';
+import { ECData, getECData } from '../../util/innerStore';
 import { createTextStyle } from '../../label/labelStyle';
+import { findEventDispatcher } from '../../util/event';
 
 const linearMap = numberUtil.linearMap;
 const each = zrUtil.each;
@@ -816,16 +817,23 @@
     }
 
     private _hoverLinkFromSeriesMouseOver(e: ElementEvent) {
-        const el = e.target;
-        const visualMapModel = this.visualMapModel;
+        let ecData: ECData;
 
-        if (!el || getECData(el).dataIndex == null) {
+        findEventDispatcher(e.target, target => {
+            const currECData = getECData(target);
+            if (currECData.dataIndex != null) {
+                ecData = currECData;
+                return true;
+            }
+        }, true);
+
+        if (!ecData) {
             return;
         }
-        const ecData = getECData(el);
 
         const dataModel = this.ecModel.getSeriesByIndex(ecData.seriesIndex);
 
+        const visualMapModel = this.visualMapModel;
         if (!visualMapModel.isTargetSeries(dataModel)) {
             return;
         }
@@ -947,4 +955,4 @@
     return orient === 'vertical' ? 'ns-resize' : 'ew-resize';
 }
 
-export default ContinuousView;
\ No newline at end of file
+export default ContinuousView;
diff --git a/src/coord/geo/geoCreator.ts b/src/coord/geo/geoCreator.ts
index 1d4bd37..f51700a 100644
--- a/src/coord/geo/geoCreator.ts
+++ b/src/coord/geo/geoCreator.ts
@@ -27,15 +27,14 @@
 import ExtensionAPI from '../../core/ExtensionAPI';
 import { CoordinateSystemCreator } from '../CoordinateSystem';
 import { NameMap } from './geoTypes';
-import SeriesModel from '../../model/Series';
 import { SeriesOption, SeriesOnGeoOptionMixin } from '../../util/types';
 import { Dictionary } from 'zrender/src/core/types';
-import GlobalModel from '../../model/Global';
-import ComponentModel from '../../model/Component';
-import { Model } from '../../echarts.all';
+import type Model from '../../model/Model';
+import type GlobalModel from '../../model/Global';
+import type SeriesModel from '../../model/Series';
+import type ComponentModel from '../../model/Component';
 import * as vector from 'zrender/src/core/vector';
 
-
 export type resizeGeoType = typeof resizeGeo;
 
 /**
diff --git a/src/coord/single/Single.ts b/src/coord/single/Single.ts
index 4632190..c9226b5 100644
--- a/src/coord/single/Single.ts
+++ b/src/coord/single/Single.ts
@@ -140,7 +140,7 @@
 
         const isHorizontal = axis.isHorizontal();
         const extent = isHorizontal ? [0, rect.width] : [0, rect.height];
-        const idx = axis.reverse ? 1 : 0;
+        const idx = axis.inverse ? 1 : 0;
 
         axis.setExtent(extent[idx], extent[1 - idx]);
 
diff --git a/src/coord/single/SingleAxis.ts b/src/coord/single/SingleAxis.ts
index 6009149..ff2db92 100644
--- a/src/coord/single/SingleAxis.ts
+++ b/src/coord/single/SingleAxis.ts
@@ -43,8 +43,6 @@
 
     orient: LayoutOrient;
 
-    reverse: boolean;
-
     coordinateSystem: Single;
 
     model: SingleAxisModel;
diff --git a/src/data/DataStore.ts b/src/data/DataStore.ts
index b839d8b..bb9dcf1 100644
--- a/src/data/DataStore.ts
+++ b/src/data/DataStore.ts
@@ -448,7 +448,7 @@
     }
 
     getValues(idx: number): ParsedValue[];
-    getValues(dimensions: readonly DimensionIndex[], idx?: number): ParsedValue[]
+    getValues(dimensions: readonly DimensionIndex[], idx?: number): ParsedValue[];
     getValues(dimensions: readonly DimensionIndex[] | number, idx?: number): ParsedValue[] {
         const values = [];
         let dimArr: DimensionIndex[] = [];
diff --git a/src/data/Graph.ts b/src/data/Graph.ts
index a250ad9..f7939a5 100644
--- a/src/data/Graph.ts
+++ b/src/data/Graph.ts
@@ -360,8 +360,8 @@
     }
 
     // TODO: TYPE Same type with Model#getModel
-    getModel<T = unknown>(): Model<T>
-    getModel<T = unknown, S extends keyof T= keyof T>(path: S): Model<T[S]>
+    getModel<T = unknown>(): Model<T>;
+    getModel<T = unknown, S extends keyof T= keyof T>(path: S): Model<T[S]>;
     getModel<T = unknown>(path?: string): Model {
         if (this.dataIndex < 0) {
             return;
@@ -410,8 +410,8 @@
         this.dataIndex = dataIndex == null ? -1 : dataIndex;
     }
 
-    getModel<T = unknown>(): Model<T>
-    getModel<T = unknown, S extends keyof T= keyof T>(path: S): Model<T[S]>
+    getModel<T = unknown>(): Model<T>;
+    getModel<T = unknown, S extends keyof T= keyof T>(path: S): Model<T[S]>;
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     getModel<T = unknown>(path?: string): Model {
         if (this.dataIndex < 0) {
diff --git a/src/data/Tree.ts b/src/data/Tree.ts
index ad7ae42..8467084 100644
--- a/src/data/Tree.ts
+++ b/src/data/Tree.ts
@@ -98,9 +98,9 @@
      * @param cb If in preorder and return false,
      *                      its subtree will not be visited.
      */
-    eachNode<Ctx>(options: TreeTraverseOrder, cb: TreeTraverseCallback<Ctx>, context?: Ctx): void
-    eachNode<Ctx>(options: TreeTraverseOption, cb: TreeTraverseCallback<Ctx>, context?: Ctx): void
-    eachNode<Ctx>(cb: TreeTraverseCallback<Ctx>, context?: Ctx): void
+    eachNode<Ctx>(options: TreeTraverseOrder, cb: TreeTraverseCallback<Ctx>, context?: Ctx): void;
+    eachNode<Ctx>(options: TreeTraverseOption, cb: TreeTraverseCallback<Ctx>, context?: Ctx): void;
+    eachNode<Ctx>(cb: TreeTraverseCallback<Ctx>, context?: Ctx): void;
     eachNode<Ctx>(
         options: TreeTraverseOrder | TreeTraverseOption | TreeTraverseCallback<Ctx>,
         cb?: TreeTraverseCallback<Ctx> | Ctx,
@@ -225,7 +225,7 @@
         return this.hostTree.data.getItemLayout(this.dataIndex);
     }
 
-    getModel<T = unknown>(): Model<T>
+    getModel<T = unknown>(): Model<T>;
     // @depcrecated
     // getModel<T = unknown, S extends keyof T = keyof T>(path: S): Model<T[S]>
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -251,8 +251,8 @@
      *  });
      */
     // TODO: TYPE
-    setVisual(key: string, value: any): void
-    setVisual(obj: Dictionary<any>): void
+    setVisual(key: string, value: any): void;
+    setVisual(obj: Dictionary<any>): void;
     setVisual(key: string | Dictionary<any>, value?: any) {
         this.dataIndex >= 0
             && this.hostTree.data.setItemVisual(this.dataIndex, key as any, value);
@@ -353,9 +353,9 @@
      * @param cb
      * @param context
      */
-    eachNode<Ctx>(options: TreeTraverseOrder, cb: TreeTraverseCallback<Ctx>, context?: Ctx): void
-    eachNode<Ctx>(options: TreeTraverseOption, cb: TreeTraverseCallback<Ctx>, context?: Ctx): void
-    eachNode<Ctx>(cb: TreeTraverseCallback<Ctx>, context?: Ctx): void
+    eachNode<Ctx>(options: TreeTraverseOrder, cb: TreeTraverseCallback<Ctx>, context?: Ctx): void;
+    eachNode<Ctx>(options: TreeTraverseOption, cb: TreeTraverseCallback<Ctx>, context?: Ctx): void;
+    eachNode<Ctx>(cb: TreeTraverseCallback<Ctx>, context?: Ctx): void;
     eachNode<Ctx>(
         options: TreeTraverseOrder | TreeTraverseOption | TreeTraverseCallback<Ctx>,
         cb?: TreeTraverseCallback<Ctx> | Ctx,
diff --git a/src/i18n/langUA.ts b/src/i18n/langUA.ts
new file mode 100644
index 0000000..38b2e10
--- /dev/null
+++ b/src/i18n/langUA.ts
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+/**
+ * Language: Ukrainian.
+ */
+
+export default {
+    time: {
+        month: [
+            'Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень',
+            'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень'
+        ],
+        monthAbbr: [
+            'Січ', 'Лют', 'Бер', 'Кві', 'Тра', 'Чер',
+            'Лип', 'Сер', 'Вер', 'Жов', 'Лис', 'Гру'
+        ],
+        dayOfWeek: [
+            'Неділя', 'Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П\'ятниця', 'Субота'
+        ],
+        dayOfWeekAbbr: [
+            'нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'
+        ]
+    },
+    legend: {
+        selector: {
+            all: 'Все',
+            inverse: 'Обернути'
+        }
+    },
+    toolbox: {
+        brush: {
+            title: {
+                rect: 'Выділити область',
+                polygon: 'Інструмент «Ласо»',
+                lineX: 'Горизонтальне виділення',
+                lineY: 'Вертикальне виділення',
+                keep: 'Залишити обране',
+                clear: 'Очистити обране'
+            }
+        },
+        dataView: {
+            title: 'Дані',
+            lang: ['Дані', 'Закрити', 'Оновити']
+        },
+        dataZoom: {
+            title: {
+                zoom: 'Збільшити',
+                back: 'Скасувати збільшення'
+            }
+        },
+        magicType: {
+            title: {
+                line: 'Переключитися на лінійний графік',
+                bar: 'Переключитися на стовпчикову діаграму',
+                stack: 'Стопка',
+                tiled: 'Плитка'
+            }
+        },
+        restore: {
+            title: 'Відновити'
+        },
+        saveAsImage: {
+            title: 'Зберегти зображення',
+            lang: ['Правий клік, щоб зберегти зображення']
+        }
+    },
+    series: {
+        typeNames: {
+            pie: 'Кругова діаграма',
+            bar: 'Стовпчикова діаграма',
+            line: 'Лінійний графік',
+            scatter: 'Точкова діаграма',
+            effectScatter: 'Точкова діаграма з хвилями',
+            radar: 'Пелюсткова діаграма',
+            tree: 'Дерево',
+            treemap: 'Пласке дерево',
+            boxplot: 'Ящик з вусами',
+            candlestick: 'Свічний графік',
+            k: 'Графік К-ліній',
+            heatmap: 'Теплова мапа',
+            map: 'Мапа',
+            parallel: 'Діаграма паралельних координат',
+            lines: 'Лінійний граф',
+            graph: 'Граф отношений',
+            sankey: 'Діаграма Санкей',
+            funnel: 'Воронкообразна діаграма',
+            gauge: 'Шкала',
+            pictorialBar: 'Стовпчик-картинка',
+            themeRiver: 'Тематична ріка',
+            sunburst: 'Сонячне проміння'
+        }
+    },
+    aria: {
+        general: {
+            withTitle: 'Це графік, що відрображує "{title}"',
+            withoutTitle: 'Це графік'
+        },
+        series: {
+            single: {
+                prefix: '',
+                withName: ' з типом {seriesType} та іменем {seriesName}.',
+                withoutName: ' з типом {seriesType}.'
+            },
+            multiple: {
+                prefix: '. Він складається з {seriesCount} серій.',
+                withName:
+                    ' Серія {seriesId} має тип {seriesType} та відображає {seriesName}.',
+                withoutName: ' Серія {seriesId} має тип {seriesType}.',
+                separator: {
+                    middle: '',
+                    end: ''
+                }
+            }
+        },
+        data: {
+            allData: 'Дані такі: ',
+            partialData: 'Перші {displayCnt} елементів: ',
+            withName: 'значення для {name} — {value}',
+            withoutName: '{value}',
+            separator: {
+                middle: ', ',
+                end: '. '
+            }
+        }
+    }
+};
diff --git a/src/model/Global.ts b/src/model/Global.ts
index d4777a4..cadc98b 100644
--- a/src/model/Global.ts
+++ b/src/model/Global.ts
@@ -696,17 +696,17 @@
     eachComponent<T>(
         cb: EachComponentAllCallback,
         context?: T
-    ): void
+    ): void;
     eachComponent<T>(
         mainType: string,
         cb: EachComponentInMainTypeCallback,
         context?: T
-    ): void
+    ): void;
     eachComponent<T>(
         mainType: QueryConditionKindA,
         cb: EachComponentInMainTypeCallback,
         context?: T
-    ): void
+    ): void;
     eachComponent<T>(
         mainType: string | QueryConditionKindA | EachComponentAllCallback,
         cb?: EachComponentInMainTypeCallback | T,
diff --git a/src/util/number.ts b/src/util/number.ts
index aab32f1..bf5b256 100644
--- a/src/util/number.ts
+++ b/src/util/number.ts
@@ -233,11 +233,27 @@
         return 0;
     }
 
+    const seats = getPercentSeats(valueList, precision);
+
+    return seats[idx] || 0;
+}
+
+/**
+ * Get a data of given precision, assuring the sum of percentages
+ * in valueList is 1.
+ * The largest remainer method is used.
+ * https://en.wikipedia.org/wiki/Largest_remainder_method
+ *
+ * @param valueList a list of all data
+ * @param precision integer number showing digits of precision
+ * @return {Array<number>}
+ */
+export function getPercentSeats(valueList: number[], precision: number): number[] {
     const sum = zrUtil.reduce(valueList, function (acc, val) {
         return acc + (isNaN(val) ? 0 : val);
     }, 0);
     if (sum === 0) {
-        return 0;
+        return [];
     }
 
     const digits = Math.pow(10, precision);
@@ -275,8 +291,9 @@
         remainder[maxId] = 0;
         ++currentSum;
     }
-
-    return seats[idx] / digits;
+    return zrUtil.map(seats, function (seat) {
+        return seat / digits;
+    });
 }
 
 /**
diff --git a/src/visual/VisualMapping.ts b/src/visual/VisualMapping.ts
index 8898bc7..f964e3f 100644
--- a/src/visual/VisualMapping.ts
+++ b/src/visual/VisualMapping.ts
@@ -377,13 +377,13 @@
         }
     }
 
-    static mapVisual<Ctx, T>(visual: T, callback: (visual: T, key?: string | number) => T, context?: Ctx): T
-    static mapVisual<Ctx, T>(visual: T[], callback: (visual: T, key?: string | number) => T[], context?: Ctx): T[]
+    static mapVisual<Ctx, T>(visual: T, callback: (visual: T, key?: string | number) => T, context?: Ctx): T;
+    static mapVisual<Ctx, T>(visual: T[], callback: (visual: T, key?: string | number) => T[], context?: Ctx): T[];
     static mapVisual<Ctx, T>(
         visual: Dictionary<T>,
         callback: (visual: T, key?: string | number) => Dictionary<T>,
         context?: Ctx
-    ): Dictionary<T>
+    ): Dictionary<T>;
     static mapVisual<Ctx, T>(
         visual: T | T[] | Dictionary<T>,
         callback: (visual: T, key?: string | number) => T | T[] | Dictionary<T>,
diff --git a/test/axis-arrow.html b/test/axis-arrow.html
index 4194631..d6a4a5d 100644
--- a/test/axis-arrow.html
+++ b/test/axis-arrow.html
@@ -23,19 +23,18 @@
         <meta charset="utf-8">
         <script src="lib/simpleRequire.js"></script>
         <script src="lib/config.js"></script>
+        <script src="lib/testHelper.js"></script>
         <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <link rel="stylesheet" href="lib/reset.css" />
     </head>
     <body>
         <style>
-            html, body, #main, .chart {
-                width: 100%;
-            }
-
-            .chart {
-                height: 300px;
+            .test-title[title=null] {
+                display: none;
             }
         </style>
-        <div id="main"></div>
+        <div id="main0"></div>
+        <div id="main1"></div>
         <script>
 
             require([
@@ -57,7 +56,7 @@
                     }]
                 }, {
                     title: {
-                        text: 'x: ["none", "arrow"]; y: "arrow" of size 30x20'
+                        text: 'x: ["none", "arrow"] symbolOffset: 10; y: "arrow" of size 30x20 symbolOffset: [-10, 10]'
                     },
                     xAxis: {
                         data: ['a', 'b', 'c', 'd', 'e'],
@@ -71,6 +70,7 @@
                     },
                     yAxis: {
                         axisLine: {
+                            show: true,
                             symbol: 'arrow',
                             symbolSize: [30, 20],
                             symbolOffset: [-10, 10]
@@ -82,7 +82,7 @@
                     }]
                 }, {
                     title: {
-                        text: 'x: "none"; y: ["none", "arrow"], inversed'
+                        text: 'x: "none"; y: ["none", "arrow"] symbolOffset: [10, -10] inversed '
                     },
                     xAxis: {
                         data: ['a', 'b', 'c', 'd', 'e'],
@@ -92,10 +92,11 @@
                     },
                     yAxis: {
                         axisLine: {
+                            show: true,
                             symbol: ['none', 'arrow'],
                             symbolOffset: [10, -10]
                         },
-                        inversed: true
+                        inverse: true
                     },
                     series: [{
                         type: 'line',
@@ -103,18 +104,59 @@
                     }]
                 }];
 
-                var main = document.getElementById('main');
+                var main = document.getElementById('main0');
                 for (var i = 0; i < options.length; ++i) {
                     var container = document.createElement('div');
-                    container.setAttribute('class', 'chart');
                     main.appendChild(container);
 
-                    var chart = echarts.init(container);
-                    chart.setOption(options[i]);
+                    testHelper.create(echarts, container, {
+                        option: options[i]
+                    });
                 }
 
             });
 
         </script>
+
+        <script>
+            require(['echarts'], function (echarts) {
+                var option = {
+                    dataset: {
+                        source: [
+                            ['水果', '价格'],
+                            ['苹果', 1],
+                            ['香蕉', 0.5],
+                            ['梨', 2],
+                            ['菠萝', 4]
+                        ]
+                    },
+                    xAxis: [{
+                        type: 'category',
+                        inverse: true,
+                        axisLine: {
+                            symbol: 'arrow'
+                        }
+                    }],
+                    yAxis: {
+                        inverse: true,
+                        axisLine: {
+                            show: true,
+                            symbol: 'arrow'
+                        }
+                    },
+                    series: [{
+                        type: 'bar'
+                    }]
+                };
+
+                var chart = testHelper.create(echarts, 'main1', {
+                    title: [
+                        'The arrows of axis line should be inverted when the axis is inverse',
+                        'Case from https://github.com/apache/echarts/issues/17325'
+                    ],
+                    option: option
+                });
+            })
+        </script>
     </body>
 </html>
diff --git a/test/custom-update.html b/test/custom-update.html
new file mode 100644
index 0000000..2015c4b
--- /dev/null
+++ b/test/custom-update.html
@@ -0,0 +1,229 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+
+
+<html>
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <script src="lib/simpleRequire.js"></script>
+        <script src="lib/config.js"></script>
+        <script src="lib/jquery.min.js"></script>
+        <script src="lib/facePrint.js"></script>
+        <script src="lib/testHelper.js"></script>
+        <!-- <script src="ut/lib/canteen.js"></script> -->
+        <link rel="stylesheet" href="lib/reset.css" />
+    </head>
+    <body>
+        <style>
+        </style>
+
+
+
+        <div id="main0"></div>
+        <div id="main1"></div>
+        <div id="main2"></div>
+        <div id="main3"></div>
+
+
+
+
+
+
+        <script>
+        require([
+            'echarts',
+            // 'map/js/china',
+            // './data/nutrients.json'
+        ], function (echarts) {
+            function createCase(isTestingNull, hasAnimation) {
+                var option;
+                var cellSize = [50, 51];
+                var isFirst = true;
+                var clickTimes = 0;
+
+                option = {
+                    calendar: [
+                        {
+                        orient: 'vertical',
+                        cellSize: cellSize,
+                        yearLabel: {
+                            show: false
+                        },
+                        monthLabel: {
+                            show: false
+                        },
+                        range: ['2022-1']
+                        }
+                    ],
+                    series: [
+                        {
+                            type: 'custom',
+                            universalTransition: {
+                                enabled: false
+                            },
+                            name: 'a',
+                            coordinateSystem: 'calendar',
+                            animation: hasAnimation ? 3000 : 0,
+                            data: [
+                                ['2022-01-16', 'e', false]
+                            ],
+                            renderItem: (params, api) => {
+                                const date = api.value(0);
+                                const cellPoint = api.coord(date);
+                                const xPos = cellPoint[0] - cellSize[0] / 2;
+                                const yPos = cellPoint[1] - cellSize[1] / 2;
+                                const name = api.value(1);
+                                const cellWidth = params.coordSys.cellWidth;
+                                const position = [xPos, yPos];
+                                const rect = {
+                                    type: 'rect',
+                                    shape: {
+                                        x: 0,
+                                        y: 0,
+                                        width: cellWidth,
+                                        height: 15
+                                    },
+                                    position,
+                                    style: {
+                                        fill: api.value(2) ? '#eee' : '#6ee'
+                                    },
+                                    textContent: {
+                                        style: {
+                                        text: name,
+                                        fill: '#888',
+                                        overflow: 'truncate',
+                                        width: cellWidth,
+                                        height: 13,
+                                        y: 1
+                                        }
+                                    },
+                                    textConfig: {
+                                        position: 'insideLeft',
+                                        distance: 2
+                                    },
+                                    name: 'rect'
+                                };
+
+                                const borderLeft = api.value(2)
+                                    ? (isTestingNull ? null : {})
+                                    : {
+                                        type: 'rect',
+                                        shape: {
+                                            x: -20,
+                                            y: 0,
+                                            width: 20,
+                                            height: 15
+                                        },
+                                        position,
+                                        style: {
+                                            fill: 'red'
+                                        },
+                                        name: 'bar'
+                                    };
+
+                                const right = api.value(2)
+                                    ? {
+                                    type: 'circle',
+                                    shape: {
+                                        cx: cellWidth + 20,
+                                        cy: 20,
+                                        r: 30
+                                    },
+                                    position,
+                                    style: {
+                                        fill: 'transparent',
+                                        stroke: 'blue',
+                                    }
+                                }
+                                : {
+                                    type: 'circle',
+                                    shape: {
+                                        cx: cellWidth + 20,
+                                        cy: 20,
+                                        r: 15
+                                    },
+                                    position,
+                                    style: {
+                                        fill: 'red'
+                                    }
+                                };
+
+                                const group = {
+                                    type: 'group',
+                                    children: [rect, borderLeft, right]
+                                };
+                                return group;
+                            },
+                            silent: true,
+                            z: 2,
+                            legendHoverLink: true,
+                            clip: false,
+                            label: {},
+                            emphasis: { label: {} }
+                        }
+                    ]
+                };
+
+                var rendered = isTestingNull ? ' NOT' : '';
+                var chartId = (isTestingNull ? 2 : 0) + (hasAnimation ? 1 : 0);
+                var chart = testHelper.create(echarts, 'main' + chartId, {
+                    title: [
+                        'Update group with ' + (isTestingNull ? 'null' : '{}') + ' as new child',
+                        'Animation: ' + (hasAnimation ? 'true' : 'false'),
+                        'The red shapes should be' + rendered + ' rendered after "Update"'
+                    ],
+                    option: option,
+                    // height: 300,
+                    buttons: [{text: 'Update', onclick: function () {
+                        isFirst = false;
+                        var testId = clickTimes % 2;
+                        chart.setOption({
+                            calendar: {
+                                range: testId === 0 ? ['2022-02'] : ['2022-01']
+                            },
+                            series: [
+                            {
+                                type: 'custom',
+                                data: [
+                                    [
+                                        testId === 0 ? '2022-02-13' : '2022-01-16' ,
+                                        'e',
+                                        testId === 0
+                                    ]
+                                ]
+                            }
+                            ]
+                        });
+                        ++clickTimes;
+                    }}]
+                });
+            }
+
+            createCase(false, false);
+            createCase(true, false);
+            createCase(false, true);
+            createCase(true, true);
+        });
+        </script>
+
+
+    </body>
+</html>
diff --git a/test/custom.html b/test/custom.html
index 1485c8a..a8b727e 100644
--- a/test/custom.html
+++ b/test/custom.html
@@ -90,29 +90,37 @@
                     {name: 'GPU', color: '#72b362'}
                 ];
 
+                var renderCount = 0;
                 // Generate mock data
-                echarts.util.each(categories, function (category, index) {
-                    var baseTime = startTime;
-                    for (var i = 0; i < dataCount; i++) {
-                        var typeItem = types[Math.round(Math.random() * (types.length - 1))];
-                        var duration = Math.round(Math.random() * 10000);
-                        data.push({
-                            name: typeItem.name,
-                            value: [
-                                index,
-                                baseTime,
-                                baseTime += duration,
-                                duration
-                            ],
-                            itemStyle: {
-                                normal: {
-                                    color: typeItem.color
+                function updateData() {
+                    data = [];
+                    echarts.util.each(categories, function (category, index) {
+                        var baseTime = startTime;
+                        for (var i = 0; i < dataCount; i++) {
+                            var typeItem = types[Math.round(Math.random() * (types.length - 1))];
+                            var duration = Math.round(Math.random() * 10000);
+                            var isEven = renderCount % 2 === 0;
+                            data.push({
+                                name: typeItem.name,
+                                value: [
+                                    index,
+                                    baseTime,
+                                    isEven ? (baseTime += duration) : NaN,
+                                    duration
+                                ],
+                                itemStyle: {
+                                    normal: {
+                                        color: typeItem.color
+                                    }
                                 }
-                            }
-                        });
-                        baseTime += Math.round(Math.random() * 2000);
-                    }
-                });
+                            });
+                            isEven && (baseTime += Math.round(Math.random() * 2000));
+                        }
+                    });
+                    renderCount++;
+                }
+
+                updateData();
 
                 console.log(JSON.stringify({
                     startTime: startTime,
@@ -211,7 +219,26 @@
                     }]
                 };
 
-                testHelper.createChart(echarts, 'profile', option);
+                var chart = testHelper.create(echarts, 'profile', {
+                    option: option,
+                    title: [
+                        'The data should be cleared when clicking the **updateData** button firstly',
+                        'Should have no errors when clicking the **updateData** button once again'
+                    ],
+                    buttons: [
+                        {
+                            text: 'updateData',
+                            onclick: function () {
+                                updateData();
+                                chart.setOption({
+                                    series: [{
+                                        data: data
+                                    }]
+                                });
+                            }
+                        }
+                    ]
+                });
             });
         </script>
 
@@ -1398,4 +1425,4 @@
 
 
     </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/test/gauge-case.html b/test/gauge-case.html
index 94f8bd5..cdbf852 100644
--- a/test/gauge-case.html
+++ b/test/gauge-case.html
@@ -65,6 +65,10 @@
                         show: true,
                         width: 18
                     },
+                    axisLabel: {
+                        distance: 30,
+                        rotate: 50
+                    },
                     data: [
                         {
                             value: 0
@@ -101,6 +105,10 @@
                                 name: 'SCORE'
                                 }
                         ],
+                        axisLabel: {
+                            distance: 30,
+                            rotate: 'radial'
+                        },
                         progress: {
                             show: true,
                             roundCap: true
diff --git a/test/gauge-simple.html b/test/gauge-simple.html
index d92a979..076e0af 100644
--- a/test/gauge-simple.html
+++ b/test/gauge-simple.html
@@ -210,6 +210,7 @@
                         color: '#464646',
                         fontSize: 20,
                         distance: -60,
+                        rotate: 'tangential',
                         formatter: function(value) {
                             if (value === 0.875) {
                                 return '优'
@@ -252,4 +253,4 @@
     </script>
 </body>
 
-</html>
\ No newline at end of file
+</html>
diff --git a/test/line-case.html b/test/line-case.html
index aa54d7c..8d76e8e 100644
--- a/test/line-case.html
+++ b/test/line-case.html
@@ -41,6 +41,7 @@
         <div id="main1"></div>
         <div id="main2"></div>
         <div id="main3"></div>
+        <div id="main4"></div>
 
 
 
@@ -610,6 +611,39 @@
             });
         </script>
 
+        <script>
+            require([
+                'echarts'
+            ], function (echarts) {
+                var option = {
+                    xAxis: {
+                        type: 'category',
+                        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+                    },
+                    yAxis: {
+                        type: 'value'
+                    },
+                    tooltip: {
+                        trigger: 'axis'
+                    },
+                    series: [
+                        {
+                            data: [150, 230, 224, 218, 135, 147, 260],
+                            type: 'line',
+                            showSymbol: false
+                        }
+                    ]
+                };
+                var chart = testHelper.create(echarts, 'main4', {
+                    title: [
+                        'Should have no following warnings when axisPointer is visible',
+                        'z / z2 / zlevel of displayable is invalid, which may cause unexpected errors'
+                    ],
+                    option: option
+                });
+            });
+        </script>
+
 
     </body>
 </html>
diff --git a/test/pie-label.html b/test/pie-label.html
index 85541ef..23cb8d3 100644
--- a/test/pie-label.html
+++ b/test/pie-label.html
@@ -51,7 +51,7 @@
         <div id="main8"></div>
         <div id="main9"></div>
         <div id="main10"></div>
-
+        <div id="main11"></div>
 
         <script>
 
@@ -828,7 +828,7 @@
                         },
                     ],
                 };
-            
+
                 var chart = testHelper.create(echarts, 'main10', {
                     title: [
                         'Label line should hide when emphasis after update the emphasis.labelLine',
@@ -865,5 +865,121 @@
 
             });
         </script>
+
+        <script>
+            require([
+                'echarts'
+            ], function (echarts) {
+                var option = {
+                    series: [{
+                        data: [
+                            {
+                                name: '三门峡市',
+                                value: 4702
+                            },
+                            {
+                                name: '内江市',
+                                value: 4516
+                            },
+                            {
+                                name: '天门市',
+                                value: 1316
+                            },
+                            {
+                                name: '昭通市',
+                                value: 6188
+                            },
+                            {
+                                name: '娄底市',
+                                value: 7120
+                            },
+                            {
+                                name: '博尔塔拉州',
+                                value: 189
+                            },
+                            {
+                                name: '丽水市',
+                                value: 6478
+                            },
+                            {
+                                name: '牡丹江市',
+                                value: 5540
+                            },
+                            {
+                                name: '桂林市',
+                                value: 15518
+                            },
+                            {
+                                name: '桃园市',
+                                value: 86
+                            },
+                            {
+                                name: '晋中市',
+                                value: 10661
+                            },
+                            {
+                                name: '雅安市',
+                                value: 2411
+                            },
+                            {
+                                name: '文昌市',
+                                value: 1420
+                            },
+                            {
+                                name: '广州市',
+                                value: 159522
+                            },
+                            {
+                                name: '文山壮族苗族自治州',
+                                value: 3168
+                            },
+                            {
+                                name: '晋城市',
+                                value: 8640
+                            },
+                            {
+                                name: '昌都市',
+                                value: 507
+                            },
+                            {
+                                name: '曲靖市',
+                                value: 10705
+                            },
+                            {
+                                name: '昌吉州',
+                                value: 801
+                            },
+                            {
+                                name: '其他',
+                                value: 60280480,
+                                selected: false
+                            }
+                        ],
+                        type: 'pie',
+                        radius: '70%',
+                        minAngle: 1,
+                        minShowLabelAngle: 2
+                    }],
+                    legend: {
+                        show: true,
+                        orient: 'vertical',
+                        left: 'left',
+                        selected: {
+                            '其他': false
+                        }
+                    }
+                };
+
+
+                var chart = testHelper.create(echarts, 'main11', {
+                    title: [
+                        'Label line should be hidden after clicking the legend item **其他**',
+                        'Test case from issue #17013',
+                    ],
+                    height: 300,
+                    option: option
+                });
+            });
+        </script>
     </body>
 </html>
diff --git a/test/pie-percent.html b/test/pie-percent.html
new file mode 100644
index 0000000..06372ba
--- /dev/null
+++ b/test/pie-percent.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+
+
+<html>
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <script src="lib/simpleRequire.js"></script>
+        <script src="lib/config.js"></script>
+        <script src="lib/jquery.min.js"></script>
+        <script src="lib/facePrint.js"></script>
+        <script src="lib/testHelper.js"></script>
+        <!-- <script src="ut/lib/canteen.js"></script> -->
+        <link rel="stylesheet" href="lib/reset.css" />
+    </head>
+    <body>
+        <style>
+        </style>
+
+
+
+        <div id="main0"></div>
+
+
+
+
+
+
+        <script>
+        require([
+            'echarts'
+        ], function (echarts) {
+            var option;
+            var data = [];
+            for (var i = 0; i < 1e3; i++) {
+                data.push({
+                    name: 'test' + i,
+                    value: Math.random() * 1000,
+                });
+            }
+            option = {
+                series: {
+                    type: 'pie',
+                    data: data,
+                    percentPrecision: 5,
+                    label: {
+                        formatter: '{b} {d}%'
+                    }
+                }
+            };
+
+            var chart = testHelper.create(echarts, 'main0', {
+                title: [
+                    'Test Pie performance'
+                ]
+            });
+
+            var startTs = performance.now();
+            chart.setOption(option);
+
+            chart.on('finished', function () {
+                var endTs = performance.now();
+                var time = endTs - startTs;
+                console.log('Finished in ' + time + 'ms');
+                startTs = endTs;
+            });
+        });
+        </script>
+
+
+    </body>
+</html>
+
diff --git a/test/pie3.html b/test/pie3.html
index e799aaa..1f3b418 100644
--- a/test/pie3.html
+++ b/test/pie3.html
@@ -74,7 +74,7 @@
                         formatter: function (params) {
                             return '<div class="tooltip-content">\
                                 <h4>' + params.name + '</h4>\
-                                <h5>' + (params.percent * 100).toFixed(1) + '%</h5>\
+                                <h5>' + params.percent.toFixed(1) + '%</h5>\
                                 </div><script>console.log(1111)<\/script>\
                             ';
                         },
@@ -125,7 +125,7 @@
                         formatter: function (params) {
                             return '<div class="tooltip-content">\
                                 <h4>' + params.name + '</h4>\
-                                <h5>' + (params.percent * 100).toFixed(1) + '%</h5>\
+                                <h5>' + params.percent.toFixed(1) + '%</h5>\
                                 </div>\
                             ';
                         },
@@ -164,4 +164,4 @@
 
         </script>
     </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/test/runTest/actions/__meta__.json b/test/runTest/actions/__meta__.json
index 473fa64..1726696 100644
--- a/test/runTest/actions/__meta__.json
+++ b/test/runTest/actions/__meta__.json
@@ -56,13 +56,14 @@
   "connect-manually": 1,
   "connect2": 1,
   "css-transform": 4,
-  "custom": 5,
+  "custom": 6,
   "custom-bmap-grid": 1,
   "custom-children-remove": 1,
   "custom-hexbin": 2,
   "custom-large": 1,
   "custom-shape-morphing": 1,
   "custom-text-content": 6,
+  "custom-update": 4,
   "dataSelect": 7,
   "dataset-case": 6,
   "dataZoom-action": 4,
@@ -88,7 +89,7 @@
   "emphasis-inherit": 1,
   "funnel": 2,
   "gauge-simple": 2,
-  "geo-map": 3,
+  "geo-map": 4,
   "geo-map-features": 3,
   "geo-svg": 8,
   "geo-svg-demo": 6,
@@ -121,7 +122,7 @@
   "line-animation": 1,
   "line-animation-update": 3,
   "line-boldWhenHover": 1,
-  "line-case": 1,
+  "line-case": 2,
   "line-crash": 1,
   "line-endLabel": 1,
   "line-sampling": 2,
@@ -149,6 +150,7 @@
   "pie-animation": 2,
   "pie-calculable": 1,
   "pie-cornerRadius": 1,
+  "pie-label": 2,
   "pie-label-extreme": 2,
   "polar-rounded": 3,
   "polarLine": 1,
@@ -169,6 +171,7 @@
   "stackBar-dataZoom": 7,
   "sunburst-book": 1,
   "sunburst-canvas": 1,
+  "symbol": 1,
   "symbol2": 1,
   "themeRiver": 1,
   "timeScale": 1,
@@ -189,8 +192,8 @@
   "tooltip-valueFormatter": 3,
   "tree-image": 1,
   "tree-legend": 1,
-  "tree-radial": 2,
   "tree-polyline": 1,
+  "tree-radial": 2,
   "treemap-action": 3,
   "treemap-disk": 3,
   "treemap-disk2": 3,
diff --git a/test/runTest/actions/custom-update.json b/test/runTest/actions/custom-update.json
new file mode 100644
index 0000000..dbacd6f
--- /dev/null
+++ b/test/runTest/actions/custom-update.json
@@ -0,0 +1 @@
+[{"name":"Action 1","ops":[{"type":"mousemove","time":678,"x":793,"y":218},{"type":"mousemove","time":878,"x":436,"y":281},{"type":"mousemove","time":1079,"x":285,"y":329},{"type":"mousemove","time":1285,"x":283,"y":329},{"type":"mousemove","time":1362,"x":282,"y":329},{"type":"mousemove","time":1562,"x":239,"y":316},{"type":"mousemove","time":1765,"x":176,"y":325},{"type":"mousemove","time":1979,"x":158,"y":325},{"type":"mousemove","time":2180,"x":72,"y":178},{"type":"mousemove","time":2386,"x":43,"y":114},{"type":"mousemove","time":2580,"x":43,"y":114},{"type":"mousedown","time":2591,"x":43,"y":114},{"type":"mouseup","time":2723,"x":43,"y":114},{"time":2724,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":4303,"x":43,"y":114},{"type":"mouseup","time":4435,"x":43,"y":114},{"time":4436,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":6044,"x":43,"y":114},{"type":"mouseup","time":6177,"x":43,"y":114},{"time":6178,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1658736074386},{"name":"Action 2","ops":[{"type":"mousemove","time":477,"x":484,"y":279},{"type":"mousemove","time":680,"x":226,"y":164},{"type":"mousemove","time":893,"x":119,"y":145},{"type":"mousemove","time":1094,"x":59,"y":132},{"type":"mousemove","time":1301,"x":51,"y":129},{"type":"mousedown","time":1423,"x":51,"y":129},{"type":"mouseup","time":1547,"x":51,"y":129},{"time":1548,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":2550,"x":51,"y":129},{"type":"mouseup","time":2684,"x":51,"y":129},{"time":2685,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":3923,"x":51,"y":129},{"type":"mouseup","time":4056,"x":51,"y":129},{"time":4057,"delay":400,"type":"screenshot-auto"}],"scrollY":530,"scrollX":0,"timestamp":1658736087421},{"name":"Action 3","ops":[{"type":"mousemove","time":399,"x":153,"y":147},{"type":"mousemove","time":600,"x":77,"y":88},{"type":"mousemove","time":805,"x":48,"y":69},{"type":"mousedown","time":931,"x":45,"y":66},{"type":"mousemove","time":1021,"x":45,"y":66},{"type":"mouseup","time":1062,"x":45,"y":66},{"time":1063,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":2000,"x":45,"y":66},{"type":"mouseup","time":2122,"x":45,"y":66},{"time":2123,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2934,"x":45,"y":66},{"type":"mousedown","time":2988,"x":45,"y":67},{"type":"mousemove","time":3136,"x":45,"y":67},{"type":"mouseup","time":3146,"x":45,"y":67},{"time":3147,"delay":400,"type":"screenshot-auto"}],"scrollY":1128,"scrollX":0,"timestamp":1658736095915},{"name":"Action 4","ops":[{"type":"mousemove","time":166,"x":266,"y":215},{"type":"mousemove","time":370,"x":79,"y":198},{"type":"mousemove","time":582,"x":55,"y":185},{"type":"mousedown","time":751,"x":52,"y":184},{"type":"mousemove","time":786,"x":52,"y":184},{"type":"mouseup","time":851,"x":52,"y":184},{"time":852,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":1708,"x":52,"y":184},{"type":"mousemove","time":1715,"x":52,"y":184},{"type":"mouseup","time":1854,"x":52,"y":184},{"time":1855,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2698,"x":52,"y":184},{"type":"mousedown","time":2732,"x":52,"y":185},{"type":"mouseup","time":2874,"x":52,"y":185},{"time":2875,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2903,"x":52,"y":185}],"scrollY":1548,"scrollX":0,"timestamp":1658736103250}]
\ No newline at end of file
diff --git a/test/runTest/actions/custom.json b/test/runTest/actions/custom.json
index 7e80989..9d0864a 100644
--- a/test/runTest/actions/custom.json
+++ b/test/runTest/actions/custom.json
@@ -1 +1 @@
-[{"name":"Action 1","ops":[{"type":"mousedown","time":408,"x":81,"y":475},{"type":"mousemove","time":570,"x":85,"y":475},{"type":"mousemove","time":770,"x":209,"y":479},{"type":"mouseup","time":1011,"x":209,"y":479},{"time":1012,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":1403,"x":209,"y":479},{"type":"mousemove","time":1537,"x":210,"y":478},{"type":"mousemove","time":1738,"x":322,"y":473},{"type":"mousemove","time":1945,"x":325,"y":473},{"type":"mousemove","time":2155,"x":326,"y":474},{"type":"mouseup","time":2168,"x":326,"y":474},{"time":2169,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2271,"x":326,"y":474},{"type":"mousedown","time":2520,"x":326,"y":474},{"type":"mousemove","time":2605,"x":327,"y":474},{"type":"mousemove","time":2806,"x":621,"y":480},{"type":"mousemove","time":3012,"x":631,"y":480},{"type":"mouseup","time":3269,"x":631,"y":480},{"time":3270,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1568035195567},{"name":"Action 2","ops":[{"type":"mousedown","time":344,"x":458,"y":537},{"type":"mousemove","time":423,"x":457,"y":537},{"type":"mousemove","time":624,"x":310,"y":538},{"type":"mousemove","time":833,"x":300,"y":540},{"type":"mouseup","time":939,"x":300,"y":540},{"time":940,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1625,"x":305,"y":540},{"type":"mousemove","time":1830,"x":384,"y":535},{"type":"mousemove","time":2043,"x":368,"y":534},{"type":"mousemove","time":2308,"x":368,"y":534},{"type":"mousedown","time":2321,"x":368,"y":534},{"type":"mousemove","time":2508,"x":430,"y":524},{"type":"mousemove","time":2709,"x":613,"y":516},{"type":"mousemove","time":2909,"x":659,"y":519},{"type":"mousemove","time":3118,"x":682,"y":517},{"type":"mousemove","time":3368,"x":686,"y":517},{"type":"mouseup","time":3436,"x":686,"y":517},{"time":3437,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3676,"x":685,"y":512},{"type":"mousemove","time":3877,"x":498,"y":192},{"type":"mousemove","time":4077,"x":437,"y":106},{"type":"mousemove","time":4280,"x":387,"y":72},{"type":"mousemove","time":4501,"x":384,"y":71},{"type":"mousedown","time":4618,"x":384,"y":71},{"type":"mouseup","time":4719,"x":384,"y":71},{"time":4720,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":5562,"x":386,"y":71},{"type":"mousemove","time":5768,"x":431,"y":68},{"type":"mousedown","time":5985,"x":431,"y":68},{"type":"mouseup","time":6086,"x":431,"y":68},{"time":6087,"delay":400,"type":"screenshot-auto"}],"scrollY":1749,"scrollX":0,"timestamp":1568035212695},{"name":"Action 3","ops":[{"type":"screenshot","time":1787},{"type":"mousedown","time":2426,"x":408,"y":89},{"type":"mouseup","time":2504,"x":408,"y":89},{"time":2505,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":3672,"x":408,"y":89},{"type":"mouseup","time":3754,"x":408,"y":89},{"time":3755,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":4015,"x":416,"y":99},{"type":"mousemove","time":4216,"x":677,"y":586},{"type":"mousemove","time":4417,"x":696,"y":564},{"type":"mousemove","time":4624,"x":711,"y":556},{"type":"mousemove","time":4840,"x":719,"y":554},{"type":"mousedown","time":5007,"x":719,"y":553},{"type":"mousemove","time":5105,"x":719,"y":553},{"type":"mousemove","time":5117,"x":717,"y":554},{"type":"mousemove","time":5317,"x":613,"y":548},{"type":"mousemove","time":5517,"x":511,"y":548},{"type":"mousemove","time":5724,"x":406,"y":555},{"type":"mousemove","time":5935,"x":312,"y":549},{"type":"mouseup","time":6333,"x":312,"y":549},{"time":6334,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":6543,"x":309,"y":550},{"type":"mousemove","time":6750,"x":304,"y":551},{"type":"mousemove","time":6984,"x":323,"y":549},{"type":"mousemove","time":7194,"x":322,"y":549},{"type":"mousemove","time":7394,"x":318,"y":549},{"type":"mousemove","time":7594,"x":264,"y":556},{"type":"mousemove","time":7800,"x":255,"y":557},{"type":"mousedown","time":7855,"x":255,"y":557},{"type":"mousemove","time":8010,"x":308,"y":555},{"type":"mousemove","time":8211,"x":522,"y":557},{"type":"mousemove","time":8421,"x":577,"y":556},{"type":"mouseup","time":8854,"x":577,"y":556},{"time":8855,"delay":400,"type":"screenshot-auto"}],"scrollY":2309,"scrollX":0,"timestamp":1568035234459},{"name":"Action 4","ops":[{"type":"mousedown","time":392,"x":485,"y":521},{"type":"mousemove","time":487,"x":477,"y":520},{"type":"mousemove","time":690,"x":396,"y":521},{"type":"mousemove","time":895,"x":315,"y":522},{"type":"mouseup","time":1150,"x":315,"y":522},{"time":1151,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1403,"x":315,"y":521},{"type":"mousemove","time":1604,"x":221,"y":201},{"type":"mousemove","time":1812,"x":176,"y":58},{"type":"mousemove","time":2004,"x":170,"y":48},{"type":"mousemove","time":2212,"x":174,"y":52},{"type":"mousedown","time":2335,"x":174,"y":52},{"type":"mouseup","time":2469,"x":174,"y":52},{"time":2470,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2499,"x":175,"y":52},{"type":"mousemove","time":2699,"x":247,"y":52},{"type":"mousemove","time":2997,"x":247,"y":52},{"type":"mousedown","time":3049,"x":247,"y":52},{"type":"mouseup","time":3138,"x":247,"y":52},{"time":3139,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3212,"x":251,"y":52},{"type":"mousemove","time":3413,"x":304,"y":58},{"type":"mousemove","time":3620,"x":320,"y":58},{"type":"mousedown","time":3669,"x":320,"y":58},{"type":"mouseup","time":3775,"x":320,"y":58},{"time":3776,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3980,"x":323,"y":58},{"type":"mousemove","time":4180,"x":376,"y":64},{"type":"mousedown","time":4360,"x":376,"y":64},{"type":"mousemove","time":4387,"x":376,"y":64},{"type":"mouseup","time":4470,"x":376,"y":64},{"time":4471,"delay":400,"type":"screenshot-auto"}],"scrollY":2916,"scrollX":0,"timestamp":1568035317710},{"name":"Action 5","ops":[{"type":"mousedown","time":448,"x":717,"y":482},{"type":"mousemove","time":556,"x":712,"y":482},{"type":"mousemove","time":756,"x":493,"y":483},{"type":"mousemove","time":957,"x":407,"y":481},{"type":"mousemove","time":1158,"x":355,"y":479},{"type":"mouseup","time":1415,"x":355,"y":479},{"time":1416,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":2050,"x":355,"y":479},{"type":"mousemove","time":2176,"x":345,"y":480},{"type":"mousemove","time":2382,"x":175,"y":486},{"type":"mousemove","time":2599,"x":161,"y":486},{"type":"mousemove","time":2725,"x":161,"y":486},{"type":"mousemove","time":2933,"x":153,"y":487},{"type":"mouseup","time":3205,"x":153,"y":487},{"time":3206,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3542,"x":152,"y":487},{"type":"mousemove","time":3744,"x":132,"y":485},{"type":"mousedown","time":3901,"x":130,"y":485},{"type":"mousemove","time":3944,"x":131,"y":485},{"type":"mousemove","time":4144,"x":267,"y":485},{"type":"mousemove","time":4344,"x":278,"y":484},{"type":"mousemove","time":4552,"x":303,"y":482},{"type":"mouseup","time":4705,"x":303,"y":482},{"time":4706,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":5380,"x":305,"y":482},{"type":"mousemove","time":5587,"x":340,"y":475},{"type":"mousemove","time":5780,"x":337,"y":475},{"type":"mousemove","time":5986,"x":333,"y":476},{"type":"mousemove","time":6236,"x":333,"y":477},{"type":"mousemove","time":6437,"x":333,"y":477},{"type":"mousedown","time":6544,"x":333,"y":477},{"type":"mousemove","time":6653,"x":339,"y":477},{"type":"mousemove","time":6862,"x":668,"y":473},{"type":"mousemove","time":7080,"x":684,"y":473},{"type":"mousemove","time":7354,"x":684,"y":473},{"type":"mouseup","time":7730,"x":684,"y":473},{"time":7731,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":7888,"x":678,"y":473},{"type":"mousemove","time":8088,"x":639,"y":472},{"type":"mousedown","time":8265,"x":620,"y":474},{"type":"mousemove","time":8296,"x":620,"y":474},{"type":"mousemove","time":8548,"x":732,"y":473},{"type":"mouseup","time":8782,"x":732,"y":473},{"time":8783,"delay":400,"type":"screenshot-auto"}],"scrollY":3541,"scrollX":0,"timestamp":1568035375040}]
\ No newline at end of file
+[{"name":"Action 1","ops":[{"type":"mousedown","time":408,"x":81,"y":475},{"type":"mousemove","time":570,"x":85,"y":475},{"type":"mousemove","time":770,"x":209,"y":479},{"type":"mouseup","time":1011,"x":209,"y":479},{"time":1012,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":1403,"x":209,"y":479},{"type":"mousemove","time":1537,"x":210,"y":478},{"type":"mousemove","time":1738,"x":322,"y":473},{"type":"mousemove","time":1945,"x":325,"y":473},{"type":"mousemove","time":2155,"x":326,"y":474},{"type":"mouseup","time":2168,"x":326,"y":474},{"time":2169,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2271,"x":326,"y":474},{"type":"mousedown","time":2520,"x":326,"y":474},{"type":"mousemove","time":2605,"x":327,"y":474},{"type":"mousemove","time":2806,"x":621,"y":480},{"type":"mousemove","time":3012,"x":631,"y":480},{"type":"mouseup","time":3269,"x":631,"y":480},{"time":3270,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1568035195567},{"name":"Action 2","ops":[{"type":"mousedown","time":344,"x":458,"y":537},{"type":"mousemove","time":423,"x":457,"y":537},{"type":"mousemove","time":624,"x":310,"y":538},{"type":"mousemove","time":833,"x":300,"y":540},{"type":"mouseup","time":939,"x":300,"y":540},{"time":940,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1625,"x":305,"y":540},{"type":"mousemove","time":1830,"x":384,"y":535},{"type":"mousemove","time":2043,"x":368,"y":534},{"type":"mousemove","time":2308,"x":368,"y":534},{"type":"mousedown","time":2321,"x":368,"y":534},{"type":"mousemove","time":2508,"x":430,"y":524},{"type":"mousemove","time":2709,"x":613,"y":516},{"type":"mousemove","time":2909,"x":659,"y":519},{"type":"mousemove","time":3118,"x":682,"y":517},{"type":"mousemove","time":3368,"x":686,"y":517},{"type":"mouseup","time":3436,"x":686,"y":517},{"time":3437,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3676,"x":685,"y":512},{"type":"mousemove","time":3877,"x":498,"y":192},{"type":"mousemove","time":4077,"x":437,"y":106},{"type":"mousemove","time":4280,"x":387,"y":72},{"type":"mousemove","time":4501,"x":384,"y":71},{"type":"mousedown","time":4618,"x":384,"y":71},{"type":"mouseup","time":4719,"x":384,"y":71},{"time":4720,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":5562,"x":386,"y":71},{"type":"mousemove","time":5768,"x":431,"y":68},{"type":"mousedown","time":5985,"x":431,"y":68},{"type":"mouseup","time":6086,"x":431,"y":68},{"time":6087,"delay":400,"type":"screenshot-auto"}],"scrollY":1749,"scrollX":0,"timestamp":1568035212695},{"name":"Action 3","ops":[{"type":"screenshot","time":1787},{"type":"mousedown","time":2426,"x":408,"y":89},{"type":"mouseup","time":2504,"x":408,"y":89},{"time":2505,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":3672,"x":408,"y":89},{"type":"mouseup","time":3754,"x":408,"y":89},{"time":3755,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":4015,"x":416,"y":99},{"type":"mousemove","time":4216,"x":677,"y":586},{"type":"mousemove","time":4417,"x":696,"y":564},{"type":"mousemove","time":4624,"x":711,"y":556},{"type":"mousemove","time":4840,"x":719,"y":554},{"type":"mousedown","time":5007,"x":719,"y":553},{"type":"mousemove","time":5105,"x":719,"y":553},{"type":"mousemove","time":5117,"x":717,"y":554},{"type":"mousemove","time":5317,"x":613,"y":548},{"type":"mousemove","time":5517,"x":511,"y":548},{"type":"mousemove","time":5724,"x":406,"y":555},{"type":"mousemove","time":5935,"x":312,"y":549},{"type":"mouseup","time":6333,"x":312,"y":549},{"time":6334,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":6543,"x":309,"y":550},{"type":"mousemove","time":6750,"x":304,"y":551},{"type":"mousemove","time":6984,"x":323,"y":549},{"type":"mousemove","time":7194,"x":322,"y":549},{"type":"mousemove","time":7394,"x":318,"y":549},{"type":"mousemove","time":7594,"x":264,"y":556},{"type":"mousemove","time":7800,"x":255,"y":557},{"type":"mousedown","time":7855,"x":255,"y":557},{"type":"mousemove","time":8010,"x":308,"y":555},{"type":"mousemove","time":8211,"x":522,"y":557},{"type":"mousemove","time":8421,"x":577,"y":556},{"type":"mouseup","time":8854,"x":577,"y":556},{"time":8855,"delay":400,"type":"screenshot-auto"}],"scrollY":2309,"scrollX":0,"timestamp":1568035234459},{"name":"Action 4","ops":[{"type":"mousedown","time":392,"x":485,"y":521},{"type":"mousemove","time":487,"x":477,"y":520},{"type":"mousemove","time":690,"x":396,"y":521},{"type":"mousemove","time":895,"x":315,"y":522},{"type":"mouseup","time":1150,"x":315,"y":522},{"time":1151,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1403,"x":315,"y":521},{"type":"mousemove","time":1604,"x":221,"y":201},{"type":"mousemove","time":1812,"x":176,"y":58},{"type":"mousemove","time":2004,"x":170,"y":48},{"type":"mousemove","time":2212,"x":174,"y":52},{"type":"mousedown","time":2335,"x":174,"y":52},{"type":"mouseup","time":2469,"x":174,"y":52},{"time":2470,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2499,"x":175,"y":52},{"type":"mousemove","time":2699,"x":247,"y":52},{"type":"mousemove","time":2997,"x":247,"y":52},{"type":"mousedown","time":3049,"x":247,"y":52},{"type":"mouseup","time":3138,"x":247,"y":52},{"time":3139,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3212,"x":251,"y":52},{"type":"mousemove","time":3413,"x":304,"y":58},{"type":"mousemove","time":3620,"x":320,"y":58},{"type":"mousedown","time":3669,"x":320,"y":58},{"type":"mouseup","time":3775,"x":320,"y":58},{"time":3776,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3980,"x":323,"y":58},{"type":"mousemove","time":4180,"x":376,"y":64},{"type":"mousedown","time":4360,"x":376,"y":64},{"type":"mousemove","time":4387,"x":376,"y":64},{"type":"mouseup","time":4470,"x":376,"y":64},{"time":4471,"delay":400,"type":"screenshot-auto"}],"scrollY":2916,"scrollX":0,"timestamp":1568035317710},{"name":"Action 5","ops":[{"type":"mousedown","time":448,"x":717,"y":482},{"type":"mousemove","time":556,"x":712,"y":482},{"type":"mousemove","time":756,"x":493,"y":483},{"type":"mousemove","time":957,"x":407,"y":481},{"type":"mousemove","time":1158,"x":355,"y":479},{"type":"mouseup","time":1415,"x":355,"y":479},{"time":1416,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":2050,"x":355,"y":479},{"type":"mousemove","time":2176,"x":345,"y":480},{"type":"mousemove","time":2382,"x":175,"y":486},{"type":"mousemove","time":2599,"x":161,"y":486},{"type":"mousemove","time":2725,"x":161,"y":486},{"type":"mousemove","time":2933,"x":153,"y":487},{"type":"mouseup","time":3205,"x":153,"y":487},{"time":3206,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3542,"x":152,"y":487},{"type":"mousemove","time":3744,"x":132,"y":485},{"type":"mousedown","time":3901,"x":130,"y":485},{"type":"mousemove","time":3944,"x":131,"y":485},{"type":"mousemove","time":4144,"x":267,"y":485},{"type":"mousemove","time":4344,"x":278,"y":484},{"type":"mousemove","time":4552,"x":303,"y":482},{"type":"mouseup","time":4705,"x":303,"y":482},{"time":4706,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":5380,"x":305,"y":482},{"type":"mousemove","time":5587,"x":340,"y":475},{"type":"mousemove","time":5780,"x":337,"y":475},{"type":"mousemove","time":5986,"x":333,"y":476},{"type":"mousemove","time":6236,"x":333,"y":477},{"type":"mousemove","time":6437,"x":333,"y":477},{"type":"mousedown","time":6544,"x":333,"y":477},{"type":"mousemove","time":6653,"x":339,"y":477},{"type":"mousemove","time":6862,"x":668,"y":473},{"type":"mousemove","time":7080,"x":684,"y":473},{"type":"mousemove","time":7354,"x":684,"y":473},{"type":"mouseup","time":7730,"x":684,"y":473},{"time":7731,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":7888,"x":678,"y":473},{"type":"mousemove","time":8088,"x":639,"y":472},{"type":"mousedown","time":8265,"x":620,"y":474},{"type":"mousemove","time":8296,"x":620,"y":474},{"type":"mousemove","time":8548,"x":732,"y":473},{"type":"mouseup","time":8782,"x":732,"y":473},{"time":8783,"delay":400,"type":"screenshot-auto"}],"scrollY":3541,"scrollX":0,"timestamp":1568035375040},{"name":"Action 6","ops":[{"type":"mousedown","time":512,"x":40,"y":163},{"type":"mouseup","time":662,"x":40,"y":163},{"type":"mousedown","time":1019,"x":40,"y":163},{"type":"mouseup","time":1164,"x":40,"y":163},{"time":1165,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1656920000014}]
\ No newline at end of file
diff --git a/test/runTest/actions/geo-map.json b/test/runTest/actions/geo-map.json
index ffbe5bc..b9f1566 100644
--- a/test/runTest/actions/geo-map.json
+++ b/test/runTest/actions/geo-map.json
@@ -1 +1 @@
-[{"name":"Action 1","ops":[{"type":"mousedown","time":750,"x":67,"y":8},{"type":"mouseup","time":835,"x":67,"y":8},{"time":836,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1086,"x":67,"y":8},{"type":"mousemove","time":1291,"x":65,"y":29},{"type":"mousemove","time":1491,"x":65,"y":30},{"type":"mousedown","time":1667,"x":65,"y":30},{"type":"mouseup","time":1785,"x":65,"y":30},{"time":1786,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2142,"x":65,"y":31},{"type":"mousemove","time":2342,"x":61,"y":61},{"type":"mousemove","time":2568,"x":61,"y":61},{"type":"mousedown","time":2652,"x":61,"y":61},{"type":"mouseup","time":2725,"x":61,"y":61},{"time":2726,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":3702,"x":61,"y":61},{"type":"mouseup","time":3775,"x":61,"y":61},{"time":3776,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3955,"x":61,"y":61},{"type":"mousemove","time":4155,"x":68,"y":46},{"type":"mousemove","time":4362,"x":71,"y":37},{"type":"mousedown","time":4510,"x":71,"y":37},{"type":"mouseup","time":4605,"x":71,"y":37},{"time":4606,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":5004,"x":71,"y":36},{"type":"mousemove","time":5226,"x":72,"y":16},{"type":"mousedown","time":5406,"x":72,"y":15},{"type":"mousemove","time":5426,"x":72,"y":15},{"type":"mouseup","time":5493,"x":72,"y":15},{"time":5494,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":6071,"x":72,"y":16},{"type":"mousemove","time":6272,"x":69,"y":35},{"type":"mousemove","time":6486,"x":69,"y":35},{"type":"mousedown","time":6614,"x":69,"y":35},{"type":"mouseup","time":6697,"x":69,"y":35},{"time":6698,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":7099,"x":69,"y":36},{"type":"mousemove","time":7299,"x":66,"y":56},{"type":"mousemove","time":7499,"x":62,"y":65},{"type":"mousedown","time":7766,"x":62,"y":65},{"type":"mouseup","time":7841,"x":62,"y":65},{"time":7842,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1568040771612},{"name":"Action 2","ops":[{"type":"mousedown","time":465,"x":18,"y":430},{"type":"mousemove","time":578,"x":18,"y":432},{"type":"mousemove","time":914,"x":24,"y":475},{"type":"mouseup","time":1111,"x":23,"y":477},{"time":1112,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1140,"x":23,"y":477},{"type":"mousemove","time":1357,"x":19,"y":571},{"type":"mousemove","time":1603,"x":21,"y":579},{"type":"mousemove","time":1807,"x":21,"y":576},{"type":"mousemove","time":2020,"x":21,"y":574},{"type":"mousedown","time":2170,"x":21,"y":573},{"type":"mousemove","time":2228,"x":21,"y":573},{"type":"mousemove","time":2277,"x":21,"y":573},{"type":"mousemove","time":2493,"x":23,"y":549},{"type":"mousemove","time":2715,"x":23,"y":543},{"type":"mousemove","time":2929,"x":23,"y":543},{"type":"mouseup","time":3233,"x":23,"y":543},{"time":3234,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3327,"x":23,"y":542},{"type":"mousemove","time":3549,"x":18,"y":516},{"type":"mousemove","time":3768,"x":14,"y":510},{"type":"mousedown","time":4021,"x":14,"y":510},{"type":"mouseup","time":4111,"x":14,"y":510},{"time":4112,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1603890244262},{"name":"Action 3","ops":[{"type":"mousemove","time":550,"x":429,"y":336},{"type":"mousedown","time":674,"x":431,"y":335},{"type":"mousemove","time":793,"x":431,"y":336},{"type":"mousemove","time":1006,"x":346,"y":462},{"type":"mousemove","time":1207,"x":350,"y":458},{"type":"mouseup","time":1343,"x":350,"y":458},{"time":1344,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1410,"x":350,"y":458},{"type":"mousemove","time":1603,"x":350,"y":457},{"type":"mousewheel","time":1686,"x":350,"y":457,"deltaY":4.000244140625},{"type":"mousewheel","time":1719,"x":350,"y":457,"deltaY":40.41015625},{"type":"mousewheel","time":1748,"x":350,"y":457,"deltaY":377.4566650390625},{"type":"mousewheel","time":1775,"x":350,"y":457,"deltaY":252.0208740234375},{"type":"mousewheel","time":1801,"x":350,"y":457,"deltaY":274.16015625},{"type":"mousewheel","time":1901,"x":350,"y":457,"deltaY":263.7664794921875},{"type":"mousemove","time":2236,"x":347,"y":454},{"type":"mousemove","time":2441,"x":308,"y":411},{"type":"mousedown","time":2514,"x":308,"y":411},{"type":"mousemove","time":2644,"x":443,"y":385},{"type":"mousemove","time":2855,"x":648,"y":301},{"type":"mousemove","time":3059,"x":670,"y":288},{"type":"mouseup","time":3161,"x":670,"y":288},{"time":3162,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3270,"x":662,"y":291},{"type":"mousemove","time":3476,"x":581,"y":308},{"type":"mousewheel","time":3521,"x":581,"y":308,"deltaY":-4.000244140625},{"type":"mousewheel","time":3545,"x":581,"y":308,"deltaY":-37.410888671875},{"type":"mousewheel","time":3570,"x":581,"y":308,"deltaY":-385.2349853515625},{"type":"mousewheel","time":3602,"x":581,"y":308,"deltaY":-252.042236328125},{"type":"mousewheel","time":3627,"x":581,"y":308,"deltaY":-271.1181640625}],"scrollY":0,"scrollX":0,"timestamp":1568969626016}]
\ No newline at end of file
+[{"name":"Action 1","ops":[{"type":"mousemove","time":461,"x":229,"y":419},{"type":"mousemove","time":735,"x":246,"y":350},{"type":"mousemove","time":1019,"x":249,"y":366},{"type":"screenshot","time":2182}],"scrollY":0,"scrollX":0,"timestamp":1657527803250},{"name":"Action 2","ops":[{"type":"mousedown","time":750,"x":67,"y":8},{"type":"mouseup","time":835,"x":67,"y":8},{"time":836,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1086,"x":67,"y":8},{"type":"mousemove","time":1291,"x":65,"y":29},{"type":"mousemove","time":1491,"x":65,"y":30},{"type":"mousedown","time":1667,"x":65,"y":30},{"type":"mouseup","time":1785,"x":65,"y":30},{"time":1786,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2142,"x":65,"y":31},{"type":"mousemove","time":2342,"x":61,"y":61},{"type":"mousemove","time":2568,"x":61,"y":61},{"type":"mousedown","time":2652,"x":61,"y":61},{"type":"mouseup","time":2725,"x":61,"y":61},{"time":2726,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":3702,"x":61,"y":61},{"type":"mouseup","time":3775,"x":61,"y":61},{"time":3776,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3955,"x":61,"y":61},{"type":"mousemove","time":4155,"x":68,"y":46},{"type":"mousemove","time":4362,"x":71,"y":37},{"type":"mousedown","time":4510,"x":71,"y":37},{"type":"mouseup","time":4605,"x":71,"y":37},{"time":4606,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":5004,"x":71,"y":36},{"type":"mousemove","time":5226,"x":72,"y":16},{"type":"mousedown","time":5406,"x":72,"y":15},{"type":"mousemove","time":5426,"x":72,"y":15},{"type":"mouseup","time":5493,"x":72,"y":15},{"time":5494,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":6071,"x":72,"y":16},{"type":"mousemove","time":6272,"x":69,"y":35},{"type":"mousemove","time":6486,"x":69,"y":35},{"type":"mousedown","time":6614,"x":69,"y":35},{"type":"mouseup","time":6697,"x":69,"y":35},{"time":6698,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":7099,"x":69,"y":36},{"type":"mousemove","time":7299,"x":66,"y":56},{"type":"mousemove","time":7499,"x":62,"y":65},{"type":"mousedown","time":7766,"x":62,"y":65},{"type":"mouseup","time":7841,"x":62,"y":65},{"time":7842,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1568040771612},{"name":"Action 3","ops":[{"type":"mousedown","time":465,"x":18,"y":430},{"type":"mousemove","time":578,"x":18,"y":432},{"type":"mousemove","time":914,"x":24,"y":475},{"type":"mouseup","time":1111,"x":23,"y":477},{"time":1112,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1140,"x":23,"y":477},{"type":"mousemove","time":1357,"x":19,"y":571},{"type":"mousemove","time":1603,"x":21,"y":579},{"type":"mousemove","time":1807,"x":21,"y":576},{"type":"mousemove","time":2020,"x":21,"y":574},{"type":"mousedown","time":2170,"x":21,"y":573},{"type":"mousemove","time":2228,"x":21,"y":573},{"type":"mousemove","time":2277,"x":21,"y":573},{"type":"mousemove","time":2493,"x":23,"y":549},{"type":"mousemove","time":2715,"x":23,"y":543},{"type":"mousemove","time":2929,"x":23,"y":543},{"type":"mouseup","time":3233,"x":23,"y":543},{"time":3234,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3327,"x":23,"y":542},{"type":"mousemove","time":3549,"x":18,"y":516},{"type":"mousemove","time":3768,"x":14,"y":510},{"type":"mousedown","time":4021,"x":14,"y":510},{"type":"mouseup","time":4111,"x":14,"y":510},{"time":4112,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1603890244262},{"name":"Action 4","ops":[{"type":"mousemove","time":550,"x":429,"y":336},{"type":"mousedown","time":674,"x":431,"y":335},{"type":"mousemove","time":793,"x":431,"y":336},{"type":"mousemove","time":1006,"x":346,"y":462},{"type":"mousemove","time":1207,"x":350,"y":458},{"type":"mouseup","time":1343,"x":350,"y":458},{"time":1344,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1410,"x":350,"y":458},{"type":"mousemove","time":1603,"x":350,"y":457},{"type":"mousewheel","time":1686,"x":350,"y":457,"deltaY":4.000244140625},{"type":"mousewheel","time":1719,"x":350,"y":457,"deltaY":40.41015625},{"type":"mousewheel","time":1748,"x":350,"y":457,"deltaY":377.4566650390625},{"type":"mousewheel","time":1775,"x":350,"y":457,"deltaY":252.0208740234375},{"type":"mousewheel","time":1801,"x":350,"y":457,"deltaY":274.16015625},{"type":"mousewheel","time":1901,"x":350,"y":457,"deltaY":263.7664794921875},{"type":"mousemove","time":2236,"x":347,"y":454},{"type":"mousemove","time":2441,"x":308,"y":411},{"type":"mousedown","time":2514,"x":308,"y":411},{"type":"mousemove","time":2644,"x":443,"y":385},{"type":"mousemove","time":2855,"x":648,"y":301},{"type":"mousemove","time":3059,"x":670,"y":288},{"type":"mouseup","time":3161,"x":670,"y":288},{"time":3162,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3270,"x":662,"y":291},{"type":"mousemove","time":3476,"x":581,"y":308},{"type":"mousewheel","time":3521,"x":581,"y":308,"deltaY":-4.000244140625},{"type":"mousewheel","time":3545,"x":581,"y":308,"deltaY":-37.410888671875},{"type":"mousewheel","time":3570,"x":581,"y":308,"deltaY":-385.2349853515625},{"type":"mousewheel","time":3602,"x":581,"y":308,"deltaY":-252.042236328125},{"type":"mousewheel","time":3627,"x":581,"y":308,"deltaY":-271.1181640625}],"scrollY":0,"scrollX":0,"timestamp":1568969626016}]
\ No newline at end of file
diff --git a/test/runTest/actions/line-case.json b/test/runTest/actions/line-case.json
index 318b5d1..3de8815 100644
--- a/test/runTest/actions/line-case.json
+++ b/test/runTest/actions/line-case.json
@@ -1 +1 @@
-[{"name":"Action 1","ops":[{"type":"mousedown","time":264,"x":423,"y":226},{"type":"mouseup","time":353,"x":423,"y":226},{"time":354,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":426,"x":425,"y":227},{"type":"mousemove","time":626,"x":456,"y":261},{"type":"mousemove","time":826,"x":499,"y":322},{"type":"mousedown","time":936,"x":499,"y":322},{"type":"mousemove","time":1027,"x":495,"y":317},{"type":"mousemove","time":1231,"x":443,"y":252},{"type":"mouseup","time":1403,"x":443,"y":251},{"time":1404,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1493,"x":443,"y":251},{"type":"mousemove","time":1976,"x":443,"y":251},{"type":"mousemove","time":2180,"x":455,"y":233},{"type":"mousemove","time":2393,"x":455,"y":231},{"type":"mousedown","time":2469,"x":455,"y":231},{"type":"mouseup","time":2532,"x":454,"y":231},{"time":2533,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2593,"x":454,"y":231}],"scrollY":1268,"scrollX":0,"timestamp":1641536392159}]
\ No newline at end of file
+[{"name":"Action 1","ops":[{"type":"mousedown","time":264,"x":423,"y":226},{"type":"mouseup","time":353,"x":423,"y":226},{"time":354,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":426,"x":425,"y":227},{"type":"mousemove","time":626,"x":456,"y":261},{"type":"mousemove","time":826,"x":499,"y":322},{"type":"mousedown","time":936,"x":499,"y":322},{"type":"mousemove","time":1027,"x":495,"y":317},{"type":"mousemove","time":1231,"x":443,"y":252},{"type":"mouseup","time":1403,"x":443,"y":251},{"time":1404,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1493,"x":443,"y":251},{"type":"mousemove","time":1976,"x":443,"y":251},{"type":"mousemove","time":2180,"x":455,"y":233},{"type":"mousemove","time":2393,"x":455,"y":231},{"type":"mousedown","time":2469,"x":455,"y":231},{"type":"mouseup","time":2532,"x":454,"y":231},{"time":2533,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2593,"x":454,"y":231}],"scrollY":1268,"scrollX":0,"timestamp":1641536392159},{"name":"Action 2","ops":[{"type":"mousemove","time":556,"x":40,"y":566},{"type":"mousemove","time":757,"x":172,"y":441},{"type":"mousemove","time":963,"x":180,"y":424},{"type":"mousemove","time":1290,"x":180,"y":425}],"scrollY":1726,"scrollX":0,"timestamp":1655695727357}]
\ No newline at end of file
diff --git a/test/runTest/actions/pie-label.json b/test/runTest/actions/pie-label.json
new file mode 100644
index 0000000..44ede7c
--- /dev/null
+++ b/test/runTest/actions/pie-label.json
@@ -0,0 +1 @@
+[{"name":"Action 1","ops":[{"type":"mousemove","time":299,"x":274,"y":345},{"type":"mousemove","time":499,"x":336,"y":332},{"type":"screenshot","time":1769},{"type":"mousemove","time":2799,"x":337,"y":332},{"type":"mousemove","time":2999,"x":316,"y":331},{"type":"mousemove","time":3205,"x":188,"y":277},{"type":"mousemove","time":3419,"x":152,"y":223},{"type":"mousemove","time":3620,"x":134,"y":197},{"type":"mousedown","time":3688,"x":133,"y":189},{"type":"mousemove","time":3837,"x":133,"y":189},{"type":"mouseup","time":3858,"x":133,"y":189},{"time":3859,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":4250,"x":133,"y":191},{"type":"mousemove","time":4450,"x":315,"y":338},{"type":"mousemove","time":4656,"x":345,"y":345},{"type":"mousemove","time":5632,"x":346,"y":345},{"type":"screenshot","time":6169}],"scrollY":4134.8564453125,"scrollX":0,"timestamp":1658391799998},{"name":"Action 2","ops":[{"type":"mousemove","time":257,"x":145,"y":492},{"type":"mousemove","time":465,"x":146,"y":478},{"type":"mousedown","time":518,"x":146,"y":478},{"type":"mouseup","time":633,"x":146,"y":478},{"time":634,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":1553,"x":146,"y":478},{"type":"mouseup","time":1719,"x":146,"y":478},{"time":1720,"delay":400,"type":"screenshot-auto"}],"scrollY":4431.60009765625,"scrollX":0,"timestamp":1658392063110}]
\ No newline at end of file
diff --git a/test/runTest/actions/symbol.json b/test/runTest/actions/symbol.json
new file mode 100644
index 0000000..a3eaba4
--- /dev/null
+++ b/test/runTest/actions/symbol.json
@@ -0,0 +1 @@
+[{"name":"Action 1","ops":[{"type":"mousemove","time":191,"x":749,"y":85},{"type":"mousemove","time":392,"x":733,"y":119},{"type":"mousemove","time":606,"x":704,"y":150},{"type":"screenshot","time":2032},{"type":"mousemove","time":2274,"x":705,"y":150},{"type":"mousemove","time":2479,"x":711,"y":74},{"type":"mousemove","time":2689,"x":706,"y":36},{"type":"mousemove","time":2897,"x":700,"y":20},{"type":"mousemove","time":3361,"x":697,"y":5},{"type":"mousemove","time":3407,"x":697,"y":7},{"type":"mousemove","time":3612,"x":696,"y":21},{"type":"valuechange","selector":"div.dg.ac>div.dg.main.a>ul>li.cr.string>div>div.c>select","value":"2","time":4315,"target":"select"},{"type":"mouseup","time":4316,"x":277,"y":-15},{"type":"mousemove","time":4330,"x":683,"y":59},{"type":"mousemove","time":4533,"x":714,"y":73},{"type":"mousedown","time":4750,"x":741,"y":109},{"type":"mousemove","time":4762,"x":741,"y":109},{"type":"mouseup","time":4863,"x":741,"y":109},{"type":"mousemove","time":5041,"x":741,"y":110},{"type":"mousemove","time":5245,"x":739,"y":117},{"type":"mousemove","time":5607,"x":737,"y":122},{"type":"mousemove","time":5821,"x":712,"y":154},{"type":"mousemove","time":7472,"x":711,"y":155},{"type":"mousemove","time":7673,"x":709,"y":137},{"type":"mousemove","time":7879,"x":703,"y":130},{"type":"mousemove","time":8090,"x":708,"y":152},{"type":"screenshot","time":8290},{"type":"mousemove","time":8495,"x":721,"y":153},{"type":"mousedown","time":15040,"x":721,"y":153},{"type":"mouseup","time":15178,"x":721,"y":153},{"type":"mousemove","time":17358,"x":721,"y":146},{"type":"mousemove","time":17576,"x":697,"y":70},{"type":"mousemove","time":17786,"x":689,"y":15},{"type":"mousemove","time":18161,"x":689,"y":21},{"type":"valuechange","selector":"div.dg.ac>div.dg.main.a>ul>li.cr.string>div>div.c>select","value":"undefined","time":19684,"target":"select"},{"type":"mouseup","time":19684,"x":277,"y":-15},{"type":"mousemove","time":19700,"x":699,"y":82},{"type":"mousemove","time":19909,"x":708,"y":105},{"type":"mousemove","time":20141,"x":711,"y":133},{"type":"mousedown","time":20325,"x":711,"y":133},{"type":"mouseup","time":20522,"x":711,"y":133},{"time":20523,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1659016158148}]
\ No newline at end of file
diff --git a/test/runTest/runtime/ActionPlayback.js b/test/runTest/runtime/ActionPlayback.js
index 6a41f42..aa50caa 100644
--- a/test/runTest/runtime/ActionPlayback.js
+++ b/test/runTest/runtime/ActionPlayback.js
@@ -186,7 +186,10 @@
                 screenshotTaken = true;
                 break;
             case 'valuechange':
-                document.querySelector(op.selector).value = op.value;
+                const selector = document.querySelector(op.selector);
+                selector.value = op.value;
+                // changing value via js won't trigger `change` event, so trigger it manually
+                selector.dispatchEvent(new Event('change'));
                 break;
         }
 
@@ -213,4 +216,4 @@
 
         return true;
     }
-};
\ No newline at end of file
+};
diff --git a/test/symbol.html b/test/symbol.html
index 808f9a7..465cb38 100644
--- a/test/symbol.html
+++ b/test/symbol.html
@@ -23,6 +23,8 @@
         <meta charset="utf-8">
         <script src="lib/simpleRequire.js"></script>
         <script src="lib/config.js"></script>
+        <script src="lib/dat.gui.min.js"></script>
+        <link rel="stylesheet" href="lib/reset.css">
     </head>
     <body>
         <style>
@@ -35,12 +37,12 @@
         <script>
 
             require([
-                'echarts'
-            ], function (echarts) {
+                '../node_modules/seedrandom/seedrandom.js',
+                'echarts',
+            ], function (seedrandom, echarts) {
+                Math.random = new seedrandom('echarts-random');
 
-                var chart = echarts.init(document.getElementById('main'), null, {
-
-                });
+                var chart = echarts.init(document.getElementById('main'));
 
                 var symbolList = [
                     'circle',
@@ -86,12 +88,6 @@
                     legend: {
                         data: series.map(function (series) {return series.name;})
                     },
-                    tooltip: {
-                        trigger: 'axis',
-                        axisPointer: {
-                            type: 'cross'
-                        }
-                    },
                     xAxis: {
                         type: 'value',
                         splitLine: {
@@ -106,8 +102,60 @@
                     },
                     series: series
                 });
+
+                window.addEventListener('resize', chart.resize);
+
+                var symbolScaleValueMap = {
+                    'undefined': undefined,
+                    'null': null,
+                    'true': true,
+                    'false': false,
+                    '0': 0,
+                    '0.5': 0.5,
+                    '1': 1,
+                    '1.1': 1.1,
+                    '2': 2,
+                    'NaN': NaN,
+                    'Infinity': Infinity,
+                    'Negative(-1)': -1,
+                    'Empty String': '',
+                    'String(\'abc\')': 'abc'
+                }
+
+                var config = {
+                    hoverScale: 'false',
+                    tooltipTrigger: 'item'
+                };
+
+                var gui = new dat.GUI();
+                gui.add(config, 'hoverScale', Object.keys(symbolScaleValueMap))
+                    .onChange(update);
+                gui.add(config, 'tooltipTrigger', ['axis', 'item'])
+                    .onChange(update);
+
+                update();
+
+                function update() {
+                    var activeHoverScale = symbolScaleValueMap[config.hoverScale];
+                    console.log('active hoverScale', activeHoverScale);
+                    series.forEach(function (series) {
+                        series.emphasis = series.emphasis || {};
+                        series.emphasis.scale = activeHoverScale;
+                    });
+                    var tooltip = {
+                        trigger: config.tooltipTrigger,
+                        axisPointer: config.tooltipTrigger === 'axis'
+                            ? { type: 'cross' }
+                            : null
+                    };
+                    console.log(tooltip);
+                    chart.setOption({
+                        tooltip: tooltip,
+                        series: series
+                    });
+                }
             });
 
         </script>
     </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/test/treemap-simple.html b/test/treemap-simple.html
index c71b812..37c7aa2 100644
--- a/test/treemap-simple.html
+++ b/test/treemap-simple.html
@@ -66,6 +66,15 @@
                             }
                         },
                         breadcrumb: {
+                            emphasis: {
+                                itemStyle: {
+                                    color: 'blue',
+                                    opacity: 0.6,
+                                    textStyle: {
+                                        color: 'green'
+                                    }
+                                },
+                            }
                         },
                         levels: [
                             {
diff --git a/theme/infographic.js b/theme/infographic.js
index 13a86c3..be5e256 100644
--- a/theme/infographic.js
+++ b/theme/infographic.js
@@ -76,9 +76,7 @@
 
         toolbox: {
             iconStyle: {
-                normal: {
-                    borderColor: colorPalette[0]
-                }
+                borderColor: colorPalette[0]
             }
         },
 
@@ -152,8 +150,10 @@
                 borderColor: '#fff',
                 lineStyle: {
                     width: 3
-                },
-                emphasis: {
+                }
+            },
+            emphasis: {
+                itemStyle: {
                     borderWidth: 0
                 }
             },
diff --git a/theme/macarons.js b/theme/macarons.js
index d78f7e9..c771d5e 100644
--- a/theme/macarons.js
+++ b/theme/macarons.js
@@ -82,9 +82,7 @@
 
         toolbox: {
             iconStyle: {
-                normal: {
-                    borderColor: colorPalette[0]
-                }
+                borderColor: colorPalette[0]
             }
         },
 
diff --git a/theme/macarons2.js b/theme/macarons2.js
index 3fdb4b9..59cdddb 100644
--- a/theme/macarons2.js
+++ b/theme/macarons2.js
@@ -88,70 +88,67 @@
             // barWidth: null,        // 默认自适应
             barGap: '30%', // 柱间距离,默认为柱形宽度的30%,可设固定值
             barCategoryGap: '20%', // 类目间柱形距离,默认为类目间距的20%,可设固定值
+            label: {
+                show: false
+                // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
+                //           'inside'|'left'|'right'|'top'|'bottom'
+                // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
+            },
             itemStyle: {
-                normal: {
-                    // color: '各异',
-                    barBorderColor: '#fff', // 柱条边线
-                    barBorderRadius: 0, // 柱条边线圆角,单位px,默认为0
-                    barBorderWidth: 1, // 柱条边线线宽,单位px,默认为1
-                    label: {
-                        show: false
-                        // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
-                        //           'inside'|'left'|'right'|'top'|'bottom'
-                        // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
-                    }
-                },
-                emphasis: {
+                // color: '各异',
+                barBorderColor: '#fff', // 柱条边线
+                barBorderRadius: 0, // 柱条边线圆角,单位px,默认为0
+                barBorderWidth: 1 // 柱条边线线宽,单位px,默认为1
+            },
+            emphasis: {
+                itemStyle: {
                     // color: '各异',
                     barBorderColor: 'rgba(0,0,0,0)', // 柱条边线
                     barBorderRadius: 0, // 柱条边线圆角,单位px,默认为0
                     barBorderWidth: 1, // 柱条边线线宽,单位px,默认为1
-                    label: {
-                        show: false
-                        // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
-                        //           'inside'|'left'|'right'|'top'|'bottom'
-                        // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
-                    }
+                },
+                label: {
+                    show: false
+                    // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
+                    //           'inside'|'left'|'right'|'top'|'bottom'
+                    // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
                 }
             }
         },
 
         line: {
+            label: {
+                show: false
+                // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
+                //           'inside'|'left'|'right'|'top'|'bottom'
+                // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
+            },
             itemStyle: {
-                normal: {
-                    // color: 各异,
-                    label: {
-                        show: false
-                        // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
-                        //           'inside'|'left'|'right'|'top'|'bottom'
-                        // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
-                    },
-                    lineStyle: {
-                        width: 2,
-                        type: 'solid',
-                        shadowColor: 'rgba(0,0,0,0)', //默认透明
-                        shadowBlur: 5,
-                        shadowOffsetX: 3,
-                        shadowOffsetY: 3
-                    }
-                },
-                emphasis: {
-                    // color: 各异,
-                    label: {
-                        show: false
-                        // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
-                        //           'inside'|'left'|'right'|'top'|'bottom'
-                        // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
-                    }
+                // color: 各异,
+            },
+            emphasis: {
+                // color: 各异,
+                label: {
+                    show: false
+                    // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
+                    //           'inside'|'left'|'right'|'top'|'bottom'
+                    // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
                 }
             },
+            lineStyle: {
+                width: 2,
+                type: 'solid',
+                shadowColor: 'rgba(0,0,0,0)', //默认透明
+                shadowBlur: 5,
+                shadowOffsetX: 3,
+                shadowOffsetY: 3
+            },
             //smooth : false,
             //symbol: null,         // 拐点图形类型
             symbolSize: 2, // 拐点图形大小
             //symbolRotate : null,  // 拐点图形旋转控制
             showAllSymbol: false // 标志图形默认只有主轴显示(随主轴标签间隔隐藏策略)
         },
-
         candlestick: {
             itemStyle: {
                 color: '#fe9778',
@@ -176,25 +173,25 @@
             startAngle: 90,
             minAngle: 0, // 最小角度改为0
             selectedOffset: 10, // 选中是扇区偏移量
+            label: {
+                show: true,
+                position: 'outer',
+                color: '#1b1b1b',
+                lineStyle: { color: '#1b1b1b' }
+                // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
+            },
             itemStyle: {
                 // color: 各异,
                 borderColor: '#fff',
-                borderWidth: 1,
-                label: {
-                    show: true,
-                    position: 'outer',
-                    color: '#1b1b1b',
-                    lineStyle: { color: '#1b1b1b' }
-                    // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
-                },
-                labelLine: {
-                    show: true,
-                    length: 20,
-                    lineStyle: {
-                        // color: 各异,
-                        width: 1,
-                        type: 'solid'
-                    }
+                borderWidth: 1
+            },
+            labelLine: {
+                show: true,
+                length: 20,
+                lineStyle: {
+                    // color: 各异,
+                    width: 1,
+                    type: 'solid'
                 }
             }
         },
diff --git a/theme/shine.js b/theme/shine.js
index e554af7..0114f7b 100644
--- a/theme/shine.js
+++ b/theme/shine.js
@@ -67,9 +67,7 @@
 
         toolbox: {
             iconStyle: {
-                normal: {
-                    borderColor: '#06467c'
-                }
+                borderColor: '#06467c'
             }
         },
 
diff --git a/theme/tech-blue.js b/theme/tech-blue.js
index e5435f0..db05ba6 100644
--- a/theme/tech-blue.js
+++ b/theme/tech-blue.js
@@ -105,8 +105,12 @@
                 color: '#00aecd'
             },
             controlStyle: {
-                normal: { color: '#00aecd' },
-                emphasis: { color: '#00aecd' }
+                color: '#00aecd',
+            },
+            emphasis: {
+                controlStyle: {
+                  color: '#00aecd'
+                }
             }
         },
 
diff --git a/theme/tool/option/area.js b/theme/tool/option/area.js
index 49c290b..037db12 100644
--- a/theme/tool/option/area.js
+++ b/theme/tool/option/area.js
@@ -49,28 +49,28 @@
             name:'Email',
             type:'line',
             stack: '总量',
-            areaStyle: {normal: {}},
+            areaStyle: {},
             data:[120, 132, 101, 134, 90, 230, 210]
         },
         {
             name:'联盟广告',
             type:'line',
             stack: '总量',
-            areaStyle: {normal: {}},
+            areaStyle: {},
             data:[220, 182, 191, 234, 290, 330, 310]
         },
         {
             name:'视频广告',
             type:'line',
             stack: '总量',
-            areaStyle: {normal: {}},
+            areaStyle: {},
             data:[150, 232, 201, 154, 190, 330, 410]
         },
         {
             name:'直接访问',
             type:'line',
             stack: '总量',
-            areaStyle: {normal: {}},
+            areaStyle: {},
             data:[320, 332, 301, 334, 390, 330, 320]
         },
         {
@@ -78,12 +78,10 @@
             type:'line',
             stack: '总量',
             label: {
-                normal: {
-                    show: true,
-                    position: 'top'
-                }
+                show: true,
+                position: 'top'
             },
-            areaStyle: {normal: {}},
+            areaStyle: {},
             data:[820, 932, 901, 934, 1290, 1330, 1320]
         }
     ]
diff --git a/theme/tool/option/bar.js b/theme/tool/option/bar.js
index 8cb7a7a..a97ea75 100644
--- a/theme/tool/option/bar.js
+++ b/theme/tool/option/bar.js
@@ -58,10 +58,8 @@
             type:'bar',
             stack: '总量',
             label: {
-                normal: {
-                    show: true,
-                    position: 'insideRight'
-                }
+                show: true,
+                position: 'insideRight'
             },
             data:[320, 302, 301, 334, 390, 330, 320]
         },
@@ -70,10 +68,8 @@
             type:'bar',
             stack: '总量',
             label: {
-                normal: {
-                    show: true,
-                    position: 'insideRight'
-                }
+                show: true,
+                position: 'insideRight'
             },
             data:[120, 132, 101, 134, 90, 230, 210]
         },
@@ -82,10 +78,8 @@
             type:'bar',
             stack: '总量',
             label: {
-                normal: {
-                    show: true,
-                    position: 'insideRight'
-                }
+                show: true,
+                position: 'insideRight'
             },
             data:[220, 182, 191, 234, 290, 330, 310]
         },
@@ -94,10 +88,8 @@
             type:'bar',
             stack: '总量',
             label: {
-                normal: {
-                    show: true,
-                    position: 'insideRight'
-                }
+                show: true,
+                position: 'insideRight'
             },
             data:[150, 212, 201, 154, 190, 330, 410]
         },
@@ -106,12 +98,10 @@
             type:'bar',
             stack: '总量',
             label: {
-                normal: {
-                    show: true,
-                    position: 'insideRight'
-                }
+                show: true,
+                position: 'insideRight'
             },
             data:[820, 832, 901, 934, 1290, 1330, 1320]
         }
     ]
-};
\ No newline at end of file
+};
diff --git a/theme/tool/option/graph.js b/theme/tool/option/graph.js
index c10878c..1b714c3 100644
--- a/theme/tool/option/graph.js
+++ b/theme/tool/option/graph.js
@@ -28,10 +28,8 @@
           "id":"0",
           "name":"Myriel",
           "label":{
-            "normal":{
-              "formatter":"Myriel",
-              "show":false
-            }
+            "formatter":"Myriel",
+            "show":false
           },
           "symbolSize":28.685715,
           "x":-266.82776,
@@ -46,10 +44,8 @@
           "id":"1",
           "name":"Napoleon",
           "label":{
-            "normal":{
-              "formatter":"Napoleon",
-              "show":false
-            }
+            "formatter":"Napoleon",
+            "show":false
           },
           "symbolSize":4,
           "x":-418.08344,
@@ -64,10 +60,8 @@
           "id":"2",
           "name":"MlleBaptistine",
           "label":{
-            "normal":{
-              "formatter":"MlleBaptistine",
-              "show":false
-            }
+            "formatter":"MlleBaptistine",
+            "show":false
           },
           "symbolSize":9.485714,
           "x":-212.76357,
@@ -82,10 +76,8 @@
           "id":"3",
           "name":"MmeMagloire",
           "label":{
-            "normal":{
-              "formatter":"MmeMagloire",
-              "show":false
-            }
+            "formatter":"MmeMagloire",
+            "show":false
           },
           "symbolSize":9.485714,
           "x":-242.82404,
@@ -100,10 +92,8 @@
           "id":"4",
           "name":"CountessDeLo",
           "label":{
-            "normal":{
-              "formatter":"CountessDeLo",
-              "show":false
-            }
+            "formatter":"CountessDeLo",
+            "show":false
           },
           "symbolSize":4,
           "x":-379.30386,
@@ -118,10 +108,8 @@
           "id":"5",
           "name":"Geborand",
           "label":{
-            "normal":{
-              "formatter":"Geborand",
-              "show":false
-            }
+            "formatter":"Geborand",
+            "show":false
           },
           "symbolSize":4,
           "x":-417.26337,
@@ -136,10 +124,8 @@
           "id":"6",
           "name":"Champtercier",
           "label":{
-            "normal":{
-              "formatter":"Champtercier",
-              "show":false
-            }
+            "formatter":"Champtercier",
+            "show":false
           },
           "symbolSize":4,
           "x":-332.6012,
@@ -154,10 +140,8 @@
           "id":"7",
           "name":"Cravatte",
           "label":{
-            "normal":{
-              "formatter":"Cravatte",
-              "show":false
-            }
+            "formatter":"Cravatte",
+            "show":false
           },
           "symbolSize":4,
           "x":-382.69568,
@@ -172,10 +156,8 @@
           "id":"8",
           "name":"Count",
           "label":{
-            "normal":{
-              "formatter":"Count",
-              "show":false
-            }
+            "formatter":"Count",
+            "show":false
           },
           "symbolSize":4,
           "x":-320.384,
@@ -190,10 +172,8 @@
           "id":"9",
           "name":"OldMan",
           "label":{
-            "normal":{
-              "formatter":"OldMan",
-              "show":false
-            }
+            "formatter":"OldMan",
+            "show":false
           },
           "symbolSize":4,
           "x":-344.39832,
@@ -208,10 +188,8 @@
           "id":"10",
           "name":"Labarre",
           "label":{
-            "normal":{
-              "formatter":"Labarre",
-              "show":false
-            }
+            "formatter":"Labarre",
+            "show":false
           },
           "symbolSize":4,
           "x":-89.34107,
@@ -226,10 +204,8 @@
           "id":"11",
           "name":"Valjean",
           "label":{
-            "normal":{
-              "formatter":"Valjean",
-              "show":  false
-            }
+            "formatter":"Valjean",
+            "show":  false
           },
           "symbolSize":100,
           "x":-87.93029,
@@ -244,10 +220,8 @@
           "id":"12",
           "name":"Marguerite",
           "label":{
-            "normal":{
-              "formatter":"Marguerite",
-              "show":false
-            }
+            "formatter":"Marguerite",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":-339.77908,
@@ -262,10 +236,8 @@
           "id":"13",
           "name":"MmeDeR",
           "label":{
-            "normal":{
-              "formatter":"MmeDeR",
-              "show":false
-            }
+            "formatter":"MmeDeR",
+            "show":false
           },
           "symbolSize":4,
           "x":-194.31313,
@@ -280,10 +252,8 @@
           "id":"14",
           "name":"Isabeau",
           "label":{
-            "normal":{
-              "formatter":"Isabeau",
-              "show":false
-            }
+            "formatter":"Isabeau",
+            "show":false
           },
           "symbolSize":4,
           "x":-158.05168,
@@ -298,10 +268,8 @@
           "id":"15",
           "name":"Gervais",
           "label":{
-            "normal":{
-              "formatter":"Gervais",
-              "show":false
-            }
+            "formatter":"Gervais",
+            "show":false
           },
           "symbolSize":4,
           "x":-127.701546,
@@ -316,10 +284,8 @@
           "id":"16",
           "name":"Tholomyes",
           "label":{
-            "normal":{
-              "formatter":"Tholomyes",
-              "show":false
-            }
+            "formatter":"Tholomyes",
+            "show":false
           },
           "symbolSize":25.942856,
           "x":-385.2226,
@@ -334,10 +300,8 @@
           "id":"17",
           "name":"Listolier",
           "label":{
-            "normal":{
-              "formatter":"Listolier",
-              "show":false
-            }
+            "formatter":"Listolier",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":-516.55884,
@@ -352,10 +316,8 @@
           "id":"18",
           "name":"Fameuil",
           "label":{
-            "normal":{
-              "formatter":"Fameuil",
-              "show":false
-            }
+            "formatter":"Fameuil",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":-464.79382,
@@ -370,10 +332,8 @@
           "id":"19",
           "name":"Blacheville",
           "label":{
-            "normal":{
-              "formatter":"Blacheville",
-              "show":false
-            }
+            "formatter":"Blacheville",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":-515.1624,
@@ -388,10 +348,8 @@
           "id":"20",
           "name":"Favourite",
           "label":{
-            "normal":{
-              "formatter":"Favourite",
-              "show":false
-            }
+            "formatter":"Favourite",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":-408.12122,
@@ -406,10 +364,8 @@
           "id":"21",
           "name":"Dahlia",
           "label":{
-            "normal":{
-              "formatter":"Dahlia",
-              "show":false
-            }
+            "formatter":"Dahlia",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":-456.44113,
@@ -424,10 +380,8 @@
           "id":"22",
           "name":"Zephine",
           "label":{
-            "normal":{
-              "formatter":"Zephine",
-              "show":false
-            }
+            "formatter":"Zephine",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":-459.1107,
@@ -442,10 +396,8 @@
           "id":"23",
           "name":"Fantine",
           "label":{
-            "normal":{
-              "formatter":"Fantine",
-              "show":  false
-            }
+            "formatter":"Fantine",
+            "show":  false
           },
           "symbolSize":42.4,
           "x":-313.42786,
@@ -460,10 +412,8 @@
           "id":"24",
           "name":"MmeThenardier",
           "label":{
-            "normal":{
-              "formatter":"MmeThenardier",
-              "show":  false
-            }
+            "formatter":"MmeThenardier",
+            "show":  false
           },
           "symbolSize":31.428574,
           "x":4.6313396,
@@ -478,10 +428,8 @@
           "id":"25",
           "name":"Thenardier",
           "label":{
-            "normal":{
-              "formatter":"Thenardier",
-              "show":  false
-            }
+            "formatter":"Thenardier",
+            "show":  false
           },
           "symbolSize":45.142853,
           "x":82.80825,
@@ -496,10 +444,8 @@
           "id":"26",
           "name":"Cosette",
           "label":{
-            "normal":{
-              "formatter":"Cosette",
-              "show":  false
-            }
+            "formatter":"Cosette",
+            "show":  false
           },
           "symbolSize":31.428574,
           "x":78.64646,
@@ -514,10 +460,8 @@
           "id":"27",
           "name":"Javert",
           "label":{
-            "normal":{
-              "formatter":"Javert",
-              "show":  false
-            }
+            "formatter":"Javert",
+            "show":  false
           },
           "symbolSize":47.88571,
           "x":-81.46074,
@@ -532,10 +476,8 @@
           "id":"28",
           "name":"Fauchelevent",
           "label":{
-            "normal":{
-              "formatter":"Fauchelevent",
-              "show":false
-            }
+            "formatter":"Fauchelevent",
+            "show":false
           },
           "symbolSize":12.228573,
           "x":-225.73984,
@@ -550,10 +492,8 @@
           "id":"29",
           "name":"Bamatabois",
           "label":{
-            "normal":{
-              "formatter":"Bamatabois",
-              "show":false
-            }
+            "formatter":"Bamatabois",
+            "show":false
           },
           "symbolSize":23.2,
           "x":-385.6842,
@@ -568,10 +508,8 @@
           "id":"30",
           "name":"Perpetue",
           "label":{
-            "normal":{
-              "formatter":"Perpetue",
-              "show":false
-            }
+            "formatter":"Perpetue",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":-403.92447,
@@ -586,10 +524,8 @@
           "id":"31",
           "name":"Simplice",
           "label":{
-            "normal":{
-              "formatter":"Simplice",
-              "show":false
-            }
+            "formatter":"Simplice",
+            "show":false
           },
           "symbolSize":12.228573,
           "x":-281.4253,
@@ -604,10 +540,8 @@
           "id":"32",
           "name":"Scaufflaire",
           "label":{
-            "normal":{
-              "formatter":"Scaufflaire",
-              "show":false
-            }
+            "formatter":"Scaufflaire",
+            "show":false
           },
           "symbolSize":4,
           "x":-122.41348,
@@ -622,10 +556,8 @@
           "id":"33",
           "name":"Woman1",
           "label":{
-            "normal":{
-              "formatter":"Woman1",
-              "show":false
-            }
+            "formatter":"Woman1",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":-234.6001,
@@ -640,10 +572,8 @@
           "id":"34",
           "name":"Judge",
           "label":{
-            "normal":{
-              "formatter":"Judge",
-              "show":false
-            }
+            "formatter":"Judge",
+            "show":false
           },
           "symbolSize":17.714287,
           "x":-387.84915,
@@ -658,10 +588,8 @@
           "id":"35",
           "name":"Champmathieu",
           "label":{
-            "normal":{
-              "formatter":"Champmathieu",
-              "show":false
-            }
+            "formatter":"Champmathieu",
+            "show":false
           },
           "symbolSize":17.714287,
           "x":-338.2307,
@@ -676,10 +604,8 @@
           "id":"36",
           "name":"Brevet",
           "label":{
-            "normal":{
-              "formatter":"Brevet",
-              "show":false
-            }
+            "formatter":"Brevet",
+            "show":false
           },
           "symbolSize":17.714287,
           "x":-453.26874,
@@ -694,10 +620,8 @@
           "id":"37",
           "name":"Chenildieu",
           "label":{
-            "normal":{
-              "formatter":"Chenildieu",
-              "show":false
-            }
+            "formatter":"Chenildieu",
+            "show":false
           },
           "symbolSize":17.714287,
           "x":-386.44904,
@@ -712,10 +636,8 @@
           "id":"38",
           "name":"Cochepaille",
           "label":{
-            "normal":{
-              "formatter":"Cochepaille",
-              "show":false
-            }
+            "formatter":"Cochepaille",
+            "show":false
           },
           "symbolSize":17.714287,
           "x":-446.7876,
@@ -730,10 +652,8 @@
           "id":"39",
           "name":"Pontmercy",
           "label":{
-            "normal":{
-              "formatter":"Pontmercy",
-              "show":false
-            }
+            "formatter":"Pontmercy",
+            "show":false
           },
           "symbolSize":9.485714,
           "x":336.49738,
@@ -748,10 +668,8 @@
           "id":"40",
           "name":"Boulatruelle",
           "label":{
-            "normal":{
-              "formatter":"Boulatruelle",
-              "show":false
-            }
+            "formatter":"Boulatruelle",
+            "show":false
           },
           "symbolSize":4,
           "x":29.187843,
@@ -766,10 +684,8 @@
           "id":"41",
           "name":"Eponine",
           "label":{
-            "normal":{
-              "formatter":"Eponine",
-              "show":  false
-            }
+            "formatter":"Eponine",
+            "show":  false
           },
           "symbolSize":31.428574,
           "x":238.36697,
@@ -784,10 +700,8 @@
           "id":"42",
           "name":"Anzelma",
           "label":{
-            "normal":{
-              "formatter":"Anzelma",
-              "show":false
-            }
+            "formatter":"Anzelma",
+            "show":false
           },
           "symbolSize":9.485714,
           "x":189.69513,
@@ -802,10 +716,8 @@
           "id":"43",
           "name":"Woman2",
           "label":{
-            "normal":{
-              "formatter":"Woman2",
-              "show":false
-            }
+            "formatter":"Woman2",
+            "show":false
           },
           "symbolSize":9.485714,
           "x":-187.00418,
@@ -820,10 +732,8 @@
           "id":"44",
           "name":"MotherInnocent",
           "label":{
-            "normal":{
-              "formatter":"MotherInnocent",
-              "show":false
-            }
+            "formatter":"MotherInnocent",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":-252.99521,
@@ -838,10 +748,8 @@
           "id":"45",
           "name":"Gribier",
           "label":{
-            "normal":{
-              "formatter":"Gribier",
-              "show":false
-            }
+            "formatter":"Gribier",
+            "show":false
           },
           "symbolSize":4,
           "x":-296.07935,
@@ -856,10 +764,8 @@
           "id":"46",
           "name":"Jondrette",
           "label":{
-            "normal":{
-              "formatter":"Jondrette",
-              "show":false
-            }
+            "formatter":"Jondrette",
+            "show":false
           },
           "symbolSize":4,
           "x":550.3201,
@@ -874,10 +780,8 @@
           "id":"47",
           "name":"MmeBurgon",
           "label":{
-            "normal":{
-              "formatter":"MmeBurgon",
-              "show":false
-            }
+            "formatter":"MmeBurgon",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":488.13535,
@@ -892,10 +796,8 @@
           "id":"48",
           "name":"Gavroche",
           "label":{
-            "normal":{
-              "formatter":"Gavroche",
-              "show":  false
-            }
+            "formatter":"Gavroche",
+            "show":  false
           },
           "symbolSize":61.600006,
           "x":387.89572,
@@ -910,10 +812,8 @@
           "id":"49",
           "name":"Gillenormand",
           "label":{
-            "normal":{
-              "formatter":"Gillenormand",
-              "show":false
-            }
+            "formatter":"Gillenormand",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":126.4831,
@@ -928,10 +828,8 @@
           "id":"50",
           "name":"Magnon",
           "label":{
-            "normal":{
-              "formatter":"Magnon",
-              "show":false
-            }
+            "formatter":"Magnon",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":127.07365,
@@ -946,10 +844,8 @@
           "id":"51",
           "name":"MlleGillenormand",
           "label":{
-            "normal":{
-              "formatter":"MlleGillenormand",
-              "show":false
-            }
+            "formatter":"MlleGillenormand",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":162.63559,
@@ -964,10 +860,8 @@
           "id":"52",
           "name":"MmePontmercy",
           "label":{
-            "normal":{
-              "formatter":"MmePontmercy",
-              "show":false
-            }
+            "formatter":"MmePontmercy",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":353.66415,
@@ -982,10 +876,8 @@
           "id":"53",
           "name":"MlleVaubois",
           "label":{
-            "normal":{
-              "formatter":"MlleVaubois",
-              "show":false
-            }
+            "formatter":"MlleVaubois",
+            "show":false
           },
           "symbolSize":4,
           "x":165.43939,
@@ -1000,10 +892,8 @@
           "id":"54",
           "name":"LtGillenormand",
           "label":{
-            "normal":{
-              "formatter":"LtGillenormand",
-              "show":false
-            }
+            "formatter":"LtGillenormand",
+            "show":false
           },
           "symbolSize":12.228573,
           "x":137.69348,
@@ -1018,10 +908,8 @@
           "id":"55",
           "name":"Marius",
           "label":{
-            "normal":{
-              "formatter":"Marius",
-              "show":  false
-            }
+            "formatter":"Marius",
+            "show":  false
           },
           "symbolSize":53.37143,
           "x":206.44687,
@@ -1036,10 +924,8 @@
           "id":"56",
           "name":"BaronessT",
           "label":{
-            "normal":{
-              "formatter":"BaronessT",
-              "show":false
-            }
+            "formatter":"BaronessT",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":194.82993,
@@ -1054,10 +940,8 @@
           "id":"57",
           "name":"Mabeuf",
           "label":{
-            "normal":{
-              "formatter":"Mabeuf",
-              "show":  false
-            }
+            "formatter":"Mabeuf",
+            "show":  false
           },
           "symbolSize":31.428574,
           "x":597.6618,
@@ -1072,10 +956,8 @@
           "id":"58",
           "name":"Enjolras",
           "label":{
-            "normal":{
-              "formatter":"Enjolras",
-              "show":  false
-            }
+            "formatter":"Enjolras",
+            "show":  false
           },
           "symbolSize":42.4,
           "x":355.78366,
@@ -1090,10 +972,8 @@
           "id":"59",
           "name":"Combeferre",
           "label":{
-            "normal":{
-              "formatter":"Combeferre",
-              "show":  false
-            }
+            "formatter":"Combeferre",
+            "show":  false
           },
           "symbolSize":31.428574,
           "x":515.2961,
@@ -1108,10 +988,8 @@
           "id":"60",
           "name":"Prouvaire",
           "label":{
-            "normal":{
-              "formatter":"Prouvaire",
-              "show":false
-            }
+            "formatter":"Prouvaire",
+            "show":false
           },
           "symbolSize":25.942856,
           "x":614.29285,
@@ -1126,10 +1004,8 @@
           "id":"61",
           "name":"Feuilly",
           "label":{
-            "normal":{
-              "formatter":"Feuilly",
-              "show":  false
-            }
+            "formatter":"Feuilly",
+            "show":  false
           },
           "symbolSize":31.428574,
           "x":550.1917,
@@ -1144,10 +1020,8 @@
           "id":"62",
           "name":"Courfeyrac",
           "label":{
-            "normal":{
-              "formatter":"Courfeyrac",
-              "show":  false
-            }
+            "formatter":"Courfeyrac",
+            "show":  false
           },
           "symbolSize":36.91429,
           "x":436.17184,
@@ -1162,10 +1036,8 @@
           "id":"63",
           "name":"Bahorel",
           "label":{
-            "normal":{
-              "formatter":"Bahorel",
-              "show":  false
-            }
+            "formatter":"Bahorel",
+            "show":  false
           },
           "symbolSize":34.17143,
           "x":602.55225,
@@ -1180,10 +1052,8 @@
           "id":"64",
           "name":"Bossuet",
           "label":{
-            "normal":{
-              "formatter":"Bossuet",
-              "show":  false
-            }
+            "formatter":"Bossuet",
+            "show":  false
           },
           "symbolSize":36.91429,
           "x":455.81955,
@@ -1198,10 +1068,8 @@
           "id":"65",
           "name":"Joly",
           "label":{
-            "normal":{
-              "formatter":"Joly",
-              "show":  false
-            }
+            "formatter":"Joly",
+            "show":  false
           },
           "symbolSize":34.17143,
           "x":516.40784,
@@ -1216,10 +1084,8 @@
           "id":"66",
           "name":"Grantaire",
           "label":{
-            "normal":{
-              "formatter":"Grantaire",
-              "show":false
-            }
+            "formatter":"Grantaire",
+            "show":false
           },
           "symbolSize":28.685715,
           "x":646.4313,
@@ -1234,10 +1100,8 @@
           "id":"67",
           "name":"MotherPlutarch",
           "label":{
-            "normal":{
-              "formatter":"MotherPlutarch",
-              "show":false
-            }
+            "formatter":"MotherPlutarch",
+            "show":false
           },
           "symbolSize":4,
           "x":668.9568,
@@ -1252,10 +1116,8 @@
           "id":"68",
           "name":"Gueulemer",
           "label":{
-            "normal":{
-              "formatter":"Gueulemer",
-              "show":false
-            }
+            "formatter":"Gueulemer",
+            "show":false
           },
           "symbolSize":28.685715,
           "x":78.4799,
@@ -1270,10 +1132,8 @@
           "id":"69",
           "name":"Babet",
           "label":{
-            "normal":{
-              "formatter":"Babet",
-              "show":false
-            }
+            "formatter":"Babet",
+            "show":false
           },
           "symbolSize":28.685715,
           "x":150.35959,
@@ -1288,10 +1148,8 @@
           "id":"70",
           "name":"Claquesous",
           "label":{
-            "normal":{
-              "formatter":"Claquesous",
-              "show":false
-            }
+            "formatter":"Claquesous",
+            "show":false
           },
           "symbolSize":28.685715,
           "x":137.3717,
@@ -1306,10 +1164,8 @@
           "id":"71",
           "name":"Montparnasse",
           "label":{
-            "normal":{
-              "formatter":"Montparnasse",
-              "show":false
-            }
+            "formatter":"Montparnasse",
+            "show":false
           },
           "symbolSize":25.942856,
           "x":234.87747,
@@ -1324,10 +1180,8 @@
           "id":"72",
           "name":"Toussaint",
           "label":{
-            "normal":{
-              "formatter":"Toussaint",
-              "show":false
-            }
+            "formatter":"Toussaint",
+            "show":false
           },
           "symbolSize":9.485714,
           "x":40.942253,
@@ -1342,10 +1196,8 @@
           "id":"73",
           "name":"Child1",
           "label":{
-            "normal":{
-              "formatter":"Child1",
-              "show":false
-            }
+            "formatter":"Child1",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":437.939,
@@ -1360,10 +1212,8 @@
           "id":"74",
           "name":"Child2",
           "label":{
-            "normal":{
-              "formatter":"Child2",
-              "show":false
-            }
+            "formatter":"Child2",
+            "show":false
           },
           "symbolSize":6.742859,
           "x":466.04922,
@@ -1378,10 +1228,8 @@
           "id":"75",
           "name":"Brujon",
           "label":{
-            "normal":{
-              "formatter":"Brujon",
-              "show":false
-            }
+            "formatter":"Brujon",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":238.79364,
@@ -1396,10 +1244,8 @@
           "id":"76",
           "name":"MmeHucheloup",
           "label":{
-            "normal":{
-              "formatter":"MmeHucheloup",
-              "show":false
-            }
+            "formatter":"MmeHucheloup",
+            "show":false
           },
           "symbolSize":20.457146,
           "x":712.18353,
@@ -2968,15 +2814,11 @@
       ],
       "roam":true,
       "label":{
-        "normal":{
-          "position":"right"
-        }
+        "position":"right"
       },
       "lineStyle":{
-        "normal":{
-          "curveness":0.3
-        }
+        "curveness":0.3
       }
     }
   ]
-};
\ No newline at end of file
+};
diff --git a/theme/tool/option/map.js b/theme/tool/option/map.js
index 1cd4f4d..3b0ce19 100644
--- a/theme/tool/option/map.js
+++ b/theme/tool/option/map.js
@@ -35,11 +35,11 @@
             map: 'china',
             showLegendSymbol: true,
             label: {
-                normal: {
-                    show: false
-                },
-                emphasis: {
-                    show: false
+                show: false,
+            },
+            emphasis: {
+                label: {
+                    show: false,
                 }
             },
             data:[
@@ -85,10 +85,10 @@
             mapType: 'china',
             showLegendSymbol: true,
             label: {
-                normal: {
-                    show: false
-                },
-                emphasis: {
+                show: false,
+            },
+            emphasis: {
+                label: {
                     show: false
                 }
             },
@@ -120,10 +120,10 @@
             mapType: 'china',
             showLegendSymbol: true,
             label: {
-                normal: {
-                    show: false
-                },
-                emphasis: {
+                show: false,
+            },
+            emphasis: {
+                label: {
                     show: false
                 }
             },
@@ -138,4 +138,4 @@
             ]
         }
     ]
-};
\ No newline at end of file
+};
diff --git a/theme/tool/option/pie.js b/theme/tool/option/pie.js
index c88e11e..1170ab1 100644
--- a/theme/tool/option/pie.js
+++ b/theme/tool/option/pie.js
@@ -29,18 +29,16 @@
             radius : [20, 80],
             center : ['25%', 110],
             label: {
-                normal: {
-                    show: false
-                },
-                emphasis: {
-                    show: true
-                }
+                show: false,
             },
             lableLine: {
-                normal: {
-                    show: false
+                show: false,
+            },
+            emphasis: {
+                label: {
+                    show: true
                 },
-                emphasis: {
+                lableLine: {
                     show: true
                 }
             },
@@ -62,9 +60,7 @@
             center : ['75%', 110],
             roseType : 'area',
             labelLine: {
-                normal: {
-                    length: 5
-                }
+                length: 5
             },
             data:[
                 {value:10, name:'rose1'},