add from, to, fromTo, and other properties

This commit is contained in:
Liam DeBeasi
2019-07-17 09:50:33 -04:00
parent 93e9d9a36d
commit ec32f56182
5 changed files with 153 additions and 50 deletions

View File

@@ -515,7 +515,7 @@ export class Animator {
_asyncEnd(dur: number, shouldComplete: boolean) {
const self = this;
function onTransitionEnd() {
const onTransitionEnd = () => {
// congrats! a successful transition completed!
// ensure transition end events and timeouts have been cleared
self._clearAsync();
@@ -525,9 +525,9 @@ export class Animator {
// transition finished
self._didFinishAll(shouldComplete, true, false);
}
};
function onTransitionFallback() {
const onTransitionFallback = () => {
// oh noz! the transition end event didn't fire in time!
// instead the fallback timer when first
// if all goes well this fallback should never fire
@@ -542,7 +542,7 @@ export class Animator {
// transition finished
self._didFinishAll(shouldComplete, true, false);
}
};
// set the TRANSITION END event on one of the transition elements
self._unregisterTrnsEnd = transitionEnd(self._transEl(), onTransitionEnd);

View File

@@ -2,9 +2,9 @@ import { Animation, AnimationBuilder } from '../../interface';
import { Animator } from './animator';
export function create(animationBuilder?: AnimationBuilder, baseEl?: any, opts?: any): Promise<Animation> {
export const create = (animationBuilder?: AnimationBuilder, baseEl?: any, opts?: any): Promise<Animation> => {
if (animationBuilder) {
return animationBuilder(Animator as any, baseEl, opts);
}
return Promise.resolve(new Animator() as any);
}
};

View File

@@ -1,20 +1,20 @@
export function transitionEnd(el: HTMLElement | null, callback: (ev?: TransitionEvent) => void) {
export const transitionEnd = (el: HTMLElement | null, callback: (ev?: TransitionEvent) => void) => {
let unRegTrans: (() => void) | undefined;
const opts: any = { passive: true };
function unregister() {
const unregister = () => {
if (unRegTrans) {
unRegTrans();
}
}
};
function onTransitionEnd(ev: Event) {
const onTransitionEnd = (ev: Event) => {
if (el === ev.target) {
unregister();
callback(ev as TransitionEvent);
}
}
};
if (el) {
el.addEventListener('webkitTransitionEnd', onTransitionEnd, opts);
@@ -27,4 +27,4 @@ export function transitionEnd(el: HTMLElement | null, callback: (ev?: Transition
}
return unregister;
}
};

View File

@@ -12,26 +12,37 @@ export interface Animation {
afterRemoveClasses: string[];
afterStylesValue: { [property: string]: any };
parent(animation: Animation): Animation;
play(): Animation;
playStep(step: number): Animation;
pause(): Animation;
stop(): Animation;
playStep(step: number): Animation;
destroy(): Animation;
from(property: string, value: any): Animation;
to(property: string, value: any): Animation;
fromTo(property: string, fromValue: any, toValue: any): Animation;
keyframes(keyframes: any[]): Animation;
addAnimation(animationToADd: Animation | Animation[] | undefined | null): Animation;
addTarget(target: string): Animation;
addElement(el: Node | Node[] | NodeList | undefined | null): Animation;
iterations(iterations: number): Animation;
fill(fill: 'auto' | 'none' | 'forwards' | 'backwards' | 'both' | undefined): Animation;
direction(direction: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' | undefined): Animation;
duration(duration: number): Animation;
easing(easing: string): Animation;
delay(delay: number): Animation;
name(name: string): Animation;
parent(animation: Animation): Animation;
getKeyframes(): any[];
getDirection(): 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' | undefined;
getFill(): 'auto' | 'none' | 'forwards' | 'backwards' | 'both' | undefined;
getDelay(): number | undefined;
getIterations(): number | undefined;
getEasing(): string | undefined;
getDuration(): number | undefined;
afterClearStyles(propertyNames: string[]): Animation;
afterStyles(styles: { [property: string]: any }): Animation;
afterRemoveClass(className: string | string[] | undefined): Animation;
@@ -40,24 +51,26 @@ export interface Animation {
beforeStyles(styles: { [property: string]: any }): Animation;
beforeRemoveClass(className: string | string[] | undefined): Animation;
beforeAddClass(className: string | string[] | undefined): Animation;
onFinish(callback: any): Animation;
}
const animationEnd = (el: HTMLElement | null, callback: (ev?: TransitionEvent) => void) => {
let unRegTrans: (() => void) | undefined;
const opts: any = { passive: true };
function unregister() {
const unregister = () => {
if (unRegTrans) {
unRegTrans();
}
}
};
function onTransitionEnd(ev: Event) {
const onTransitionEnd = (ev: Event) => {
if (el === ev.target) {
unregister();
callback(ev as TransitionEvent);
}
}
};
if (el) {
el.addEventListener('webkitAnimationEnd', onTransitionEnd, opts);
@@ -73,7 +86,7 @@ const animationEnd = (el: HTMLElement | null, callback: (ev?: TransitionEvent) =
};
const supportsWebAnimations = (): boolean => {
return !!(window as any).Animation;
return !!(window as any).Animation;
};
const generateKeyframeString = (name: string | undefined, keyframes: any[] = []): string => {
@@ -124,9 +137,10 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
let _duration: number | undefined;
let _easing: string | undefined;
let _iterations: number | undefined;
let _fill: 'auto' | 'none' | 'forwards' | 'backwards' | 'both' | undefined;
let _direction: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' | undefined;
let _keyframes: any[] = [];
let _keyframeString = '';
let initialized = false;
@@ -143,6 +157,7 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
let afterStylesValue: { [property: string]: any } = {};
let webAnimations: any[] = [];
let onFinishCallback: any | undefined;
/**
* Destroy this animation and all child animations.
@@ -167,6 +182,12 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
cleanUpStyleSheets();
};
const onFinish = (callback: any): Animation => {
onFinishCallback = callback;
return generatePublicAPI();
};
const cleanUpElements = () => {
if (supportsWebAnimations()) {
webAnimations.forEach(animation => {
@@ -277,6 +298,21 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
return generatePublicAPI();
};
const getFill = (): 'auto' | 'none' | 'forwards' | 'backwards' | 'both' | undefined => {
if (_fill !== undefined) { return _fill; }
if (parentAnimation) { return parentAnimation.getFill(); }
return undefined;
};
const getDirection = (): 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' | undefined => {
if (_direction !== undefined) { return _direction; }
if (parentAnimation) { return parentAnimation.getDirection(); }
return undefined;
};
const getEasing = (): string | undefined => {
if (_easing !== undefined) { return _easing; }
if (parentAnimation) { return parentAnimation.getEasing(); }
@@ -315,6 +351,19 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
return generatePublicAPI();
};
const direction = (animationDirection: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse'): Animation => {
_direction = animationDirection;
return generatePublicAPI();
};
const fill = (animationFill: 'auto' | 'none' | 'forwards' | 'backwards' | 'both'): Animation => {
_fill = animationFill;
return generatePublicAPI();
};
const delay = (animationDelay: number): Animation => {
_delay = animationDelay;
@@ -387,10 +436,6 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
const keyframes = (keyframeValues: any[]) => {
_keyframes = keyframeValues;
if (!supportsWebAnimations()) {
_keyframeString = generateKeyframeString(_name, keyframeValues);
}
return generatePublicAPI();
};
@@ -431,7 +476,9 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
}
});
cleanUpElements();
if (onFinishCallback !== undefined) {
onFinishCallback(generatePublicAPI());
}
};
const initializeAnimation = () => {
@@ -443,7 +490,9 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
delay: getDelay(),
duration: getDuration(),
easing: getEasing(),
iterations: getIterations()
iterations: getIterations(),
fill: getFill(),
direction: getDirection()
});
if (i === 0) {
@@ -458,34 +507,45 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
});
} else {
if (!stylesheet) {
stylesheet = createKeyframeStylesheet(_keyframeString);
stylesheet = createKeyframeStylesheet(generateKeyframeString(_name, _keyframes));
}
const animationDuration = getDuration();
const animationEasing = getEasing();
const animationIterationCount = getIterations();
const animationDelay = getDelay();
const animationFill = getFill();
const animationDirection = getDirection();
elements.forEach(element => {
if (_name !== undefined) {
(element as HTMLElement).style.animationName = _name;
element.style.setProperty('animation-name', _name);
}
if (animationDuration !== undefined) {
(element as HTMLElement).style.animationDuration = `${animationDuration}ms`;
element.style.setProperty('animation-duration', `${animationDuration}ms`);
}
if (animationEasing !== undefined) {
(element as HTMLElement).style.animationTimingFunction = animationEasing;
element.style.setProperty('animation-timing-function', animationEasing);
}
if (animationIterationCount !== undefined) {
(element as HTMLElement).style.animationIterationCount = (animationIterationCount === Infinity) ? 'infinite' : animationIterationCount.toString();
element.style.setProperty('animation-iteration-count', (animationIterationCount === Infinity) ? 'infinite' : animationIterationCount.toString());
}
if (animationDelay !== undefined) {
(element as HTMLElement).style.animationDelay = `${animationDelay}ms`;
element.style.setProperty('animation-delay', `${animationDelay}ms`);
}
if (animationFill !== undefined) {
element.style.setProperty('animation-fill-mode', animationFill);
}
if (animationDirection !== undefined) {
element.style.setProperty('animation-direction', animationDirection);
}
});
@@ -580,6 +640,52 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
return generatePublicAPI();
};
const from = (property: string, value: any): Animation => {
const keyframeValues = getKeyframes();
const firstFrame = keyframeValues[0];
if (firstFrame != null && (firstFrame.offset === undefined || firstFrame.offset === 0)) {
firstFrame[property] = value;
} else {
const object: any = {
offset: 0
};
object[property] = value;
_keyframes = [
object,
..._keyframes
];
}
return generatePublicAPI();
};
const to = (property: string, value: any): Animation => {
const keyframeValues = getKeyframes();
const lastFrame = keyframeValues[keyframes.length - 1];
if (lastFrame != null && (lastFrame.offset === undefined || lastFrame.offset === 1)) {
lastFrame[property] = value;
} else {
const object: any = {
offset: 1
};
object[property] = value;
_keyframes = [
..._keyframes,
object
];
}
return generatePublicAPI();
};
const fromTo = (property: string, fromValue: any, toValue: any): Animation => {
return from(property, fromValue).to(property, toValue);
};
const generatePublicAPI = (): Animation => {
return {
parentAnimation,
@@ -591,6 +697,9 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
afterAddClasses,
afterRemoveClasses,
afterStylesValue,
from,
to,
fromTo,
parent,
play,
pause,
@@ -601,12 +710,16 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
addAnimation,
addTarget,
addElement,
fill,
direction,
iterations,
duration,
easing,
delay,
name,
getKeyframes,
getFill,
getDirection,
getDelay,
getIterations,
getEasing,
@@ -619,6 +732,7 @@ export const createAnimation = (animationNameValue: string | undefined): Animati
beforeStyles,
beforeRemoveClass,
beforeAddClass,
onFinish,
};
};

View File

@@ -19,24 +19,12 @@
animation
.addElement(square)
.duration(2000)
.easing('linear')
.iterations(1)
.keyframes([
{ transform: 'scale(1) rotate(0deg)', opacity: 1, offset: 0 },
{ transform: 'scale(1.5) rotate(45deg)', opacity: 0.5, offset: 0.5 },
{ transform: 'scale(1) rotate(0deg)', opacity: 1, offset: 1 }
])
.beforeAddClass(['hello', 'ionic', 'world'])
.beforeRemoveClass('liam-was-here')
.beforeStyles({
'background': 'rgba(255, 0, 0, 0.5)',
'color': 'white'
})
.afterStyles({
'background': 'rgba(0, 255, 0, 0.5)',
});
.duration(1000)
.easing('ease-in-out')
.direction('alternate')
.iterations(Infinity)
.fromTo('opacity', 0.1, 1);
animation.play();
</script>
@@ -50,6 +38,7 @@
margin-left: 25px;
margin-top: 25px;
margin-bottom: 25px;
opacity: 0;
}
</style>
</head>