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


The following commit(s) were added to refs/heads/graphic-animation by this push:
     new 72ea7a6  feat(graphic): support clipPath
72ea7a6 is described below

commit 72ea7a6897d650a91f853fba82a22a279f23c150
Author: pissang <[email protected]>
AuthorDate: Fri Dec 10 20:48:38 2021 +0800

    feat(graphic): support clipPath
---
 src/animation/customGraphicKeyframeAnimation.ts | 19 +++++---
 src/component/graphic/GraphicModel.ts           |  9 +++-
 src/component/graphic/GraphicView.ts            | 65 ++++++++++++++++++++-----
 src/util/model.ts                               |  5 +-
 4 files changed, 77 insertions(+), 21 deletions(-)

diff --git a/src/animation/customGraphicKeyframeAnimation.ts 
b/src/animation/customGraphicKeyframeAnimation.ts
index a585313..0de270a 100644
--- a/src/animation/customGraphicKeyframeAnimation.ts
+++ b/src/animation/customGraphicKeyframeAnimation.ts
@@ -91,10 +91,21 @@ export function applyKeyframeAnimation<T extends 
Record<string, any>>(
 
         let animator: ReturnType<Element['animate']>;
         let endFrameIsSet = false;
+
+        // Sort keyframes by percent.
+        keyframes.sort((a, b) => a.percent - b.percent);
+
         each(keyframes, kf => {
             // Stop current animation.
             const animators = el.animators;
             const kfValues = targetPropName ? kf[targetPropName] : kf;
+
+            if (__DEV__) {
+                if (kf.percent >= 1) {
+                    endFrameIsSet = true;
+                }
+            }
+
             if (!kfValues) {
                 return;
             }
@@ -111,14 +122,8 @@ export function applyKeyframeAnimation<T extends 
Record<string, any>>(
                 return;
             }
 
-            if (__DEV__) {
-                if (kf.percent >= 1) {
-                    endFrameIsSet = true;
-                }
-            }
-
             if (!animator) {
-                animator = el.animate(targetPropName, animationOpts.loop);
+                animator = el.animate(targetPropName, animationOpts.loop, 
true);
                 animator.scope = 'keyframe';
             }
             for (let i = 0; i < animators.length; i++) {
diff --git a/src/component/graphic/GraphicModel.ts 
b/src/component/graphic/GraphicModel.ts
index bf619a1..5f32583 100644
--- a/src/component/graphic/GraphicModel.ts
+++ b/src/component/graphic/GraphicModel.ts
@@ -110,7 +110,11 @@ interface GraphicComponentBaseElementOption extends
      */
     info?: GraphicExtraElementInfo;
 
-    textContent?: GraphicComponentTextOption;
+
+    // `false` means remove the clipPath
+    clipPath?: Omit<GraphicComponentZRPathOption, 'clipPath'> | false;
+
+    textContent?: Omit<GraphicComponentTextOption, 'clipPath'>;
     textConfig?: ElementTextConfig;
 
     $action?: 'merge' | 'replace' | 'remove';
@@ -270,6 +274,9 @@ function mergeNewElOptionToExist(
             copyTransitionInfo(newElOption, existElOption, 'shape');
             copyTransitionInfo(newElOption, existElOption, 'style');
             copyTransitionInfo(newElOption, existElOption, 'extra');
+
+            // Copy clipPath
+            newElOption.clipPath = existElOption.clipPath;
         }
         else {
             existList[index] = newElOptCopy;
diff --git a/src/component/graphic/GraphicView.ts 
b/src/component/graphic/GraphicView.ts
index 131a223..7dadea8 100644
--- a/src/component/graphic/GraphicView.ts
+++ b/src/component/graphic/GraphicView.ts
@@ -67,6 +67,7 @@ export const inner = modelUtil.makeInner<{
     height: number;
     isNew: boolean;
     id: string;
+    type: string;
     option: GraphicComponentElementOption
 }, Element>();
 // ------------------------
@@ -167,7 +168,9 @@ export class GraphicComponentView extends ComponentView {
             }
 
             const $action = elOption.$action || 'merge';
-            if ($action === 'merge') {
+            const isMerge = $action === 'merge';
+            const isReplace = $action === 'replace';
+            if (isMerge) {
                 const isInit = !elExisting;
                 let el = elExisting;
                 if (isInit) {
@@ -188,7 +191,7 @@ export class GraphicComponentView extends ComponentView {
                     updateZ(el, elOption, globalZ, globalZLevel);
                 }
             }
-            else if ($action === 'replace') {
+            else if (isReplace) {
                 removeEl(elExisting, elOption, elMap, graphicModel);
                 const el = createEl(id, targetElParent, elOption.type, elMap);
                 if (el) {
@@ -209,18 +212,49 @@ export class GraphicComponentView extends ComponentView {
             const el = elMap.get(id);
 
             if (el && textContentOption) {
-                if ($action === 'merge') {
+                if (isMerge) {
                     const textContentExisting = el.getTextContent();
                     textContentExisting
                         ? textContentExisting.attr(textContentOption)
                         : el.setTextContent(new 
graphicUtil.Text(textContentOption));
                 }
-                else if ($action === 'replace') {
+                else if (isReplace) {
                     el.setTextContent(new graphicUtil.Text(textContentOption));
                 }
             }
 
             if (el) {
+                const clipPathOption = elOption.clipPath;
+                if (clipPathOption) {
+                    const clipPathType = clipPathOption.type;
+                    let clipPath: graphicUtil.Path;
+                    let isInit = false;
+                    if (isMerge) {
+                        const oldClipPath = el.getClipPath();
+                        isInit = !oldClipPath
+                            || inner(oldClipPath).type !== clipPathType;
+                        clipPath = isInit ? newEl(clipPathType) as 
graphicUtil.Path : oldClipPath;
+                    }
+                    else if (isReplace) {
+                        isInit = true;
+                        clipPath = newEl(clipPathType) as graphicUtil.Path;
+                    }
+
+                    el.setClipPath(clipPath);
+
+                    applyUpdateTransition(
+                        clipPath,
+                        clipPathOption,
+                        graphicModel,
+                        { isInit}
+                    );
+                    applyKeyframeAnimation(
+                        clipPath,
+                        clipPathOption.keyframeAnimation,
+                        graphicModel
+                    );
+                }
+
                 const elInner = inner(el);
 
                 el.setTextConfig(textConfig);
@@ -345,13 +379,8 @@ export class GraphicComponentView extends ComponentView {
         this._clear();
     }
 }
-function createEl(
-    id: string,
-    targetElParent: graphicUtil.Group,
-    graphicType: string,
-    elMap: ElementMap
-): Element {
 
+function newEl(graphicType: string) {
     if (__DEV__) {
         zrUtil.assert(graphicType, 'graphic type MUST be set');
     }
@@ -365,10 +394,22 @@ function createEl(
     ) as { new(opt: GraphicComponentElementOption): Element; };
 
     if (__DEV__) {
-        zrUtil.assert(Clz, 'graphic type can not be found');
+        zrUtil.assert(Clz, `graphic type ${graphicType} can not be found`);
     }
 
     const el = new Clz({});
+    inner(el).type = graphicType;
+    return el;
+}
+function createEl(
+    id: string,
+    targetElParent: graphicUtil.Group,
+    graphicType: string,
+    elMap: ElementMap
+): Element {
+
+    const el = newEl(graphicType);
+
     targetElParent.add(el);
     elMap.set(id, el);
     inner(el).id = id;
@@ -413,7 +454,7 @@ function getCleanedElOption(
 ): Omit<GraphicComponentElementOption, 'textContent'> {
     elOption = zrUtil.extend({}, elOption);
     zrUtil.each(
-        ['id', 'parentId', '$action', 'hv', 'bounding', 
'textContent'].concat(layoutUtil.LOCATION_PARAMS),
+        ['id', 'parentId', '$action', 'hv', 'bounding', 'textContent', 
'clipPath'].concat(layoutUtil.LOCATION_PARAMS),
         function (name) {
             delete (elOption as any)[name];
         }
diff --git a/src/util/model.ts b/src/util/model.ts
index 9f78c15..2495723 100644
--- a/src/util/model.ts
+++ b/src/util/model.ts
@@ -51,9 +51,12 @@ import SeriesModel from '../model/Series';
 import CartesianAxisModel from '../coord/cartesian/AxisModel';
 import GridModel from '../coord/cartesian/GridModel';
 import { isNumeric, getRandomIdBase, getPrecision, round } from './number';
-import { interpolateNumber } from 'zrender/src/animation/Animator';
 import { warn } from './log';
 
+function interpolateNumber(p0: number, p1: number, percent: number): number {
+    return (p1 - p0) * percent + p0;
+}
+
 /**
  * Make the name displayable. But we should
  * make sure it is not duplicated with user

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to