feat:define animation
This commit is contained in:
parent
007898329f
commit
85a8e0fdaf
@ -1,3 +1,5 @@
|
||||
import { Modeling, Model } from "../util/types"
|
||||
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
@ -14,159 +16,196 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
export type AnimatedKey = "translationX" | "translationY" | "scaleX" | "scaleY" | "rotation" | "pivotX" | "pivotY"
|
||||
export enum RepeatMode {
|
||||
RESTART,
|
||||
REVERSE,
|
||||
}
|
||||
|
||||
export class Animation {
|
||||
|
||||
translationX?: number
|
||||
|
||||
translationY?: number
|
||||
|
||||
scaleX?: number
|
||||
|
||||
scaleY?: number
|
||||
|
||||
pivotX?: number
|
||||
|
||||
pivotY?: number
|
||||
|
||||
rotation?: number
|
||||
|
||||
duration = 100
|
||||
|
||||
startDelay = 0
|
||||
|
||||
repeatCount = 1
|
||||
|
||||
repeatMode = RepeatMode.RESTART
|
||||
export interface IAnimation extends Modeling {
|
||||
repeatCount?: number
|
||||
repeatMode?: RepeatMode
|
||||
duration: number
|
||||
delay?: number
|
||||
}
|
||||
|
||||
export class AnimationSetBuilder {
|
||||
currentNode: Node
|
||||
group: AnimationSet
|
||||
|
||||
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
|
||||
}
|
||||
export interface Changeable {
|
||||
fromValue: number
|
||||
toValue: number
|
||||
key: AnimatedKey
|
||||
}
|
||||
class Node {
|
||||
children: Set<Node> = new Set
|
||||
siblings: Set<Node> = new Set
|
||||
parents: Set<Node> = new Set
|
||||
animation: Animation
|
||||
built = false
|
||||
|
||||
constructor(anim: Animation) {
|
||||
this.animation = anim
|
||||
}
|
||||
abstract class Animation implements IAnimation {
|
||||
changeables: Map<AnimatedKey, Changeable> = new Map
|
||||
duration = 0
|
||||
repeatCount?: number
|
||||
repeatMode?: RepeatMode
|
||||
delay?: number
|
||||
|
||||
addParent(node: Node) {
|
||||
if (!this.parents.has(node)) {
|
||||
this.parents.add(node);
|
||||
node.addChild(this);
|
||||
}
|
||||
}
|
||||
|
||||
addSibling(node: Node) {
|
||||
if (!this.siblings.has(node)) {
|
||||
this.siblings.add(node);
|
||||
node.addSibling(this);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
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
|
||||
})
|
||||
})
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ import { uniqueId } from "../util/uniqueId";
|
||||
import { loge } from "../util/log";
|
||||
import { BridgeContext } from "../runtime/global";
|
||||
import { LayoutConfig } from '../util/layoutconfig'
|
||||
import { IAnimation } from "./animation";
|
||||
|
||||
export function Property(target: Object, propKey: string) {
|
||||
Reflect.defineMetadata(propKey, true, target)
|
||||
@ -333,6 +334,10 @@ export abstract class View implements Modeling, IView {
|
||||
@Property
|
||||
rotation?: number
|
||||
/**----------transform----------*/
|
||||
|
||||
doAnimation(context: BridgeContext, animation: IAnimation) {
|
||||
return this.nativeChannel(context, "doAnimation")(animation)
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class Superview extends View {
|
||||
|
Reference in New Issue
Block a user