You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2021/11/19 03:34:40 UTC

[echarts] 02/02: fix(transition): not do strict checking. some code cleanup

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

shenyi pushed a commit to branch graphic-animation
in repository https://gitbox.apache.org/repos/asf/echarts.git

commit cca220611466bc265add8481540f9cfd29675c61
Author: pissang <bm...@gmail.com>
AuthorDate: Fri Nov 19 11:33:24 2021 +0800

    fix(transition): not do strict checking. some code cleanup
---
 src/animation/customGraphicTransition.ts | 123 +++++++++++--------------------
 src/chart/custom/CustomView.ts           |   8 +-
 src/component/graphic/GraphicModel.ts    |   1 +
 src/component/graphic/GraphicView.ts     |  42 ++++++++---
 test/graphic-transition.html             |  39 ++++++++++
 5 files changed, 118 insertions(+), 95 deletions(-)

diff --git a/src/animation/customGraphicTransition.ts b/src/animation/customGraphicTransition.ts
index 6ae2106..7459f53 100644
--- a/src/animation/customGraphicTransition.ts
+++ b/src/animation/customGraphicTransition.ts
@@ -34,12 +34,26 @@ import { AnimationOptionMixin, ZRStyleProps } from '../util/types';
 import { Dictionary } from 'zrender/lib/core/types';
 import { PathStyleProps } from 'zrender';
 
