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) {
this.currentNode = group.getNodeForAnimation(anim)
this.group = group
}
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) { abstract class Animation implements IAnimation {
this.animation = anim changeables: Map<AnimatedKey, Changeable> = new Map
} duration = 0
repeatCount?: number
repeatMode?: RepeatMode
delay?: number
addParent(node: Node) { toModel() {
if (!this.parents.has(node)) { const ret = []
this.parents.add(node); for (let e of this.changeables.values()) {
node.addChild(this); ret.push({
} repeatCount: this.repeatCount,
} repeatMode: this.repeatMode,
delay: this.delay,
addSibling(node: Node) { duration: this.duration,
if (!this.siblings.has(node)) { key: e.key,
this.siblings.add(node); fromValue: e.fromValue,
node.addSibling(this); toValue: e.toValue,
}
}
addChild(node: Node) {
if (!this.children.has(node)) {
this.children.add(node)
node.addParent(this)
}
}
}
export class AnimationSet {
nodeMap: Map<Animation, Node> = new Map
nodes: Node[] = []
getNodeForAnimation(anim: Animation) {
let node = this.nodeMap.get(anim)
if (node === undefined) {
node = new Node(anim)
this.nodeMap.set(anim, node)
this.nodes.push(node)
}
return node;
}
play(animation: Animation) {
return new AnimationSetBuilder(this, animation)
}
playTogether(animations: Animation[]) {
if (animations.length == 1) {
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[]) {
if (animations.length == 1) {
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)
}) })
} }
} return ret
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 => {
node.parents.forEach(p => {
s.addParent(p)
})
s.built = true
})
})
} }
} }
export class ScaleAnimation extends Animation {
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)
}
set fromScaleX(v: number) {
this.scaleXChaneable.fromValue = v
}
get fromScaleX() {
return this.scaleXChaneable.fromValue
}
set toScaleX(v: number) {
this.scaleXChaneable.toValue = v
}
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 TranslationAnimation extends Animation {
private translationXChangeable: Changeable = {
key: "translationX",
fromValue: 1,
toValue: 1,
}
private translationYChangeable: Changeable = {
key: "translationY",
fromValue: 1,
toValue: 1,
}
constructor() {
super()
this.changeables.set("translationX", this.translationXChangeable)
this.changeables.set("translationY", this.translationYChangeable)
}
set fromTranslationX(v: number) {
this.translationXChangeable.fromValue = v
}
get fromTranslationX() {
return this.translationXChangeable.fromValue
}
set toTranslationX(v: number) {
this.translationXChangeable.toValue = v
}
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 {