web: add AnimatePlugin
This commit is contained in:
		
							
								
								
									
										197
									
								
								doric-web/dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										197
									
								
								doric-web/dist/index.js
									
									
									
									
										vendored
									
									
								
							| @@ -4550,57 +4550,67 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|         } |         } | ||||||
|         configBorder() { |         configBorder() { | ||||||
|             if (this.border) { |             if (this.border) { | ||||||
|                 this.view.style.borderStyle = "solid"; |                 this.applyCSSStyle({ | ||||||
|                 this.view.style.borderWidth = toPixelString(this.border.width); |                     borderStyle: "solid", | ||||||
|                 this.view.style.borderColor = toRGBAString(this.border.color); |                     borderWidth: toPixelString(this.border.width), | ||||||
|  |                     borderColor: toRGBAString(this.border.color), | ||||||
|  |                 }); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         configWidth() { |         configWidth() { | ||||||
|  |             let width; | ||||||
|             switch (this.layoutConfig.widthSpec) { |             switch (this.layoutConfig.widthSpec) { | ||||||
|                 case exports.LayoutSpec.WRAP_CONTENT: |                 case exports.LayoutSpec.WRAP_CONTENT: | ||||||
|                     this.view.style.width = "max-content"; |                     width = "max-content"; | ||||||
|                     break; |                     break; | ||||||
|                 case exports.LayoutSpec.AT_MOST: |                 case exports.LayoutSpec.AT_MOST: | ||||||
|                     this.view.style.width = "100%"; |                     width = "100%"; | ||||||
|                     break; |                     break; | ||||||
|                 case exports.LayoutSpec.EXACTLY: |                 case exports.LayoutSpec.EXACTLY: | ||||||
|                 default: |                 default: | ||||||
|                     this.view.style.width = toPixelString(this.frameWidth |                     width = toPixelString(this.frameWidth | ||||||
|                         - this.paddingLeft - this.paddingRight |                         - this.paddingLeft - this.paddingRight | ||||||
|                         - this.borderWidth * 2); |                         - this.borderWidth * 2); | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
|  |             this.applyCSSStyle({ width }); | ||||||
|         } |         } | ||||||
|         configHeight() { |         configHeight() { | ||||||
|  |             let height; | ||||||
|             switch (this.layoutConfig.heightSpec) { |             switch (this.layoutConfig.heightSpec) { | ||||||
|                 case exports.LayoutSpec.WRAP_CONTENT: |                 case exports.LayoutSpec.WRAP_CONTENT: | ||||||
|                     this.view.style.height = "max-content"; |                     height = "max-content"; | ||||||
|                     break; |                     break; | ||||||
|                 case exports.LayoutSpec.AT_MOST: |                 case exports.LayoutSpec.AT_MOST: | ||||||
|                     this.view.style.height = "100%"; |                     height = "100%"; | ||||||
|                     break; |                     break; | ||||||
|                 case exports.LayoutSpec.EXACTLY: |                 case exports.LayoutSpec.EXACTLY: | ||||||
|                 default: |                 default: | ||||||
|                     this.view.style.height = toPixelString(this.frameHeight |                     height = toPixelString(this.frameHeight | ||||||
|                         - this.paddingTop - this.paddingBottom |                         - this.paddingTop - this.paddingBottom | ||||||
|                         - this.borderWidth * 2); |                         - this.borderWidth * 2); | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
|  |             this.applyCSSStyle({ height }); | ||||||
|         } |         } | ||||||
|         configMargin() { |         configMargin() { | ||||||
|             if (this.layoutConfig.margin) { |             if (this.layoutConfig.margin) { | ||||||
|                 this.view.style.marginLeft = toPixelString(this.layoutConfig.margin.left || 0); |                 this.applyCSSStyle({ | ||||||
|                 this.view.style.marginRight = toPixelString(this.layoutConfig.margin.right || 0); |                     marginLeft: toPixelString(this.layoutConfig.margin.left || 0), | ||||||
|                 this.view.style.marginTop = toPixelString(this.layoutConfig.margin.top || 0); |                     marginRight: toPixelString(this.layoutConfig.margin.right || 0), | ||||||
|                 this.view.style.marginBottom = toPixelString(this.layoutConfig.margin.bottom || 0); |                     marginTop: toPixelString(this.layoutConfig.margin.top || 0), | ||||||
|  |                     marginBottom: toPixelString(this.layoutConfig.margin.bottom || 0), | ||||||
|  |                 }); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         configPadding() { |         configPadding() { | ||||||
|             if (this.padding) { |             if (this.padding) { | ||||||
|                 this.view.style.paddingLeft = toPixelString(this.paddingLeft); |                 this.applyCSSStyle({ | ||||||
|                 this.view.style.paddingRight = toPixelString(this.paddingRight); |                     paddingLeft: toPixelString(this.paddingLeft), | ||||||
|                 this.view.style.paddingTop = toPixelString(this.paddingTop); |                     paddingRight: toPixelString(this.paddingRight), | ||||||
|                 this.view.style.paddingBottom = toPixelString(this.paddingBottom); |                     paddingTop: toPixelString(this.paddingTop), | ||||||
|  |                     paddingBottom: toPixelString(this.paddingBottom), | ||||||
|  |                 }); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         layout() { |         layout() { | ||||||
| @@ -4647,35 +4657,61 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|                     break; |                     break; | ||||||
|                 case 'corners': |                 case 'corners': | ||||||
|                     if (typeof prop === 'object') { |                     if (typeof prop === 'object') { | ||||||
|                         this.view.style.borderTopLeftRadius = toPixelString(prop.leftTop); |                         this.applyCSSStyle({ | ||||||
|                         this.view.style.borderTopRightRadius = toPixelString(prop.rightTop); |                             borderTopLeftRadius: toPixelString(prop.leftTop), | ||||||
|                         this.view.style.borderBottomRightRadius = toPixelString(prop.rightBottom); |                             borderTopRightRadius: toPixelString(prop.rightTop), | ||||||
|                         this.view.style.borderBottomLeftRadius = toPixelString(prop.leftBottom); |                             borderBottomRightRadius: toPixelString(prop.rightBottom), | ||||||
|  |                             borderBottomLeftRadius: toPixelString(prop.leftBottom), | ||||||
|  |                         }); | ||||||
|                     } |                     } | ||||||
|                     else { |                     else { | ||||||
|                         this.view.style.borderRadius = toPixelString(prop); |                         this.applyCSSStyle({ borderRadius: toPixelString(prop) }); | ||||||
|                     } |                     } | ||||||
|                     break; |                     break; | ||||||
|                 case 'shadow': |                 case 'shadow': | ||||||
|                     const opacity = prop.opacity || 0; |                     const opacity = prop.opacity || 0; | ||||||
|  |                     let boxShadow; | ||||||
|                     if (opacity > 0) { |                     if (opacity > 0) { | ||||||
|                         const offsetX = prop.offsetX || 0; |                         const offsetX = prop.offsetX || 0; | ||||||
|                         const offsetY = prop.offsetY || 0; |                         const offsetY = prop.offsetY || 0; | ||||||
|                         const shadowColor = prop.color || 0xff000000; |                         const shadowColor = prop.color || 0xff000000; | ||||||
|                         const shadowRadius = prop.radius; |                         const shadowRadius = prop.radius; | ||||||
|                         const alpha = opacity * 255; |                         const alpha = opacity * 255; | ||||||
|                         this.view.style.boxShadow = `${toPixelString(offsetX)} ${toPixelString(offsetY)} ${toPixelString(shadowRadius)} ${toRGBAString((shadowColor & 0xffffff) | ((alpha & 0xff) << 24))} `; |                         boxShadow = `${toPixelString(offsetX)} ${toPixelString(offsetY)} ${toPixelString(shadowRadius)} ${toRGBAString((shadowColor & 0xffffff) | ((alpha & 0xff) << 24))} `; | ||||||
|                     } |                     } | ||||||
|                     else { |                     else { | ||||||
|                         this.view.style.boxShadow = ""; |                         boxShadow = ""; | ||||||
|                     } |                     } | ||||||
|  |                     this.applyCSSStyle({ | ||||||
|  |                         boxShadow, | ||||||
|  |                     }); | ||||||
|                     break; |                     break; | ||||||
|                 case 'alpha': |                 case 'alpha': | ||||||
|                     this.view.style.opacity = `${prop}`; |                     this.applyCSSStyle({ | ||||||
|  |                         opacity: `${prop}`, | ||||||
|  |                     }); | ||||||
|                     break; |                     break; | ||||||
|                 case 'rotation': |                 case 'rotation': | ||||||
|                     this.transform.rotation = prop; |                     this.transform.rotation = prop; | ||||||
|                     break; |                     break; | ||||||
|  |                 case 'rotationX': | ||||||
|  |                     this.transform.rotationX = prop; | ||||||
|  |                     break; | ||||||
|  |                 case 'rotationY': | ||||||
|  |                     this.transform.rotationY = prop; | ||||||
|  |                     break; | ||||||
|  |                 case 'scaleX': | ||||||
|  |                     this.transform.scaleX = prop; | ||||||
|  |                     break; | ||||||
|  |                 case 'scaleY': | ||||||
|  |                     this.transform.scaleY = prop; | ||||||
|  |                     break; | ||||||
|  |                 case 'translationX': | ||||||
|  |                     this.transform.translateX = prop; | ||||||
|  |                     break; | ||||||
|  |                 case 'translationY': | ||||||
|  |                     this.transform.translateY = prop; | ||||||
|  |                     break; | ||||||
|                 case 'pivotX': |                 case 'pivotX': | ||||||
|                     if (this.transformOrigin) { |                     if (this.transformOrigin) { | ||||||
|                         this.transformOrigin.x = prop; |                         this.transformOrigin.x = prop; | ||||||
| @@ -4699,12 +4735,9 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|                     } |                     } | ||||||
|                     break; |                     break; | ||||||
|                 case 'hidden': |                 case 'hidden': | ||||||
|                     if (prop === true) { |                     this.applyCSSStyle({ | ||||||
|                         this.view.style.display = "none"; |                         display: prop === true ? "none" : this._originDisplay | ||||||
|                     } |                     }); | ||||||
|                     else { |  | ||||||
|                         this.view.style.display = this._originDisplay; |  | ||||||
|                     } |  | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|                     console.error(`Cannot blend prop for ${propName}`); |                     console.error(`Cannot blend prop for ${propName}`); | ||||||
| @@ -4712,7 +4745,7 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         set backgroundColor(v) { |         set backgroundColor(v) { | ||||||
|             this.view.style.backgroundColor = toRGBAString(v); |             this.applyCSSStyle({ backgroundColor: toRGBAString(v) }); | ||||||
|         } |         } | ||||||
|         static create(context, type) { |         static create(context, type) { | ||||||
|             const viewNodeClass = acquireViewNode(type); |             const viewNodeClass = acquireViewNode(type); | ||||||
| @@ -4748,7 +4781,8 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|             return Reflect.apply(this.context.pureInvokeEntityMethod, this.context, argumentsList); |             return Reflect.apply(this.context.pureInvokeEntityMethod, this.context, argumentsList); | ||||||
|         } |         } | ||||||
|         updateTransform() { |         updateTransform() { | ||||||
|             this.view.style.transform = Object.entries(this.transform).filter((e) => !!e[1]).map((e) => { |             this.applyCSSStyle({ | ||||||
|  |                 transform: Object.entries(this.transform).filter((e) => !!e[1]).map((e) => { | ||||||
|                     const v = e[1] || 0; |                     const v = e[1] || 0; | ||||||
|                     switch (e[0]) { |                     switch (e[0]) { | ||||||
|                         case "translateX": |                         case "translateX": | ||||||
| @@ -4759,19 +4793,32 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|                             return `scaleY(${v})`; |                             return `scaleY(${v})`; | ||||||
|                         case "rotation": |                         case "rotation": | ||||||
|                             return `rotate(${v / 2}turn)`; |                             return `rotate(${v / 2}turn)`; | ||||||
|                     case "rotateX": |                         case "rotationX": | ||||||
|                             return `rotateX(${v / 2}turn)`; |                             return `rotateX(${v / 2}turn)`; | ||||||
|                     case "rotateY": |                         case "rotationY": | ||||||
|                             return `rotateY(${v / 2}turn)`; |                             return `rotateY(${v / 2}turn)`; | ||||||
|                         default: |                         default: | ||||||
|                             console.error(`Do not support transform ${e[0]}`); |                             console.error(`Do not support transform ${e[0]}`); | ||||||
|                             return ""; |                             return ""; | ||||||
|                     } |                     } | ||||||
|             }).join(" "); |                 }).join(" ") | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
|         updateTransformOrigin() { |         updateTransformOrigin() { | ||||||
|             if (this.transformOrigin) { |             if (this.transformOrigin) { | ||||||
|                 this.view.style.transformOrigin = `${Math.round(this.transformOrigin.x * 100)}% ${Math.round(this.transformOrigin.y * 100)}%`; |                 this.applyCSSStyle({ | ||||||
|  |                     transformOrigin: `${Math.round(this.transformOrigin.x * 100)}% ${Math.round(this.transformOrigin.y * 100)}%` | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         applyCSSStyle(cssStyle) { | ||||||
|  |             if (this.context.inAnimation()) { | ||||||
|  |                 this.context.addAnimation(this, cssStyle); | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 for (let v in cssStyle) { | ||||||
|  |                     Reflect.set(this.view.style, v, cssStyle[v]); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         /** ++++++++++call from doric ++++++++++*/ |         /** ++++++++++call from doric ++++++++++*/ | ||||||
| @@ -5164,28 +5211,33 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|         } |         } | ||||||
|         configOffset() { |         configOffset() { | ||||||
|             this.childNodes.forEach(e => { |             this.childNodes.forEach(e => { | ||||||
|                 e.view.style.position = "absolute"; |                 const position = "absolute"; | ||||||
|                 e.view.style.left = toPixelString(e.offsetX + this.paddingLeft); |                 let left = toPixelString(e.offsetX + this.paddingLeft); | ||||||
|                 e.view.style.top = toPixelString(e.offsetY + this.paddingTop); |                 let top = toPixelString(e.offsetY + this.paddingTop); | ||||||
|                 const gravity = e.layoutConfig.alignment; |                 const gravity = e.layoutConfig.alignment; | ||||||
|                 if ((gravity & LEFT) === LEFT) { |                 if ((gravity & LEFT) === LEFT) { | ||||||
|                     e.view.style.left = toPixelString(0); |                     left = toPixelString(0); | ||||||
|                 } |                 } | ||||||
|                 else if ((gravity & RIGHT) === RIGHT) { |                 else if ((gravity & RIGHT) === RIGHT) { | ||||||
|                     e.view.style.left = toPixelString(this.view.offsetWidth - e.view.offsetWidth); |                     left = toPixelString(this.view.offsetWidth - e.view.offsetWidth); | ||||||
|                 } |                 } | ||||||
|                 else if ((gravity & CENTER_X) === CENTER_X) { |                 else if ((gravity & CENTER_X) === CENTER_X) { | ||||||
|                     e.view.style.left = toPixelString(this.view.offsetWidth / 2 - e.view.offsetWidth / 2); |                     left = toPixelString(this.view.offsetWidth / 2 - e.view.offsetWidth / 2); | ||||||
|                 } |                 } | ||||||
|                 if ((gravity & TOP) === TOP) { |                 if ((gravity & TOP) === TOP) { | ||||||
|                     e.view.style.top = toPixelString(0); |                     top = toPixelString(0); | ||||||
|                 } |                 } | ||||||
|                 else if ((gravity & BOTTOM) === BOTTOM) { |                 else if ((gravity & BOTTOM) === BOTTOM) { | ||||||
|                     e.view.style.top = toPixelString(this.view.offsetHeight - e.view.offsetHeight); |                     top = toPixelString(this.view.offsetHeight - e.view.offsetHeight); | ||||||
|                 } |                 } | ||||||
|                 else if ((gravity & CENTER_Y) === CENTER_Y) { |                 else if ((gravity & CENTER_Y) === CENTER_Y) { | ||||||
|                     e.view.style.top = toPixelString(this.view.offsetHeight / 2 - e.view.offsetHeight / 2); |                     top = toPixelString(this.view.offsetHeight / 2 - e.view.offsetHeight / 2); | ||||||
|                 } |                 } | ||||||
|  |                 e.applyCSSStyle({ | ||||||
|  |                     position, | ||||||
|  |                     left, | ||||||
|  |                     top, | ||||||
|  |                 }); | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -6076,6 +6128,48 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     class AnimatePlugin extends DoricPlugin { | ||||||
|  |         submit() { | ||||||
|  |             return Promise.resolve(); | ||||||
|  |         } | ||||||
|  |         animateRender(args) { | ||||||
|  |             var _a; | ||||||
|  |             this.context.animationSet = []; | ||||||
|  |             if (((_a = this.context.rootNode.viewId) === null || _a === void 0 ? void 0 : _a.length) > 0) { | ||||||
|  |                 const viewNode = this.context.targetViewNode(args.id); | ||||||
|  |                 viewNode === null || viewNode === void 0 ? void 0 : viewNode.blend(args.props); | ||||||
|  |                 viewNode === null || viewNode === void 0 ? void 0 : viewNode.onBlended(); | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 this.context.rootNode.viewId = args.id; | ||||||
|  |                 this.context.rootNode.blend(args.props); | ||||||
|  |                 this.context.rootNode.onBlended(); | ||||||
|  |             } | ||||||
|  |             return new Promise(resolve => { | ||||||
|  |                 Promise.resolve().then(() => { | ||||||
|  |                     var _a; | ||||||
|  |                     Promise.all(((_a = this.context.animationSet) === null || _a === void 0 ? void 0 : _a.map(e => { | ||||||
|  |                         return new Promise(resolve => { | ||||||
|  |                             const animation = e.viewNode.view.animate([e.keyFrame], { | ||||||
|  |                                 duration: args.duration, | ||||||
|  |                                 fill: "forwards" | ||||||
|  |                             }); | ||||||
|  |                             animation.onfinish = () => { | ||||||
|  |                                 resolve(true); | ||||||
|  |                             }; | ||||||
|  |                         }); | ||||||
|  |                     })) || []) | ||||||
|  |                         .then(() => { | ||||||
|  |                         resolve(0); | ||||||
|  |                     }) | ||||||
|  |                         .finally(() => { | ||||||
|  |                         this.context.animationSet = undefined; | ||||||
|  |                     }); | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     const bundles = new Map; |     const bundles = new Map; | ||||||
|     const plugins = new Map; |     const plugins = new Map; | ||||||
|     const nodes = new Map; |     const nodes = new Map; | ||||||
| @@ -6102,6 +6196,7 @@ var doric_web = (function (exports, axios, sandbox) { | |||||||
|     registerPlugin('storage', StoragePlugin); |     registerPlugin('storage', StoragePlugin); | ||||||
|     registerPlugin('navigator', NavigatorPlugin); |     registerPlugin('navigator', NavigatorPlugin); | ||||||
|     registerPlugin('popover', PopoverPlugin); |     registerPlugin('popover', PopoverPlugin); | ||||||
|  |     registerPlugin('animate', AnimatePlugin); | ||||||
|     registerViewNode('Stack', DoricStackNode); |     registerViewNode('Stack', DoricStackNode); | ||||||
|     registerViewNode('VLayout', DoricVLayoutNode); |     registerViewNode('VLayout', DoricVLayoutNode); | ||||||
|     registerViewNode('HLayout', DoricHLayoutNode); |     registerViewNode('HLayout', DoricHLayoutNode); | ||||||
| @@ -6309,6 +6404,16 @@ ${content} | |||||||
|         build(frame) { |         build(frame) { | ||||||
|             this.invokeEntityMethod("__build__", frame); |             this.invokeEntityMethod("__build__", frame); | ||||||
|         } |         } | ||||||
|  |         inAnimation() { | ||||||
|  |             return !!this.animationSet; | ||||||
|  |         } | ||||||
|  |         addAnimation(viewNode, keyFrame) { | ||||||
|  |             var _a; | ||||||
|  |             (_a = this.animationSet) === null || _a === void 0 ? void 0 : _a.push({ | ||||||
|  |                 viewNode, | ||||||
|  |                 keyFrame | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|         teardown() { |         teardown() { | ||||||
|             for (let plugin of this.pluginInstances.values()) { |             for (let plugin of this.pluginInstances.values()) { | ||||||
|                 plugin.onTearDown(); |                 plugin.onTearDown(); | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								doric-web/dist/index.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								doric-web/dist/index.js.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -20,6 +20,7 @@ export class DoricContext { | |||||||
|     pluginInstances: Map<string, DoricPlugin> = new Map |     pluginInstances: Map<string, DoricPlugin> = new Map | ||||||
|     rootNode: DoricStackNode |     rootNode: DoricStackNode | ||||||
|     headNodes: Map<string, Map<string, DoricViewNode>> = new Map |     headNodes: Map<string, Map<string, DoricViewNode>> = new Map | ||||||
|  |     animationSet?: { viewNode: DoricViewNode, keyFrame: Partial<CSSStyleDeclaration> }[] | ||||||
|  |  | ||||||
|     constructor(content: string) { |     constructor(content: string) { | ||||||
|         createContext(this.contextId, content) |         createContext(this.contextId, content) | ||||||
| @@ -84,6 +85,18 @@ export class DoricContext { | |||||||
|     }) { |     }) { | ||||||
|         this.invokeEntityMethod("__build__", frame) |         this.invokeEntityMethod("__build__", frame) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     inAnimation() { | ||||||
|  |         return !!this.animationSet | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     addAnimation(viewNode: DoricViewNode, keyFrame: Partial<CSSStyleDeclaration>) { | ||||||
|  |         this.animationSet?.push({ | ||||||
|  |             viewNode, | ||||||
|  |             keyFrame | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     teardown() { |     teardown() { | ||||||
|         for (let plugin of this.pluginInstances.values()) { |         for (let plugin of this.pluginInstances.values()) { | ||||||
|             plugin.onTearDown() |             plugin.onTearDown() | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ import { DoricListItemNode } from "./shader/DoricListItemNode" | |||||||
| import { DoricListNode } from "./shader/DoricListNode" | import { DoricListNode } from "./shader/DoricListNode" | ||||||
| import { DoricDraggableNode } from "./shader/DoricDraggableNode" | import { DoricDraggableNode } from "./shader/DoricDraggableNode" | ||||||
| import { DoricRefreshableNode } from "./shader/DoricRefreshableNode" | import { DoricRefreshableNode } from "./shader/DoricRefreshableNode" | ||||||
|  | import { AnimatePlugin } from "./plugins/AnimatePlugin" | ||||||
|  |  | ||||||
| const bundles: Map<string, string> = new Map | const bundles: Map<string, string> = new Map | ||||||
|  |  | ||||||
| @@ -54,6 +55,7 @@ registerPlugin('modal', ModalPlugin) | |||||||
| registerPlugin('storage', StoragePlugin) | registerPlugin('storage', StoragePlugin) | ||||||
| registerPlugin('navigator', NavigatorPlugin) | registerPlugin('navigator', NavigatorPlugin) | ||||||
| registerPlugin('popover', PopoverPlugin) | registerPlugin('popover', PopoverPlugin) | ||||||
|  | registerPlugin('animate', AnimatePlugin) | ||||||
|  |  | ||||||
| registerViewNode('Stack', DoricStackNode) | registerViewNode('Stack', DoricStackNode) | ||||||
| registerViewNode('VLayout', DoricVLayoutNode) | registerViewNode('VLayout', DoricVLayoutNode) | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								doric-web/src/plugins/AnimatePlugin.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								doric-web/src/plugins/AnimatePlugin.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | import { DoricPlugin } from "../DoricPlugin"; | ||||||
|  |  | ||||||
|  | export class AnimatePlugin extends DoricPlugin { | ||||||
|  |     submit() { | ||||||
|  |         return Promise.resolve() | ||||||
|  |     } | ||||||
|  |     animateRender(args: { | ||||||
|  |         duration: number, | ||||||
|  |         id: string, | ||||||
|  |         props: any | ||||||
|  |     }) { | ||||||
|  |         this.context.animationSet = [] | ||||||
|  |         if (this.context.rootNode.viewId?.length > 0) { | ||||||
|  |             const viewNode = this.context.targetViewNode(args.id) | ||||||
|  |             viewNode?.blend(args.props) | ||||||
|  |             viewNode?.onBlended() | ||||||
|  |         } else { | ||||||
|  |             this.context.rootNode.viewId = args.id | ||||||
|  |             this.context.rootNode.blend(args.props) | ||||||
|  |             this.context.rootNode.onBlended() | ||||||
|  |         } | ||||||
|  |         return new Promise(resolve => { | ||||||
|  |             Promise.resolve().then(() => { | ||||||
|  |                 Promise.all( | ||||||
|  |                     this.context.animationSet?.map(e => { | ||||||
|  |                         return new Promise(resolve => { | ||||||
|  |                             const animation = e.viewNode.view.animate( | ||||||
|  |                                 [e.keyFrame as Keyframe], | ||||||
|  |                                 { | ||||||
|  |                                     duration: args.duration, | ||||||
|  |                                     fill: "forwards" | ||||||
|  |                                 }) | ||||||
|  |                             animation.onfinish = () => { | ||||||
|  |                                 resolve(true) | ||||||
|  |                             } | ||||||
|  |                         }) | ||||||
|  |                     }) || []) | ||||||
|  |                     .then(() => { | ||||||
|  |                         resolve(0) | ||||||
|  |                     }) | ||||||
|  |                     .finally(() => { | ||||||
|  |                         this.context.animationSet = undefined | ||||||
|  |                     }) | ||||||
|  |             }) | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -39,24 +39,29 @@ export class DoricStackNode extends DoricGroupViewNode { | |||||||
|  |  | ||||||
|     configOffset() { |     configOffset() { | ||||||
|         this.childNodes.forEach(e => { |         this.childNodes.forEach(e => { | ||||||
|             e.view.style.position = "absolute" |             const position = "absolute" | ||||||
|             e.view.style.left = toPixelString(e.offsetX + this.paddingLeft) |             let left = toPixelString(e.offsetX + this.paddingLeft) | ||||||
|             e.view.style.top = toPixelString(e.offsetY + this.paddingTop) |             let top = toPixelString(e.offsetY + this.paddingTop) | ||||||
|             const gravity = e.layoutConfig.alignment |             const gravity = e.layoutConfig.alignment | ||||||
|             if ((gravity & LEFT) === LEFT) { |             if ((gravity & LEFT) === LEFT) { | ||||||
|                 e.view.style.left = toPixelString(0) |                 left = toPixelString(0) | ||||||
|             } else if ((gravity & RIGHT) === RIGHT) { |             } else if ((gravity & RIGHT) === RIGHT) { | ||||||
|                 e.view.style.left = toPixelString(this.view.offsetWidth - e.view.offsetWidth) |                 left = toPixelString(this.view.offsetWidth - e.view.offsetWidth) | ||||||
|             } else if ((gravity & CENTER_X) === CENTER_X) { |             } else if ((gravity & CENTER_X) === CENTER_X) { | ||||||
|                 e.view.style.left = toPixelString(this.view.offsetWidth / 2 - e.view.offsetWidth / 2) |                 left = toPixelString(this.view.offsetWidth / 2 - e.view.offsetWidth / 2) | ||||||
|             } |             } | ||||||
|             if ((gravity & TOP) === TOP) { |             if ((gravity & TOP) === TOP) { | ||||||
|                 e.view.style.top = toPixelString(0) |                 top = toPixelString(0) | ||||||
|             } else if ((gravity & BOTTOM) === BOTTOM) { |             } else if ((gravity & BOTTOM) === BOTTOM) { | ||||||
|                 e.view.style.top = toPixelString(this.view.offsetHeight - e.view.offsetHeight) |                 top = toPixelString(this.view.offsetHeight - e.view.offsetHeight) | ||||||
|             } else if ((gravity & CENTER_Y) === CENTER_Y) { |             } else if ((gravity & CENTER_Y) === CENTER_Y) { | ||||||
|                 e.view.style.top = toPixelString(this.view.offsetHeight / 2 - e.view.offsetHeight / 2) |                 top = toPixelString(this.view.offsetHeight / 2 - e.view.offsetHeight / 2) | ||||||
|             } |             } | ||||||
|  |             e.applyCSSStyle({ | ||||||
|  |                 position, | ||||||
|  |                 left, | ||||||
|  |                 top, | ||||||
|  |             }) | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -172,64 +172,75 @@ export abstract class DoricViewNode { | |||||||
|  |  | ||||||
|     configBorder() { |     configBorder() { | ||||||
|         if (this.border) { |         if (this.border) { | ||||||
|             this.view.style.borderStyle = "solid" |             this.applyCSSStyle({ | ||||||
|             this.view.style.borderWidth = toPixelString(this.border.width) |                 borderStyle: "solid", | ||||||
|             this.view.style.borderColor = toRGBAString(this.border.color) |                 borderWidth: toPixelString(this.border.width), | ||||||
|  |                 borderColor: toRGBAString(this.border.color), | ||||||
|  |             }) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     configWidth() { |     configWidth() { | ||||||
|  |         let width: string | ||||||
|         switch (this.layoutConfig.widthSpec) { |         switch (this.layoutConfig.widthSpec) { | ||||||
|             case LayoutSpec.WRAP_CONTENT: |             case LayoutSpec.WRAP_CONTENT: | ||||||
|                 this.view.style.width = "max-content" |                 width = "max-content" | ||||||
|                 break |                 break | ||||||
|  |  | ||||||
|             case LayoutSpec.AT_MOST: |             case LayoutSpec.AT_MOST: | ||||||
|                 this.view.style.width = "100%" |                 width = "100%" | ||||||
|                 break |                 break | ||||||
|  |  | ||||||
|             case LayoutSpec.EXACTLY: |             case LayoutSpec.EXACTLY: | ||||||
|             default: |             default: | ||||||
|                 this.view.style.width = toPixelString(this.frameWidth |                 width = toPixelString(this.frameWidth | ||||||
|                     - this.paddingLeft - this.paddingRight |                     - this.paddingLeft - this.paddingRight | ||||||
|                     - this.borderWidth * 2) |                     - this.borderWidth * 2) | ||||||
|                 break |                 break | ||||||
|         } |         } | ||||||
|  |         this.applyCSSStyle({ width }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     configHeight() { |     configHeight() { | ||||||
|  |         let height | ||||||
|         switch (this.layoutConfig.heightSpec) { |         switch (this.layoutConfig.heightSpec) { | ||||||
|             case LayoutSpec.WRAP_CONTENT: |             case LayoutSpec.WRAP_CONTENT: | ||||||
|                 this.view.style.height = "max-content" |                 height = "max-content" | ||||||
|                 break |                 break | ||||||
|  |  | ||||||
|             case LayoutSpec.AT_MOST: |             case LayoutSpec.AT_MOST: | ||||||
|                 this.view.style.height = "100%" |                 height = "100%" | ||||||
|                 break |                 break | ||||||
|  |  | ||||||
|             case LayoutSpec.EXACTLY: |             case LayoutSpec.EXACTLY: | ||||||
|             default: |             default: | ||||||
|                 this.view.style.height = toPixelString(this.frameHeight |                 height = toPixelString(this.frameHeight | ||||||
|                     - this.paddingTop - this.paddingBottom |                     - this.paddingTop - this.paddingBottom | ||||||
|                     - this.borderWidth * 2) |                     - this.borderWidth * 2) | ||||||
|                 break |                 break | ||||||
|         } |         } | ||||||
|  |         this.applyCSSStyle({ height }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     configMargin() { |     configMargin() { | ||||||
|         if (this.layoutConfig.margin) { |         if (this.layoutConfig.margin) { | ||||||
|             this.view.style.marginLeft = toPixelString(this.layoutConfig.margin.left || 0) |             this.applyCSSStyle({ | ||||||
|             this.view.style.marginRight = toPixelString(this.layoutConfig.margin.right || 0) |                 marginLeft: toPixelString(this.layoutConfig.margin.left || 0), | ||||||
|             this.view.style.marginTop = toPixelString(this.layoutConfig.margin.top || 0) |                 marginRight: toPixelString(this.layoutConfig.margin.right || 0), | ||||||
|             this.view.style.marginBottom = toPixelString(this.layoutConfig.margin.bottom || 0) |                 marginTop: toPixelString(this.layoutConfig.margin.top || 0), | ||||||
|  |                 marginBottom: toPixelString(this.layoutConfig.margin.bottom || 0), | ||||||
|  |             }) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     configPadding() { |     configPadding() { | ||||||
|         if (this.padding) { |         if (this.padding) { | ||||||
|             this.view.style.paddingLeft = toPixelString(this.paddingLeft) |             this.applyCSSStyle({ | ||||||
|             this.view.style.paddingRight = toPixelString(this.paddingRight) |                 paddingLeft: toPixelString(this.paddingLeft), | ||||||
|             this.view.style.paddingTop = toPixelString(this.paddingTop) |                 paddingRight: toPixelString(this.paddingRight), | ||||||
|             this.view.style.paddingBottom = toPixelString(this.paddingBottom) |                 paddingTop: toPixelString(this.paddingTop), | ||||||
|  |                 paddingBottom: toPixelString(this.paddingBottom), | ||||||
|  |             }) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -278,33 +289,59 @@ export abstract class DoricViewNode { | |||||||
|                 break |                 break | ||||||
|             case 'corners': |             case 'corners': | ||||||
|                 if (typeof prop === 'object') { |                 if (typeof prop === 'object') { | ||||||
|                     this.view.style.borderTopLeftRadius = toPixelString(prop.leftTop) |                     this.applyCSSStyle({ | ||||||
|                     this.view.style.borderTopRightRadius = toPixelString(prop.rightTop) |                         borderTopLeftRadius: toPixelString(prop.leftTop), | ||||||
|                     this.view.style.borderBottomRightRadius = toPixelString(prop.rightBottom) |                         borderTopRightRadius: toPixelString(prop.rightTop), | ||||||
|                     this.view.style.borderBottomLeftRadius = toPixelString(prop.leftBottom) |                         borderBottomRightRadius: toPixelString(prop.rightBottom), | ||||||
|  |                         borderBottomLeftRadius: toPixelString(prop.leftBottom), | ||||||
|  |                     }) | ||||||
|                 } else { |                 } else { | ||||||
|                     this.view.style.borderRadius = toPixelString(prop) |                     this.applyCSSStyle({ borderRadius: toPixelString(prop) }) | ||||||
|                 } |                 } | ||||||
|                 break |                 break | ||||||
|             case 'shadow': |             case 'shadow': | ||||||
|                 const opacity = prop.opacity || 0 |                 const opacity = prop.opacity || 0 | ||||||
|  |                 let boxShadow | ||||||
|                 if (opacity > 0) { |                 if (opacity > 0) { | ||||||
|                     const offsetX = prop.offsetX || 0 |                     const offsetX = prop.offsetX || 0 | ||||||
|                     const offsetY = prop.offsetY || 0 |                     const offsetY = prop.offsetY || 0 | ||||||
|                     const shadowColor = prop.color || 0xff000000 |                     const shadowColor = prop.color || 0xff000000 | ||||||
|                     const shadowRadius = prop.radius |                     const shadowRadius = prop.radius | ||||||
|                     const alpha = opacity * 255 |                     const alpha = opacity * 255 | ||||||
|                     this.view.style.boxShadow = `${toPixelString(offsetX)} ${toPixelString(offsetY)} ${toPixelString(shadowRadius)} ${toRGBAString((shadowColor & 0xffffff) | ((alpha & 0xff) << 24))} ` |                     boxShadow = `${toPixelString(offsetX)} ${toPixelString(offsetY)} ${toPixelString(shadowRadius)} ${toRGBAString((shadowColor & 0xffffff) | ((alpha & 0xff) << 24))} ` | ||||||
|                 } else { |                 } else { | ||||||
|                     this.view.style.boxShadow = "" |                     boxShadow = "" | ||||||
|                 } |                 } | ||||||
|  |                 this.applyCSSStyle({ | ||||||
|  |                     boxShadow, | ||||||
|  |                 }) | ||||||
|                 break |                 break | ||||||
|             case 'alpha': |             case 'alpha': | ||||||
|                 this.view.style.opacity = `${prop}` |                 this.applyCSSStyle({ | ||||||
|  |                     opacity: `${prop}`, | ||||||
|  |                 }) | ||||||
|                 break |                 break | ||||||
|             case 'rotation': |             case 'rotation': | ||||||
|                 this.transform.rotation = prop |                 this.transform.rotation = prop | ||||||
|                 break |                 break | ||||||
|  |             case 'rotationX': | ||||||
|  |                 this.transform.rotationX = prop | ||||||
|  |                 break | ||||||
|  |             case 'rotationY': | ||||||
|  |                 this.transform.rotationY = prop | ||||||
|  |                 break | ||||||
|  |             case 'scaleX': | ||||||
|  |                 this.transform.scaleX = prop | ||||||
|  |                 break | ||||||
|  |             case 'scaleY': | ||||||
|  |                 this.transform.scaleY = prop | ||||||
|  |                 break | ||||||
|  |             case 'translationX': | ||||||
|  |                 this.transform.translateX = prop | ||||||
|  |                 break | ||||||
|  |             case 'translationY': | ||||||
|  |                 this.transform.translateY = prop | ||||||
|  |                 break | ||||||
|             case 'pivotX': |             case 'pivotX': | ||||||
|                 if (this.transformOrigin) { |                 if (this.transformOrigin) { | ||||||
|                     this.transformOrigin.x = prop |                     this.transformOrigin.x = prop | ||||||
| @@ -326,11 +363,9 @@ export abstract class DoricViewNode { | |||||||
|                 } |                 } | ||||||
|                 break |                 break | ||||||
|             case 'hidden': |             case 'hidden': | ||||||
|                 if (prop === true) { |                 this.applyCSSStyle({ | ||||||
|                     this.view.style.display = "none" |                     display: prop === true ? "none" : this._originDisplay | ||||||
|                 } else { |                 }) | ||||||
|                     this.view.style.display = this._originDisplay |  | ||||||
|                 } |  | ||||||
|                 break |                 break | ||||||
|             default: |             default: | ||||||
|                 console.error(`Cannot blend prop for ${propName}`) |                 console.error(`Cannot blend prop for ${propName}`) | ||||||
| @@ -339,7 +374,7 @@ export abstract class DoricViewNode { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     set backgroundColor(v: number) { |     set backgroundColor(v: number) { | ||||||
|         this.view.style.backgroundColor = toRGBAString(v) |         this.applyCSSStyle({ backgroundColor: toRGBAString(v) }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static create(context: DoricContext, type: string) { |     static create(context: DoricContext, type: string) { | ||||||
| @@ -381,7 +416,8 @@ export abstract class DoricViewNode { | |||||||
|  |  | ||||||
|  |  | ||||||
|     updateTransform() { |     updateTransform() { | ||||||
|         this.view.style.transform = Object.entries(this.transform).filter((e: [string, number?]) => !!e[1]).map((e: [string, number?]) => { |         this.applyCSSStyle({ | ||||||
|  |             transform: Object.entries(this.transform).filter((e: [string, number?]) => !!e[1]).map((e: [string, number?]) => { | ||||||
|                 const v = e[1] || 0 |                 const v = e[1] || 0 | ||||||
|                 switch (e[0]) { |                 switch (e[0]) { | ||||||
|                     case "translateX": |                     case "translateX": | ||||||
| @@ -392,20 +428,33 @@ export abstract class DoricViewNode { | |||||||
|                         return `scaleY(${v})` |                         return `scaleY(${v})` | ||||||
|                     case "rotation": |                     case "rotation": | ||||||
|                         return `rotate(${v / 2}turn)` |                         return `rotate(${v / 2}turn)` | ||||||
|                 case "rotateX": |                     case "rotationX": | ||||||
|                         return `rotateX(${v / 2}turn)` |                         return `rotateX(${v / 2}turn)` | ||||||
|                 case "rotateY": |                     case "rotationY": | ||||||
|                         return `rotateY(${v / 2}turn)` |                         return `rotateY(${v / 2}turn)` | ||||||
|                     default: |                     default: | ||||||
|                         console.error(`Do not support transform ${e[0]}`) |                         console.error(`Do not support transform ${e[0]}`) | ||||||
|                         return "" |                         return "" | ||||||
|                 } |                 } | ||||||
|             }).join(" ") |             }).join(" ") | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     updateTransformOrigin() { |     updateTransformOrigin() { | ||||||
|         if (this.transformOrigin) { |         if (this.transformOrigin) { | ||||||
|             this.view.style.transformOrigin = `${Math.round(this.transformOrigin.x * 100)}% ${Math.round(this.transformOrigin.y * 100)}%` |             this.applyCSSStyle({ | ||||||
|  |                 transformOrigin: `${Math.round(this.transformOrigin.x * 100)}% ${Math.round(this.transformOrigin.y * 100)}%` | ||||||
|  |             }) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     applyCSSStyle(cssStyle: Partial<CSSStyleDeclaration>) { | ||||||
|  |         if (this.context.inAnimation()) { | ||||||
|  |             this.context.addAnimation(this, cssStyle) | ||||||
|  |         } else { | ||||||
|  |             for (let v in cssStyle) { | ||||||
|  |                 Reflect.set(this.view.style, v, cssStyle[v]) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     /** ++++++++++call from doric ++++++++++*/ |     /** ++++++++++call from doric ++++++++++*/ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user