指南 · 02
Web 与 React Native
两个平台用同一个 import。Metro 选择原生实现,Web 打包工具选择 DOM 实现。
同一个 import
安装一个包,在两个平台上都从它的根路径导入。唯一必需的 peer 依赖是 React;React Native 是原生应用的可选 peer 依赖。两个平台都不需要 Provider、包裹组件或初始化调用。
// Web and React Native: the same import.
import { MotionNumber, MotionList } from '@kkwaenggwari/animated-chorus';
export function Score({ points, players }) {
return (
<>
<MotionNumber value={points} />
<MotionList items={players} renderItem={(player) => player.name} />
</>
);
}动效如何播放
在 Web 上,组件以 Web Animations API 播放经解析采样的弹簧,因此无需加载动画库,也不会每帧触发 React 渲染。在 React Native 上,组件使用 Animated:transform 和 opacity 走原生驱动,只有布局(宽度或高度)变化时才用 JS 驱动。
| 部分 | Web | React Native |
|---|---|---|
| transform 和 opacity | Web Animations API | Animated,原生驱动 |
| 宽度和高度 | Web Animations API | Animated,JS 驱动 |
| 流式文本 | 字符淡入,每秒只有几次 React 渲染 | 真正的 Text,不淡入 |
| 底部面板与缩放 | 顶层的原生 dialog | 透明的 Modal |
| 后台 | 在隐藏的标签页中,流式文本会一次性显示 | 动效直接落到结束状态 |
React Native 的特别之处
API 相同;以下是你在设备上会注意到的差异。
- 数字和流式文本始终是真正的
Text,所以选择、换行、numberOfLines和无障碍功能都照常工作。 MotionSheet和MotionZoom渲染在透明的Modal中,返回键可将其关闭。- 面板内部的
ScrollView保留自己的手势;面板通过把手和静态区域拖动。 MotionHold通过无障碍的激活操作直接确认。- 行内的
MotionSwap按单行测量新内容;会换行的内容请使用inline=—。
import { Text, View } from 'react-native';
import { MotionNumber, MotionSheet } from '@kkwaenggwari/animated-chorus';
export function Wallet({ balance, open, setOpen }) {
return (
<View>
<MotionNumber
value={balance}
intl
locale="en-US"
format={{ style: 'currency', currency: 'USD' }}
/>
<MotionSheet open={open} onOpenChange={setOpen} detents={[0.5, 0.9]}>
<Text>Recent activity</Text>
</MotionSheet>
</View>
);
}布局始终归你所有
组件保持平台自身的布局:字体度量、换行、字体缩放、父元素约束以及你的样式。动效绝不会给你的文本强加固定字宽、固定文本高度或裁剪遮罩。
在哪里验证了什么
Web 行为在真实浏览器中验证。React Native 行为由共享模型的测试和模拟渲染器覆盖,所以发布前请在目标设备上检查手势和布局。