react-native-reanimated Layout Animations 入门:用 Entering/Exiting 动画让组件优雅地出现与消失
react-native-reanimated Layout Animations 入门用 Entering/Exiting 动画让组件优雅地出现与消失【免费下载链接】react-native-reanimatedReact Natives Animated library reimplemented项目地址: https://gitcode.com/GitHub_Trending/re/react-native-reanimated本篇指南以 react-native-reanimated 的 Layout Animations 为主题讲解如何为组件的挂载进入视图层级与卸载离开视图层级注入动画从预设动画的引入、挂载到entering/exiting属性再到通过duration、springify、withInitialValues等修饰符精细调参最后深入源码剖析其底层实现原理。读完你将能够直接在项目中复现官方案例代码并理解这些动画在 UI 线程上执行的工作机制。为什么需要 Layout Animations在 React Native 中每当你把组件加入组件树时它都会瞬间出现没有任何过渡过程——这并不符合真实世界的视觉直觉。同样当组件从视图层级中卸载时它会在下一帧直接消失显得生硬突兀。Layout Animations 正是为了解决这个问题而设计的它帮助你为任意视图的出现过程添加动画Entering Animations并为组件的消失过程添加优雅的退出动画Exiting Animations。在 react-native-reanimated 中该能力自 v2.3.0 起可用v2.x 时代的官方入门文档位于 docs/docs-reanimated/versioned_docs/version-2.x/fundamentals/layout_animations.md完整的 v2.x API 参考见 Entering Animations 与 Exiting Animations。三步使用预设 Entering / Exiting 动画使用预设动画非常简单官方文档给出了三步流程可同时套用于 entering 与 exiting 动画。第一步导入所选动画从react-native-reanimated导入动画构建器AnimationName只是一个占位符实际使用时应替换为具体动画名例如FadeIn、SlideOutLeftimport { FadeIn } from react-native-reanimated;第二步挂载到 Animated 组件上将动画传给 Animated 组件的entering出现时播放或exiting消失时播放属性。AnimatedComponent既可以是 Reanimated 导出的Animated.View等内置组件也可以是由createAnimatedComponent包装的自定义组件AnimatedComponent entering{FadeIn} exiting{FadeOut} ... /AnimatedComponent第三步链式调用修饰符定制动画不同类型的动画可定制的选项不同通过链式方法组合即可例如让FadeIn的时长变为 3 秒AnimatedComponent entering{FadeIn.duration(3000).delay(200)}一个完整的 Fade 示例出自 v4 文档 entering-exiting-animations.mdximport { FadeIn, FadeOut } from react-native-reanimated; function App() { return Animated.View entering{FadeIn} exiting{FadeOut} /; }预设动画全览Reanimated 内置了大量开箱即用的预设动画按视觉类型分组。以下是 v2.x 文档与当前源码中共同覆盖的动画族类型说明Entering 动画Exiting 动画Fade基于透明度变化FadeIn、FadeInRight、FadeInLeft、FadeInUp、FadeInDownFadeOut、FadeOutRight、FadeOutLeft、FadeOutUp、FadeOutDownBounce基于平滑弹跳BounceIn、BounceInRight、BounceInLeft、BounceInUp、BounceInDownBounceOut及同名方向变体Flip绕指定轴 3D 翻转FlipInYRight、FlipInYLeft、FlipInXUp、FlipInXDown、FlipInEasyX、FlipInEasyYFlipOutYRight等对称变体Stretch改变宽度/高度StretchInX、StretchInYStretchOutX、StretchOutYZoom改变缩放ZoomIn、ZoomInRotate、ZoomInRight、ZoomInLeft、ZoomInUp、ZoomInDown、ZoomInEasyUp、ZoomInEasyDownZoomOut及对称变体Slide水平/垂直移动SlideInRight、SlideInLeft、SlideInUp、SlideInDownSlideOutRight等对称变体LightSpeed水平移动 透明度 skewLightSpeedInRight、LightSpeedInLeftLightSpeedOutRight、LightSpeedOutLeftPinwheel旋转 缩放 透明度PinwheelInPinwheelOutRoll水平移动 旋转RollInLeft、RollInRightRollOutLeft、RollOutRightRotate绕角旋转RotateInDownLeft、RotateInDownRight、RotateInUpLeft、RotateInUpRightRotateOutDownLeft等对称变体当前版本中这些类在 defaultAnimations 目录下按类型拆分为Fade.ts、Bounce.ts、Flip.ts、Lightspeed.ts、Pinwheel.ts、Roll.ts、Rotate.ts、Slide.ts、Stretch.ts、Zoom.ts并通过 index.ts 统一导出。修饰符精细控制每个动画所有预设动画都继承自构建器基类支持链式修饰。v2.x 文档将其按三种形态组织时间型、弹簧型与通用型。时间型修饰符基于withTiming时间型修饰符依赖withTiming动画函数适合控制时长与缓动曲线FadeOutLeft.duration(500).easing(Easing.ease);.duration(durationMs)动画时长毫秒默认 300。.easing(easingFunction)定义动画曲线的缓动函数默认Easing.inOut(Easing.quad)。注意使用.springify()时时间型修饰符不再生效。弹簧型修饰符基于withSpring弹簧型修饰符依赖withSpring动画函数适合制作带回弹、过冲质感的动画FadeInUp.springify() .damping(30) .mass(5) .stiffness(10) .overshootClamping(false) .energyThreshold(6e-8);.springify()启用弹簧动画配置。.damping(value)决定弹簧停止的速度数值越大停得越快。.mass(value)弹簧的质量减小该值可让动画更快。.stiffness(value)决定弹簧的弹性/回弹程度。.overshootClamping(boolean)是否允许弹簧越过目标位置产生过冲。.energyThreshold(value)低于该相对能量阈值时弹簧直接归位、不再振荡。版本差异提示v2.x 文档记载的弹簧默认值为damping: 10、mass: 1、stiffness: 100、restDisplacementThreshold: 0.001、restSpeedThreshold: 0.001当前版本文档记载为damping: 120、mass: 4、stiffness: 900、energyThreshold: 6e-9。升级版本后请以所用版本的实际默认值为准。通用修饰符通用修饰符对时间型与弹簧型动画都适用FadeInDown.delay(500) .randomDelay() .reduceMotion(ReduceMotion.Never) .withInitialValues({ translateY: 420 }) .withTargetValues({ translateY: 0 }) .withCallback((finished) { console.log(finished without interruptions: ${finished}); });.delay(durationMs)动画开始前的延迟毫秒默认 0。.randomDelay()在 0 与所设 delay 之间随机化延迟未设 delay 时以 1000 ms 为上限。.reduceMotion(reduceMotion)决定动画如何响应设备的减弱动态效果无障碍设置。.withInitialValues(values)覆盖动画的初始值元素开始时的状态。.withTargetValues(values)覆盖动画的目标值元素最终到达的状态。.withCallback(callback)动画结束后触发回调finished为true表示未被打断地完成否则为false。源码剖析预设动画是如何工作的以 Fade.ts 中的FadeIn为例可以看到预设动画的本质每个动画类都继承自ComplexAnimationBuilder并实现IEntryExitAnimationBuilder接口通过build()方法返回一个worklet 函数该函数返回{ animations, initialValues, callback }结构build (): EntryExitAnimationFunction { const delayFunction this.getDelayFunction(); const [animation, config] this.getAnimationAndConfig(); // ... return () { worklet; return { animations: { opacity: delayFunction( delay, animation(targetValues?.opacity ?? 1, config) ), }, initialValues: { opacity: initialValues?.opacity ?? 0, }, callback, }; }; };关键点animations描述要动画化的属性此处opacity及其动画函数initialValues描述起始状态FadeIn从opacity: 0开始FadeOut从opacity: 1开始这与文档中的初始值表完全对应标有worklet的返回函数运行在UI 线程上保证动画的每一帧都由原生侧驱动不阻塞 JS 线程——这正是 Reanimated 布局动画流畅的原因。带位移的变体如FadeInRight则额外通过 utils.ts 中的pickTransformValues与animateTransformToValues两个辅助函数构造transform数组前者负责按扁平属性优先、transform元组次之、预设默认值兜底的优先级解析初始值后者为每个 transform 槽位绑定带延迟的动画函数。构建器基类修饰符的底层实现所有链式修饰符最终都在 BaseAnimationBuilder.ts 与 ComplexAnimationBuilder.ts 中实现。以 ComplexAnimationBuilder.ts 中的springify为例springify(duration?: number): this { this.durationV duration; this.type withSpring as AnimationFunction; return this; }可以看到springify()的本质只是把内部动画类型切换为withSpring而duration、delay等通用选项则存储在构建器实例的字段中如durationV、delayV由build()统一读取并注入最终生成的动画函数。这种静态方法创建实例 实例方法链式赋值 build 时统一编译的设计使得FadeIn.duration(300).delay(100)这类写法既能保持类型安全又能被 Babel 插件识别并序列化为 UI 线程可执行的工作单元。平台兼容性与使用注意事项在Web 平台上弹簧型动画.springify()相关选项尚未完整引入spring 参数目前主要适用于 iOS 与 Android。建议将布局动画构建器定义在组件外部或配合useMemo使用以保证最佳性能——因为每个entering{SomeAnimation}表达式都会创建新的构建器实例若在渲染函数体内直接书写组件每次重渲染都会重建动画配置。withInitialValues与withTargetValues是按预设类型化的每个预设只接受它实际动画化的属性例如FadeIn只接受opacity传入无关属性会触发类型错误。对于 transform 类动画当前版本更推荐使用扁平顶层属性如{ translateX: 50 }而非transform: [{ translateX: 50 }]元组形式元组形式仍可用但已标记为废弃自 4.4.0 起。在New Architecture新架构下nativeID会被内部用于配置进入动画若自行覆盖将导致 entering 动画不运行某些组件如TouchableWithoutFeedback会覆盖子元素的nativeID此时可用View包裹动画子元素规避移除非动画视图会触发其子元素的 exiting 动画但父视图不会等待子元素动画结束这是视图扁平化view flattening导致的行为可通过collapsable{false}缓解。进一步探索预设动画之外官方文档还提供了三个进阶方向Keyframe 动画将动画拆分为多个关键帧实现更复杂的时序控制详见 keyframe-animations.mdx自定义动画通过实现IEntryExitAnimationBuilder接口或直接编写 worklet 动画函数创造完全自定义的进入/退出效果详见 custom-animations.mdxLayout Transitions当组件自身尺寸或位置变化时播放过渡动画layout属性让布局变化也动起来详见 layout-transitions.mdx。源码层面所有预设与过渡动画统一位于 layoutReanimation 目录其中 animationsManager.native.ts 负责在原生侧调度动画的启动与回调SharedTransition.ts 则实现了跨页面共享元素过渡。结合这些源码阅读可以完整理解 Layout Animations 从 JS 配置到 UI 线程渲染的整条链路。【免费下载链接】react-native-reanimatedReact Natives Animated library reimplemented项目地址: https://gitcode.com/GitHub_Trending/re/react-native-reanimated创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考