三方模型同 prompt 构建 Robinhood 克隆 App(含 Skia 动画),对比生成质量与保真度,GPT-5.6 和 Claude Fable 5 在复杂动画场景下表现更稳定。
原文首次发布于 Motionary 博客。
一条提示词,一段参考视频,三个模型。我们让 GPT-5.6 Sol High、Claude Fable 5 和 Kimi K3 High 用 React Native 和 Expo 构建一个 Robinhood 克隆版,使用 Reanimated、Gesture Handler 和 Skia,逐帧匹配动效。然后我们手动构建了同样的三个屏幕,作为可以真实对比的基准。
这个问题在我们的私信里不断出现,通常以某种版本的形式出现——"我能不能就让 AI 来做?"这是一个合理的问题,值得一个真实的答案而不是凭感觉的判断,所以我们用三款当前的主流旗舰产品正经地跑了一把:ChatGPT 中的 GPT-5.6 Sol High、Claude Fable 5 和 Kimi K3 High。相同的提示词、相同的参考视频、相同的起点、相同的设备,没有人出问题的时候去救场。
需求文档:用 React Native 和 Expo 重建 Robinhood 的三个屏幕。Discover(发现)页面、一个带有可拖动 Skia 图表的代币详情页面(含价格和 Buy 揭示),以及 Swap 金额键盘页面,金额数字逐位动画。足够小到一条提示词就可以公平对待,又足够依赖动效以至于不能用布局来糊弄。关键在于,需求追求的是动效保真度而非功能——匹配真实应用的重力、时序、手势响应、触觉反馈和排版(数字应该逐位动画)。
以下就是三个模型被要求逐帧匹配的视频。所有内容都以此为基准衡量。
一条提示词。没有追问,没有"其实修复一下……",没有把它拉回正轨。
三者共用同一个空白项目:全新的 Expo 应用、TypeScript、除了模板外没有预装任何依赖。
相同的参考视频附在提示词里,所以没有人需要猜测 Robinhood 长什么样。
必须在真机上运行。只能编译通过但无法运行的代码算失败。
计时从发送提示词开始,到应用首次无红框渲染出屏幕时停止。
Token 数量和成本是整个运行的总计,含思考过程。
确切版本号以确保可复现:GPT-5.6 Sol High、Claude Fable 5 和 Kimi K3 High,均在同一天运行。
三者完全相同,冷启动粘贴,视频附在提示词中:
Recreate the Robinhood app screens shown in the attached video as a React Native
(Expo) app. Build three screens: Discover, Token detail (scrubbable chart with
price + Buy reveal), and the Swap/amount keypad screen.
Priority is fidelity of motion and feel, not features — match the real app's
easing, timing, gesture response, haptics, and typography (numbers should
animate digit-by-digit). Use Reanimated + Gesture Handler, and Skia for the
chart. Mock all data locally; no backend.
Watch the video closely and match what you see frame for frame. Tell me which
interactions you couldn't reproduce and why.
ChatGPT(GPT-5.6 Sol High)—— 获胜者
GPT-5.6 Sol High 做得最接近。三个屏幕都在,且能被识别为 Robinhood:Discover 列表、带可实际拖动的 Skia 图表的代币详情,以及 Swap 键盘。它把动效需求当作动效需求来理解,这正是所问的,而且用不到亚军一半的时间和约 75% 的成本完成了。
逐帧回放中,价格跳动器的数字变化是最大的破绽:它逐位滚动,和参考应用一样的里程表式运动,而不是简单的交叉淡入。代币详情图表和 Swap 键盘的布局都与参考足够接近,以至于并排看起来是同一屏幕。它与其他两者共同的问题是下面的缺陷:价格跳动器和图表通过 React state 重绘而非 UI 线程的 worklet,所以本应即时响应手指的操作会承受 JS 线程的税赋,而参考应用从不如此。
先别急着鼓掌。冠军和失败者有着同样的缺陷,而且对于一个动效需求,这是唯一无法一笔带过的缺陷。证据在后面。
Claude(Fable 5)—— 亚军
Claude Fable 5 排名第二,为此付出了最多的努力。它一条提示词写了 +2,780 行代码然后删除了 197 行,63 分钟中花了 57 分钟真正在调用 API,缓存命中率达到 99%。输出是三者中最完整、结构最清晰的。也是最贵的,$19.32,而且耗时大约是 GPT-5.6 Sol High 的两倍,最终到达的位置差不多。
额外的努力是可见的,不只是推测出来的:代币详情屏幕是三者中功能最完善的,市场数据和交易量数据都整洁地呈现出来了。但它在这个过程中偏离了需求——参考全程使用 Solana,详情屏幕捕获的却是 Bitcoin。把图表切换到 5 年期会抛出一个现场的屏幕级 React 错误:Maximum update depth exceeded,这是 setState 循环嵌套在 useEffect 内部的典型标志,在演示中途出现。在 Swap 键盘上,数字输入也没有干净的滚动:画面中显示重叠、残影的数字,而非干净的过渡,动画比 GPT-5.6 Sol 的更粗糙。
Kimi(K3 High)—— 最便宜,而且看得出来
Kimi K3 High 排名最后,差距不小。它的构建没有任何一部分匹配视频。屏幕存在,应用能启动(修复一次后),但几乎没有任何布局、间距、排版或动效与给出的参考相似。最明显的破绽在上面的片段中:Swap 屏幕的本职工作是一个数字键盘,数字却散落在网格之外。
它确实是最便宜的,大约是其他两者成本的十分之一,但便宜到此就不再是优点了。一次必须推倒重来的构建不是省钱,只有当尝试成功了,成本才有意义。
键盘散落之外还有两个失误:Swap 屏幕添加了预设的快捷金额标签($10 / $50 / $100),而参考中根本不存在这些;在捕获的画面中,金额显示为 $0 而手指已经按下了 1——点击没有与其他两个构建那样与触摸同步响应。
现在看证据。烧掉的 Token、花掉的美元,以及每个模型到达一个可运行屏幕所花的时间。
每次运行的总计,含思考过程。时间更短和成本更低并不能说明结果是否更好——看上方的三个片段。
成本计算方式:Token 定价按百万计且分输入输出方向,所以单一的"成本"始终是估算,而且展示计算过程才是公平的。GPT-5.6 Sol 输入每百万 $5,输出每百万 $30。我们的运行烧掉了两百万 Token。全作输入是 $10,全作输出是 $60,按实际的 90/10 比例分配是 1.8M × $5 + 0.2M × $30 ≈ $15,还不含任何工具调用费用。Claude Fable 5 不需要估算:会话自行报告了总计 $19.32,这就是表格中的数字。同一个面板报告了分钟数、代码行变更数和 99% 的缓存命中率,但没有 Token 数量,所以 Claude 的 Token 栏是破折号而非猜测。Kimi K3 High 是弱项:我们没有它的 Token 报告,所以它的行是基于 Kimi 公布的每百万费率用一次规模相近的运行估算的。
三者共同犯的错误
三个模型都产出了能跑的东西,也都产出了卡顿的东西。不是轻微的卡顿。是三次同样的失败,来自三个不同的模型:React state 过多,变化过于频繁。每次交互都触发一次新的 setState,每次 setState 都重渲染一棵树,JavaScript 线程从未获得过一个安静的帧。结果是在应用只是在移动一张卡片这种简单操作时,JS 端出现丢帧。
为什么 JS 线程是问题暴露的地方
React Native 在一个线程上运行 JavaScript,在另一个线程上合成 UI。这种分离是动画在这个平台上有自己规则的根本原因。留在 UI 线程的工作即使 JavaScript 忙碌时也能保持 60fps 绘制,而每一帧都需要 JavaScript 参与的工作则取决于队列中排着什么。一个 React state 更新,本质上就是 JavaScript 工作。用一个 state 更新来驱动动画,就等于让应用中最繁忙的线程每秒钟 60 次去命中 16ms 预算,同时它还在协调、diff 和运行各种 effects。拖动时打开 Expo 性能监控:UI FPS 保持在 60 附近,而 JS FPS 则一落千丈。那个差距就是 bug,这是 React Native 动画感觉不对时最值得看的东西。
它们写的代码,以及应该写的代码
下面的模式是每个运行中都出现的形态。它也是完全符合习惯的 React 代码,这正是大语言模型会写成这样的原因。
// 三个模型都写成这样:每个手势帧都触发一次 React 渲染。
const [offset, setOffset] = useState(0);
const pan = Gesture.Pan().onUpdate((e) => {
setOffset(e.translationY); // JS 线程,大约每秒 60 次
});
return <View style={{ transform: [{ translateY: offset }] }} />;
// 实际能保持 60fps 的写法:值从不进入 React。
const offset = useSharedValue(0);
```js
const pan = Gesture.Pan().onUpdate((e) => {
'worklet';
offset.value = e.translationY; // UI thread, no re-render
});
const style = useAnimatedStyle(() => ({
transform: [{ translateY: offset.value }],
}));
return <Animated.View style={style} />;
第二个版本只渲染一次。值存在于共享值中,手势处理程序是在 UI 线程上运行的工作程序,useAnimatedStyle 在 React 毫不知情的情况下应用它。视觉效果相同,没有任何额外开销。规则简单到可以装进脑子里:如果一个数字在某个东西移动时发生变化,它就不应该出现在 useState 中。
值得明确说清楚:这不是在贬低这些模型。三款模型都在半小时内写出了比大多数人在第一个月写的更正确的 React Native 代码,它们生成的代码是优秀 React 开发者会写的代码。这才是真正的问题:惯用写法和高性能写法在这里是不同的答案,源代码中没有任何内容告诉你你拿到的是哪一个。掉帧在 diff 中是看不见的。只有把手机拿在手里才能发现。
然后我们自己动手了
同一个应用,用我们构建每个交互动画的方式构建:手动,在真机上调试,直到弹簧不再和你较劲。手势附近没有任何 React 状态,每个动画值都在 Reanimated 共享值中,图表用 Skia,触觉反馈在它们所属的那一帧上。
Motionary — 推荐
逐帧对比,这是四个方案中唯一一个在价格滚动和交换键盘上与参考实现匹配且没有可见瑕疵的:没有重影数字,没有屏幕错误,没有输入卡住。键盘逐键镜像参考实现,包括相同的 1–9、小数点、0、退格顺序,而 Kimi 的构建重新排列了这些键位,Claude 的构建压缩了它们。这才是 Reanimated 共享值相对于通过 React 状态驱动的动画真正买到的差异:同样的交互体验,没有任何东西能在镜头下露馅。
这个演示是 Motionary 四十五秒的完整卖点:你可以真正买到的动画 React Native 组件,每一个都是用 Reanimated、Gesture Handler 和 Skia 手工构建的,并以你拥有、可阅读、可重新样式化、可拆解的源代码形式交付。可以把它想象成 React Native 版的 shadcn,只不过这些组件是会动的。
四款放在一起比较
同样的三个衡量维度,把手工构建版本也放入表中。成本列故意不是同类对比。三款模型的运行是按次计费的:一张屏幕十五到二十美元,下一张屏幕又要收费,每一次运行需要第二次或第三次尝试都要再收费。最后一行是一次付费获取 50+ 个动画,已经构建好、已经调好,当你需要下一个时不会重新开始计时。
成本是三款模型各跑一次对阵最后一行一次付费、永久使用的对比。时间是指到一张能在设备上运行的屏幕。
所以你应该用哪个?
从这个证据来看,React Native UI 工作中最好的 AI 是 GPT-5.6 Sol High。它把一个动效简报当作动效简报来读,最接近参考实现,而且用最少的时间和最少的钱做到了。Claude Fable 5 在你需要数量和结构、且不介意为此付出一小时的情况下值得使用:保真度第二,彻底程度第一。Kimi K3 High 以任何价格来推荐做这类工作都很勉强,因为当几乎没有任何东西能匹配时,价格不是问题。
更大的发现是没有任何一款逃脱了同一个问题。三款都很擅长前百分之九十,但都因为同一个原因交付了卡顿的屏幕:惯用的 React 答案和 60fps 的 React Native 答案是不同的答案。模型可以读遍有史以来写的每一篇 Reanimated 文档,但仍然感受不到一次掉帧。最后那一步——把手机拿在手里直到动画停止说谎——才是我们卖的东西。这也正是模型目前还做不到的唯一一部分。
一次付费,不是按屏幕付费
上面的每次运行都是用真金白银买一张屏幕,动画还要修复。这三个 Robinhood 屏幕都是交互动画,目录里还有 50+ 个:用 Skia 构建的可拖动图表、底部弹窗、键盘、走马灯、整屏,每一帧都在真机上手工构建直到保持 60fps。一次付费拿走全部,算下来大约每个动画一块五,而且当你需要下一个时价格不会变动。
获取终身通行证 · 浏览全部动画
你用了每款模型的付费层吗? 是的,这里没有任何东西是在免费层上跑的。GPT-5.6 Sol High 在付费 ChatGPT 计划内运行,Claude Fable 5 通过 Claude Code 运行,后者按 token 计费并自己报出了 19.32 美元,Kimi K3 High 按其公布的每百万 token 费率运行。表中的成本是运行消耗的费用,不是订阅费用。
一个更好的提示词能修复它吗? 部分可以,这样说也是公平的。如果你已经知道失败模式,你就可以把修复方案写到简报里:永远不要用 React 状态驱动动画,把手势值保存在 Reanimated 共享值中,在 UI 线程的工作程序中做动画。像这样的提示词可能会让三款都避免卡顿版本。问题是谁能写出它。你必须在问问题之前就知道答案,因为输出中没有任何东西警告你模型选择了慢的惯用语;代码看起来完全一样。这正是第二部分测试的内容:同样的简报,允许跟进提问,性能监控器开着,需要多少次尝试就尝试多少次直到达到 60fps。有趣的问题不是谁在冷启动时获胜,而是谁可以被引导。
为什么 AI 生成的动画会卡顿? 因为它用 React 状态驱动了动画。每一帧手势都调用 setState,每次调用都重新渲染,JavaScript 线程预算耗尽,所以 JS 帧率崩溃,而 UI 线程闲置。把动画值移到 Reanimated 共享值中并用 useAnimatedStyle 应用,让工作在 UI 线程上进行,卡顿就消失了。三款模型都犯了这个错误。
你日常用哪款模型? 主要是 Claude,在 Claude Code 里用,因为日常工作是在现有代码库上编辑而不是一次性搞定一个全新的项目,这是它最强的地方。对于在一个全新 UI 上的冷启动,这个测试说是 GPT-5.6 Sol。它们都做不到的是交付一个交互动画:目录中的每个动画在上架之前仍然需要在真机上编写、运行和调优。
ChatGPT 能构建 React Native 应用吗? 能,而且在这个测试中它是三款中最擅长此事的。GPT-5.6 Sol High 在 32 分钟内把一个提示词变成了一个可运行的 Expo 三屏 Robinhood 克隆,包括一个可拖动的 Skia 图表。它做不到的是让动画流畅:与 Claude 和 Kimi 一样,它用 React 状态驱动动画,所以构建在手势被改写成 Reanimated 工作程序之前都是卡顿的。AI 能给你一张能用的屏幕;它目前还不能给你一张感觉对的屏幕。
我可以购买 React Native 动画组件而不是生成它们吗? 能。Motionary 正是如此:高级、生产就绪的动画 React Native 组件,每一个都是用 Reanimated、Gesture Handler 和 Skia 手工构建的,在真机上调优,并以你拥有源代码的形式交付。你可以单独购买一个动画,也可以获取终身通行证,这是一次付费拿走整个目录,包括这三个 Robinhood 屏幕,以及之后上架的所有内容。
这是第一部分。一个提示词,一次尝试,没有跟进提问,这是测试的最严苛版本,不是任何人实际工作的方式。第二部分让同样的三款模型在同样的简报下放开手脚:允许跟进提示词,性能监控器开着,需要多少次尝试就尝试多少次直到达到 60fps。有趣的问题不是谁在冷启动时获胜,而是谁可以被引导。
如果你想让三款模型在下一场对决中争夺某个特定应用,在 X 上告诉我们,我们会把它放进擂台。 🐦⬛