Merge pull request #14630 from apache/fix-pie-display-nan

fix(pie): fix pie display NaN labels  
diff --git a/src/chart/map/MapView.ts b/src/chart/map/MapView.ts
index 48df6e8..1a960d5 100644
--- a/src/chart/map/MapView.ts
+++ b/src/chart/map/MapView.ts
@@ -25,17 +25,9 @@
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../core/ExtensionAPI';
 import { Payload, DisplayState, ECElement } from '../../util/types';
-import Model from '../../model/Model';
 import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';
 import { Z2_EMPHASIS_LIFT } from '../../util/states';
 
-interface HighDownRecord {
-    recordVersion: number;
-    labelModel: Model;
-    hoverLabelModel: Model;
-    emphasisText: string;
-    normalText: string;
-};
 
 class MapView extends ChartView {
 
@@ -64,6 +56,10 @@
             return;
         }
 
+        if (this._mapDraw && payload && payload.type === 'geoRoam') {
+            this._mapDraw.resetForLabelLayout();
+        }
+
         // Not update map if it is an roam action from self
         if (!(payload && payload.type === 'geoRoam'
                 && payload.componentType === 'series'
diff --git a/src/component/graphic/install.ts b/src/component/graphic/install.ts
index bda54f3..61ed438 100644
--- a/src/component/graphic/install.ts
+++ b/src/component/graphic/install.ts
@@ -45,7 +45,6 @@
 import { TextStyleProps } from 'zrender/src/graphic/Text';
 import { isEC4CompatibleStyle, convertFromEC4CompatibleStyle } from '../../util/styleCompat';
 import { EChartsExtensionInstallRegisters } from '../../extension';
-import { graphic } from '../../export/api';
 
 const TRANSFORM_PROPS = {
     x: 1,
diff --git a/src/component/helper/MapDraw.ts b/src/component/helper/MapDraw.ts
index 5388053..aefc310 100644
--- a/src/component/helper/MapDraw.ts
+++ b/src/component/helper/MapDraw.ts
@@ -38,10 +38,9 @@
 import MapView from '../../chart/map/MapView';
 import Geo from '../../coord/geo/Geo';
 import Model from '../../model/Model';
-import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';
+import { setLabelStyle, getLabelStatesModels, enableLayoutLayoutFeatures } from '../../label/labelStyle';
 import { getECData } from '../../util/innerStore';
 import { createOrUpdatePatternFromDecal } from '../../util/decal';
-import { makeInner } from '../../util/model';
 import ZRText, {TextStyleProps} from 'zrender/src/graphic/Text';
 import { ViewCoordSysTransformInfoPart } from '../../coord/View';
 import { GeoSVGGraphicRecord, GeoSVGResource } from '../../coord/geo/GeoSVGResource';
@@ -50,11 +49,7 @@
 import List from '../../data/List';
 import { GeoJSONRegion } from '../../coord/geo/Region';
 import { SVGNodeTagLower } from 'zrender/src/tool/parseSVG';
-
-const mapLabelTransform = makeInner<{
-    x: number
-    y: number
-}, ZRText>();
+import { makeInner } from '../../util/model';
 
 interface RegionsGroup extends graphic.Group {
 }
@@ -96,6 +91,9 @@
 const LABEL_HOST_MAP = zrUtil.createHashMap<number, SVGNodeTagLower>(
     OPTION_STYLE_ENABLED_TAGS.concat(['g']) as SVGNodeTagLower[]
 );
+const mapLabelRaw = makeInner<{
+    ignore: boolean
+}, ZRText>();
 
 
 function getFixedItemStyle(model: Model<GeoItemStyleOption>) {
@@ -520,30 +518,11 @@
             return action;
         }
 
-        const updateLabelTransforms = () => {
-            const group = this.group;
-            this._regionsGroup.traverse(function (el) {
-                const textContent = el.getTextContent();
-                if (textContent) {
-                    el.setTextConfig({
-                        local: true
-                    });
-                    textContent.x = mapLabelTransform(textContent).x || 0;
-                    textContent.y = mapLabelTransform(textContent).y || 0;
-                    textContent.scaleX = 1 / group.scaleX;
-                    textContent.scaleY = 1 / group.scaleY;
-                    textContent.markRedraw();
-                }
-            });
-        };
-
         controller.off('pan').on('pan', function (e) {
             this._mouseDownFlag = false;
 
             roamHelper.updateViewOnPan(controllerHost, e.dx, e.dy);
 
-            updateLabelTransforms();
-
             api.dispatchAction(zrUtil.extend(makeActionBase(), {
                 dx: e.dx,
                 dy: e.dy
@@ -555,8 +534,6 @@
 
             roamHelper.updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
 
-            updateLabelTransforms();
-
             api.dispatchAction(zrUtil.extend(makeActionBase(), {
                 zoom: e.scale,
                 originX: e.originX,
@@ -571,6 +548,26 @@
         });
     }
 
+    /**
+     * FIXME: this is a temporarily workaround.
+     * When `geoRoam` the elements need to be reset in `MapView['render']`, because the props like
+     * `ignore` might have been modified by `LabelManager`, and `LabelManager#addLabelsOfSeries`
+     * will subsequently cache `defaultAttr` like `ignore`. If do not do this reset, the modified
+     * props will have no chance to be restored.
+     * Note: this reset should be after `clearStates` in `renderSeries` becuase `useStates` in
+     * `renderSeries` will cache the modified `ignore` to `el._normalState`.
+     * TODO:
+     * Use clone/immutable in `LabelManager`?
+     */
+    resetForLabelLayout() {
+        this.group.traverse(el => {
+            const label = el.getTextContent();
+            if (label) {
+                label.ignore = mapLabelRaw(label).ignore;
+            }
+        });
+    }
+
     private _updateMapSelectHandler(
         mapOrGeoModel: GeoModel | MapSeries,
         regionsGroup: RegionsGroup,
@@ -600,16 +597,6 @@
 
 };
 
-function labelTextAfterUpdate(this: graphic.Text) {
-    // Make the label text apply only translate of this host el
-    // but no other transform like scale,rotation of this host el.
-    const mt = this.transform;
-    mt[0] = 1;
-    mt[1] = 0;
-    mt[2] = 0;
-    mt[3] = 1;
-}
-
 function applyOptionStyleForRegion(
     viewBuildCtx: ViewBuildContext,
     el: Displayable,
@@ -727,20 +714,22 @@
 
         const textEl = el.getTextContent();
         if (textEl) {
-            mapLabelTransform(textEl).x = textEl.x = labelXY ? labelXY[0] : 0;
-            mapLabelTransform(textEl).y = textEl.y = labelXY ? labelXY[1] : 0;
-            textEl.z2 = 10;
-            textEl.afterUpdate = labelTextAfterUpdate;
-        }
+            mapLabelRaw(textEl).ignore = textEl.ignore;
 
-        // Need to apply the `translate`.
-        if (el.textConfig) {
-            el.textConfig.local = true;
-            if (labelXY) {
-                el.textConfig.position = null;
+            if (el.textConfig) {
+                if (labelXY) {
+                    // Compute a relative offset based on the el bounding rect.
+                    const rect = el.getBoundingRect().clone();
+                    el.textConfig.position = [
+                        ((labelXY[0] - rect.x) / rect.width * 100) + '%',
+                        ((labelXY[1] - rect.y) / rect.height * 100) + '%'
+                    ];
+                }
             }
         }
 
+        enableLayoutLayoutFeatures(el, dataIdx, null);
+
         (el as ECElement).disableLabelAnimation = true;
     }
     else {
diff --git a/src/component/legend/LegendModel.ts b/src/component/legend/LegendModel.ts
index ca5e094..ccf5ba8 100644
--- a/src/component/legend/LegendModel.ts
+++ b/src/component/legend/LegendModel.ts
@@ -29,9 +29,6 @@
     LabelOption,
     LayoutOrient,
     CommonTooltipOption,
-    ZRColor,
-    DecalObject,
-    ZRLineType,
     ItemStyleOption,
     LineStyleOption
 } from '../../util/types';
@@ -39,7 +36,6 @@
 import GlobalModel from '../../model/Global';
 import { ItemStyleProps } from '../../model/mixin/itemStyle';
 import { LineStyleProps } from './../../model/mixin/lineStyle';
-import {SeriesModel} from '../../echarts';
 import {PathStyleProps} from 'zrender/src/graphic/Path';
 
 type LegendDefaultSelectorOptionsProps = {
diff --git a/src/component/legend/LegendView.ts b/src/component/legend/LegendView.ts
index 8b0a775..7d7cab4 100644
--- a/src/component/legend/LegendView.ts
+++ b/src/component/legend/LegendView.ts
@@ -27,7 +27,14 @@
 import {makeBackground} from '../helper/listComponent';
 import * as layoutUtil from '../../util/layout';
 import ComponentView from '../../view/Component';
-import LegendModel, { LegendItemStyleOption, LegendLineStyleOption, LegendOption, LegendSelectorButtonOption, LegendSymbolParams, LegendTooltipFormatterParams } from './LegendModel';
+import LegendModel, {
+    LegendItemStyleOption,
+    LegendLineStyleOption,
+    LegendOption,
+    LegendSelectorButtonOption,
+    LegendSymbolParams,
+    LegendTooltipFormatterParams
+} from './LegendModel';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../core/ExtensionAPI';
 import {
@@ -39,10 +46,10 @@
     SymbolOptionMixin
 } from '../../util/types';
 import Model from '../../model/Model';
-import {SeriesModel} from '../../echarts';
 import {LineStyleProps, LINE_STYLE_KEY_MAP} from '../../model/mixin/lineStyle';
 import {ITEM_STYLE_KEY_MAP} from '../../model/mixin/itemStyle';
 import {createSymbol, ECSymbol} from '../../util/symbol';
+import SeriesModel from '../../model/Series';
 
 const curry = zrUtil.curry;
 const each = zrUtil.each;
@@ -347,7 +354,15 @@
         symbolType = legendIconType || symbolType || 'roundRect';
 
         const legendLineStyle = legendModel.getModel('lineStyle');
-        const style = getLegendStyle(symbolType, itemModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected);
+        const style = getLegendStyle(
+            symbolType,
+            itemModel,
+            legendLineStyle,
+            lineVisualStyle,
+            itemVisualStyle,
+            drawType,
+            isSelected
+        );
 
         const itemGroup = new Group();
 
diff --git a/src/coord/View.ts b/src/coord/View.ts
index f6a68f9..452fb0e 100644
--- a/src/coord/View.ts
+++ b/src/coord/View.ts
@@ -226,14 +226,22 @@
         roam: ViewCoordSysTransformInfoPart
         raw: ViewCoordSysTransformInfoPart
     } {
-        const roamTransformable = this._roamTransformable;
         const rawTransformable = this._rawTransformable;
+
+        const roamTransformable = this._roamTransformable;
+        // Becuase roamTransformabel has `originX/originY` modified,
+        // but the caller of `getTransformInfo` can not handle `originX/originY`,
+        // so need to recalcualte them.
+        const dummyTransformable = new Transformable();
+        dummyTransformable.transform = roamTransformable.transform;
+        dummyTransformable.decomposeTransform();
+
         return {
             roam: {
-                x: roamTransformable.x,
-                y: roamTransformable.y,
-                scaleX: roamTransformable.scaleX,
-                scaleY: roamTransformable.scaleY
+                x: dummyTransformable.x,
+                y: dummyTransformable.y,
+                scaleX: dummyTransformable.scaleX,
+                scaleY: dummyTransformable.scaleY
             },
             raw: {
                 x: rawTransformable.x,
diff --git a/src/coord/geo/GeoSVGResource.ts b/src/coord/geo/GeoSVGResource.ts
index 8018f39..e0e6d59 100644
--- a/src/coord/geo/GeoSVGResource.ts
+++ b/src/coord/geo/GeoSVGResource.ts
@@ -236,6 +236,12 @@
             rootFromParse.y = viewBoxTransform.y;
         }
 
+        // SVG needs to clip based on `viewBox`. And some SVG files really rely on this feature.
+        // They do not strictly confine all of the content inside a display rect, but deliberately
+        // use a `viewBox` to define a displayable rect.
+        // PENDING:
+        // The drawback of the `setClipPath` here is: the region label (genereted by echarts) near the
+        // edge might also be clipped, because region labels are put as `textContent` of the SVG path.
         root.setClipPath(new Rect({
             shape: boundingRect.plain()
         }));
diff --git a/src/label/labelStyle.ts b/src/label/labelStyle.ts
index 713093a..002a77d 100644
--- a/src/label/labelStyle.ts
+++ b/src/label/labelStyle.ts
@@ -30,7 +30,8 @@
     ColorString,
     ZRStyleProps,
     AnimationOptionMixin,
-    InterpolatableValue
+    InterpolatableValue,
+    SeriesDataType
 } from '../util/types';
 import GlobalModel from '../model/Global';
 import { isFunction, retrieve2, extend, keys, trim } from 'zrender/src/core/util';
@@ -39,6 +40,7 @@
 import { makeInner, interpolateRawValues } from '../util/model';
 import List from '../data/List';
 import { initProps, updateProps } from '../util/graphic';
+import { getECData } from '../util/innerStore';
 
 type TextCommonParams = {
     /**
@@ -727,3 +729,12 @@
         : updateProps
     )(textEl, {}, animatableModel, dataIndex, null, during);
 }
+
+export function enableLayoutLayoutFeatures(
+    el: Element,
+    dataIndex: number,
+    dataType: SeriesDataType
+): void {
+    getECData(el).dataIndex = dataIndex;
+    getECData(el).dataType = dataType;
+}
diff --git a/src/model/Series.ts b/src/model/Series.ts
index 2056c39..8e90bf3 100644
--- a/src/model/Series.ts
+++ b/src/model/Series.ts
@@ -20,7 +20,6 @@
 import * as zrUtil from 'zrender/src/core/util';
 import env from 'zrender/src/core/env';
 import type {MorphDividingMethod} from 'zrender/src/tool/morphPath';
-import {PathStyleProps} from 'zrender/src/graphic/Path';
 import * as modelUtil from '../util/model';
 import {
     DataHost, DimensionName, StageHandlerProgressParams,
diff --git a/src/util/symbol.ts b/src/util/symbol.ts
index bc8de18..dee0263 100644
--- a/src/util/symbol.ts
+++ b/src/util/symbol.ts
@@ -288,7 +288,7 @@
         return res;
     },
 
-    buildPath: function (ctx, shape, inBundle) {
+    buildPath(ctx, shape, inBundle) {
         let symbolType = shape.symbolType;
         if (symbolType !== 'none') {
             let proxySymbol = symbolBuildProxies[symbolType];
diff --git a/test/label-layout.html b/test/label-layout.html
index 6c49908..cf23862 100644
--- a/test/label-layout.html
+++ b/test/label-layout.html
@@ -52,6 +52,8 @@
         <div id="main9"></div>
         <div id="main10"></div>
         <div id="main11"></div>
+        <div id="main12"></div>
+        <div id="main13"></div>
 
 
 
@@ -827,6 +829,96 @@
                 });
             });
         </script>
+
+
+        <script>
+        require(['echarts'/*, 'map/js/china' */], function (echarts) {
+            const svg = [
+                '<?xml version="1.0" encoding="utf-8"?>',
+                '<svg viewBox="-25 0 300 100" xmlns="http://www.w3.org/2000/svg" xmlns:ooo="http://xml.openoffice.org/svg/export" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" fill-rule="evenodd" xml:space="preserve">',
+                '<path name="left_rect" d="M 0,0 L 0,100 100,100 100,0 Z" fill="#765" stroke="rgb(56,93,138)" stroke-width="0" stroke-linecap="square" stroke-linejoin="miter"/>',
+                '<path name="right_rect" d="M 150,0 L 150,100 250,100 250,0 Z" fill="#567" stroke="rgb(56,93,138)" stroke-width="0" stroke-linecap="square" stroke-linejoin="miter"/>',
+                '</svg>'
+            ].join('')
+
+            echarts.registerMap('testGeoSVG_coord1', { svg: svg });
+
+            option = {
+                series: [{
+                    type: 'map',
+                    roam: true,
+                    top: 10,
+                    bottom: 10,
+                    left: 10,
+                    right: 10,
+                    selectedMode: 'multiple',
+                    map: 'testGeoSVG_coord1',
+                    select: {
+                        itemStyle: {
+                            color: 'red'
+                        },
+                        label: {
+                            color: '#fff'
+                        }
+                    },
+                    label: {
+                        show: true,
+                        fontSize: 30
+                    },
+                    labelLayout: {
+                        hideOverlap: true
+                    }
+                }]
+            };
+
+            var chart = testHelper.create(echarts, 'main12', {
+                title: [
+                    'Click both rect make them selected (become red)',
+                    '(1) zoom to trigger label **hideOverlap**',
+                    'zoom back, check labels should be restored',
+                    '(2) mouseover one the **right rect** and zoom to trigger label **hideOverlap**',
+                    'zoom back, mouseout, check the label should not disappear'
+                ],
+                option: option,
+                height: 200,
+            });
+        });
+        </script>
+
+
+
+        <script>
+        require(['echarts'/*, 'map/js/china' */], function (echarts) {
+            const svg = [
+                '<?xml version="1.0" encoding="utf-8"?>',
+                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:ooo="http://xml.openoffice.org/svg/export" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" fill-rule="evenodd" xml:space="preserve">',
+                '<path name="left_rect" d="M 0,0 L 0,100 100,100 100,0 Z" fill="#765" stroke="rgb(56,93,138)" stroke-width="0" stroke-linecap="square" stroke-linejoin="miter"/>',
+                '</svg>'
+            ].join('')
+
+            echarts.registerMap('testGeoSVG_coord2', { svg: svg });
+
+            option = {
+                geo: {
+                    map: 'testGeoSVG_coord2',
+                    roam: true
+                }
+            };
+
+            var chart = testHelper.create(echarts, 'main13', {
+                title: [
+                    '(geo coordSys) label displayed only on hover',
+                    'zoom: label should keep displayed.'
+                ],
+                option: option,
+                height: 200,
+            });
+        });
+        </script>
+
+
+
+
     </body>
 </html>
 
diff --git a/test/runTest/actions/__meta__.json b/test/runTest/actions/__meta__.json
index b082222..53217ac 100644
--- a/test/runTest/actions/__meta__.json
+++ b/test/runTest/actions/__meta__.json
@@ -94,7 +94,7 @@
   "hoverStyle": 14,
   "hoverStyle2": 1,
   "label-animation": 3,
-  "label-layout": 2,
+  "label-layout": 4,
   "label-position": 1,
   "largeLine-tooltip": 1,
   "legend": 11,
diff --git a/test/runTest/actions/label-layout.json b/test/runTest/actions/label-layout.json
index a1bd982..dbf8a20 100644
--- a/test/runTest/actions/label-layout.json
+++ b/test/runTest/actions/label-layout.json
@@ -1 +1 @@
-[{"name":"Action 1","ops":[{"type":"mousemove","time":47,"x":689,"y":417},{"type":"mousemove","time":320,"x":689,"y":415},{"type":"mousemove","time":473,"x":689,"y":415},{"type":"mousedown","time":546,"x":689,"y":415},{"type":"mousemove","time":679,"x":682,"y":380},{"type":"mousemove","time":1002,"x":675,"y":339},{"type":"mouseup","time":1054,"x":675,"y":339},{"time":1055,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1240,"x":674,"y":339},{"type":"mousemove","time":1441,"x":524,"y":208},{"type":"mousemove","time":1641,"x":506,"y":166},{"type":"mousemove","time":1842,"x":498,"y":140},{"type":"mousedown","time":1956,"x":497,"y":138},{"type":"mousemove","time":2042,"x":486,"y":153},{"type":"mousemove","time":2256,"x":374,"y":206},{"type":"mousemove","time":2458,"x":149,"y":277},{"type":"mousemove","time":2665,"x":111,"y":290},{"type":"mouseup","time":2949,"x":111,"y":290},{"time":2950,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3377,"x":111,"y":290},{"type":"mousemove","time":3584,"x":111,"y":292},{"type":"mousedown","time":3741,"x":112,"y":286},{"type":"mousemove","time":3794,"x":119,"y":290},{"type":"mousemove","time":4007,"x":381,"y":351},{"type":"mousemove","time":4210,"x":389,"y":362},{"type":"mousemove","time":4410,"x":375,"y":410},{"type":"mousemove","time":4611,"x":359,"y":502},{"type":"mousemove","time":4811,"x":353,"y":532},{"type":"mousemove","time":5021,"x":353,"y":533},{"type":"mouseup","time":5029,"x":353,"y":533},{"time":5030,"delay":400,"type":"screenshot-auto"}],"scrollY":3167,"scrollX":0,"timestamp":1603949926971},{"name":"Action 2","ops":[{"type":"mousewheel","time":616,"x":446,"y":370,"deltaY":4.000244140625},{"type":"mousewheel","time":647,"x":446,"y":370,"deltaY":68.49853515625},{"type":"mousewheel","time":716,"x":446,"y":370,"deltaY":195.638427734375},{"type":"mousewheel","time":850,"x":446,"y":370,"deltaY":177.509765625},{"type":"mousemove","time":1199,"x":446,"y":370},{"type":"mousemove","time":1399,"x":445,"y":374},{"type":"mousedown","time":1578,"x":280,"y":451},{"type":"mousemove","time":1600,"x":280,"y":451},{"type":"mousemove","time":1816,"x":490,"y":390},{"type":"mousemove","time":2016,"x":596,"y":356},{"type":"mousemove","time":2220,"x":609,"y":350},{"type":"mouseup","time":2276,"x":609,"y":350},{"time":2277,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2483,"x":609,"y":350},{"type":"mousemove","time":2689,"x":612,"y":352},{"type":"mousemove","time":2750,"x":612,"y":353},{"type":"mousedown","time":2796,"x":611,"y":354},{"type":"mousemove","time":2959,"x":513,"y":392},{"type":"mousemove","time":3166,"x":367,"y":426},{"type":"mousemove","time":3374,"x":259,"y":450},{"type":"mouseup","time":3513,"x":259,"y":450},{"time":3514,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3616,"x":259,"y":450},{"type":"mousemove","time":3817,"x":269,"y":448},{"type":"mousemove","time":4023,"x":270,"y":448}],"scrollY":4498,"scrollX":0,"timestamp":1617325616129}]
\ No newline at end of file
+[{"name":"Action 1","ops":[{"type":"mousemove","time":47,"x":689,"y":417},{"type":"mousemove","time":320,"x":689,"y":415},{"type":"mousemove","time":473,"x":689,"y":415},{"type":"mousedown","time":546,"x":689,"y":415},{"type":"mousemove","time":679,"x":682,"y":380},{"type":"mousemove","time":1002,"x":675,"y":339},{"type":"mouseup","time":1054,"x":675,"y":339},{"time":1055,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1240,"x":674,"y":339},{"type":"mousemove","time":1441,"x":524,"y":208},{"type":"mousemove","time":1641,"x":506,"y":166},{"type":"mousemove","time":1842,"x":498,"y":140},{"type":"mousedown","time":1956,"x":497,"y":138},{"type":"mousemove","time":2042,"x":486,"y":153},{"type":"mousemove","time":2256,"x":374,"y":206},{"type":"mousemove","time":2458,"x":149,"y":277},{"type":"mousemove","time":2665,"x":111,"y":290},{"type":"mouseup","time":2949,"x":111,"y":290},{"time":2950,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3377,"x":111,"y":290},{"type":"mousemove","time":3584,"x":111,"y":292},{"type":"mousedown","time":3741,"x":112,"y":286},{"type":"mousemove","time":3794,"x":119,"y":290},{"type":"mousemove","time":4007,"x":381,"y":351},{"type":"mousemove","time":4210,"x":389,"y":362},{"type":"mousemove","time":4410,"x":375,"y":410},{"type":"mousemove","time":4611,"x":359,"y":502},{"type":"mousemove","time":4811,"x":353,"y":532},{"type":"mousemove","time":5021,"x":353,"y":533},{"type":"mouseup","time":5029,"x":353,"y":533},{"time":5030,"delay":400,"type":"screenshot-auto"}],"scrollY":3167,"scrollX":0,"timestamp":1603949926971},{"name":"Action 2","ops":[{"type":"mousewheel","time":616,"x":446,"y":370,"deltaY":4.000244140625},{"type":"mousewheel","time":647,"x":446,"y":370,"deltaY":68.49853515625},{"type":"mousewheel","time":716,"x":446,"y":370,"deltaY":195.638427734375},{"type":"mousewheel","time":850,"x":446,"y":370,"deltaY":177.509765625},{"type":"mousemove","time":1199,"x":446,"y":370},{"type":"mousemove","time":1399,"x":445,"y":374},{"type":"mousedown","time":1578,"x":280,"y":451},{"type":"mousemove","time":1600,"x":280,"y":451},{"type":"mousemove","time":1816,"x":490,"y":390},{"type":"mousemove","time":2016,"x":596,"y":356},{"type":"mousemove","time":2220,"x":609,"y":350},{"type":"mouseup","time":2276,"x":609,"y":350},{"time":2277,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2483,"x":609,"y":350},{"type":"mousemove","time":2689,"x":612,"y":352},{"type":"mousemove","time":2750,"x":612,"y":353},{"type":"mousedown","time":2796,"x":611,"y":354},{"type":"mousemove","time":2959,"x":513,"y":392},{"type":"mousemove","time":3166,"x":367,"y":426},{"type":"mousemove","time":3374,"x":259,"y":450},{"type":"mouseup","time":3513,"x":259,"y":450},{"time":3514,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3616,"x":259,"y":450},{"type":"mousemove","time":3817,"x":269,"y":448},{"type":"mousemove","time":4023,"x":270,"y":448}],"scrollY":4498,"scrollX":0,"timestamp":1617325616129},{"name":"Action 3","ops":[{"type":"mousemove","time":571,"x":387,"y":200},{"type":"mousemove","time":772,"x":299,"y":198},{"type":"mousedown","time":885,"x":294,"y":198},{"type":"mousemove","time":982,"x":294,"y":198},{"type":"mouseup","time":1031,"x":294,"y":198},{"time":1032,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1321,"x":298,"y":198},{"type":"mousemove","time":1521,"x":384,"y":196},{"type":"mousemove","time":1721,"x":511,"y":186},{"type":"mousedown","time":1830,"x":517,"y":190},{"type":"mousemove","time":1929,"x":517,"y":190},{"type":"mouseup","time":1966,"x":517,"y":190},{"time":1967,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2171,"x":517,"y":190},{"type":"mousemove","time":2379,"x":507,"y":193},{"type":"mousemove","time":2596,"x":506,"y":193},{"type":"mousemove","time":2771,"x":505,"y":193},{"type":"mousemove","time":2971,"x":468,"y":203},{"type":"mousemove","time":3171,"x":303,"y":198},{"type":"mousemove","time":3372,"x":298,"y":194},{"type":"mousemove","time":3583,"x":281,"y":190},{"type":"mousewheel","time":3837,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":3859,"x":281,"y":190,"deltaY":2},{"type":"mousewheel","time":3879,"x":281,"y":190,"deltaY":3},{"type":"mousewheel","time":3899,"x":281,"y":190,"deltaY":2},{"type":"mousewheel","time":3918,"x":281,"y":190,"deltaY":2},{"type":"mousewheel","time":4121,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4141,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4160,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4180,"x":281,"y":190,"deltaY":-2},{"type":"mousewheel","time":4201,"x":281,"y":190,"deltaY":-3},{"type":"mousewheel","time":4221,"x":281,"y":190,"deltaY":-2},{"type":"mousewheel","time":4241,"x":281,"y":190,"deltaY":-3},{"type":"mousewheel","time":4262,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4283,"x":281,"y":190,"deltaY":-2},{"type":"mousewheel","time":4303,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4323,"x":281,"y":190,"deltaY":-3},{"type":"mousewheel","time":4343,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4363,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4384,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4922,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":4942,"x":281,"y":190,"deltaY":-5},{"type":"mousewheel","time":4962,"x":281,"y":190,"deltaY":-3},{"type":"mousewheel","time":4981,"x":281,"y":190,"deltaY":-2},{"type":"mousewheel","time":4999,"x":281,"y":190,"deltaY":-2},{"type":"mousewheel","time":5037,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":5104,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":5154,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":5177,"x":281,"y":190,"deltaY":-2},{"type":"mousewheel","time":5198,"x":281,"y":190,"deltaY":-3},{"type":"mousewheel","time":5222,"x":281,"y":190,"deltaY":-1},{"type":"mousewheel","time":5244,"x":281,"y":190,"deltaY":0},{"type":"mousewheel","time":5266,"x":281,"y":190,"deltaY":0},{"type":"mousewheel","time":5293,"x":281,"y":190,"deltaY":0},{"type":"mousewheel","time":5316,"x":281,"y":190,"deltaY":0},{"type":"mousewheel","time":5338,"x":281,"y":190,"deltaY":0},{"type":"mousewheel","time":5360,"x":281,"y":190,"deltaY":0},{"type":"mousewheel","time":5383,"x":281,"y":190,"deltaY":0},{"type":"mousewheel","time":5638,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":5661,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":5696,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":5719,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":5743,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":5766,"x":281,"y":190,"deltaY":2},{"type":"mousewheel","time":5789,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":5812,"x":281,"y":190,"deltaY":3},{"type":"mousewheel","time":5836,"x":281,"y":190,"deltaY":3},{"type":"mousewheel","time":5864,"x":281,"y":190,"deltaY":3},{"type":"mousewheel","time":5885,"x":281,"y":190,"deltaY":4},{"type":"mousewheel","time":5907,"x":281,"y":190,"deltaY":2},{"type":"mousewheel","time":5987,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":6054,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":6075,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":6099,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":6122,"x":281,"y":190,"deltaY":2},{"type":"mousewheel","time":6146,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":6170,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":6322,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":7054,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":7122,"x":281,"y":190,"deltaY":1},{"type":"mousewheel","time":7188,"x":281,"y":190,"deltaY":0},{"type":"mousemove","time":7806,"x":281,"y":190},{"type":"mousemove","time":8006,"x":287,"y":190},{"type":"mousemove","time":8216,"x":353,"y":184},{"type":"mousemove","time":8435,"x":353,"y":184},{"type":"mousemove","time":8621,"x":356,"y":184},{"type":"mousemove","time":8821,"x":430,"y":191},{"type":"mousemove","time":9032,"x":434,"y":191},{"type":"mousewheel","time":9288,"x":434,"y":191,"deltaY":-1},{"type":"mousewheel","time":9311,"x":434,"y":191,"deltaY":-4},{"type":"mousewheel","time":9333,"x":434,"y":191,"deltaY":-6},{"type":"mousewheel","time":9355,"x":434,"y":191,"deltaY":-3},{"type":"mousewheel","time":9377,"x":434,"y":191,"deltaY":-2},{"type":"mousewheel","time":9397,"x":434,"y":191,"deltaY":-2},{"type":"mousewheel","time":9419,"x":434,"y":191,"deltaY":-3},{"type":"mousewheel","time":9442,"x":434,"y":191,"deltaY":-2},{"type":"mousewheel","time":9467,"x":434,"y":191,"deltaY":-3},{"type":"mousewheel","time":9492,"x":434,"y":191,"deltaY":-3},{"type":"mousewheel","time":9522,"x":434,"y":191,"deltaY":-2},{"type":"mousewheel","time":9548,"x":434,"y":191,"deltaY":-1},{"type":"mousewheel","time":9587,"x":434,"y":191,"deltaY":-1},{"type":"mousewheel","time":9615,"x":434,"y":191,"deltaY":-1},{"type":"mousewheel","time":9639,"x":434,"y":191,"deltaY":-2},{"type":"mousewheel","time":9666,"x":434,"y":191,"deltaY":-3},{"type":"mousewheel","time":9693,"x":434,"y":191,"deltaY":-3},{"type":"mousewheel","time":9723,"x":434,"y":191,"deltaY":-4},{"type":"mousewheel","time":9755,"x":434,"y":191,"deltaY":-2},{"type":"mousewheel","time":10228,"x":434,"y":191,"deltaY":1},{"type":"mousewheel","time":10252,"x":434,"y":191,"deltaY":1},{"type":"mousewheel","time":10276,"x":434,"y":191,"deltaY":3},{"type":"mousewheel","time":10302,"x":434,"y":191,"deltaY":2},{"type":"mousewheel","time":10326,"x":434,"y":191,"deltaY":1},{"type":"mousewheel","time":10353,"x":434,"y":191,"deltaY":1},{"type":"mousewheel","time":10377,"x":434,"y":191,"deltaY":2},{"type":"mousewheel","time":10402,"x":434,"y":191,"deltaY":3},{"type":"mousewheel","time":10427,"x":434,"y":191,"deltaY":3},{"type":"mousewheel","time":10447,"x":434,"y":191,"deltaY":3},{"type":"mousewheel","time":10467,"x":434,"y":191,"deltaY":2},{"type":"mousewheel","time":10492,"x":434,"y":191,"deltaY":2},{"type":"mousewheel","time":10525,"x":434,"y":191,"deltaY":1},{"type":"mousewheel","time":10548,"x":434,"y":191,"deltaY":1},{"type":"mousewheel","time":10578,"x":434,"y":191,"deltaY":4},{"type":"mousewheel","time":10607,"x":434,"y":191,"deltaY":1},{"type":"mousewheel","time":10645,"x":434,"y":191,"deltaY":0},{"type":"mousewheel","time":10682,"x":434,"y":191,"deltaY":1},{"type":"mousewheel","time":10739,"x":434,"y":191,"deltaY":0},{"type":"mousewheel","time":10760,"x":434,"y":191,"deltaY":1},{"type":"mousemove","time":11139,"x":432,"y":192},{"type":"mousemove","time":11339,"x":404,"y":216},{"type":"mousemove","time":11548,"x":386,"y":230},{"type":"mousemove","time":12188,"x":386,"y":230},{"type":"mousemove","time":12399,"x":387,"y":228},{"type":"mousemove","time":12604,"x":426,"y":204},{"type":"mousemove","time":12816,"x":431,"y":201},{"type":"mousemove","time":13022,"x":407,"y":210},{"type":"mousemove","time":13231,"x":373,"y":219}],"scrollY":5104,"scrollX":0,"timestamp":1617864060859},{"name":"Action 4","ops":[{"type":"mousemove","time":508,"x":436,"y":480},{"type":"mousemove","time":719,"x":443,"y":483},{"type":"mousemove","time":925,"x":504,"y":476},{"type":"mousemove","time":1126,"x":512,"y":471},{"type":"mousemove","time":1326,"x":492,"y":475},{"type":"mousemove","time":1526,"x":435,"y":481},{"type":"mousemove","time":1752,"x":434,"y":481},{"type":"mousemove","time":1942,"x":434,"y":481},{"type":"mousemove","time":2142,"x":470,"y":477},{"type":"mousemove","time":2342,"x":502,"y":469},{"type":"mousemove","time":2542,"x":505,"y":468},{"type":"mousemove","time":2642,"x":505,"y":468},{"type":"mousemove","time":2842,"x":472,"y":468},{"type":"mousemove","time":3053,"x":421,"y":472},{"type":"mousewheel","time":3259,"x":421,"y":472,"deltaY":1},{"type":"mousewheel","time":3280,"x":421,"y":472,"deltaY":2},{"type":"mousewheel","time":3299,"x":421,"y":472,"deltaY":2},{"type":"mousewheel","time":3320,"x":421,"y":472,"deltaY":3},{"type":"mousewheel","time":3342,"x":421,"y":472,"deltaY":3},{"type":"mousewheel","time":3362,"x":421,"y":472,"deltaY":2},{"type":"mousewheel","time":3384,"x":421,"y":472,"deltaY":3},{"type":"mousewheel","time":3404,"x":421,"y":472,"deltaY":2},{"type":"mousewheel","time":3424,"x":421,"y":472,"deltaY":2},{"type":"mousewheel","time":3592,"x":421,"y":472,"deltaY":-1},{"type":"mousewheel","time":3613,"x":421,"y":472,"deltaY":-1},{"type":"mousewheel","time":3633,"x":421,"y":472,"deltaY":-3},{"type":"mousewheel","time":3654,"x":421,"y":472,"deltaY":-2},{"type":"mousewheel","time":3675,"x":421,"y":472,"deltaY":-3},{"type":"mousewheel","time":3694,"x":421,"y":472,"deltaY":-3},{"type":"mousewheel","time":3717,"x":421,"y":472,"deltaY":-1}],"scrollY":5104,"scrollX":0,"timestamp":1617864079638}]
\ No newline at end of file
diff --git a/test/runTest/client/index.html b/test/runTest/client/index.html
index 2d94b97..d58bd83 100644
--- a/test/runTest/client/index.html
+++ b/test/runTest/client/index.html
@@ -24,7 +24,7 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
-    <link rel="shortcut icon" href="https://www.echartsjs.com/zh/images/favicon.png">
+    <link rel="shortcut icon" href="https://echarts.apache.org/zh/images/favicon.png">
     <title>Visual Regression Testing Tool</title>
 </head>
 <body>