diff --git a/nativescript-angular/animations/animation-player.ts b/nativescript-angular/animations/animation-player.ts index fcc60d8f1..fdaeb4503 100644 --- a/nativescript-angular/animations/animation-player.ts +++ b/nativescript-angular/animations/animation-player.ts @@ -1,11 +1,9 @@ import { AnimationPlayer } from "@angular/animations"; -import { - KeyframeAnimation, - KeyframeAnimationInfo, -} from "tns-core-modules/ui/animation/keyframe-animation"; +import { KeyframeAnimation } + from "tns-core-modules/ui/animation/keyframe-animation"; import { NgView } from "../element-registry"; -import { Keyframe, getAnimationCurve, parseAnimationKeyframe } from "./utils"; +import { Keyframe, createKeyframeAnimation } from "./utils"; export class NativeScriptAnimationPlayer implements AnimationPlayer { public parentPlayer: AnimationPlayer = null; @@ -86,15 +84,7 @@ export class NativeScriptAnimationPlayer implements AnimationPlayer { } private initKeyframeAnimation(keyframes: Keyframe[], duration: number, delay: number, easing: string) { - let info = new KeyframeAnimationInfo(); - info.isForwards = true; - info.iterations = 1; - info.duration = duration === 0 ? 0.01 : duration; - info.delay = delay; - info.curve = getAnimationCurve(easing); - info.keyframes = keyframes.map(parseAnimationKeyframe); - - this.animation = KeyframeAnimation.keyframeAnimationFromInfo(info); + this.animation = createKeyframeAnimation(keyframes, duration, delay, easing); } private onFinish() { diff --git a/nativescript-angular/animations/utils.ts b/nativescript-angular/animations/utils.ts index 05833e3a3..d8dc38f18 100644 --- a/nativescript-angular/animations/utils.ts +++ b/nativescript-angular/animations/utils.ts @@ -1,139 +1,54 @@ import { + KeyframeAnimation, + KeyframeAnimationInfo, KeyframeDeclaration, KeyframeInfo, } from "tns-core-modules/ui/animation/keyframe-animation"; -import { CssAnimationProperty } from "tns-core-modules/ui/core/properties"; -import { AnimationCurve } from "tns-core-modules/ui/enums"; +import { parseKeyframeDeclarations } from "tns-core-modules/ui/styling/css-animation-parser"; +import { animationTimingFunctionConverter } from "tns-core-modules/ui/styling/converters"; export interface Keyframe { [key: string]: string | number; -} - -interface Transformation { - property: string; - value: number | { x: number, y: number }; -} - -const TRANSFORM_MATCHER = new RegExp(/(.+)\((.+)\)/); -const TRANSFORM_SPLITTER = new RegExp(/[\s,]+/); - -const STYLE_TRANSFORMATION_MAP = Object.freeze({ - "scale": value => ({ property: "scale", value }), - "scale3d": value => ({ property: "scale", value }), - "scaleX": value => ({ property: "scale", value: { x: value, y: 1 } }), - "scaleY": value => ({ property: "scale", value: { x: 1, y: value } }), - - "translate": value => ({ property: "translate", value }), - "translate3d": value => ({ property: "translate", value }), - "translateX": value => ({ property: "translate", value: { x: value, y: 0 } }), - "translateY": value => ({ property: "translate", value: { x: 0, y: value } }), - - "rotate": value => ({ property: "rotate", value }), - - "none": _value => [ - { property: "scale", value: { x: 1, y: 1 } }, - { property: "translate", value: { x: 0, y: 0 } }, - { property: "rotate", value: 0 }, - ], -}); - -const STYLE_CURVE_MAP = Object.freeze({ - "ease": AnimationCurve.ease, - "linear": AnimationCurve.linear, - "ease-in": AnimationCurve.easeIn, - "ease-out": AnimationCurve.easeOut, - "ease-in-out": AnimationCurve.easeInOut, - "spring": AnimationCurve.spring, -}); - -export function getAnimationCurve(value: string): any { - if (!value) { - return AnimationCurve.ease; - } - - const curve = STYLE_CURVE_MAP[value]; - if (curve) { - return curve; - } - - const [, property = "", pointsString = ""] = TRANSFORM_MATCHER.exec(value) || []; - const coords = pointsString.split(TRANSFORM_SPLITTER).map(stringToBezieCoords); - - if (property !== "cubic-bezier" || coords.length !== 4) { - throw new Error(`Invalid value for animation: ${value}`); - } else { - return (AnimationCurve).cubicBezier(...coords); + offset: number; +} + +export function createKeyframeAnimation( + styles: Keyframe[], + duration: number, + delay: number, + easing: string) + : KeyframeAnimation { + + const info = createKeyframeAnimationInfo(styles, duration, delay, easing); + return KeyframeAnimation.keyframeAnimationFromInfo(info); +} + +const createKeyframeAnimationInfo = ( + styles: Keyframe[], + duration: number, + delay: number, + easing: string + ): KeyframeAnimationInfo => ({ + isForwards: true, + duration: duration || 0.01, + delay, + curve: getCurve(easing), + keyframes: styles.map(parseAnimationKeyframe), } -} - -export function parseAnimationKeyframe(styles: Keyframe) { - let keyframeInfo = {}; - keyframeInfo.duration = styles.offset; - keyframeInfo.declarations = Object.keys(styles).reduce((declarations, prop) => { - let value = styles[prop]; - - const property = CssAnimationProperty._getByCssName(prop); - if (property) { - if (typeof value === "string" && property._valueConverter) { - value = property._valueConverter(value); - } - declarations.push({ property: property.name, value }); - } else if (typeof value === "string" && prop === "transform") { - declarations.push(...parseTransformation(value)); - } +); - return declarations; - }, new Array()); - - return keyframeInfo; -} - -function stringToBezieCoords(value: string): number { - let result = parseFloat(value); - if (result < 0) { - return 0; - } else if (result > 1) { - return 1; - } - - return result; -} +const getCurve = (value: string) => animationTimingFunctionConverter(value); -function parseTransformation(styleString: string): KeyframeDeclaration[] { - return parseStyle(styleString) - .reduce((transformations, style) => { - const transform = STYLE_TRANSFORMATION_MAP[style.property](style.value); - - if (Array.isArray(transform)) { - transformations.push(...transform); - } else if (typeof transform !== "undefined") { - transformations.push(transform); - } - - return transformations; - }, new Array()); -} - -function parseStyle(text: string): Transformation[] { - return text.split(TRANSFORM_SPLITTER).map(stringToTransformation).filter(t => !!t); -} - -function stringToTransformation(text: string): Transformation { - const [, property = "", stringValue = ""] = TRANSFORM_MATCHER.exec(text) || []; - if (!property) { - return; - } +const parseAnimationKeyframe = (styles: Keyframe): KeyframeInfo => ({ + duration: getKeyframeDuration(styles), + declarations: getDeclarations(styles), +}); - const [x, y] = stringValue.split(",").map(parseFloat); - if (x && y) { - return { property, value: {x, y} }; - } else { - let value: number = x; +const getKeyframeDuration = (styles: Keyframe): number => styles.offset; - if (stringValue.slice(-3) === "rad") { - value *= 180.0 / Math.PI; - } +function getDeclarations(styles: Keyframe): KeyframeDeclaration[] { + const unparsedDeclarations: KeyframeDeclaration[] = + Object.keys(styles).map(property => ({ property, value: styles[property] })); - return { property, value }; - } + return parseKeyframeDeclarations(unparsedDeclarations); }