
图形学移动开发跨平台UI组件【免费下载链接】react-native-skiaHigh-performance React Native Graphics using Skia项目地址https://gitcode.com/gh_mirrors/re/react-native-skia点击查看免费下载react-native-skiashopify/react-native-skia除了绘制 Skia 图形还提供了一项少见的原生能力——对任意 React Native 原生视图“截图”。本文围绕官方文档 snapshot-views.md 展开讲清makeImageFromView的用法、collapsable{false}这一关键注意事项并沿 JS 封装层、JSI 宿主函数 到 Android/iOS 截图服务 逐层拆解底层实现帮助你把“把 RN View 变成可再次绘制的 SkImage”这一能力真正用到项目中例如做入场动画、分享卡片、离屏合成。makeImageFromView从一个 ref 到一张 SkImagemakeImageFromView接受一个指向原生视图的 ref返回一个 Promise成功后 resolve 为SkImage实例。也就是说快照结果不是 PNG 字节或ImageSource而是一个可以直接参与 Skia 绘制的图像对象——你可以把它交给Image组件、ImageShader、RuntimeShader等任何接受SkImage的 API 继续做混合、滤镜或着色器处理。从 Image.ts 的源码可以看到它的完整签名export const makeImageFromView T extends | number | React.Componentunknown, unknown | React.ComponentClassunknown | null, ( viewRef: React.RefObjectT, callback: | null | ((viewRef: React.RefObjectT) PromiseSkImage | null) null ) { ... };两个参数viewRef要快照的视图 ref。在原生平台上内部通过Platform.findNodeHandle(viewRef.current)解析出 React 的 view tag再调用Skia.Image.MakeImageFromViewTag(viewTag)交给原生层截图callbackWeb 平台必需。Web 实现会把工作完全委托给这个回调由调用方自己实现“从 ref 生成 SkImage”的逻辑如果 Web 上不提供 callback函数会 reject 并提示 “Callback is required on web in the makeImageFromView function.”。因此原生平台上你可以忽略该参数Web 平台则必须自行兜底。官方示例点击按钮为 View 拍照以下是官方文档中的完整示例可直接复制运行import { useState, useRef } from react; import { View, Text, PixelRatio, StyleSheet, Pressable } from react-native; import type { SkImage } from shopify/react-native-skia; import { makeImageFromView, Canvas, Image } from shopify/react-native-skia; const pd PixelRatio.get(); const Demo () { // 为要快照的视图创建 ref const ref useRefView(null); // 用 state 保存快照结果 const [image, setImage] useStateSkImage | null(null); const onPress async () { // 对视图进行快照 const snapshot await makeImageFromView(ref); setImage(snapshot); }; return ( View style{{ flex: 1 }} Pressable onPress{onPress} View ref{ref} // 这里是关键collapsable{false} collapsable{false} style{{ backgroundColor: cyan, flex: 1 }} TextThis is a React Native View/Text /View /Pressable { image ( Canvas style{StyleSheet.absoluteFill} Image image{image} x{0} y{0} width{image.width() / pd} height{image.height() / pd} / /Canvas ) } /View ) };这个示例包含三个必须注意的实战细节collapsable{false}不能省。文档明确警告React Native 会把没有子节点交互、被认为“可折叠”的空 View 直接优化掉不创建对应原生节点。一旦根视图被优化移除makeImageFromView会崩溃或返回错误结果。所以被快照视图的根部应显式设置collapsable{false}。SkImage的尺寸是物理像素。快照得到的SkImage分辨率为视图的物理像素尺寸width × 屏幕密度。用Image组件按逻辑点渲染时需要除以PixelRatio.get()示例中image.width() / pd就是这么处理的如果忘了缩放图片会放大pd倍。结果是异步的。截图发生在平台主线程Promise 可能跨越一帧甚至更久才 resolve建议在await期间避免移动/卸载被快照的视图。JSI 层MakeImageFromViewTag 的 Promise 链路原生端入口是 JsiSkImageFactory.h 中注册为 JS 宿主方法的MakeImageFromViewTagJSI_HOST_FUNCTION(MakeImageFromViewTag) { auto viewTag arguments[0].asNumber(); auto context getContext(); return RNJsi::JsiPromises::createPromiseAsJSIValue( runtime, context std::move(context), viewTag - void { context-makeViewScreenshot( viewTag, runtime, context std::move(context), promise std::move(promise) { context-runOnJavascriptThread([runtime, ...]() { if (result nullptr) { promise-reject(Failed to create image from view tag); return; } promise-resolve(...); }); }); }); }这段代码揭示了失败语义截图回调如果带回nullptr视图不存在、尺寸为 0 等Promise 会以 “Failed to create image from view tag” reject。这也与 JS 层的 “Invalid view tag” reject 形成两层防护。makeViewScreenshot的默认实现在 RNSkPlatformContext.h它在主线程上执行takeScreenshotFromViewTag(viewTag)完成后通过回调把sk_spSkImage传回再切回 JS 线程 resolve Promise。因此该 API 只能在视图已挂载并布局完成宽高 0后调用否则会拿到 null。Android 实现ViewScreenshotService 递归重绘视图树Android 侧的实际工作由 ViewScreenshotService.java 完成PlatformContext.java 只是把 viewTag 转发进来。读这个文件能看到不少“截图保真”的工程细节入口makeViewScreenshotFromTag通过UIManagerHelper.getUIManagerForReactTaguiManager.resolveView(tag)找到 View视图解析失败或宽高 ≤ 0 时直接返回 null对应上文的 Promise reject。位图格式以视图宽高创建ARGB_8888位图画布先translate(-view.getLeft(), -view.getTop())再递归绘制Paint 开启抗锯齿、滤镜与抖动createPaint()。递归渲染renderViewToCanvas逐层应用view.getMatrix()与位置/内边距/滚动偏移变换applyTransformations并按父级透明度 × 当前 alpha累积透明度绘制保证带opacity的视图树截图结果与原样一致。ScrollView 视口裁剪对ScrollView/HorizontalScrollView显式clipRect到scrollX/scrollY 宽高防止超大子视图例如宽大的 SkiaCanvasTextureView在截图中溢出视口。overflow 裁剪复刻因为不会调用dispatchDraw()TextureView/SurfaceView 需要特殊处理手动遍历子视图代码显式复刻了ReactViewGroup.dispatchDraw()中overflow: hidden的裁剪逻辑BackgroundStyleApplicator.clipToPaddingBox。TextureView用getBitmap(...)取出其纹理内容后drawBitmap。SurfaceViewAndroid N 以上使用PixelCopy.request带 5 秒超时失败时回退到 drawing cache。这些细节决定了“哪些内容能被截到”普通 RN 视图树、背景、变换、透明度基本都保真而独立 SurfaceSurfaceView依赖 PixelCopy 结果若被系统占用可能超时回退。Apple 实现ViewScreenshotServiceApple 端同样有一个独立服务接口见 ViewScreenshotService.hinterface ViewScreenshotService : NSObject { } - (instancetype)initWithUiManager:(RCTUIManager *)uiManager; - (sk_spSkImage)screenshotOfViewWithTag:(NSNumber *)viewTag; end它持有RCTUIManager并按 view tag 生成sk_spSkImage与 Android 一样属于平台各自的takeScreenshotFromViewTag实现macOS 分支通过 AppKit 导入头文件。具体绘制逻辑在对应的.mm实现中从源码结构看其流程与 Android 版本一一对应按 tag 解析视图、离屏渲染、转换为 SkImage。进阶玩法把快照丢进 RuntimeShader仓库自带的 Snapshot 示例 展示了快照图像的二次利用先await makeImageFromView(viewRef)得到SkImage再传入Skia.RuntimeEffect.Make创建的运行时着色器作为uniform shader image实现正弦波纹扭曲的“拍照变形”效果const source Skia.RuntimeEffect.Make( uniform shader image; uniform float r; half4 main(float2 xy) { xy.x sin(xy.y / r) * 4; return image.eval(xy).rgba; })!;同一文件中也可以看到collapsable{false}在真实项目里的用法View ref{viewRef} ... collapsable{false}快照结果被存入 reanimated 的useSharedValue里驱动动画。这说明快照不仅用于静态展示也是做“截图 → 动画过渡 → 回到真实视图”这类无闪屏过渡的常用手段。测试入口可在 Tests.tsx 中找到对应的引用示例路由入口为 API/Snapshot.tsx。适用前提与常见失败点小结场景结果依据视图被 RN 折叠优化掉未设collapsable{false}崩溃或错误结果官方文档警告Web 平台未提供 callbackreject“Callback is required on web...”Image.tsref 解析不出合法 view tagreject“Invalid view tag”Image.ts视图宽高为 0 或解析失败Promise reject“Failed to create image from view tag”JsiSkImageFactory.h、ViewScreenshotService.javaSurfaceView 像素拷贝超时5s回退 drawing cache可能拿到旧帧ViewScreenshotService.java总结一下makeImageFromView的使用成本极低——一个 ref 加一句await得到的SkImage可以无缝进入 Skia 的整套绘制体系工程上需要记住的只有三件事根部视图加collapsable{false}、渲染时按PixelRatio缩放、Web 平台必须自行提供 callback。结合源码可以确认这条 API 在 Android/iOS 上都是“主线程离屏重绘视图树 → 转 SkImage → 回 JS 线程 resolve”的可靠链路且对变换、透明度、滚动裁剪、TextureView/SurfaceView 都做了专门处理是 react-native-skia 把原生视图与 Skia 图形世界打通的关键桥梁。赞分享图形学移动开发跨平台UI组件【免费下载链接】react-native-skiaHigh-performance React Native Graphics using Skia项目地址https://gitcode.com/gh_mirrors/re/react-native-skia点击查看免费下载相关推荐MARL-code-pytorch进阶如何修改代码支持自定义多智能体环境MARL code pytorch进阶如何修改代码支持自定义多智能体环境 MARL code pytorch是一个简洁的PyTorch实现的多智能体强化学习人工智能强化学习为什么选择AI-ModelScope/vit-base-patch16-224对比CNN模型的5大优势为什么选择AI ModelScope/vit base patch16 224对比CNN模型的5大优势 在计算机视觉领域传统的卷积神经网络CNN长期以来TiXL 快照控制视图Snapshot Control View完全指南参数级快照捕获、控制器索引网格与 Section 分组实战TiXL 快照控制视图Snapshot Control View完全指南参数级快照捕获、控制器索引网格与 Section 分组实战 快照Snapshot音视频图形学桌面应用上一篇react-native-router-flux 测试覆盖率报告趋势与改进下一篇RAWGraphs-app设计决策案例从用户研究到界面实现记录创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考