You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Solito+Next.js,React Native Web布局过渡实现方案(无Reanimated)

实现Solito+Next.js三端共享中Reanimated布局动画的Web端兼容方案

问题背景

我用Solito+Next.js做三端代码共享,目前Reanimated的Layout Animations API不支持Web(对应Git issue #2993),CSS transition无法实现布局过渡效果,手动逐处适配成本太高。Native端用Reanimated Layout Animations运行正常,但Web端完全没动画效果,现有代码片段如下:

import Animated, { Layout, Easing} from 'react-native-reanimated'
...

<AnimatedSolitoImage
  className="transition-all duration-1000"
  src={logo}
  alt="Logo"
  height={60}
  width={130}
  layout={Layout.easing(Easing.ease)
    .duration(duration * 0.8)
    .delay(duration * 0.2)}
/>

可行实现思路

1. 跨平台组件封装(最直接落地方案)

封装统一的布局动画组件,根据平台自动切换底层实现:

  • Native端:继续使用Reanimated的Animated组件+layout属性
  • Web端:替换为Framer Motion的motion组件+layout属性,同时将Reanimated的动画配置(easing、duration、delay)映射为Framer Motion的对应参数

示例代码:

import { Platform } from 'react-native';
import Animated, { Layout, Easing } from 'react-native-reanimated';
import { motion } from 'framer-motion';
import SolitoImage from 'solito/image';

const AnimatedLayoutImage = (props) => {
  const { layout, className, ...restProps } = props;
  
  if (Platform.OS === 'web') {
    // 将Reanimated的Layout配置转换为Framer Motion的过渡参数
    const framerTransition = {
      type: 'tween',
      ease: layout?._easing || 'easeInOut',
      duration: layout?._duration || 300,
      delay: layout?._delay || 0,
    };
    
    return (
      <motion(SolitoImage)
        className={className}
        layout
        layoutTransition={framerTransition}
        {...restProps}
      />
    );
  }
  
  return (
    <Animated(SolitoImage)
      className={className}
      layout={layout}
      {...restProps}
    />
  );
};

// 使用时直接替换原组件
<AnimatedLayoutImage
  className="transition-all duration-1000"
  src={logo}
  alt="Logo"
  height={60}
  width={130}
  layout={Layout.easing(Easing.ease)
    .duration(duration * 0.8)
    .delay(duration * 0.2)}
/>

2. Babel插件自动转换(无侵入式适配)

开发自定义Babel插件,在编译阶段自动将Reanimated的layout相关代码转换为Web端的Framer Motion代码:

  • 识别代码中Animated.Xxx组件的layout属性,替换为motion(Xxx)的layout配置
  • 解析Layout.easing(...).duration(...)链式调用,转换为Framer Motion的layoutTransition对象
  • 优点:业务代码完全无需修改,编译后自动适配Web端

3. CSS变量+Intersection Observer模拟布局过渡(轻量替代方案)

如果不想引入Framer Motion,可以用原生API模拟简单的布局动画:

  • 给目标元素添加ref,用Intersection Observer监听元素位置变化
  • 计算元素前后位置的偏移量,通过CSS变量动态设置transform: translate()
  • 配合CSS transition实现平滑过渡,适合简单布局变化场景

示例代码思路:

import { useEffect, useRef, useState } from 'react';
import SolitoImage from 'solito/image';

const LayoutAnimatedImage = (props) => {
  const ref = useRef(null);
  const [prevPos, setPrevPos] = useState({ x: 0, y: 0 });
  
  useEffect(() => {
    const updatePosition = () => {
      if (!ref.current) return;
      const { left, top } = ref.current.getBoundingClientRect();
      setPrevPos(prev => ({ x: left - prev.x, y: top - prev.y }));
    };
    
    updatePosition();
    window.addEventListener('resize', updatePosition);
    return () => window.removeEventListener('resize', updatePosition);
  }, []);
  
  return (
    <SolitoImage
      ref={ref}
      className="transition-transform duration-800 delay-200"
      style={{
        transform: `translate(${prevPos.x}px, ${prevPos.y}px)`
      }}
      {...props}
    />
  );
};

4. React Native Web动画适配层(底层透明适配)

扩展React Native Web的Animated组件,为layout属性添加polyfill:

  • 在Web端重写Animated组件的渲染逻辑,内部使用Framer Motion处理布局动画
  • 上层业务代码完全复用Reanimated的API,无需修改
  • 优点:对业务层完全透明,适配成本极低,但需要深入React Native Web源码逻辑

内容的提问来源于stack exchange,提问作者COC Hindi by sourabh soni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 23:25:24