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 48ba921  feat(animation): restore props after keyframe animation is 
stopped
48ba921 is described below

commit 48ba9213aeddb10c85b66a101d42ebd3c27cdf6f
Author: pissang <[email protected]>
AuthorDate: Wed Dec 1 12:27:13 2021 +0800

    feat(animation): restore props after keyframe animation is stopped
---
 src/animation/customGraphicKeyframeAnimation.ts | 40 +++++++++++++++++++------
 src/component/graphic/GraphicView.ts            |  8 ++++-
 test/graphic-animation-wave.html                |  8 -----
 test/graphic-animation.html                     |  4 +--
 4 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/src/animation/customGraphicKeyframeAnimation.ts 
b/src/animation/customGraphicKeyframeAnimation.ts
index 3116a33..20c9d7e 100644
--- a/src/animation/customGraphicKeyframeAnimation.ts
+++ b/src/animation/customGraphicKeyframeAnimation.ts
@@ -21,10 +21,11 @@ import { AnimationEasing } from 
'zrender/src/animation/easing';
 import Element from 'zrender/src/Element';
 import { keys, filter, each } from 'zrender/src/core/util';
 import { ELEMENT_ANIMATABLE_PROPS } from './customGraphicTransition';
-import { AnimationOption, AnimationOptionMixin } from '../util/types';
+import { AnimationOption, AnimationOptionMixin, Dictionary } from 
'../util/types';
 import { Model } from '../echarts.all';
 import { getAnimationConfig } from './basicTrasition';
 import { warn } from '../util/log';
+import { makeInner } from '../util/model';
 
 // Helpers for creating keyframe based animations in custom series and graphic 
components.
 
@@ -33,12 +34,26 @@ type AnimationKeyframe<T extends Record<string, any>> = T & 
{
     percent?: number    // 0 - 1
 };
 
+type StateToRestore = Dictionary<any>;
+const getStateToRestore = makeInner<StateToRestore, Element>();
+
 export interface ElementKeyframeAnimationOption<Props extends Record<string, 
any>> extends AnimationOption {
     // Animation configuration for keyframe based animation.
     loop?: boolean
     keyframes?: AnimationKeyframe<Props>[]
 }
 
