feat(animation): add animation utility (#18918)

* Add new keyframes proof of concept

* update esm import

* add base before and after methods, add tests

* add base before and after hooks

* update clean up methods, add tests

* add web animations support, change to arrow functions

* remove console logs

* add from, to, fromTo, and other properties

* add more tests, fix onFinish functionality, being testing with nav transitions

* add progress methods, use force linear

* run linter

* Add playSync

* integrate animations with framework components

* onFinish now supports multiple callbacks

* change const to let

* testing reverse

* add support for both animation utilities

* bug fix

* export createAnimation, a few tweaks

* add base tests

* fix issue with onFinish being called out of order. added tests

* fix race conditions in tests

* clean up

* fix bug where onFinish not calling for empty elements array,  update test

* clean up

* fix treeshaking, remove old comments

* remove old tests

* Add test for animationbuilder backwards compat

* update typings for menu controller

* mock web animations in tests

* run build

* fix type errors

* sync with master

* use requestAnimationFrame instead of writeTask

* fix flaky tests, fix menu

* fix ordering

* update webdriver

* fix wrong version

* Revert "fix wrong version"

This reverts commit be91296e9701399f8d784b08d09a3c475ca15df7.

Revert chromedriver update

* Revert "update webdriver"

This reverts commit e49bc9d76e335a0af5828725065399bd6795fa37.

Revert chromedriver update

* expose raw animation object, add tests

* add stylesheet recycling

* finalize before and after hook tests

* a few styling changes

* fix lint warnings

* get rid of old code

* Fix progressStep overflow bug

* disable reuse stylesheet

* small updates

* fix old animation create

* setStyleProperty helper

* reuse keyframe styles

* keyframes

* fix css animation issue with display: none, add tests

* add comment

* fix issue with progress animations and css animations

* clean up

* clean up pt2

* fix tests

* fix linter

* add fill for overlays

* fix swipe to go back

* clean up css animations when done

* fix edge cases with css animations

* fix menu open and close

* add reset function

* clean up reset fn

* Fix issue where animation always being reset

* allow updating animations on the fly

* add clear onfinish method

* fix linter

* add callback options, expand force direction

* ensure opts is defined

* fix css animations open and close for menus

* remove test

* add extra check

* clean up

* fix css anim bug swipe to go back

* fix pause

* setup alt animation to avoid flickering

* clean up

* reset flags on destroy

* add ability to change duration on progressEnd

* fix flicker on duration change for css animations

* fix ios transition

* remove unneeded recursion

* increase durability of updating css animations on the fly

* fix gesture anim

* fix web anim as well. more work for cleanup

* simplify progressEnd for css animations

* fix swipe to go back race condition

* clean up

* Add todo

* fix one more bug
This commit is contained in:
Liam DeBeasi
2019-08-12 10:05:04 -04:00
committed by GitHub
parent e33cf854a9
commit 30ca46ab12
70 changed files with 3974 additions and 762 deletions

View File

@ -0,0 +1,95 @@
export const setStyleProperty = (element: HTMLElement, propertyName: string, value: string | null) => {
element.style.setProperty(propertyName, value);
};
export const removeStyleProperty = (element: HTMLElement, propertyName: string) => {
element.style.removeProperty(propertyName);
};
export const animationEnd = (el: HTMLElement | null, callback: (ev?: TransitionEvent) => void) => {
let unRegTrans: (() => void) | undefined;
const opts: any = { passive: true };
const unregister = () => {
if (unRegTrans) {
unRegTrans();
}
};
const onTransitionEnd = (ev: Event) => {
if (el === ev.target) {
unregister();
callback(ev as TransitionEvent);
}
};
if (el) {
el.addEventListener('webkitAnimationEnd', onTransitionEnd, opts);
el.addEventListener('animationend', onTransitionEnd, opts);
unRegTrans = () => {
el.removeEventListener('webkitAnimationEnd', onTransitionEnd, opts);
el.removeEventListener('animationend', onTransitionEnd, opts);
};
}
return unregister;
};
export const generateKeyframeRules = (keyframes: any[] = []) => {
return keyframes.map(keyframe => {
const offset = keyframe.offset;
const frameString = [];
for (const property in keyframe) {
if (keyframe.hasOwnProperty(property) && property !== 'offset') {
frameString.push(`${property}: ${keyframe[property]};`);
}
}
return `${offset * 100}% { ${frameString.join(' ')} }`;
}).join(' ');
};
const keyframeIds: string[] = [];
export const generateKeyframeName = (keyframeRules: string) => {
let index = keyframeIds.indexOf(keyframeRules);
if (index < 0) {
index = (keyframeIds.push(keyframeRules) - 1);
}
return `ion-animation-${index}`;
};
export const getStyleContainer = (element: HTMLElement) => {
const rootNode = (element.getRootNode() as any);
return (rootNode.head || rootNode);
};
export const createKeyframeStylesheet = (keyframeName: string, keyframeRules: string, element: HTMLElement): HTMLElement => {
const styleContainer = getStyleContainer(element);
const existingStylesheet = styleContainer.querySelector('#' + keyframeName);
if (existingStylesheet) {
return existingStylesheet;
}
const stylesheet = (element.ownerDocument || document).createElement('style');
stylesheet.id = keyframeName;
stylesheet.innerHTML = `@keyframes ${keyframeName} { ${keyframeRules} } @keyframes ${keyframeName}-alt { ${keyframeRules} }`;
styleContainer.appendChild(stylesheet);
return stylesheet;
};
export const addClassToArray = (classes: string[] = [], className: string | string[] | undefined): string[] => {
if (className !== undefined) {
const classNameToAppend = (Array.isArray(className)) ? className : [className];
return [...classes, ...classNameToAppend];
}
return classes;
};