web: add AnimatePlugin
This commit is contained in:
parent
900bccb98a
commit
d1cc17c7a0
229
doric-web/dist/index.js
vendored
229
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,30 +4781,44 @@ 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({
|
||||||
const v = e[1] || 0;
|
transform: Object.entries(this.transform).filter((e) => !!e[1]).map((e) => {
|
||||||
switch (e[0]) {
|
const v = e[1] || 0;
|
||||||
case "translateX":
|
switch (e[0]) {
|
||||||
return `translateX(${v}px)`;
|
case "translateX":
|
||||||
case "scaleX":
|
return `translateX(${v}px)`;
|
||||||
return `scaleX(${v})`;
|
case "scaleX":
|
||||||
case "scaleY":
|
return `scaleX(${v})`;
|
||||||
return `scaleY(${v})`;
|
case "scaleY":
|
||||||
case "rotation":
|
return `scaleY(${v})`;
|
||||||
return `rotate(${v / 2}turn)`;
|
case "rotation":
|
||||||
case "rotateX":
|
return `rotate(${v / 2}turn)`;
|
||||||
return `rotateX(${v / 2}turn)`;
|
case "rotationX":
|
||||||
case "rotateY":
|
return `rotateX(${v / 2}turn)`;
|
||||||
return `rotateY(${v / 2}turn)`;
|
case "rotationY":
|
||||||
default:
|
return `rotateY(${v / 2}turn)`;
|
||||||
console.error(`Do not support transform ${e[0]}`);
|
default:
|
||||||
return "";
|
console.error(`Do not support transform ${e[0]}`);
|
||||||
}
|
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,31 +416,45 @@ 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({
|
||||||
const v = e[1] || 0
|
transform: Object.entries(this.transform).filter((e: [string, number?]) => !!e[1]).map((e: [string, number?]) => {
|
||||||
switch (e[0]) {
|
const v = e[1] || 0
|
||||||
case "translateX":
|
switch (e[0]) {
|
||||||
return `translateX(${v}px)`
|
case "translateX":
|
||||||
case "scaleX":
|
return `translateX(${v}px)`
|
||||||
return `scaleX(${v})`
|
case "scaleX":
|
||||||
case "scaleY":
|
return `scaleX(${v})`
|
||||||
return `scaleY(${v})`
|
case "scaleY":
|
||||||
case "rotation":
|
return `scaleY(${v})`
|
||||||
return `rotate(${v / 2}turn)`
|
case "rotation":
|
||||||
case "rotateX":
|
return `rotate(${v / 2}turn)`
|
||||||
return `rotateX(${v / 2}turn)`
|
case "rotationX":
|
||||||
case "rotateY":
|
return `rotateX(${v / 2}turn)`
|
||||||
return `rotateY(${v / 2}turn)`
|
case "rotationY":
|
||||||
default:
|
return `rotateY(${v / 2}turn)`
|
||||||
console.error(`Do not support transform ${e[0]}`)
|
default:
|
||||||
return ""
|
console.error(`Do not support transform ${e[0]}`)
|
||||||
}
|
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