-const LEGACY_TRANSFORM_PROPS = {
+const LEGACY_TRANSFORM_PROPS_MAP = {
     position: ['x', 'y'],
     scale: ['scaleX', 'scaleY'],
     origin: ['originX', 'originY']
 } as const;
-type LegacyTransformProp = keyof typeof LEGACY_TRANSFORM_PROPS;
+const LEGACY_TRANSFORM_PROPS = keys(LEGACY_TRANSFORM_PROPS_MAP);
+type LegacyTransformProp = keyof typeof LEGACY_TRANSFORM_PROPS_MAP;
+
+const TRANSFORM_PROPS_MAP = {
+    x: 1,
+    y: 1,
+    scaleX: 1,
+    scaleY: 1,
+    originX: 1,
+    originY: 1,
+    rotation: 1
+} as const;
+type TransformProp = keyof typeof TRANSFORM_PROPS_MAP;
+const TRANSFORM_PROPS = keys(TRANSFORM_PROPS_MAP);
+const transformPropNamesStr = TRANSFORM_PROPS.join(', ');
 
 export type CustomTransitionProps = string | string[];
 export interface TransitionOptionMixin {
@@ -55,17 +69,6 @@ export type ElementTransitionOptionMixin = {
 };
 type ElementRootTransitionProp = TransformProp | 'shape' | 'extra' | 'style';
 
-export const TRANSFORM_PROPS = {
-    x: 1,
-    y: 1,
-    scaleX: 1,
-    scaleY: 1,
-    originX: 1,
-    originY: 1,
-    rotation: 1
-} as const;
-export type TransformProp = keyof typeof TRANSFORM_PROPS;
-
 interface LooseElementProps extends ElementProps {
     style?: ZRStyleProps;
     shape?: Dictionary<unknown>;
@@ -88,30 +91,6 @@ const transitionInnerStore = makeInner<{
     userDuring: (params: TransitionDuringAPI) => void;
 }, Element>();
 
-const transformPropNamesStr = keys(TRANSFORM_PROPS).join(', ');
-
-function setLegacyTransformProp(
-    elOption: TransitionElementOption,
-    targetProps: Partial<Pick<Transformable, TransformProp>>,
-    legacyName: LegacyTransformProp
-): void {
-    const legacyArr = (elOption as any)[legacyName];
-    const xyName = LEGACY_TRANSFORM_PROPS[legacyName];
-    if (legacyArr) {
-        targetProps[xyName[0]] = legacyArr[0];
-        targetProps[xyName[1]] = legacyArr[1];
-    }
-}
-
-function setTransformProp(
-    elOption: TransitionElementOption,
-    allProps: Partial<Pick<Transformable, TransformProp>>,
-    name: TransformProp
-): void {
-    if (elOption[name] != null) {
-        allProps[name] = elOption[name];
-    }
-}
 
 function setTransformPropToTransitionFrom(
     transitionFrom: Partial<Pick<Transformable, TransformProp>>,
@@ -158,10 +137,13 @@ export function applyUpdateTransition(
 
     prepareShapeOrExtraTransitionFrom('shape', el, elOption, transFromProps, isInit);
     prepareShapeOrExtraAllPropsFinal('shape', elOption, propsToSet);
+
     prepareTransformTransitionFrom(el, elOption, transFromProps, isInit);
     prepareTransformAllPropsFinal(el, elOption, propsToSet);
+
     prepareShapeOrExtraTransitionFrom('extra', el, elOption, transFromProps, isInit);
     prepareShapeOrExtraAllPropsFinal('extra', elOption, propsToSet);
+
     prepareStyleTransitionFrom(el, elOption, styleOpt, transFromProps, isInit);
     (propsToSet as DisplayableProps).style = styleOpt;
     applyPropsDirectly(el, propsToSet);
@@ -291,14 +273,14 @@ const transitionDuringAPI: TransitionDuringAPI = {
     // Usually other props do not need to be changed in animation during.
     setTransform(key: TransformProp, val: unknown) {
         if (__DEV__) {
-            assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `setTransform`.');
+            assert(hasOwn(TRANSFORM_PROPS_MAP, key), 'Only ' + transformPropNamesStr + ' available in `setTransform`.');
         }
         tmpDuringScope.el[key] = val as number;
         return this;
     },
     getTransform(key: TransformProp): number {
         if (__DEV__) {
-            assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `getTransform`.');
+            assert(hasOwn(TRANSFORM_PROPS_MAP, key), 'Only ' + transformPropNamesStr + ' available in `getTransform`.');
         }
         return tmpDuringScope.el[key];
     },
@@ -463,10 +445,6 @@ function prepareShapeOrExtraTransitionFrom(
             for (let i = 0; i < transitionKeys.length; i++) {
                 const key = transitionKeys[i];
                 const elVal = elPropsInAttr[key];
-                if (__DEV__) {
-                    checkNonStyleTansitionRefer(key, (attrOpt as any)[key], elVal);
-                }
-                // Do not clone, see `checkNonStyleTansitionRefer`.
                 transFromPropsInAttr[key] = elVal;
             }
         }
@@ -544,9 +522,8 @@ function prepareTransformTransitionFrom(
                 const elVal = el[key];
                 if (__DEV__) {
                     checkTransformPropRefer(key, 'el.transition');
-                    checkNonStyleTansitionRefer(key, elOption[key], elVal);
                 }
-                // Do not clone, see `checkNonStyleTansitionRefer`.
+                // Do not clone, animator will perform that clone.
                 transFromProps[key] = elVal;
             }
         }
@@ -576,17 +553,22 @@ function prepareTransformAllPropsFinal(
     elOption: TransitionElementOption,
     allProps: ElementProps
 ): void {
-    setLegacyTransformProp(elOption, allProps, 'position');
-    setLegacyTransformProp(elOption, allProps, 'scale');
-    setLegacyTransformProp(elOption, allProps, 'origin');
-
-    setTransformProp(elOption, allProps, 'x');
-    setTransformProp(elOption, allProps, 'y');
-    setTransformProp(elOption, allProps, 'scaleX');
-    setTransformProp(elOption, allProps, 'scaleY');
-    setTransformProp(elOption, allProps, 'originX');
-    setTransformProp(elOption, allProps, 'originY');
-    setTransformProp(elOption, allProps, 'rotation');
+    for (let i = 0; i < LEGACY_TRANSFORM_PROPS.length; i++) {
+        const legacyName = LEGACY_TRANSFORM_PROPS[i];
+        const xyName = LEGACY_TRANSFORM_PROPS_MAP[legacyName];
+        const legacyArr = (elOption as any)[legacyName];
+        if (legacyArr) {
+            allProps[xyName[0]] = legacyArr[0];
+            allProps[xyName[1]] = legacyArr[1];
+        }
+    }
+
+    for (let i = 0; i < TRANSFORM_PROPS.length; i++) {
+        const key = TRANSFORM_PROPS[i];
+        if (elOption[key] != null) {
+            allProps[key] = elOption[key];
+        }
+    }
 }
 
 function prepareStyleTransitionFrom(
@@ -657,26 +639,6 @@ function prepareStyleTransitionFrom(
     }
 }
 
-let checkNonStyleTansitionRefer: (propName: string, optVal: unknown, elVal: unknown) => void;
-if (__DEV__) {
-    checkNonStyleTansitionRefer = function (propName: string, optVal: unknown, elVal: unknown): void {
-        if (!isArrayLike(optVal)) {
-            assert(
-                optVal != null && isFinite(optVal as number),
-                'Prop `' + propName + '` must refer to a finite number or ArrayLike for transition.'
-            );
-        }
-        else {
-            // Try not to copy array for performance, but if user use the same object in different
-            // call of `renderItem`, it will casue animation transition fail.
-            assert(
-                optVal !== elVal,
-                'Prop `' + propName + '` must use different Array object each time for transition.'
-            );
-        }
-    };
-}
-
 function isNonStyleTransitionEnabled(optVal: unknown, elVal: unknown): boolean {
     // The same as `checkNonStyleTansitionRefer`.
     return !isArrayLike(optVal)
@@ -687,11 +649,10 @@ function isNonStyleTransitionEnabled(optVal: unknown, elVal: unknown): boolean {
 let checkTransformPropRefer: (key: string, usedIn: string) => void;
 if (__DEV__) {
     checkTransformPropRefer = function (key: string, usedIn: string): void {
-        assert(
-            hasOwn(TRANSFORM_PROPS, key),
-            'Prop `' + key + '` is not a permitted in `' + usedIn + '`. '
-                + 'Only `' + keys(TRANSFORM_PROPS).join('`, `') + '` are permitted.'
-        );
+        if (!hasOwn(TRANSFORM_PROPS_MAP, key)) {
+            warn('Prop `' + key + '` is not a permitted in `' + usedIn + '`. '
+               + 'Only `' + keys(TRANSFORM_PROPS_MAP).join('`, `') + '` are permitted.');
+        }
     };
 }
 
diff --git a/src/chart/custom/CustomView.ts b/src/chart/custom/CustomView.ts
index 2d80864..47f90f1 100644
--- a/src/chart/custom/CustomView.ts
+++ b/src/chart/custom/CustomView.ts
@@ -491,9 +491,7 @@ function updateElOnState(
     el: Element,
     elStateOpt: CustomElementOptionOnState,
     styleOpt: CustomElementOptionOnState['style'],
-    attachedTxInfo: AttachedTxInfo,
-    isRoot: boolean,
-    isTextContent: boolean
+    attachedTxInfo: AttachedTxInfo
 ): void {
     const elDisplayable = el.isGroup ? null : el as Displayable;
     const txCfgOpt = attachedTxInfo && attachedTxInfo[state].cfg;
@@ -1009,7 +1007,7 @@ function doCreateOrUpdateEl(
         if (stateName !== NORMAL) {
             const otherStateOpt = retrieveStateOption(elOption, stateName);
             const otherStyleOpt = retrieveStyleOptionOnState(elOption, otherStateOpt, stateName);
-            updateElOnState(stateName, el, otherStateOpt, otherStyleOpt, attachedTxInfoTmp, isRoot, false);
+            updateElOnState(stateName, el, otherStateOpt, otherStyleOpt, attachedTxInfoTmp);
         }
     }
 
@@ -1161,7 +1159,7 @@ function doCreateOrUpdateAttachedTx(
                         textContent,
                         txConOptOtherState,
                         retrieveStyleOptionOnState(txConOptNormal, txConOptOtherState, stateName),
-                        null, false, true
+                        null
                     );
                 }
             }
diff --git a/src/component/graphic/GraphicModel.ts b/src/component/graphic/GraphicModel.ts
index 8b14ea9..8c49869 100644
--- a/src/component/graphic/GraphicModel.ts
+++ b/src/component/graphic/GraphicModel.ts
@@ -123,6 +123,7 @@ export interface GraphicComponentDisplayableOption extends
     Partial<Pick<Displayable, 'zlevel' | 'z' | 'z2' | 'invisible' | 'cursor'>> {
 
     style?: ZRStyleProps & TransitionOptionMixin
+    z2?: number
 }
 // TODO: states?
 // interface GraphicComponentDisplayableOptionOnState extends Partial<Pick<
diff --git a/src/component/graphic/GraphicView.ts b/src/component/graphic/GraphicView.ts
index 6225923..9158cc0 100644
--- a/src/component/graphic/GraphicView.ts
+++ b/src/component/graphic/GraphicView.ts
@@ -18,16 +18,17 @@
 */
 
 import * as zrUtil from 'zrender/src/core/util';
+import { TextStyleProps } from 'zrender/src/graphic/Text';
+import Displayable from 'zrender/src/graphic/Displayable';
+import Element from 'zrender/src/Element';
 import * as modelUtil from '../../util/model';
 import * as graphicUtil from '../../util/graphic';
 import * as layoutUtil from '../../util/layout';
 import { parsePercent } from '../../util/number';
-import Element from 'zrender/src/Element';
 import GlobalModel from '../../model/Global';
 import ComponentView from '../../view/Component';
 import ExtensionAPI from '../../core/ExtensionAPI';
 import { getECData } from '../../util/innerStore';
-import { TextStyleProps } from 'zrender/src/graphic/Text';
 import { isEC4CompatibleStyle, convertFromEC4CompatibleStyle } from '../../util/styleCompat';
 import {
     ElementMap,
@@ -106,6 +107,9 @@ export class GraphicComponentView extends ComponentView {
         const elMap = this._elMap;
         const rootGroup = this.group;
 
+        const globalZ = graphicModel.get('z');
+        const globalZLevel = graphicModel.get('zlevel');
+
         // Top-down tranverse to assign graphic settings to each elements.
         zrUtil.each(elOptionsToUpdate, function (elOption) {
             const id = modelUtil.convertOptionIdName(elOption.id, null);
@@ -158,13 +162,16 @@ export class GraphicComponentView extends ComponentView {
                 if (isInit) {
                     el = createEl(id, targetElParent, elOption.type, elMap);
                 }
-                el && applyUpdateTransition(
-                    el,
-                    elOptionCleaned,
-                    graphicModel,
-                    0,  // TODO Fixed dataIndex to be 0
-                    isInit
-                );
+                if (el) {
+                    applyUpdateTransition(
+                        el,
+                        elOptionCleaned,
+                        graphicModel,
+                        0,  // TODO Fixed dataIndex to be 0
+                        isInit
+                    );
+                    updateZ(el, elOption, globalZ, globalZLevel);
+                }
             }
             else if ($action === 'replace') {
                 removeEl(elExisting, elMap, graphicModel);
@@ -177,6 +184,7 @@ export class GraphicComponentView extends ComponentView {
                         0,  // TODO Fixed dataIndex to be 0
                         true
                     );
+                    updateZ(el, elOption, globalZ, globalZLevel);
                 }
             }
             else if ($action === 'remove') {
@@ -335,6 +343,22 @@ function removeEl(elExisting: Element, elMap: ElementMap, graphicModel: GraphicC
         elMap.removeKey(inner(elExisting).id);
     }
 }
+
+function updateZ(el: Element, elOption: GraphicComponentElementOption, defaultZ: number, defaultZlevel: number) {
+    if (el.isGroup) {
+        return;
+    }
+
+    const elDisplayable = el as Displayable;
+    // We should not support configure z and zlevel in the element level.
+    // But seems we didn't limit it previously. So here still use it to avoid breaking.
+    elDisplayable.z = zrUtil.retrieve2((elOption as any).z, defaultZ);
+    elDisplayable.zlevel = zrUtil.retrieve2((elOption as any).zlevel, defaultZlevel);
+    // z2 must not be null/undefined, otherwise sort error may occur.
+    const optZ2 = (elOption as GraphicComponentDisplayableOption).z2;
+    optZ2 != null && (elDisplayable.z2 = optZ2 || 0);
+
+}
 // Remove unnecessary props to avoid potential problems.
 function getCleanedElOption(
     elOption: GraphicComponentElementOption
diff --git a/test/graphic-transition.html b/test/graphic-transition.html
index 20bd92c..b4c8de9 100644
--- a/test/graphic-transition.html
+++ b/test/graphic-transition.html
@@ -99,6 +99,22 @@ under the License.
                             })
                         }
                     },
+
+                    {
+                        text: 'Move to x: 100, y: 50',
+                        onclick() {
+                            chart.setOption({
+                                graphic: {
+                                    elements: [{
+                                        type: 'circle',
+                                        transition: ['x', 'y'],
+                                        x: 100,
+                                        y: 50
+                                    }]
+                                }
+                            })
+                        }
+                    }
                 ]
             });
 
@@ -114,11 +130,34 @@ under the License.
         <script>
         require(['echarts'/*, 'map/js/china' */], function (echarts) {
             var option;
+            // Enter transition
+        });
+        </script>
 
+        <script>
+        require(['echarts'/*, 'map/js/china' */], function (echarts) {
+            var option;
+
+            // Leave transition
+        });
+        </script>
+
+        <script>
+        require(['echarts'/*, 'map/js/china' */], function (echarts) {
+            var option;
+
+            // Replace transition
         });
         </script>
 
 
+        <script>
+            require(['echarts'/*, 'map/js/china' */], function (echarts) {
+                var option;
+
+                // During transition
+            });
+        </script>
     </body>
 </html>
 

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