diff --git a/docs-vitepress/guide/rn/component.md b/docs-vitepress/guide/rn/component.md index bfe0fb3a56..19b30102a3 100644 --- a/docs-vitepress/guide/rn/component.md +++ b/docs-vitepress/guide/rn/component.md @@ -47,16 +47,16 @@ 视图容器。 属性 -| 属性名 | 类型 | 默认值 | 说明 | -| ----------------------- | ------- | ------------- | ---------------------------------------------------------- | -| hover-class | string | | 指定按下去的样式类。 | -| hover-start-time | number | `50` | 按住后多久出现点击态,单位毫秒| -| hover-stay-time | number | `400` | 手指松开后点击态保留时间,单位毫秒 | -| animation | object | | 传递动画的实例, 可配合mpx.createAnimation方法一起使用| -| enable-background | boolean | `false ` | RN环境特有属性,是否要开启background-image、background-size和background-position的相关计算或渲染,请根据实际情况开启 | -| enable-animation | boolean | `false` | RN环境特有属性,开启要开启动画渲染,请根据实际情况开启 | -| enable-fast-image | boolean | `false` | RN环境特有属性,开启后将使用 react-native-fast-image 进行图片渲染,请根据实际情况开启 | -| is-simple | - | - | RN环境特有标记,设置后将使用简单版本的 view 组件渲染,该组件不包含 css var、calc、ref 等拓展功能,但性能更优,请根据实际情况设置 | +| 属性名 | 类型 | 默认值 | 说明 | +| ----------------------- |---------|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------| +| hover-class | string | | 指定按下去的样式类。 | +| hover-start-time | number | `50` | 按住后多久出现点击态,单位毫秒 | +| hover-stay-time | number | `400` | 手指松开后点击态保留时间,单位毫秒 | +| animation | object | | 传递动画的实例, 可配合mpx.createAnimation方法一起使用 | +| enable-background | boolean | `false ` | RN环境特有属性,是否要开启background-image、background-size和background-position的相关计算或渲染,请根据实际情况开启 | +| enable-animation | boolean\|enum(`api`/`transition`) | 默认会根据 css 中的动画属性设置 enable-animation | 设置 api/transition 可指定使用 createAnimation API/transition 的动画形式,enable-animation 设置 true 默认为 createAnimation API 形式,需要注意的是指定动画类型后,对应的动画参数也需要匹配设置 | +| enable-fast-image | boolean | `false` | RN环境特有属性,开启后将使用 react-native-fast-image 进行图片渲染,请根据实际情况开启 | +| is-simple | - | - | RN环境特有标记,设置后将使用简单版本的 view 组件渲染,该组件不包含 css var、calc、ref 等拓展功能,但性能更优,请根据实际情况设置 | 事件 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..244ac56ae2 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/animationHooks/useTransitionHooks.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/animationHooks/useTransitionHooks.ts @@ -144,7 +144,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, @@ -157,17 +157,51 @@ function parseTransitionStyle (originalStyle: ExtendedViewStyle) { return transitionMap } +const transitionKeys = ['transition', 'transitionDuration', 'transitionTimingFunction', 'transitionDelay', 'transitionProperty'] as const + +function getTransitionPropertyKeys (map: TransitionMap): string { + return Object.keys(map).sort().join(',') +} + export default function useTransitionHooks (props: AnimationHooksPropsType) { // console.log(`useTransitionHooks, props=`, props) 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 中获取动画数据 + // transition 时序属性动态更新追踪 + const lastTransitionStyleRef = useRef>( + transitionKeys.reduce((acc, key) => { acc[key] = originalStyle[key]; return acc }, {} as Record) + ) + const prevTransitionMapRef = useRef(null) + // ** 从 style 中获取动画数据(支持动态更新 transitionDuration/transitionDelay/transitionTimingFunction) const transitionMap = useMemo(() => { - return parseTransitionStyle(originalStyle) - }, []) + const prevStyle = lastTransitionStyleRef.current + // 检测 transition 时序属性是否变化并更新 + let hasChanged = false + transitionKeys.forEach(key => { + if (prevStyle[key] !== originalStyle[key]) { + hasChanged = true + prevStyle[key] = originalStyle[key] + } + }) + // 时序属性未变化且非首次计算,跳过重新解析 + if (!hasChanged && prevTransitionMapRef.current) { + return prevTransitionMapRef.current + } + const newTransitionMap = parseTransitionStyle(originalStyle) + if (!prevTransitionMapRef.current) { + // 首次计算 + prevTransitionMapRef.current = newTransitionMap + return newTransitionMap + } + // 检测 transitionProperty 是否变化,变化时直接返回上一次的 transitionMap + if (getTransitionPropertyKeys(newTransitionMap) !== getTransitionPropertyKeys(prevTransitionMapRef.current)) { + error('[Mpx runtime error]: dynamic setting transitionProperty is not supported') + return prevTransitionMapRef.current + } + prevTransitionMapRef.current = newTransitionMap + return newTransitionMap + }, [originalStyle]) // ** style prop sharedValue interpolateOutput: SharedValue const { shareValMap, animatedKeys, animatedStyleKeys } = useMemo(() => { // 记录需要执行动画的 propName