从截图生成 React 组件
此应用使用 Grok API 将界面截图转成 React 组件,并让 Grok 对照原图检查生成结果。示例演示如何以高细节模式发送图片,获取结构化的代码输出,直接预览而无需构建。
提供一张界面截图,应用便会编写可复现该界面的 React 组件。网页实时展示 Grok 的推理和正在生成的代码,然后将组件与原图并排显示。第二轮中,页面会对组件截图,让 Grok 与原图比较并修正不一致之处。
你将学到
以高细节模式将图片发送给 Grok
以结构化输出获取代码,省去从响应中剥离 Markdown 的步骤,并实时显示流式传入的代码
无需构建即可预览生成的组件
在一个请求中发送多张图像,包括能向 Grok 显示组件偏差位置的叠加图
降低推理强度,将单轮耗时从数分钟缩短至数十秒
向 Node 服务器上传文件,并通过服务器发送事件将进度实时传回网页
运行示例
需要 Node.js 22.13 或更高版本。将 API 密钥放在 .env(仓库根目录),或导出环境变量 XAI_API_KEY。
cd examples/screenshot-to-component/typescript
npm install
npm run web打开 http://localhost:3000,拖入、粘贴或打开一张截图并点击 Make component,也可以点击 Try the sample。页面的使用方式与设计稿转代码工具相似:截图和组件并排显示,代码实时写入下方编辑器,右侧逐轮列出分数和 Grok 修正的差异。第二轮会自动开始。切换至 Outlines 可查看用于比较的轮廓图,点击 Compare again 可再进行一轮。一次运行约需一两分钟。预览通过 CDN 加载 React、Babel、Tailwind 和 html-to-image,因此需要连接互联网。
在终端生成组件时,传入截图即可:
npm start -- ./your-screenshot.png未提供参数时使用 sample-screenshot.png,即一张价格页面截图。组件保存至 output/<Name>.tsx。在浏览器中打开 output/preview.html 即可与原图比较。终端版在第一轮结束后停止,因为后续轮次需要浏览器对组件截图。
工作原理
共享代码位于 src/component.ts:
writeComponent()发送截图,设置detail: "high",并要求grok-4.7生成一个使用 Tailwind 类的 TSX 文件,按照给定规则精确匹配颜色、尺寸和文字。它以流式方式接收响应,实时报告 Grok 的推理、组件名称和代码。响应遵循包含组件名称和代码的 JSON Schema,因此代码会作为普通字符串返回。流式输出过程中,
json事件会向writeComponent()提供截至当前的 JSON,其中尚未完成的代码字符串会临时闭合,以便边生成边展示。Schema 中的pattern将名称限制为字母和数字,因为它会用作文件名。componentPage()会生成 HTML 页面,在浏览器中用 Babel 编译并渲染组件,通过 CDN 加载 React 和 Tailwind。refineComponent()负责后续轮次:发送原图、同尺寸的组件截图、两者的叠加图及代码,要求 Grok 先列出要修正的差异,再返回修正后的文件。叠加图用蓝色描出原图边缘、红色描出组件边缘,帮助 Grok 直接定位偏差。仅用两张独立图片时,Grok 容易误判尺寸和位置,在默认推理强度下可能观察数分钟。有了叠加图,低强度推理即可,每轮约 30 秒。如果组件页面比截图高,请求还会指出相差多少像素。页面过高会妨碍内容正确居中,使布局整体偏移,而 Grok 仅凭图片无法判断页面是否滚动。
src/server.ts 为页面运行 writeComponent() 和 refineComponent()。EventSource 只能发送 GET 请求,因此页面先将截图上传到 /api/screenshots,再打开 /api/component 并使用返回的 ID,随后以服务器发送事件接收每一步进度。后续轮次以同样方式通过 /api/refinements 和 /api/refinement 进行。页面关闭时,服务器会停止请求。
public/index.html 使用原生 HTML 和 JavaScript 展示这些事件,并在沙盒 iframe 中渲染最终组件。iframe 的实际尺寸与截图相同,再缩小显示在原图旁边,以保持相同的换行效果。iframe 内不滚动,显示范围就是比较区域。注入 iframe 的脚本使用 html-to-image 截取组件画面,并将截图和组件页面高度发回。页面描出两张图的轮廓以生成叠加图并评分:某一轮廓离另一张图中最近的轮廓越远,得分就越低。应用保留得分最高的组件,退回效果变差的改动,下一轮仍从最佳版本开始。
src/index.ts 在终端执行第一轮并写入 preview.html,其中使用相同的缩放 iframe。