Skip to content

Commit 1abebb6

Browse files
authored
fix(animations): use parsers from core modules (#844)
fixes #738
1 parent 6168ddb commit 1abebb6

File tree

2 files changed

+44
-139
lines changed

2 files changed

+44
-139
lines changed

Diff for: nativescript-angular/animations/animation-player.ts

+4-14
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import { AnimationPlayer } from "@angular/animations";
2-
import {
3-
KeyframeAnimation,
4-
KeyframeAnimationInfo,
5-
} from "tns-core-modules/ui/animation/keyframe-animation";
2+
import { KeyframeAnimation }
3+
from "tns-core-modules/ui/animation/keyframe-animation";
64

75
import { NgView } from "../element-registry";
8-
import { Keyframe, getAnimationCurve, parseAnimationKeyframe } from "./utils";
6+
import { Keyframe, createKeyframeAnimation } from "./utils";
97

108
export class NativeScriptAnimationPlayer implements AnimationPlayer {
119
public parentPlayer: AnimationPlayer = null;
@@ -86,15 +84,7 @@ export class NativeScriptAnimationPlayer implements AnimationPlayer {
8684
}
8785

8886
private initKeyframeAnimation(keyframes: Keyframe[], duration: number, delay: number, easing: string) {
89-
let info = new KeyframeAnimationInfo();
90-
info.isForwards = true;
91-
info.iterations = 1;
92-
info.duration = duration === 0 ? 0.01 : duration;
93-
info.delay = delay;
94-
info.curve = getAnimationCurve(easing);
95-
info.keyframes = keyframes.map(parseAnimationKeyframe);
96-
97-
this.animation = KeyframeAnimation.keyframeAnimationFromInfo(info);
87+
this.animation = createKeyframeAnimation(keyframes, duration, delay, easing);
9888
}
9989

10090
private onFinish() {

Diff for: nativescript-angular/animations/utils.ts

+40-125
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,54 @@
11
import {
2+
KeyframeAnimation,
3+
KeyframeAnimationInfo,
24
KeyframeDeclaration,
35
KeyframeInfo,
46
} from "tns-core-modules/ui/animation/keyframe-animation";
5-
import { CssAnimationProperty } from "tns-core-modules/ui/core/properties";
6-
import { AnimationCurve } from "tns-core-modules/ui/enums";
7+
import { parseKeyframeDeclarations } from "tns-core-modules/ui/styling/css-animation-parser";
8+
import { animationTimingFunctionConverter } from "tns-core-modules/ui/styling/converters";
79

810
export interface Keyframe {
911
[key: string]: string | number;
10-
}
11-
12-
interface Transformation {
13-
property: string;
14-
value: number | { x: number, y: number };
15-
}
16-
17-
const TRANSFORM_MATCHER = new RegExp(/(.+)\((.+)\)/);
18-
const TRANSFORM_SPLITTER = new RegExp(/[\s,]+/);
19-
20-
const STYLE_TRANSFORMATION_MAP = Object.freeze({
21-
"scale": value => ({ property: "scale", value }),
22-
"scale3d": value => ({ property: "scale", value }),
23-
"scaleX": value => ({ property: "scale", value: { x: value, y: 1 } }),
24-
"scaleY": value => ({ property: "scale", value: { x: 1, y: value } }),
25-
26-
"translate": value => ({ property: "translate", value }),
27-
"translate3d": value => ({ property: "translate", value }),
28-
"translateX": value => ({ property: "translate", value: { x: value, y: 0 } }),
29-
"translateY": value => ({ property: "translate", value: { x: 0, y: value } }),
30-
31-
"rotate": value => ({ property: "rotate", value }),
32-
33-
"none": _value => [
34-
{ property: "scale", value: { x: 1, y: 1 } },
35-
{ property: "translate", value: { x: 0, y: 0 } },
36-
{ property: "rotate", value: 0 },
37-
],
38-
});
39-
40-
const STYLE_CURVE_MAP = Object.freeze({
41-
"ease": AnimationCurve.ease,
42-
"linear": AnimationCurve.linear,
43-
"ease-in": AnimationCurve.easeIn,
44-
"ease-out": AnimationCurve.easeOut,
45-
"ease-in-out": AnimationCurve.easeInOut,
46-
"spring": AnimationCurve.spring,
47-
});
48-
49-
export function getAnimationCurve(value: string): any {
50-
if (!value) {
51-
return AnimationCurve.ease;
52-
}
53-
54-
const curve = STYLE_CURVE_MAP[value];
55-
if (curve) {
56-
return curve;
57-
}
58-
59-
const [, property = "", pointsString = ""] = TRANSFORM_MATCHER.exec(value) || [];
60-
const coords = pointsString.split(TRANSFORM_SPLITTER).map(stringToBezieCoords);
61-
62-
if (property !== "cubic-bezier" || coords.length !== 4) {
63-
throw new Error(`Invalid value for animation: ${value}`);
64-
} else {
65-
return (<any>AnimationCurve).cubicBezier(...coords);
12+
offset: number;
13+
}
14+
15+
export function createKeyframeAnimation(
16+
styles: Keyframe[],
17+
duration: number,
18+
delay: number,
19+
easing: string)
20+
: KeyframeAnimation {
21+
22+
const info = createKeyframeAnimationInfo(styles, duration, delay, easing);
23+
return KeyframeAnimation.keyframeAnimationFromInfo(info);
24+
}
25+
26+
const createKeyframeAnimationInfo = (
27+
styles: Keyframe[],
28+
duration: number,
29+
delay: number,
30+
easing: string
31+
): KeyframeAnimationInfo => ({
32+
isForwards: true,
33+
duration: duration || 0.01,
34+
delay,
35+
curve: getCurve(easing),
36+
keyframes: styles.map(parseAnimationKeyframe),
6637
}
67-
}
68-
69-
export function parseAnimationKeyframe(styles: Keyframe) {
70-
let keyframeInfo = <KeyframeInfo>{};
71-
keyframeInfo.duration = <number>styles.offset;
72-
keyframeInfo.declarations = Object.keys(styles).reduce((declarations, prop) => {
73-
let value = styles[prop];
74-
75-
const property = CssAnimationProperty._getByCssName(prop);
76-
if (property) {
77-
if (typeof value === "string" && property._valueConverter) {
78-
value = property._valueConverter(<string>value);
79-
}
80-
declarations.push({ property: property.name, value });
81-
} else if (typeof value === "string" && prop === "transform") {
82-
declarations.push(...parseTransformation(<string>value));
83-
}
38+
);
8439

85-
return declarations;
86-
}, new Array<KeyframeDeclaration>());
87-
88-
return keyframeInfo;
89-
}
90-
91-
function stringToBezieCoords(value: string): number {
92-
let result = parseFloat(value);
93-
if (result < 0) {
94-
return 0;
95-
} else if (result > 1) {
96-
return 1;
97-
}
98-
99-
return result;
100-
}
40+
const getCurve = (value: string) => animationTimingFunctionConverter(value);
10141

102-
function parseTransformation(styleString: string): KeyframeDeclaration[] {
103-
return parseStyle(styleString)
104-
.reduce((transformations, style) => {
105-
const transform = STYLE_TRANSFORMATION_MAP[style.property](style.value);
106-
107-
if (Array.isArray(transform)) {
108-
transformations.push(...transform);
109-
} else if (typeof transform !== "undefined") {
110-
transformations.push(transform);
111-
}
112-
113-
return transformations;
114-
}, new Array<Transformation>());
115-
}
116-
117-
function parseStyle(text: string): Transformation[] {
118-
return text.split(TRANSFORM_SPLITTER).map(stringToTransformation).filter(t => !!t);
119-
}
120-
121-
function stringToTransformation(text: string): Transformation {
122-
const [, property = "", stringValue = ""] = TRANSFORM_MATCHER.exec(text) || [];
123-
if (!property) {
124-
return;
125-
}
42+
const parseAnimationKeyframe = (styles: Keyframe): KeyframeInfo => ({
43+
duration: getKeyframeDuration(styles),
44+
declarations: getDeclarations(styles),
45+
});
12646

127-
const [x, y] = stringValue.split(",").map(parseFloat);
128-
if (x && y) {
129-
return { property, value: {x, y} };
130-
} else {
131-
let value: number = x;
47+
const getKeyframeDuration = (styles: Keyframe): number => styles.offset;
13248

133-
if (stringValue.slice(-3) === "rad") {
134-
value *= 180.0 / Math.PI;
135-
}
49+
function getDeclarations(styles: Keyframe): KeyframeDeclaration[] {
50+
const unparsedDeclarations: KeyframeDeclaration[] =
51+
Object.keys(styles).map(property => ({ property, value: styles[property] }));
13652

137-
return { property, value };
138-
}
53+
return parseKeyframeDeclarations(unparsedDeclarations);
13954
}

0 commit comments

Comments
 (0)