diff --git a/packages/webpack-plugin/lib/runtime/components/react/animationHooks/useTransitionHooks.ts b/packages/webpack-plugin/lib/runtime/components/react/animationHooks/useTransitionHooks.ts index 75f8014f08..f6f4ce63bc 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/animationHooks/useTransitionHooks.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/animationHooks/useTransitionHooks.ts @@ -43,6 +43,7 @@ const propName = { const behaviorExp = /^(allow-discrete|normal)$/ const defaultValueExp = /^(inherit|initial|revert|revert-layer|unset)$/ const timingFunctionExp = /^(step-start|step-end|steps)/ +const transitionKeys = ['transition', 'transitionDuration', 'transitionProperty', 'transitionTimingFunction', 'transitionDelay'] as const // cubic-bezier 参数解析 function getBezierParams (str: string) { // ease 0.25, 0.1, 0.25, 1.0 @@ -94,6 +95,7 @@ function parseTransitionSingleProp (vals: string[], property: string) { } }).filter(item => item !== undefined) } + // transition 解析 function parseTransitionStyle (originalStyle: ExtendedViewStyle) { let transitionData: AnimationDataType[] = [] @@ -144,7 +146,7 @@ function parseTransitionStyle (originalStyle: ExtendedViewStyle) { const transitionMap = transitionData.reduce((acc, cur) => { // hasOwn(transitionSupportedProperty, dash2hump(val)) || val === Transform const { property = '', duration = 0, delay = 0, easing = Easing.inOut(Easing.ease) } = cur - if ((hasOwn(transitionSupportedProperty, dash2hump(property)) || property === 'transform') && duration > 0) { + if ((hasOwn(transitionSupportedProperty, dash2hump(property)) || property === 'transform') && duration >= 0) { acc[property] = { duration, delay, @@ -162,19 +164,17 @@ export default function useTransitionHooks (props: AnimationHooksPropsType const { style: originalStyle = {}, transitionend } = props // style变更标识(首次render不执行),初始值为0,首次渲染后为1 const animationDeps = useRef(0) - // 记录上次style map - // const lastStyleRef = useRef({} as {[propName: keyof ExtendedViewStyle]: number|string}) - // ** 从 style 中获取动画数据 - const transitionMap = useMemo(() => { - return parseTransitionStyle(originalStyle) - }, []) + // 记录上次 transition 相关属性,用于判断是否需要重新解析 + const lastTransitionStyleRef = useRef>({}) // ** style prop sharedValue interpolateOutput: SharedValue - const { shareValMap, animatedKeys, animatedStyleKeys } = useMemo(() => { + const { shareValMap, animatedKeys, animatedStyleKeys, transitionMap } = useMemo(() => { // 记录需要执行动画的 propName const animatedKeys = [] as string[] // 有动画样式的 style key(useAnimatedStyle使用) const animatedStyleKeys = [] as (string|string[])[] const transforms = [] as string[] + // ** 从 style 中获取动画数据 + const transitionMap = parseTransitionStyle(originalStyle) const shareValMap = Object.keys(transitionMap).reduce((valMap, property) => { // const { property } = transition || {} if (property === 'transform') { @@ -199,9 +199,11 @@ export default function useTransitionHooks (props: AnimationHooksPropsType return { shareValMap, animatedKeys, - animatedStyleKeys + animatedStyleKeys, + transitionMap } }, []) + const transitionMapRef = useRef(transitionMap) const runOnJSCallbackRef = useRef({}) const runOnJSCallback = useRunOnJSCallback(runOnJSCallbackRef) // 根据 animation action 创建&驱动动画 @@ -234,7 +236,7 @@ export default function useTransitionHooks (props: AnimationHooksPropsType shareValMap[key].value = toVal } else { // console.log(`key=${key} oldVal=${shareValMap[key].value} newVal=${toVal}`) - const { delay = 0, duration, easing } = transitionMap[isTransformKey ? 'transform' : key] + const { delay = 0, duration = 0, easing = Easing.inOut(Easing.ease) } = transitionMapRef.current[isTransformKey ? 'transform' : key] || {} // console.log('animationOptions=', { delay, duration, easing }) let callback if (transitionend && (!isTransformKey || !transformTransitionendDone)) { @@ -269,6 +271,23 @@ export default function useTransitionHooks (props: AnimationHooksPropsType animationDeps.current = 1 return } + // 仅当 transition 相关属性变化时才重新解析 + const prevStyle = lastTransitionStyleRef.current + const hasTransitionChanged = transitionKeys.some(key => prevStyle[key] !== originalStyle[key]) + const currentTransitionMap = hasTransitionChanged + // 从当前 style 解析最新 timing + ? parseTransitionStyle(originalStyle) + : transitionMapRef.current + if (hasTransitionChanged) { + lastTransitionStyleRef.current = { + transition: originalStyle.transition, + transitionDuration: originalStyle.transitionDuration, + transitionProperty: originalStyle.transitionProperty, + transitionTimingFunction: originalStyle.transitionTimingFunction, + transitionDelay: originalStyle.transitionDelay + } + transitionMapRef.current = currentTransitionMap + } createAnimation() }, [originalStyle]) // ** 清空动画