UNPKG

react-native-reanimated

Version:

More powerful alternative to Animated library for React Native.

159 lines (136 loc) 4.32 kB
'use strict'; import { LayoutAnimationType } from '../../../commonTypes'; import type { ReanimatedHTMLElement } from '../../../ReanimatedModule/js-reanimated'; import type { TransitionData } from '../animationParser'; import type { AnimationConfig } from '../config'; import type { WebEasingsNames } from '../Easing.web'; import { getEasingByName } from '../Easing.web'; function resetStyle(component: HTMLElement) { component.style.animationName = ''; // This line prevents unwanted entering animation component.style.position = 'absolute'; component.style.top = '0px'; component.style.left = '0px'; component.style.margin = '0px'; component.style.width = '100%'; component.style.height = '100%'; } function showChildren( parent: HTMLElement, childrenDisplayProperty: Map<HTMLElement, string>, shouldShow: boolean ) { for (let i = 0; i < parent.children.length; ++i) { const child = parent.children[i] as HTMLElement; if (shouldShow) { child.style.display = childrenDisplayProperty.get(child)!; } else { childrenDisplayProperty.set(child, child.style.display); child.style.display = 'none'; } } } function prepareParent( element: ReanimatedHTMLElement, dummy: ReanimatedHTMLElement, animationConfig: AnimationConfig, transitionData: TransitionData ) { // Adjust configs for `CurvedTransition` and create config object for dummy animationConfig.easing = getEasingByName( transitionData.easingX as WebEasingsNames ); const childrenDisplayProperty = new Map<HTMLElement, string>(); showChildren(element, childrenDisplayProperty, false); const originalBackgroundColor = element.style.backgroundColor; element.style.backgroundColor = 'transparent'; const onFinalize = () => { if (element.contains(dummy)) { element.removeChild(dummy); } showChildren(element, childrenDisplayProperty, true); element.style.backgroundColor = originalBackgroundColor; }; const animationCancelCallback = () => { onFinalize(); element.removeEventListener('animationcancel', animationCancelCallback); }; const animationEndCallback = () => { onFinalize(); element.removeEventListener('animationend', animationEndCallback); }; element.addEventListener('animationend', animationEndCallback); element.addEventListener('animationcancel', animationCancelCallback); element.appendChild(dummy); } function prepareDummy( element: ReanimatedHTMLElement, animationConfig: AnimationConfig, transitionData: TransitionData, dummyTransitionKeyframeName: string ) { const dummyAnimationConfig: AnimationConfig = { animationName: dummyTransitionKeyframeName, animationType: LayoutAnimationType.LAYOUT, duration: animationConfig.duration, delay: animationConfig.delay, easing: getEasingByName(transitionData.easingY as WebEasingsNames), callback: null, reversed: false, }; const dummy = element.cloneNode(true) as ReanimatedHTMLElement; resetStyle(dummy); return { dummy, dummyAnimationConfig }; } export function prepareCurvedTransition( element: ReanimatedHTMLElement, animationConfig: AnimationConfig, transitionData: TransitionData, dummyTransitionKeyframeName: string ) { const { dummy, dummyAnimationConfig } = prepareDummy( element, animationConfig, transitionData, dummyTransitionKeyframeName ); prepareParent(element, dummy, animationConfig, transitionData); return { dummy, dummyAnimationConfig }; } export function CurvedTransition( keyframeXName: string, keyframeYName: string, transitionData: TransitionData ) { const keyframeXObj = { name: keyframeXName, style: { 0: { transform: [ { translateX: `${transitionData.translateX}px`, scale: `${transitionData.scaleX},${transitionData.scaleY}`, }, ], }, }, duration: 300, }; const keyframeYObj = { name: keyframeYName, style: { 0: { transform: [ { translateY: `${transitionData.translateY}px`, scale: `${transitionData.scaleX},${transitionData.scaleY}`, }, ], }, }, duration: 300, }; return { firstKeyframeObj: keyframeXObj, secondKeyframeObj: keyframeYObj, }; }