feat:iOS support fillmode and delay

This commit is contained in:
pengfei.zhou 2019-12-02 15:04:03 +08:00
parent b12930605e
commit 9b9d8de262
4 changed files with 76 additions and 24 deletions

View File

@ -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()) {

View File

@ -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)

View File

@ -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

View File

@ -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 objects 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 {
animations: this.animations.map(e => {
return e.toModel() return e.toModel()
}) as Model }) as Model,
fillMode: this.fillMode,
delay: this.delay,
}
} }
} }