import * as React from "react"; import {useSharedValue, useAnimatedStyle, withTiming, Easing, ReduceMotion,} from 'react-native-reanimated'; import {EmitterParams, IProps, PopupLayerAnimatedName} from "./popupLayer"; import {animatedType, configName, directionType, scaleType, storageArr} from "./config"; import app, {ThemeCss} from "../app"; const useData = (props: IProps) => { const css = app.theme.useGet(); // 宽度 const width = props.width ?? (props.edge ? (css.width - (props.edge * 2)) : css.width); // 高度 const height = props.height ?? (props.edge ? (css.height - (props.edge * 2)) : (css.height * scaleType["50"])); // 方向 const direction = props.direction ?? directionType.bottom; // 动画 const animated = props.animated ?? animatedType.bottom; // 是否可以点击隐藏 const isClickHide = typeof props.isClickHide === 'boolean' ? props.isClickHide : true; // 是否显示 const [isDisplay, setIsDisplay] = React.useState(false); // 是否执行动画 const [isAnimated, setIsAnimated] = React.useState(false); // 初始化动画参数 const layerAnimatedValue = _getLayerValue(animated); // 动画 const layerXY = useSharedValue(layerAnimatedValue); // 渐变动画 const layerOpacity = useSharedValue(0); // 执行的动画 const layerAnimatedXYStyle = useAnimatedStyle(() => { let transform = []; if (animated === animatedType.left || animated === animatedType.right) transform = [{translateX: layerXY.value}]; else if (animated === animatedType.top || animated === animatedType.bottom) transform = [{translateY: layerXY.value}]; return {transform} }); const layerAnimatedOpacity = useAnimatedStyle(() => ({ opacity: layerOpacity.value })) React.useLayoutEffect(() => { const name = `${configName}_${props.name}`; const emitterData = app.emitter.get(name, (params: EmitterParams) => { // 打开回调 if (typeof props.openCallback === "function" && params.display) props.openCallback(props.name); // 关闭回调 if (typeof props.closeCallback === "function" && !params.display) props.closeCallback(props.name); // 添加缓存 const storageData = storageArr.getByParams({name}) as any; if (storageData) storageArr.update(storageData.id, {display: params.display}); else storageArr.add({name, display: params.display}); setIsAnimated(params.display); if (params.display) setIsDisplay(true); }) return () => { emitterData.remove(); } }, []) // 动画或方向变化后重置动画 React.useEffect(() => { layerXY.value = layerAnimatedValue; }, [props.animated, props.direction]) React.useEffect(() => { // 当显示的时候,调用动画 if (!isDisplay) return; const userConfig = { duration: 150, easing: Easing.out(Easing.cubic), reduceMotion: ReduceMotion.System, }; if (isAnimated) { // 新动画 layerXY.value = withTiming(0, userConfig); layerOpacity.value = withTiming(1, userConfig); } else { // 新动画 layerXY.value = withTiming(layerAnimatedValue, userConfig); layerOpacity.value = withTiming(0, userConfig); setTimeout(() => { setIsDisplay(false); }, userConfig.duration) } }, [isAnimated, isDisplay]); return { css, width, height, direction, isClickHide, isDisplay, layerAnimatedXYStyle, layerAnimatedOpacity, } } /** * 获取layer初始化动画value * @param value */ const _getLayerValue = (value: PopupLayerAnimatedName) => { let result = 0, size = 50; if (value === animatedType.left || value === animatedType.top) result = -size; if (value === animatedType.right || value === animatedType.bottom) result = size; return result } export default { useData }