diff --git a/demo/index.ts b/demo/index.ts index 0ee06023..cabb9c45 100644 --- a/demo/index.ts +++ b/demo/index.ts @@ -14,5 +14,6 @@ export default [ 'src/NavbarDemo', 'src/RefreshableDemo', 'src/FlowLayoutDemo', - 'src/PopoverDemo' + 'src/PopoverDemo', + 'src/AnimatorDemo', ] \ No newline at end of file diff --git a/demo/src/AnimatorDemo.ts b/demo/src/AnimatorDemo.ts new file mode 100644 index 00000000..b5a12243 --- /dev/null +++ b/demo/src/AnimatorDemo.ts @@ -0,0 +1,80 @@ +import { Group, Panel, popover, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, modal, IText, network, animator, View, stack } from "doric"; +import { title, label, colors, box } from "./utils"; + +@Entry +class AnimatorDemo extends Panel { + build(rootView: Group): void { + const view = box(2) + scroller(vlayout([ + title("Animator Demo"), + label('Reset').apply({ + width: 100, + height: 50, + bgColor: colors[4], + textSize: 20, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + } as IText).also(v => { + v.onClick = () => { + animator(this)({ + animations: () => { + view.width = view.height = 20 + }, + duration: 3000, + }) + } + }), + label('Width').apply({ + width: 100, + height: 50, + bgColor: colors[0], + textSize: 20, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + } as IText).also(v => { + v.onClick = () => { + animator(this)({ + animations: () => { + view.width = 500 + }, + duration: 3000, + }) + } + }), + label('Height').apply({ + width: 100, + height: 50, + bgColor: colors[0], + textSize: 20, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + } as IText).also(v => { + v.onClick = () => { + animator(this)({ + animations: () => { + view.height = 500 + }, + duration: 3000, + complete: () => { + modal(context).toast('Fininshed') + } + }) + } + }), + stack([ + view.also(v => { + v.left = 20 + }) + ]).apply({ + layoutConfig: layoutConfig().atmost(), + bgColor: colors[3], + }), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(rootView) + } +} \ No newline at end of file diff --git a/iOS/Pod/Classes/Plugin/DoricShaderPlugin.m b/iOS/Pod/Classes/Plugin/DoricShaderPlugin.m index 22f989e2..d7dbd985 100644 --- a/iOS/Pod/Classes/Plugin/DoricShaderPlugin.m +++ b/iOS/Pod/Classes/Plugin/DoricShaderPlugin.m @@ -23,7 +23,6 @@ #import "DoricShaderPlugin.h" #import "DoricRootNode.h" #import "DoricUtil.h" -#import "Doric.h" #import @@ -141,4 +140,27 @@ - (id)findClass:(Class)clz target:(id)target method:(NSString *)name promise:(Do return ret; } +- (void)animator:(NSDictionary *)args withPromise:(DoricPromise *)promise { + [promise resolve:nil]; +} + +- (void)animateRender:(NSDictionary *)args withPromise:(DoricPromise *)promise { + NSNumber *duration = args[@"duration"]; + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *viewId = args[@"id"]; + [UIView animateWithDuration:[duration floatValue] / 1000 + animations:^{ + if (self.doricContext.rootNode.viewId == nil) { + self.doricContext.rootNode.viewId = viewId; + [self.doricContext.rootNode blend:args[@"props"]]; + } else { + DoricViewNode *viewNode = [self.doricContext targetViewNode:viewId]; + [viewNode blend:args[@"props"]]; + } + } + completion:^(BOOL finished) { + [promise resolve:nil]; + }]; + }); +} @end diff --git a/js-framework/src/ui/animation.ts b/js-framework/src/ui/animation.ts index 2bdce10b..40ffb071 100644 --- a/js-framework/src/ui/animation.ts +++ b/js-framework/src/ui/animation.ts @@ -1,3 +1,8 @@ +import { Panel } from "./panel" +import { takeLet } from "../pattern/candies" +import { O_TRUNC } from "constants" +import { modal } from "../native/modal" + /* * Copyright [2019] [Doric.Pub] * @@ -151,4 +156,39 @@ export class AnimationSet { }) }) } +} + +export function animator(panel: Panel) { + return (args: { + animations: () => void, + duration: number, + complete?: () => void + }) => { + takeLet(panel.context.shader)(it => { + it.animator().then(() => { + args.animations() + return takeLet(panel.getRootView())(root => { + if (root.isDirty()) { + const model = root.toModel(); + (model as any).duration = args.duration + const ret = it.animateRender(model) + root.clean() + return ret + } + for (let v of panel.allHeadViews()) { + if (v.isDirty()) { + const model = v.toModel() + const ret = it.animateRender(model) + it.clean() + return ret + } + } + }) + }).then(() => { + if (args.complete) { + args.complete() + } + }) + }) + } } \ No newline at end of file diff --git a/js-framework/src/ui/panel.ts b/js-framework/src/ui/panel.ts index 7c488b1b..b8c3d98e 100644 --- a/js-framework/src/ui/panel.ts +++ b/js-framework/src/ui/panel.ts @@ -49,7 +49,9 @@ export abstract class Panel { addHeadView(v: View) { this.headviews.set(v.viewId, v) } - + allHeadViews() { + return this.headviews.values() + } removeHeadView(v: View | string) { if (v instanceof View) { this.headviews.delete(v.viewId)