feat:define animation

This commit is contained in:
pengfei.zhou 2019-11-30 16:14:22 +08:00
parent 007898329f
commit 85a8e0fdaf
2 changed files with 187 additions and 143 deletions

View File

@ -1,3 +1,5 @@
import { Modeling, Model } from "../util/types"
/* /*
* Copyright [2019] [Doric.Pub] * Copyright [2019] [Doric.Pub]
* *
@ -14,159 +16,196 @@
* limitations under the License. * limitations under the License.
*/ */
export type AnimatedKey = "translationX" | "translationY" | "scaleX" | "scaleY" | "rotation" | "pivotX" | "pivotY"
export enum RepeatMode { export enum RepeatMode {
RESTART, RESTART,
REVERSE, REVERSE,
} }
export interface IAnimation extends Modeling {
export class Animation { repeatCount?: number
repeatMode?: RepeatMode
translationX?: number duration: number
delay?: number
translationY?: number
scaleX?: number
scaleY?: number
pivotX?: number
pivotY?: number
rotation?: number
duration = 100
startDelay = 0
repeatCount = 1
repeatMode = RepeatMode.RESTART
} }
export class AnimationSetBuilder { export interface Changeable {
currentNode: Node fromValue: number
group: AnimationSet toValue: number
key: AnimatedKey
}
constructor(group: AnimationSet, anim: Animation) { abstract class Animation implements IAnimation {
this.currentNode = group.getNodeForAnimation(anim) changeables: Map<AnimatedKey, Changeable> = new Map
this.group = group duration = 0
repeatCount?: number
repeatMode?: RepeatMode
delay?: number
toModel() {
const ret = []
for (let e of this.changeables.values()) {
ret.push({
repeatCount: this.repeatCount,
repeatMode: this.repeatMode,
delay: this.delay,
duration: this.duration,
key: e.key,
fromValue: e.fromValue,
toValue: e.toValue,
})
} }
return ret
with(animation: Animation) {
const node = this.group.getNodeForAnimation(animation)
this.currentNode.addSibling(node)
return this
}
after(animation: Animation) {
const node = this.group.getNodeForAnimation(animation)
this.currentNode.addParent(node)
return this
}
before(animation: Animation) {
const node = this.group.getNodeForAnimation(animation)
this.currentNode.addChild(node)
return this
} }
} }
class Node {
children: Set<Node> = new Set
siblings: Set<Node> = new Set
parents: Set<Node> = new Set
animation: Animation
built = false
constructor(anim: Animation) { export class ScaleAnimation extends Animation {
this.animation = anim private scaleXChaneable: Changeable = {
key: "scaleX",
fromValue: 1,
toValue: 1,
}
private scaleYChangeable: Changeable = {
key: "scaleY",
fromValue: 1,
toValue: 1,
}
constructor() {
super()
this.changeables.set("scaleX", this.scaleXChaneable)
this.changeables.set("scaleY", this.scaleXChaneable)
} }
addParent(node: Node) {
if (!this.parents.has(node)) { set fromScaleX(v: number) {
this.parents.add(node); this.scaleXChaneable.fromValue = v
node.addChild(this);
}
} }
addSibling(node: Node) { get fromScaleX() {
if (!this.siblings.has(node)) { return this.scaleXChaneable.fromValue
this.siblings.add(node);
node.addSibling(this);
}
} }
addChild(node: Node) { set toScaleX(v: number) {
if (!this.children.has(node)) { this.scaleXChaneable.toValue = v
this.children.add(node)
node.addParent(this)
} }
get toScaleX() {
return this.scaleXChaneable.toValue
}
set fromScaleY(v: number) {
this.scaleYChangeable.fromValue = v
}
get fromScaleY() {
return this.scaleYChangeable.fromValue
}
set toScaleY(v: number) {
this.scaleYChangeable.toValue = v
}
get toScaleY() {
return this.scaleYChangeable.toValue
} }
} }
export class AnimationSet {
nodeMap: Map<Animation, Node> = new Map
nodes: Node[] = []
getNodeForAnimation(anim: Animation) { export class TranslationAnimation extends Animation {
let node = this.nodeMap.get(anim) private translationXChangeable: Changeable = {
if (node === undefined) { key: "translationX",
node = new Node(anim) fromValue: 1,
this.nodeMap.set(anim, node) toValue: 1,
this.nodes.push(node)
} }
return node; private translationYChangeable: Changeable = {
key: "translationY",
fromValue: 1,
toValue: 1,
} }
play(animation: Animation) { constructor() {
return new AnimationSetBuilder(this, animation) super()
this.changeables.set("translationX", this.translationXChangeable)
this.changeables.set("translationY", this.translationYChangeable)
} }
playTogether(animations: Animation[]) { set fromTranslationX(v: number) {
if (animations.length == 1) { this.translationXChangeable.fromValue = v
this.play(animations[0]);
} else {
for (let i = 0; i < animations.length - 1; i++) {
this.play(animations[i]).with(animations[i + 1])
}
}
} }
playSequentially(animations: Animation[]) { get fromTranslationX() {
if (animations.length == 1) { return this.translationXChangeable.fromValue
this.play(animations[0]);
} else {
for (let i = 0; i < animations.length - 1; i++) {
this.play(animations[i]).before(animations[i + 1])
} }
}
}
findSiblings(node: Node, siblings: Set<Node>) {
if (!siblings.has(node)) {
siblings.add(node)
node.siblings.forEach(e => {
this.findSiblings(e, siblings)
})
}
}
createDependencyGraph() {
this.nodes.forEach(node => {
if (node.built) {
return
}
this.findSiblings(node, node.siblings)
node.siblings.delete(node)
node.siblings.forEach(e => {
e.parents.forEach(p => {
node.addParent(p)
})
})
node.built = true
node.siblings.forEach(s => { set toTranslationX(v: number) {
node.parents.forEach(p => { this.translationXChangeable.toValue = v
s.addParent(p) }
})
s.built = true get toTranslationX() {
}) return this.translationXChangeable.toValue
}) }
set fromTranslationY(v: number) {
this.translationYChangeable.fromValue = v
}
get fromTranslationY() {
return this.translationYChangeable.fromValue
}
set toTranslationY(v: number) {
this.translationYChangeable.toValue = v
}
get toTranslationY() {
return this.translationYChangeable.toValue
}
}
export class RotationAnimation extends Animation {
private rotationChaneable: Changeable = {
key: "rotation",
fromValue: 1,
toValue: 1,
}
constructor() {
super()
this.changeables.set("rotation", this.rotationChaneable)
}
set fromRotation(v: number) {
this.rotationChaneable.fromValue = v
}
get fromRotation() {
return this.rotationChaneable.fromValue
}
set toRotation(v: number) {
this.rotationChaneable.toValue = v
}
get toRotation() {
return this.rotationChaneable.toValue
}
}
export class AnimaionSet implements IAnimation {
animations: IAnimation[] = []
_duration = 0
repeatCount?: number
repeatMode?: RepeatMode
delay?: number
get duration() {
return this._duration
}
set duration(v: number) {
this._duration = v
this.animations.forEach(e => e.duration = v)
}
toModel() {
return this.animations.map(e => {
return e.toModel()
}) as Model
} }
} }

View File

@ -19,6 +19,7 @@ import { uniqueId } from "../util/uniqueId";
import { loge } from "../util/log"; import { loge } from "../util/log";
import { BridgeContext } from "../runtime/global"; import { BridgeContext } from "../runtime/global";
import { LayoutConfig } from '../util/layoutconfig' import { LayoutConfig } from '../util/layoutconfig'
import { IAnimation } from "./animation";
export function Property(target: Object, propKey: string) { export function Property(target: Object, propKey: string) {
Reflect.defineMetadata(propKey, true, target) Reflect.defineMetadata(propKey, true, target)
@ -333,6 +334,10 @@ export abstract class View implements Modeling, IView {
@Property @Property
rotation?: number rotation?: number
/**----------transform----------*/ /**----------transform----------*/
doAnimation(context: BridgeContext, animation: IAnimation) {
return this.nativeChannel(context, "doAnimation")(animation)
}
} }
export abstract class Superview extends View { export abstract class Superview extends View {