+/**
+ * Stopped previous keyframe animation and restore the attributes.
+ * Avoid new keyframe animation starts with wrong internal state when the 
percent: 0 is not set.
+ */
+export function stopPreviousKeyframeAnimationAndRestore(el: Element) {
+    // Stop previous keyframe animation.
+    el.stopAnimation('keyframe');
+    // Restore
+    el.attr(getStateToRestore(el));
+}
+
 export function applyKeyframeAnimation<T extends Record<string, any>>(
     el: Element,
     animationOpts: ElementKeyframeAnimationOption<T>,
@@ -48,9 +63,6 @@ export function applyKeyframeAnimation<T extends 
Record<string, any>>(
         return;
     }
 
-    // Stop previous keyframe animation.
-    el.stopAnimation('keyframe');
-
     const keyframes = animationOpts.keyframes;
     let duration = animationOpts.duration;
 
@@ -63,8 +75,10 @@ export function applyKeyframeAnimation<T extends 
Record<string, any>>(
         return;
     }
 
-    function applyKeyframeAnimationOnProp(propName: typeof 
ELEMENT_ANIMATABLE_PROPS[number]) {
-        if (propName && !(el as any)[propName]) {
+    const stateToRestore: StateToRestore = getStateToRestore(el);
+
+    function applyKeyframeAnimationOnProp(targetPropName: typeof 
ELEMENT_ANIMATABLE_PROPS[number]) {
+        if (targetPropName && !(el as any)[targetPropName]) {
             return;
         }
 
@@ -73,13 +87,13 @@ export function applyKeyframeAnimation<T extends 
Record<string, any>>(
         each(keyframes, kf => {
             // Stop current animation.
             const animators = el.animators;
-            const kfValues = propName ? kf[propName] : kf;
+            const kfValues = targetPropName ? kf[targetPropName] : kf;
             if (!kfValues) {
                 return;
             }
 
             let propKeys = keys(kfValues);
-            if (!propName) {
+            if (!targetPropName) {
                 // PENDING performance?
                 propKeys = filter(
                     propKeys, key => key !== 'percent' && key !== 'easing'
@@ -97,7 +111,7 @@ export function applyKeyframeAnimation<T extends 
Record<string, any>>(
             }
 
             if (!animator) {
-                animator = el.animate(propName, animationOpts.loop);
+                animator = el.animate(targetPropName, animationOpts.loop);
                 animator.scope = 'keyframe';
             }
             for (let i = 0; i < animators.length; i++) {
@@ -107,6 +121,14 @@ export function applyKeyframeAnimation<T extends 
Record<string, any>>(
                 }
             }
 
+            targetPropName && (stateToRestore[targetPropName] = 
stateToRestore[targetPropName] || {});
+
+            const savedTarget = targetPropName ? 
stateToRestore[targetPropName] : stateToRestore;
+            each(propKeys, key => {
+                // Save original value.
+                savedTarget[key] = ((targetPropName ? (el as 
any)[targetPropName] : el) || {})[key];
+            });
+
             animator.whenWithKeys(duration * kf.percent, kfValues, propKeys, 
kf.easing);
         });
         if (!animator) {
diff --git a/src/component/graphic/GraphicView.ts 
b/src/component/graphic/GraphicView.ts
index 4ca8b95..f790db8 100644
--- a/src/component/graphic/GraphicView.ts
+++ b/src/component/graphic/GraphicView.ts
@@ -45,7 +45,10 @@ import {
     updateLeaveTo
 } from '../../animation/customGraphicTransition';
 import { updateProps } from '../../animation/basicTrasition';
-import { applyKeyframeAnimation } from 
'../../animation/customGraphicKeyframeAnimation';
+import {
+    applyKeyframeAnimation,
+    stopPreviousKeyframeAnimationAndRestore
+} from '../../animation/customGraphicKeyframeAnimation';
 
 const nonShapeGraphicElements = {
     // Reserved but not supported in graphic component.
@@ -154,6 +157,7 @@ export class GraphicComponentView extends ComponentView {
             // Remove unnecessary props to avoid potential problems.
             const elOptionCleaned = getCleanedElOption(elOption);
 
+
             // For simple, do not support parent change, otherwise reorder is 
needed.
             if (__DEV__) {
                 elExisting && zrUtil.assert(
@@ -171,6 +175,8 @@ export class GraphicComponentView extends ComponentView {
                 }
                 else {
                     el && (inner(el).isNew = false);
+                    // Stop and restore before update any other attributes.
+                    stopPreviousKeyframeAnimationAndRestore(el);
                 }
                 if (el) {
                     applyUpdateTransition(
diff --git a/test/graphic-animation-wave.html b/test/graphic-animation-wave.html
index c2477a1..44a4864 100644
--- a/test/graphic-animation-wave.html
+++ b/test/graphic-animation-wave.html
@@ -101,14 +101,6 @@ under the License.
                                     loop: true,
                                     delay: (rand - 1) * 4000,
                                     keyframes: [{
-                                        percent: 0.,
-                                        easing: 'sinusoidalInOut',
-                                        style: {
-                                            fill: config.color1
-                                        },
-                                        scaleX: 1,
-                                        scaleY: 1
-                                    }, {
                                         percent: 0.5,
                                         easing: 'sinusoidalInOut',
                                         style: {
diff --git a/test/graphic-animation.html b/test/graphic-animation.html
index 2cb5ec6..4ebf2db 100644
--- a/test/graphic-animation.html
+++ b/test/graphic-animation.html
@@ -44,7 +44,7 @@ under the License.
 
 
 
-<!--
+
         <script>
         require(['echarts'/*, 'map/js/china' */], function (echarts) {
             var option = {
@@ -89,7 +89,7 @@ under the License.
             });
 
         });
-        </script> -->
+        </script>
 
         <script>
             require(['echarts'/*, 'map/js/china' */], function (echarts) {

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

Reply via email to