mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-17 02:31:34 +08:00
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:
95
core/src/utils/animation/animation-utils.ts
Normal file
95
core/src/utils/animation/animation-utils.ts
Normal 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;
|
||||
};
|
Reference in New Issue
Block a user