You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2020/06/27 04:38:44 UTC

[incubator-echarts] 02/03: feature: custom series, add "extra" in el options for users to config their own properties for animation.

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

sushuang pushed a commit to branch custom-series-enhance
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git

commit 4d76f23e3727b296de85d8827ee05bd30d3bf2a3
Author: 100pah <su...@gmail.com>
AuthorDate: Wed Jun 24 00:45:27 2020 +0800

    feature: custom series, add "extra" in el options for users to config their own properties for animation.
---
 src/chart/custom.ts          | 116 ++++++++++++++++++++++-----------
 test/custom-transition.html  |  36 +++++-----
 test/custom-transition2.html | 152 ++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 233 insertions(+), 71 deletions(-)

diff --git a/src/chart/custom.ts b/src/chart/custom.ts
index a29d872..05a9fd7 100644
--- a/src/chart/custom.ts
+++ b/src/chart/custom.ts
@@ -78,7 +78,6 @@ import {
 import Transformable from 'zrender/src/core/Transformable';
 import { ItemStyleProps } from '../model/mixin/itemStyle';
 import { cloneValue } from 'zrender/src/animation/Animator';
-import { number } from '../export';
 
 
 const inner = makeInner<{
@@ -133,8 +132,8 @@ interface CustomBaseElementOption extends Partial<Pick<
     textContent?: CustomTextOption | false;
     // `false` means remove the clipPath
     clipPath?: CustomZRPathOption | false;
-    // Shape can be set in any el option for custom prop for annimation duration.
-    shape?: TransitionAnyOption;
+    // `extra` can be set in any el option for custom prop for annimation duration.
+    extra?: TransitionAnyOption;
     // updateDuringAnimation
     during?(params: typeof customDuringAPI): void;
 };
@@ -197,8 +196,8 @@ interface CustomSeriesRenderItemAPI extends
         CustomSeriesRenderItemCoordinateSystemAPI,
         Pick<ExtensionAPI, 'getWidth' | 'getHeight' | 'getZr' | 'getDevicePixelRatio'> {
     value(dim: DimensionLoose, dataIndexInside?: number): ParsedValue;
-    style(extra?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps;
-    styleEmphasis(extra?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps;
+    style(userProps?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps;
+    styleEmphasis(userProps?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps;
     visual(visualType: string, dataIndexInside?: number): ReturnType<List['getItemVisual']>;
     barLayout(opt: Omit<Parameters<typeof getLayoutOnAxis>[0], 'axis'>): ReturnType<typeof getLayoutOnAxis>;
     currentSeriesIndices(): ReturnType<GlobalModel['getCurrentSeriesIndices']>;
@@ -264,6 +263,7 @@ interface CustomSeriesOption extends
 interface LooseElementProps extends ElementProps {
     style?: ZRStyleProps;
     shape?: Dictionary<unknown>;
+    extra?: Dictionary<unknown>;
 }
 
 // Also compat with ec4, where
@@ -635,7 +635,8 @@ function updateElNormal(
     const allProps = {} as ElementProps;
     const elDisplayable = el.isGroup ? null : el as Displayable;
 
-    prepareShapeUpdate(el, elOption, allProps, transFromProps, isInit);
+    prepareShapeOrExtraUpdate('shape', el, elOption, allProps, transFromProps, isInit);
+    prepareShapeOrExtraUpdate('extra', el, elOption, allProps, transFromProps, isInit);
     prepareTransformUpdate(el, elOption, allProps, transFromProps, isInit);
 
     const txCfgOpt = attachedTxInfo && attachedTxInfo.normal.cfg;
@@ -723,7 +724,8 @@ function updateElNormal(
 }
 
 // See [STRATEGY_TRANSITION]
-function prepareShapeUpdate(
+function prepareShapeOrExtraUpdate(
+    mainAttr: 'shape' | 'extra',
     el: Element,
     elOption: CustomElementOption,
     allProps: LooseElementProps,
@@ -731,58 +733,58 @@ function prepareShapeUpdate(
     isInit: boolean
 ): void {
 
-    const shapeOpt = (elOption as CustomElementOption).shape;
-    if (!shapeOpt) {
+    const attrOpt: Dictionary<unknown> & TransitionAnyOption = (elOption as any)[mainAttr];
+    if (!attrOpt) {
         return;
     }
 
-    const elShape = (el as LooseElementProps).shape;
-    let tranFromShapeProps: LooseElementProps['shape'];
+    const elPropsInAttr = (el as LooseElementProps)[mainAttr];
+    let transFromPropsInAttr: Dictionary<unknown>;
 
-    const enterFrom = shapeOpt.enterFrom;
+    const enterFrom = attrOpt.enterFrom;
     if (isInit && enterFrom) {
-        !tranFromShapeProps && (tranFromShapeProps = transFromProps.shape = {});
+        !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {});
         const enterFromKeys = keys(enterFrom);
         for (let i = 0; i < enterFromKeys.length; i++) {
             // `enterFrom` props are not necessarily also declared in `shape`/`style`/...,
             // for example, `opacity` can only declared in `enterFrom` but not in `style`.
             const key = enterFromKeys[i];
             // Do not clone, animator will perform that clone.
-            tranFromShapeProps[key] = enterFrom[key];
+            transFromPropsInAttr[key] = enterFrom[key];
         }
     }
 
-    if (!isInit && elShape && shapeOpt.transition) {
-        !tranFromShapeProps && (tranFromShapeProps = transFromProps.shape = {});
-        const transitionKeys = normalizeToArray(shapeOpt.transition);
+    if (!isInit && elPropsInAttr && attrOpt.transition) {
+        !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {});
+        const transitionKeys = normalizeToArray(attrOpt.transition);
         for (let i = 0; i < transitionKeys.length; i++) {
             const key = transitionKeys[i];
-            const elVal = elShape[key];
+            const elVal = elPropsInAttr[key];
             if (__DEV__) {
-                checkTansitionRefer(key, (shapeOpt as any)[key], elVal);
+                checkTansitionRefer(key, (attrOpt as any)[key], elVal);
             }
             // Do not clone, see `checkTansitionRefer`.
-            tranFromShapeProps[key] = elVal;
+            transFromPropsInAttr[key] = elVal;
         }
     }
 
-    const allPropsShape = allProps.shape = {} as LooseElementProps['shape'];
-    const shapeOptKeys = keys(shapeOpt);
-    for (let i = 0; i < shapeOptKeys.length; i++) {
-        const key = shapeOptKeys[i];
+    const allPropsInAttr = allProps[mainAttr] = {} as Dictionary<unknown>;
+    const keysInAttr = keys(attrOpt);
+    for (let i = 0; i < keysInAttr.length; i++) {
+        const key = keysInAttr[i];
         // To avoid share one object with different element, and
         // to avoid user modify the object inexpectedly, have to clone.
-        allPropsShape[key] = cloneValue((shapeOpt as any)[key]);
+        allPropsInAttr[key] = cloneValue((attrOpt as any)[key]);
     }
 
-    const leaveTo = shapeOpt.leaveTo;
+    const leaveTo = attrOpt.leaveTo;
     if (leaveTo) {
         const leaveToProps = getOrCreateLeaveToPropsFromEl(el);
-        const leaveToShapeProps = leaveToProps.shape || (leaveToProps.shape = {});
+        const leaveToPropsInAttr: Dictionary<unknown> = leaveToProps[mainAttr] || (leaveToProps[mainAttr] = {});
         const leaveToKeys = keys(leaveTo);
         for (let i = 0; i < leaveToKeys.length; i++) {
             const key = leaveToKeys[i];
-            leaveToShapeProps[key] = leaveTo[key];
+            leaveToPropsInAttr[key] = leaveTo[key];
         }
     }
 }
@@ -955,19 +957,28 @@ const customDuringAPI = {
         return tmpDuringScope.el[key];
     },
     setShape(key: string, val: unknown) {
-        // In custom series, el other than Path can also has `shape` for intepolating props.
-        const shape = (tmpDuringScope.el as any).shape || ((tmpDuringScope.el as any).shape = {});
+        if (__DEV__) {
+            assertNotReserved(key);
+        }
+        const shape = (tmpDuringScope.el as graphicUtil.Path).shape
+            || ((tmpDuringScope.el as graphicUtil.Path).shape = {});
         shape[key] = val;
         tmpDuringScope.isShapeDirty = true;
         return this;
     },
     getShape(key: string): unknown {
-        const shape = (tmpDuringScope.el as any).shape;
+        if (__DEV__) {
+            assertNotReserved(key);
+        }
+        const shape = (tmpDuringScope.el as graphicUtil.Path).shape;
         if (shape) {
             return shape[key];
         }
     },
     setStyle(key: string, val: unknown) {
+        if (__DEV__) {
+            assertNotReserved(key);
+        }
         const style = (tmpDuringScope.el as Displayable).style;
         if (style) {
             style[key] = val;
@@ -976,13 +987,42 @@ const customDuringAPI = {
         return this;
     },
     getStyle(key: string): unknown {
+        if (__DEV__) {
+            assertNotReserved(key);
+        }
         const style = (tmpDuringScope.el as Displayable).style;
         if (style) {
             return style[key];
         }
+    },
+    setExtra(key: string, val: unknown) {
+        if (__DEV__) {
+            assertNotReserved(key);
+        }
+        const extra = (tmpDuringScope.el as LooseElementProps).extra
+            || ((tmpDuringScope.el as LooseElementProps).extra = {});
+        extra[key] = val;
+        return this;
+    },
+    getExtra(key: string): unknown {
+        if (__DEV__) {
+            assertNotReserved(key);
+        }
+        const extra = (tmpDuringScope.el as LooseElementProps).extra;
+        if (extra) {
+            return extra[key];
+        }
     }
 };
 
+function assertNotReserved(key: string) {
+    if (__DEV__) {
+        if (key === 'transition' || key === 'enterFrom' || key === 'leaveTo') {
+            throw new Error('key must not be "' + key + '"');
+        }
+    }
+}
+
 function elUpdateDuringAnimation(this: Element, key: string): void {
     // Do not provide "percent" until some requirements come.
     // Because consider thies case:
@@ -1297,7 +1337,7 @@ function makeRenderItem(
      * @public
      * @param dataIndexInside by default `currDataIndexInside`.
      */
-    function style(extra?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps {
+    function style(userProps?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps {
         if (__DEV__) {
             warnDeprecated('api.style', 'Please write literal style directly instead.');
         }
@@ -1326,10 +1366,10 @@ function makeRenderItem(
             : null;
         const textConfig = graphicUtil.createTextConfig(textStyle, labelModel, opt, false);
 
-        preFetchFromExtra(extra, itemStyle);
+        preFetchFromExtra(userProps, itemStyle);
         itemStyle = convertToEC4StyleForCustomSerise(itemStyle, textStyle, textConfig);
 
-        extra && applyExtraAfter(itemStyle, extra);
+        userProps && applyUserPropsAfter(itemStyle, userProps);
         (itemStyle as LegacyStyleProps).legacy = true;
 
         return itemStyle;
@@ -1340,7 +1380,7 @@ function makeRenderItem(
      * @public
      * @param dataIndexInside by default `currDataIndexInside`.
      */
-    function styleEmphasis(extra?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps {
+    function styleEmphasis(userProps?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps {
         if (__DEV__) {
             warnDeprecated('api.styleEmphasis', 'Please write literal style directly instead.');
         }
@@ -1359,16 +1399,16 @@ function makeRenderItem(
             : null;
         const textConfig = graphicUtil.createTextConfig(textStyle, labelModel, null, true);
 
-        preFetchFromExtra(extra, itemStyle);
+        preFetchFromExtra(userProps, itemStyle);
         itemStyle = convertToEC4StyleForCustomSerise(itemStyle, textStyle, textConfig);
 
-        extra && applyExtraAfter(itemStyle, extra);
+        userProps && applyUserPropsAfter(itemStyle, userProps);
         (itemStyle as LegacyStyleProps).legacy = true;
 
         return itemStyle;
     }
 
-    function applyExtraAfter(itemStyle: ZRStyleProps, extra: ZRStyleProps): void {
+    function applyUserPropsAfter(itemStyle: ZRStyleProps, extra: ZRStyleProps): void {
         for (const key in extra) {
             if (hasOwn(extra, key)) {
                 (itemStyle as any)[key] = (extra as any)[key];
diff --git a/test/custom-transition.html b/test/custom-transition.html
index 27c0a0b..24bd2fc 100644
--- a/test/custom-transition.html
+++ b/test/custom-transition.html
@@ -177,7 +177,9 @@ under the License.
                     children.push({
                         type: 'polygon',
                         shape: {
-                            points: makeShapePoints(api, valOnRadius, valOnAngle),
+                            points: makeShapePoints(api, valOnRadius, valOnAngle)
+                        },
+                        extra: {
                             valOnAngle: valOnAngle,
                             transition: 'valOnAngle'
                         },
@@ -188,7 +190,7 @@ under the License.
                         },
                         during: function (apiDuring) {
                             apiDuring.setShape('points', makeShapePoints(
-                                api, valOnRadius, apiDuring.getShape('valOnAngle')
+                                api, valOnRadius, apiDuring.getExtra('valOnAngle')
                             ));
                         }
                     });
@@ -217,7 +219,7 @@ under the License.
                         type: 'text',
                         x: point[0],
                         y: point[1],
-                        shape: {
+                        extra: {
                             valOnAngle: valOnAngle,
                             transition: 'valOnAngle'
                         },
@@ -232,7 +234,7 @@ under the License.
                         },
                         z2: 50,
                         during: function (apiDuring) {
-                            var iValOnAngle = apiDuring.getShape('valOnAngle');
+                            var iValOnAngle = apiDuring.getExtra('valOnAngle');
                             var point = makeLabelPosition(api, valOnRadius, iValOnAngle);
                             apiDuring.setTransform('x', point[0]).setTransform('y', point[1]);
                             apiDuring.setStyle('text', getText(iValOnAngle));
@@ -403,7 +405,9 @@ under the License.
                     children.push({
                         type: 'polygon',
                         shape: {
-                            points: makeShapePoints(params, widthRadius, startRadius, endRadian),
+                            points: makeShapePoints(params, widthRadius, startRadius, endRadian)
+                        },
+                        extra: {
                             widthRadius: widthRadius,
                             startRadius: startRadius,
                             endRadian: endRadian,
@@ -417,9 +421,9 @@ under the License.
                         during: function (apiDuring) {
                             apiDuring.setShape('points', makeShapePoints(
                                 params,
-                                apiDuring.getShape('widthRadius'),
-                                apiDuring.getShape('startRadius'),
-                                apiDuring.getShape('endRadian')
+                                apiDuring.getExtra('widthRadius'),
+                                apiDuring.getExtra('startRadius'),
+                                apiDuring.getExtra('endRadian')
                             ));
                         }
                     });
@@ -460,7 +464,7 @@ under the License.
                         type: 'text',
                         x: point[0],
                         y: point[1],
-                        shape: {
+                        extra: {
                             startRadius: startRadius,
                             endRadian: endRadian,
                             widthRadius: widthRadius,
@@ -481,11 +485,11 @@ under the License.
                         },
                         z2: 50,
                         during: function (apiDuring) {
-                            var endRadian = apiDuring.getShape('endRadian');
+                            var endRadian = apiDuring.getExtra('endRadian');
                             var point = makeLabelPosition(
                                 params,
-                                apiDuring.getShape('widthRadius'),
-                                apiDuring.getShape('startRadius'),
+                                apiDuring.getExtra('widthRadius'),
+                                apiDuring.getExtra('startRadius'),
                                 endRadian
                             );
                             apiDuring.setTransform('x', point[0]).setTransform('y', point[1]);
@@ -663,6 +667,8 @@ under the License.
                                 type: 'polygon',
                                 shape: {
                                     points: makePionterPoints(params, polarEndRadian),
+                                },
+                                extra: {
                                     polarEndRadian: polarEndRadian,
                                     transition: 'polarEndRadian',
                                     enterFrom: { polarEndRadian: 0 }
@@ -670,7 +676,7 @@ under the License.
                                 during: function (apiDuring) {
                                     apiDuring.setShape(
                                         'points',
-                                        makePionterPoints(params, apiDuring.getShape('polarEndRadian'))
+                                        makePionterPoints(params, apiDuring.getExtra('polarEndRadian'))
                                     );
                                 }
                             },
@@ -690,7 +696,7 @@ under the License.
                             }
                         }, {
                             type: 'text',
-                            shape: {
+                            extra: {
                                 valOnRadian: valOnRadian,
                                 transition: 'valOnRadian',
                                 enterFrom: { valOnRadian: 0 }
@@ -706,7 +712,7 @@ under the License.
                                 enterFrom: { opacity: 0 }
                             },
                             during: function (apiDuring) {
-                                apiDuring.setStyle('text', makeText(apiDuring.getShape('valOnRadian')));
+                                apiDuring.setStyle('text', makeText(apiDuring.getExtra('valOnRadian')));
                             }
                         }]
                     };
diff --git a/test/custom-transition2.html b/test/custom-transition2.html
index a2a4caf..3e9eb56 100644
--- a/test/custom-transition2.html
+++ b/test/custom-transition2.html
@@ -148,15 +148,12 @@ under the License.
                 var clusterIdx = api.value(2);
                 var isNewCluster = clusterIdx === api.value(3);
 
-                var shape = {
-                    cx: 0,
-                    cy: 0,
-                    r: 10,
+                var extra = {
                     transition: []
                 };
 
                 var contentColor = colorAll[clusterIdx];
-                addColorTransition(shape, contentColor, 'content');
+                addColorTransition(extra, contentColor, 'content');
                 // var borderColor = isNewCluster ? '#333' : '#fff';
                 // addColorTransition(shape, borderColor, 'border');
 
@@ -167,7 +164,12 @@ under the License.
                     // scaleX: isNewCluster ? 1.2 : 1,
                     // scaleY: isNewCluster ? 1.2 : 1,
                     // transition: ['scaleX', 'scaleY'],
-                    shape: shape,
+                    shape: {
+                        cx: 0,
+                        cy: 0,
+                        r: 10
+                    },
+                    extra: extra,
                     style: {
                         fill: contentColor,
                         stroke: '#333',
@@ -197,10 +199,10 @@ under the License.
 
             function getColorInTransition(apiDuring, key) {
                 var colorArr = [
-                    apiDuring.getShape(key + 'R'),
-                    apiDuring.getShape(key + 'G'),
-                    apiDuring.getShape(key + 'B'),
-                    apiDuring.getShape(key + 'A')
+                    apiDuring.getExtra(key + 'R'),
+                    apiDuring.getExtra(key + 'G'),
+                    apiDuring.getExtra(key + 'B'),
+                    apiDuring.getExtra(key + 'A')
                 ];
                 return echarts.color.stringify(colorArr, 'rgba');
             }
@@ -216,10 +218,16 @@ under the License.
                 return {
                     type: 'circle',
                     shape: {
-                        cx: isNaN(center[0]) ? 0 : center[0],
-                        cy: isNaN(center[1]) ? 0 : center[1],
-                        r: isNaN(radius) ? 0 : radius,
-                        // transition: 'newCluIdx'
+                        cx: 0,
+                        cy: 0,
+                        r: 0
+                    },
+                    extra: {
+                        cxNext: isNaN(center[0]) ? 0 : center[0],
+                        cyNext: isNaN(center[1]) ? 0 : center[1],
+                        rNext: isNaN(radius) ? 0 : radius,
+                        renderNumber: ++renderNumber,
+                        transition: 'renderNumber'
                     },
                     style: {
                         fill: null,
@@ -229,12 +237,118 @@ under the License.
                         // opacity: 0
                     },
                     during: function (apiDuring) {
-                        apiDuring.setShape('cx', Math.random() * 10);
-                        // var cluIdx = apiDuring.setShape('newCluIdx');
-                        // var percent = Math.ceil(cluIdx) - cluIdx;
-                        // var opacity = (Math.ceil(cluIdx) - cluIdx) > 0.5 ?
+                        var currNum = apiDuring.getExtra('renderNumber');
+                        if (apiDuring.getStyle('opacity') < 0.9) {
+                            apiDuring
+                                .setShape('cx', apiDuring.getExtra('cxNext'))
+                                .setShape('cy', apiDuring.getExtra('cyNext'))
+                                .setShape('r', apiDuring.getExtra('rNext'));
+                        }
+                        apiDuring.setStyle('opacity', 1 - (renderNumber - currNum));
                     }
                 };
+
+                // return {
+                //     type: 'group',
+                //     children: [{
+                //         type: 'circle',
+                //         shape: {
+                //             cx: 0,
+                //             cy: 0,
+                //             r: 0,
+                //         },
+                //         extra: {
+                //             renderNumber: ++renderNumber,
+                //             cxNext: isNaN(center[0]) ? 0 : center[0],
+                //             cyNext: isNaN(center[1]) ? 0 : center[1],
+                //             rNext: isNaN(radius) ? 0 : radius,
+                //             transition: 'renderNumber'
+                //         },
+                //         style: {
+                //             fill: null,
+                //             stroke: '#bbb',
+                //             lineDash: [5, 5],
+                //             lineWidth: 3
+                //         },
+                //         during: function (apiDuring) {
+                //             var currNum = apiDuring.getExtra('renderNumber');
+                //             var progress = 0.5 - (renderNumber - currNum);
+                //             if (progress >= 0) {
+                //                 apiDuring
+                //                     .setShape('cx', apiDuring.getExtra('cxNext'))
+                //                     .setShape('cy', apiDuring.getExtra('cyNext'))
+                //                     .setShape('r', apiDuring.getExtra('rNext'));
+                //             }
+                //             var opacity = Math.abs(progress) / 0.5;
+                //             apiDuring.setStyle('opacity', opacity);
+                //         }
+                //     }, {
+                //         type: 'circle',
+                //         shape: {
+                //             cx: 0,
+                //             cy: 0,
+                //             r: 0,
+                //         },
+                //         extra: {
+                //             renderNumber: ++renderNumber,
+                //             cxNext: isNaN(center[0]) ? 0 : center[0],
+                //             cyNext: isNaN(center[1]) ? 0 : center[1],
+                //             rNext: isNaN(radius) ? 0 : radius,
+                //             transition: 'renderNumber'
+                //         },
+                //         style: {
+                //             fill: null,
+                //             stroke: '#bbb',
+                //             lineDash: [5, 5],
+                //             lineWidth: 3
+                //         },
+                //         during: function (apiDuring) {
+                //             var currNum = apiDuring.getExtra('renderNumber');
+                //             var progress = 0.5 - (renderNumber - currNum);
+                //             if (progress >= 0) {
+                //                 apiDuring
+                //                     .setShape('cx', apiDuring.getExtra('cxNext'))
+                //                     .setShape('cy', apiDuring.getExtra('cyNext'))
+                //                     .setShape('r', apiDuring.getExtra('rNext'));
+                //             }
+                //             var opacity = Math.abs(progress) / 0.5;
+                //             apiDuring.setStyle('opacity', opacity);
+                //         }
+                //     }]
+                // };
+                // return {
+                //     type: 'circle',
+                //     shape: {
+                //         cx: 0,
+                //         cy: 0,
+                //         r: 0,
+                //     },
+                //     extra: {
+                //         renderNumber: ++renderNumber,
+                //         cxNext: isNaN(center[0]) ? 0 : center[0],
+                //         cyNext: isNaN(center[1]) ? 0 : center[1],
+                //         rNext: isNaN(radius) ? 0 : radius,
+                //         transition: 'renderNumber'
+                //     },
+                //     style: {
+                //         fill: null,
+                //         stroke: '#bbb',
+                //         lineDash: [5, 5],
+                //         lineWidth: 3
+                //     },
+                //     during: function (apiDuring) {
+                //         var currNum = apiDuring.getExtra('renderNumber');
+                //         var progress = 0.5 - (renderNumber - currNum);
+                //         if (progress >= 0) {
+                //             apiDuring
+                //                 .setShape('cx', apiDuring.getExtra('cxNext'))
+                //                 .setShape('cy', apiDuring.getExtra('cyNext'))
+                //                 .setShape('r', apiDuring.getExtra('rNext'));
+                //         }
+                //         var opacity = Math.abs(progress) / 0.5;
+                //         apiDuring.setStyle('opacity', opacity);
+                //     }
+                // };
             }
 
             function makeStepOption(option, stepResult) {
@@ -268,6 +382,8 @@ under the License.
                 });
             }
 
+            var renderNumber = 0;
+
             var option = {
                 timeline: {
                     top: 'center',


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