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]
|
* 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
|
||||||
|
}
|
||||||
|
}
|
@ -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 {
|
||||||
|
Reference in New Issue
Block a user