feat:iOS support fillmode and delay
This commit is contained in:
		| @@ -656,10 +656,15 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Animator parseAnimator(JSValue value) { |     private Animator parseAnimator(JSValue value) { | ||||||
|         if (value.isArray()) { |         if (!value.isObject()) { | ||||||
|  |             DoricLog.e("parseAnimator error"); | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         JSValue animations = value.asObject().getProperty("animations"); | ||||||
|  |         if (animations.isArray()) { | ||||||
|             AnimatorSet animatorSet = new AnimatorSet(); |             AnimatorSet animatorSet = new AnimatorSet(); | ||||||
|             for (int i = 0; i < value.asArray().size(); i++) { |             for (int i = 0; i < animations.asArray().size(); i++) { | ||||||
|                 animatorSet.play(parseAnimator(value.asArray().get(i))); |                 animatorSet.play(parseAnimator(animations.asArray().get(i))); | ||||||
|             } |             } | ||||||
|             return animatorSet; |             return animatorSet; | ||||||
|         } else if (value.isObject()) { |         } else if (value.isObject()) { | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { animate, Group, Panel, gravity, Color, AnimationSet, vlayout, scroller, layoutConfig, IVLayout, modal, IText, network, View, stack, IHLayout, hlayout, IView, text, TranslationAnimation, ScaleAnimation, RotationAnimation } from "doric"; | import { animate, Group, Panel, gravity, Color, AnimationSet, vlayout, scroller, layoutConfig, IVLayout, modal, IText, network, View, stack, IHLayout, hlayout, IView, text, TranslationAnimation, ScaleAnimation, RotationAnimation, FillMode } from "doric"; | ||||||
| import { title, colors, box } from "./utils"; | import { title, colors, box } from "./utils"; | ||||||
|  |  | ||||||
| function thisLabel(str: string) { | function thisLabel(str: string) { | ||||||
| @@ -17,10 +17,13 @@ function thisLabel(str: string) { | |||||||
| class AnimatorDemo extends Panel { | class AnimatorDemo extends Panel { | ||||||
|     build(rootView: Group): void { |     build(rootView: Group): void { | ||||||
|         const view = box(2) |         const view = box(2) | ||||||
|  |         view.onClick = () => { | ||||||
|  |             modal(context).toast('Clicked') | ||||||
|  |         } | ||||||
|         const view2 = box(3) |         const view2 = box(3) | ||||||
|         let idx = 0 |         let idx = 0 | ||||||
|         vlayout([ |         vlayout([ | ||||||
|             title("Animator zDemo"), |             title("Animator Demo"), | ||||||
|             vlayout( |             vlayout( | ||||||
|                 [ |                 [ | ||||||
|                     hlayout([ |                     hlayout([ | ||||||
| @@ -167,27 +170,26 @@ class AnimatorDemo extends Panel { | |||||||
|                         thisLabel('animationSet').apply({ |                         thisLabel('animationSet').apply({ | ||||||
|                             onClick: () => { |                             onClick: () => { | ||||||
|                                 const animationSet = new AnimationSet |                                 const animationSet = new AnimationSet | ||||||
|  |                                 animationSet.fillMode = FillMode.Forward | ||||||
|  |                                 animationSet.delay = 2000 | ||||||
|                                 const translate = new TranslationAnimation |                                 const translate = new TranslationAnimation | ||||||
|                                 translate.fromTranslationX = 10 |                                 translate.fromTranslationX = 100 | ||||||
|                                 translate.toTranslationX = 200 |                                 translate.toTranslationX = 200 | ||||||
|                                 translate.fromTranslationY = 10 |                                 translate.fromTranslationY = 10 | ||||||
|                                 translate.toTranslationY = 200 |                                 translate.toTranslationY = 200 | ||||||
|                                 translate.duration = 3000 |                                 translate.duration = 2000 | ||||||
|                                 translate.delay = 1000 |                                 translate.delay = 1000 | ||||||
|                                 const scale = new ScaleAnimation |                                 const scale = new ScaleAnimation | ||||||
|                                 scale.fromScaleX = 1 |                                 scale.fromScaleX = 1 | ||||||
|                                 scale.toScaleX = 5 |                                 scale.toScaleX = 5 | ||||||
|                                 scale.fromScaleY = 1 |                                 scale.fromScaleY = 1 | ||||||
|                                 scale.toScaleY = 5 |                                 scale.toScaleY = 5 | ||||||
|                                 scale.duration = 3000 |                                 //scale.delay = 1000 | ||||||
|  |                                 scale.duration = 2000 | ||||||
|                                 const rotation = new RotationAnimation |                                 const rotation = new RotationAnimation | ||||||
|                                 rotation.fromRotation = 0 |                                 rotation.fromRotation = 0 | ||||||
|                                 rotation.toRotation = 6 |                                 rotation.toRotation = 6.2 | ||||||
|                                 rotation.delay = 1000 |  | ||||||
|                                 rotation.duration = 3000 |                                 rotation.duration = 3000 | ||||||
|  |  | ||||||
|                                 animationSet.addAnimation(translate) |                                 animationSet.addAnimation(translate) | ||||||
|                                 animationSet.addAnimation(scale) |                                 animationSet.addAnimation(scale) | ||||||
|                                 animationSet.addAnimation(rotation) |                                 animationSet.addAnimation(rotation) | ||||||
|   | |||||||
| @@ -323,14 +323,15 @@ - (void)blendLayoutConfig:(NSDictionary *)params { | |||||||
| 
 | 
 | ||||||
| - (void)doAnimation:(id)params withPromise:(DoricPromise *)promise { | - (void)doAnimation:(id)params withPromise:(DoricPromise *)promise { | ||||||
|     CAAnimation *animation = [self parseAnimation:params]; |     CAAnimation *animation = [self parseAnimation:params]; | ||||||
|     animation.removedOnCompletion = NO; |  | ||||||
|     animation.fillMode = kCAFillModeForwards; |  | ||||||
|     AnimationCallback *animationCallback = [[AnimationCallback new] also:^(AnimationCallback *it) { |     AnimationCallback *animationCallback = [[AnimationCallback new] also:^(AnimationCallback *it) { | ||||||
|         it.endBlock = ^{ |         it.endBlock = ^{ | ||||||
|             [promise resolve:nil]; |             [promise resolve:nil]; | ||||||
|         }; |         }; | ||||||
|     }]; |     }]; | ||||||
|     animation.delegate = animationCallback; |     animation.delegate = animationCallback; | ||||||
|  |     if (params[@"delay"]) { | ||||||
|  |         animation.beginTime = CACurrentMediaTime() + [params[@"delay"] floatValue] / 1000; | ||||||
|  |     } | ||||||
|     [self.view.layer addAnimation:animation forKey:nil]; |     [self.view.layer addAnimation:animation forKey:nil]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @@ -343,15 +344,20 @@ - (CFTimeInterval)computeDurationOfAnimations:(NSArray<CAAnimation *> *)animatio | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| - (CAAnimation *)parseAnimation:(id)params { | - (CAAnimation *)parseAnimation:(id)params { | ||||||
|     if ([params isKindOfClass:[NSArray class]]) { |     if (params[@"animations"]) { | ||||||
|         NSArray *anims = params; |         NSArray *anims = params[@"animations"]; | ||||||
|         CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; |         CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; | ||||||
|         NSMutableArray *animations = [NSMutableArray new]; |         NSMutableArray *animations = [NSMutableArray new]; | ||||||
|         [anims forEach:^(id obj) { |         [anims forEach:^(id obj) { | ||||||
|             [animations addObject:[self parseAnimation:obj]]; |             [animations addObject:[self parseAnimation:obj]]; | ||||||
|         }]; |         }]; | ||||||
|         animationGroup.duration = [self computeDurationOfAnimations:animations]; |         animationGroup.duration = [self computeDurationOfAnimations:animations]; | ||||||
|  |         animationGroup.fillMode = [self translateToFillMode:params[@"fillMode"]]; | ||||||
|  |         animationGroup.removedOnCompletion = [animationGroup.fillMode isEqualToString:kCAFillModeRemoved]; | ||||||
|         animationGroup.animations = animations; |         animationGroup.animations = animations; | ||||||
|  |         if (params[@"delay"]) { | ||||||
|  |             animationGroup.beginTime = [params[@"delay"] floatValue] / 1000; | ||||||
|  |         } | ||||||
|         return animationGroup; |         return animationGroup; | ||||||
|     } else if ([params isKindOfClass:[NSDictionary class]]) { |     } else if ([params isKindOfClass:[NSDictionary class]]) { | ||||||
|         NSArray<NSDictionary *> *changeables = params[@"changeables"]; |         NSArray<NSDictionary *> *changeables = params[@"changeables"]; | ||||||
| @@ -405,8 +411,8 @@ - (void)setAnimation:(CAAnimation *)animation params:(NSDictionary *)params { | |||||||
|         animation.beginTime = [params[@"delay"] floatValue] / 1000; |         animation.beginTime = [params[@"delay"] floatValue] / 1000; | ||||||
|     } |     } | ||||||
|     animation.duration = [params[@"duration"] floatValue] / 1000; |     animation.duration = [params[@"duration"] floatValue] / 1000; | ||||||
|     animation.removedOnCompletion = NO; |     animation.fillMode = [self translateToFillMode:params[@"fillMode"]]; | ||||||
|     animation.fillMode = kCAFillModeForwards; |     animation.removedOnCompletion = [animation.fillMode isEqualToString:kCAFillModeRemoved]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| - (CAAnimation *)parseChangeable:(NSDictionary *)params { | - (CAAnimation *)parseChangeable:(NSDictionary *)params { | ||||||
| @@ -432,4 +438,17 @@ - (CAAnimation *)parseChangeable:(NSDictionary *)params { | |||||||
|     return animation; |     return animation; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | - (CAMediaTimingFillMode)translateToFillMode:(NSNumber *)fillMode { | ||||||
|  |     switch ([fillMode integerValue]) { | ||||||
|  |         case 1: | ||||||
|  |             return kCAFillModeForwards; | ||||||
|  |         case 2: | ||||||
|  |             return kCAFillModeBackwards; | ||||||
|  |         case 3: | ||||||
|  |             return kCAFillModeBoth; | ||||||
|  |         default: | ||||||
|  |             return kCAFillModeRemoved; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @end | @end | ||||||
|   | |||||||
| @@ -18,13 +18,16 @@ import { Modeling, Model } from "../util/types" | |||||||
|  |  | ||||||
|  |  | ||||||
| export type AnimatedKey = "translationX" | "translationY" | "scaleX" | "scaleY" | "rotation" | "pivotX" | "pivotY" | export type AnimatedKey = "translationX" | "translationY" | "scaleX" | "scaleY" | "rotation" | "pivotX" | "pivotY" | ||||||
|  |  | ||||||
| export enum RepeatMode { | export enum RepeatMode { | ||||||
|     RESTART = 1, |     RESTART = 1, | ||||||
|     REVERSE = 2, |     REVERSE = 2, | ||||||
| } | } | ||||||
|  |  | ||||||
| export interface IAnimation extends Modeling { | export interface IAnimation extends Modeling { | ||||||
|     duration: number |     duration: number | ||||||
|     delay?: number |     delay?: number | ||||||
|  |     fillMode: FillMode | ||||||
| } | } | ||||||
|  |  | ||||||
| export interface Changeable { | export interface Changeable { | ||||||
| @@ -34,6 +37,24 @@ export interface Changeable { | |||||||
|     repeatCount?: number |     repeatCount?: number | ||||||
|     repeatMode?: RepeatMode |     repeatMode?: RepeatMode | ||||||
| } | } | ||||||
|  | export enum FillMode { | ||||||
|  |     /** | ||||||
|  |      * The receiver is removed from the presentation when the animation is completed. | ||||||
|  |      */ | ||||||
|  |     Removed = 0, | ||||||
|  |     /** | ||||||
|  |      * The receiver remains visible in its final state when the animation is completed. | ||||||
|  |      */ | ||||||
|  |     Forward = 1, | ||||||
|  |     /** | ||||||
|  |      * The receiver clamps values before zero to zero when the animation is completed. | ||||||
|  |      */ | ||||||
|  |     Backward = 2, | ||||||
|  |     /** | ||||||
|  |      * The receiver clamps values at both ends of the object’s time space | ||||||
|  |      */ | ||||||
|  |     Both = 3, | ||||||
|  | } | ||||||
|  |  | ||||||
| abstract class Animation implements IAnimation { | abstract class Animation implements IAnimation { | ||||||
|     changeables: Map<AnimatedKey, Changeable> = new Map |     changeables: Map<AnimatedKey, Changeable> = new Map | ||||||
| @@ -41,7 +62,7 @@ abstract class Animation implements IAnimation { | |||||||
|     repeatCount?: number |     repeatCount?: number | ||||||
|     repeatMode?: RepeatMode |     repeatMode?: RepeatMode | ||||||
|     delay?: number |     delay?: number | ||||||
|  |     fillMode = FillMode.Forward | ||||||
|     toModel() { |     toModel() { | ||||||
|         const changeables = [] |         const changeables = [] | ||||||
|         for (let e of this.changeables.values()) { |         for (let e of this.changeables.values()) { | ||||||
| @@ -58,6 +79,7 @@ abstract class Animation implements IAnimation { | |||||||
|             changeables, |             changeables, | ||||||
|             repeatCount: this.repeatCount, |             repeatCount: this.repeatCount, | ||||||
|             repeatMode: this.repeatMode, |             repeatMode: this.repeatMode, | ||||||
|  |             fillMode: this.fillMode, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -193,7 +215,7 @@ export class AnimationSet implements IAnimation { | |||||||
|     private animations: IAnimation[] = [] |     private animations: IAnimation[] = [] | ||||||
|     _duration = 0 |     _duration = 0 | ||||||
|     delay?: number |     delay?: number | ||||||
|  |     fillMode = FillMode.Removed | ||||||
|     addAnimation(anim: IAnimation) { |     addAnimation(anim: IAnimation) { | ||||||
|         this.animations.push(anim) |         this.animations.push(anim) | ||||||
|     } |     } | ||||||
| @@ -208,8 +230,12 @@ export class AnimationSet implements IAnimation { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     toModel() { |     toModel() { | ||||||
|         return this.animations.map(e => { |         return { | ||||||
|             return e.toModel() |             animations: this.animations.map(e => { | ||||||
|         }) as Model |                 return e.toModel() | ||||||
|  |             }) as Model, | ||||||
|  |             fillMode: this.fillMode, | ||||||
|  |             delay: this.delay, | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user