ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

React 360 分层包架构全解析:从 webgl-lite 到 react-360 的 monorepo 设计

React 360 分层包架构全解析:从 webgl-lite 到 react-360 的 monorepo 设计 前端3D渲染【免费下载链接】react-360Create amazing 360 and VR content using React项目地址https://gitcode.com/gh_mirrors/re/react-360点击查看免费下载React 360 并非一个单一的大库而是由一系列职责单一的 npm 包逐层叠加而成的360 沉浸式环境。本文以仓库 packages/README.md 为核心骨架深入拆解这套分层架构底层webgl-lite负责原始 WebGL 资源管理webgl-ui提供WebGL 世界的 DOMreact-webgl注入真正的 React 绑定最终由react-360收束到全景环境、空间表面与 VR 头显。读完本文你将掌握每个包的边界与依赖关系、它们如何协同完成一次界面渲染到 3D 空间的完整链路以及基于 Lerna 的构建、版本管理与发布流程。一、设计哲学单一职责的分层组合packages/README.md开篇就点明了核心设计思想React 360 由一系列分层叠加的包组成每个包只提供一项单一功能让开发者可以按需挑选所需部分而不是被迫引入整个框架。这套分层可以概括为一条清晰的渲染流水线webgl-liteWebGL 原始资源管理 ↓ webgl-ui2D 界面原语View / Text / Image Flexbox ↓ react-webglReact 组件化绑定渲染到 Canvas 或纹理 ↓ react-360放入 360 全景 / VR 空间绑定表面、音视频、头显仓库根目录的 package.json 印证了这一组合方式根工程本身是private: true的容器通过 Yarn workspaces 声明workspaces: [packages/*]而根脚本build: lerna run build一次性串联所有子包的构建。二、Lerna Monorepo一个脚本管理 16 个包packages/README.md明确指出该目录是一个Lerna monorepo目的是用单个脚本管理许多包。仓库中的 lerna.json 给出了具体配置{ packages: [packages/*], npmClient: yarn, useWorkspaces: true, version: 0.2.0 }packages: [packages/*]monorepo 管理的范围是packages目录下的所有子目录npmClient: yarn配合根package.json的workspaces字段统一由 Yarn 管理依赖安装useWorkspaces: true复用 Yarn workspaces 做依赖提升hoisting子包之间的本地依赖例如webgl-ui依赖webgl-lite ~0.3.0可以在仓库内直接解析。从packages目录实际内容看monorepo 共包含 16 个子包webgl-lite、webgl-ui、react-webgl、react-360、react-360-controls、react-360-native-compat、react-360-surfaces、react-webgl-video-manager、animated-react-webgl、vr-audio、vr-input-source、vr-state、webgl-ui-sdf-font、webgl-ui-system-font、webgl-lite-gltf、ref-count-cache、transition-value。它们可以归为四层渲染基础设施、2D 界面层、React 绑定层、3D/VR 支撑层。三、第一层webgl-lite —— 轻量 WebGL 资源管理packages/README.md对webgl-lite的定位是实现渲染 2D UI 元素和基础 3D 场景所需的底层 WebGL 操作刻意保持轻量并针对界面绘制库的使用场景优化。packages/webgl-lite/README.md 给出了更精确的边界WebGL Lite 实现了对 WebGL 底层与高层 API 的便捷封装。它让构造 shader program、将 program 与一组 attribute/uniform 关联、把多个元素合并为一次渲染变得容易并在渲染时自动绑定纹理、在支持时自动使用 WebGL 2.0 shader、为整个场景设置默认 uniform。同时它明确声明webgl-lite 本身不是完整的 3D 渲染环境——它不实现任何原语也没有场景图而是为 2D/3D 库提供组合更大 WebGL 场景的钩子。这种克制正是它能被其他 WebGL 项目轻松集成的关键由于几乎不往 WebGL 原语上叠加额外逻辑webgl-lite渲染的内容可以无缝嵌入其他渲染管线。包入口 packages/webgl-lite/index.js 直接导出编译后的dist/WebGL其 package.json 描述为 Basic resource management for WebGL and WebGL2构建脚本用 Babel babel/plugin-transform-flow-strip-types将 Flow 类型源码转译为纯 JS。其src目录下的Program、ProgramManager、Texture、VertexBuffer、IndexBuffer、Geometry、RenderGroup、FrameBuffer等模块正是这套资源管理的具体实现。四、第二层webgl-ui —— WebGL 世界的 DOMpackages/README.md将webgl-ui形容为可灵活设置样式的 2D 界面原语就像 WebGL 里的 DOM。在一个webgl-uisurface 内你可以构造矩形、文本、图片用 CSS 风格的属性为其设置样式并通过 Flexbox 布局组合它们。4.1 Surface布局与绘制的核心载体packages/webgl-ui/README.md 详细说明了Surface的职责它像一个画布/文档组织 UI 元素树负责调整 Flexbox 布局、重算几何、调整元素渲染顺序并处理事件。渲染前必须设置视口大小例如要填充一块 400×600 的纹理import {Surface} from webgl-ui; const canvas document.getElementById(canvas); const gl canvas.getContext(webgl); const surface new Surface(gl); surface.setViewport(400, 600);Surface 只有一个根节点通过createView()setRootNode()挂载 UI 树并在帧循环中持续更新与绘制const root surface.createView(); surface.setRootNode(root); function frame() { surface.updateGeometry(); // 重算脏的 Flexbox 布局尺寸变化节点重建几何 if (surface.isDirty()) { // 仅脏时才重绘避免过度绘制 surface.clear(); surface.draw(); } } requestAnimationFrame(frame);4.2 三个核心原语View / Text / ImageView绘制矩形支持全部 Flexbox 布局属性外观由背景色、边框、圆角配置Text渲染字符串。构造前需在 Surface 上设置TextImplementation文本通过追加一个或多个createTextNode()生成的 RawText 节点组合从而可以只更新变化的子串而无需重建整段文本import {Surface, SDFTextImplementation} from webgl-ui; const surface new Surface(gl); surface.useTextImplementation(new SDFTextImplementation(gl)); const text surface.createText(); const labelText surface.createTextNode(Count: ); const countText surface.createTextNode(5); text.appendChild(labelText); text.appendChild(countText);Image在 View 的基础上增加纹理显示能力。构造前需在 Surface 上设置TextureManager负责纹理加载去重两个 Image 引用同一资源不会重复加载。Image 的尺寸必须显式设置因为像 HTML 的 img 那样等加载完成后自动撑开会触发内容回流import {Surface, TextureManager, setStyle} from webgl-ui; const surface new Surface(gl); surface.useTextureManager(new TextureManager(gl)); const image surface.createImage(); image.setSource({uri: http://example.net/image_3.jpg}); setStyle(image, {width: 350, height: 200});Image 支持cover、contain、center、stretch默认四种 resizeMode。此外TextureManager允许注册自定义协议默认内置的texture://协议可以把任意本地 Image/Canvas 元素作为纹理源const myCanvas document.getElementById(myCanvas); const manager new TextureManager(); manager.registerLocalTextureSource(myTex, myCanvas); image.setSource({uri: texture://myTex});4.3 样式系统与事件模型样式通过__setStyle__foo(value)风格的方法设置该命名刻意独特以避免与其他成员方法冲突并提供了批量设置工具setStyle(view, {...})。事件方面Surface 通过跟踪光标位置可来自鼠标、触摸屏或 3D 场景的光线投射计算命中集setCursor/clearCursor维护光标dispatchEvent把事件分发给命中集中的元素canvas.addEventListener(mousemove, e surface.setCursor(e.offsetX, e.offsetY)); canvas.addEventListener(mouseexit, () surface.clearCursor()); canvas.addEventListener(click, e { surface.dispatchEvent(click, {x: e.offsetX, y: e.offsetY}); });元素用addEventListener(event, callback)注册回调。特别地enter和exit是内建的特殊事件当元素进入/离开命中集时自动触发非常适合实现 hover 高亮效果view.addEventListener(enter, () setStyle(view, {borderColor: rgba(255, 255, 255, 1)})); view.addEventListener(exit, () setStyle(view, {borderColor: rgba(255, 255, 255, 0.5)}));4.4 绘制到纹理Surface 的draw()会以当前 GL 上下文设置运行 shader。要绘制到绑定了 framebuffer 的 GL 纹理只需在调用前绑定 framebuffer、结束后解绑gl.bindFramebuffer(gl.FRAMEBUFFER, fb); surface.draw(); gl.bindFramebuffer(gl.FRAMEBUFFER, null);这正是把 2D 界面嵌入 3D 场景的基础机制——webgl-ui的 package.json 声明依赖webgl-lite ~0.3.0说明其几何与渲染底层完全建立在 webgl-lite 之上。五、第三层react-webgl —— 真正的 React 绑定packages/README.md指出react-webgl为webgl-ui提供真正的 React 绑定允许用 React 在 WebGL 中构建 UI渲染到任意 Canvas 或纹理并负责事件收集还包含绘制到 canvas 或 framebuffer 的便捷封装动画能力可通过animated-react-webgl引入。packages/react-webgl/README.md 透露其实现本质这是一个实验性的、同步的 React-to-WebGL renderer直接工作于 React Reconciler依赖react-reconciler 0.20.4见 package.json充分利用 React 16 的可复用架构组件可直接挂接到渲染流程中。5.1 三个核心组件与 React Native 的 Primitives 几乎一致react-webgl提供View、Text、Image三个组件import {View} from react-webgl; const RedSquare () ( View style{{width: 100, height: 100, backgroundColor: #ff0000}} / );import {Text} from react-webgl; const LargeWhiteCenteredText ({label}) ( Text style{{fontSize: 40, color: #ffffff, textAlign: center}} {label} /Text );Image通过内容根的 TextureManager不仅可以显示静态图片还能把视频、其他 Canvas 甚至 3D 场景投影到图像上配合react-webgl-video-manager可用Image播放视频import {Image} from react-webgl; const RoundProfilePicture ({imagePath}) ( Image style{{ backgroundColor: #000000, borderColor: #ffffff, borderWidth: 2, borderRadius: 40, height: 80, width: 80, resizeMode: cover, source: {uri: imagePath}, }} / );5.2 两种渲染目标CanvasRoot2D内联渲染 2D 界面到浏览器 Canvas与其他 DOM 组件共存import * as ReactWGL from react-webgl; const root new ReactWGL.CanvasRoot({width: 300, height: 300}); ReactWGL.render(CanvasDemo /, root); document.body.appendChild(root.getCanvas()); function frame() { root.update(); requestAnimationFrame(frame); } requestAnimationFrame(frame);RenderTargetRoot纹理渲染到可作纹理的 render target适合存在于 3D/VR 中的界面。每帧调用root.update()后通过root.getFrameBuffer().getTexture().getGLTexture()取得原始 WebGL 纹理引用交由 3D 场景使用。六、3D 与 VR 支撑包把界面放进空间6.1 react-360-surfaces空间中的平面与圆柱表面该包提供构建和操作位于 3D 空间中的 2D 表面的代码包括平面与圆柱面用于把 React WebGL 界面放进 3D/VR 应用同时包含可显示 180°/360° 等距柱状equirectangular照片与视频的环境球逻辑用于创建 VR 场景的沉浸背景README。其实现亮点在于平面/圆柱表面的光标命中采用基于三角函数的交点计算而非传统几何求交在移动芯片上更快并为未来 WebXR 特性渲染后期再绘制表面以获得更高分辨率预留了空间。src下的computeFlatIntersection.js、computeCylinderIntersection.js、generateFlatSurface.js、generateCylinderSurface.js、generateEnvironmentSphere.js正是这些能力的实现。6.2 react-360-controls无头显时的相机控制该包在无 VR 头显时更新 3D 场景渲染所用的相机参数README。相机控制每帧被查询一次可更新相机位置XYZ 向量与朝向旋转四元数。控制项实现为有序队列每帧系统遍历队列直到遇到一个更新相机的控制其余控制被忽略——这使得鼠标拖拽、设备方向等多个输入源可以级联用户正在操作哪个就用哪个。包内MousePanCameraController、ScrollPanCameraController、DeviceOrientationCameraController等实现了移动端/触摸屏/桌面端的基础移动同时它也与输入光标紧密相关包含鼠标与触摸屏的光线投射实现。6.3 vr-audioWeb Audio 位置音频README 说明它用 Web Audio API 模拟位置音频positional audio根据用户头部的位置与旋转让声音听起来来自现实 3D 空间中的某个点——配合 VR 头显时声音会先到达一只耳朵再到达另一只随用户转头或移动而变化。src下的VRAudio.js、AudioManager.js、AudioInstance.js、AudioNode.js实现了这一空间音频链路。6.4 vr-input-source位置追踪游戏手柄README 描述其职责追踪所有报告物理位置的游戏手柄暴露类似 WebXRXRInputSource的 API。由于 Web Gamepad API 依赖轮询而非事件该包每帧检查手柄状态并触发selectstart/selectend/select主按钮类似 mousedown/mouseup/click、pressstart/pressend/press任意按钮、touchstart/touchend电容按钮等事件在多手柄如 Oculus Touch 双手柄同时使用时追踪最近使用的一个作为光标控制设备。已知手柄的主/副按钮映射表在WellKnownGamepads.js中维护未识别的手柄默认所有按钮都算主按钮以面向未来新硬件。6.5 vr-state 与 ref-count-cachevr-state 集中追踪 WebVR displays监听连接与激活、在进入/退出 VR 时触发逻辑、干净地关闭已断开的显示设备。ref-count-cache 则提供引用计数缓存用于管理纹理等需要按引用数释放的资源。七、生态扩展包动画、视频与字体animated-react-webgl为 React WebGL 提供独立版 React NativeAnimated的绑定README对应packages/README.md提到的动画支持react-webgl-video-manager集中式视频管理器挂在webgl-ui的TextureManager上通过自定义的video://协议让 Image 组件播放视频README。用法是先建单例VideoManager再创建具名 playerimport {VideoManager, BrowserVideoImplementation} from react-webgl-video-manager; const textureManager root.getTextureManager(); const videos new VideoManager(textureManager); const player videos.createPlayer(birds-footage); player.setSource(https://example.net/birds.webm); player.play(); // 组件侧引用 image source{{uri: video://birds-footage}} width{320} height{180} /webgl-ui-sdf-font/webgl-ui-system-font两类文本实现。SDF有符号距离场字体任意尺寸渲染边缘平滑但需要预先计算的特殊字体文件、增加包体积README系统字体实现则从系统字体生成字形纹理构造时只需传入 WebGL 上下文READMEimport {FontImplementation} from webgl-ui-system-font; import {Surface} from webgl-ui; const surface new Surface(gl); surface.useTextImplementation(new FontImplementation(gl));react-360-native-compat旧版 React 360 构建在 React Native 之上引入 React Fiber 后可以构建更干净、更快的自定义 renderer 集成代码全部运行在主线程但为兼容旧代码仍实现了 Native Modules 等旧式 APIREADMEwebgl-lite-gltf在 webgl-lite 之上加载并渲染 glTF 2.0 模型的配套包transition-value为过渡动画提供数值插值能力的工具包。八、顶层收束react-360 包packages/README.md对react-360的定位是把 React WebGL 的界面构建能力带入 360 环境——可以把 React WebGL 组件绘制到 3D 空间的表面上、显示全景环境、播放音视频、配合 VR 头显工作目录中的大多数包都是为了支撑它而存在。其 package.jsonnpm 名react-360-next版本 0.3.0描述为 Experimental new version of React 360展示了它的聚合本质依赖react-360-controls、react-360-surfaces、react-webgl、react-webgl-video-manager、vr-audio、vr-input-source、vr-state、webgl-lite、webgl-ui等全部核心包均为~0.3.0。src下的React360.js、Container.js、Overlay.js、Glyphs.js、WebVRCameraController.js构成上层应用框架controller子目录则是相机与输入整合层。九、构建与发布Flow 类型提取与独立版本号packages/README.md的Building and Publishing Packages一节详细给出了发布流程这是 monorepo 运维的关键实操1. 构建提取 Flow 类型大多数包在发布前需要构建——本质是提取其 Flow 类型以便被不使用 Flow 的项目导入。构建全部包只需lerna run build任何带build脚本的包都会生成一个包含构建产物的目录各包package.json的files字段指向dist/用户在 npm 拉取包时引用的正是这些产物。从各包构建脚本看实际是调用 Babel 将src转译到dist并用babel/plugin-transform-flow-strip-types剥离 Flow 类型、--ignore src/**/__tests__/*.js跳过测试文件react-webgl与react-360额外使用babel/preset-react处理 JSX。2. 独立版本管理项目不依赖 Lerna 为所有包统一发号每个包允许有独立版本号以便按需发布补丁与热修复。流程为有改动的包可用lerna changed查看需更新其package.json的 version 字段并提交回仓库版本更新后在各包目录内执行npm publish完成发布。这与lerna.json中version: 0.2.0看似矛盾实则一致Lerna 的version仅在固定fixed模式下统一发号而该仓库采用独立independent模式实践——实际各包版本已出现分化如webgl-lite、webgl-ui、react-webgl、react-360-next均为 0.3.0并保持~0.3.0的互依范围。十、总结一条可裁剪的渲染链路React 360 的包架构给出了一条可裁剪的完整渲染链路webgl-lite管好 WebGL 资源webgl-ui提供界面原语与 Flexbox 布局react-webgl带来 React 声明式开发体验react-360-surfaces/react-360-controls把界面与相机放进 3D 空间vr-audio/vr-input-source/vr-state补齐沉浸式感官输入最终由react-360聚合为开箱即用的 360/VR 开发环境。由于每层都保持单一职责开发者可以只取所需——例如在普通 WebGL 项目中直接使用webgl-lite渲染内容或用webgl-ui构建无 React 依赖的 2D 界面再或用react-webgl享受 React 的组件化开发。理解这套分层是深入阅读 packages 下任意子包源码、乃至自行扩展渲染能力的最佳起点。赞分享前端3D渲染【免费下载链接】react-360Create amazing 360 and VR content using React项目地址https://gitcode.com/gh_mirrors/re/react-360点击查看免费下载相关推荐ESLint v4.0.0 迁移指南从升级破坏性变更到自定义规则与集成 API 适配ESLint v4.0.0 迁移指南从升级破坏性变更到自定义规则与集成 API 适配 本指南围绕 ESLint v4.0.0本仓库第四个主版本的官方迁移文前端3D渲染React 360 原生兼容层react-360-native-compat深入解析从 React Native 时代迁移到 React WebGLReact 360 原生兼容层react 360 native compat深入解析从 React Native 时代迁移到 React WebGL 导读前端3D渲染React 360源码解析核心渲染流程与架构设计React 360源码解析核心渲染流程与架构设计 React 360作为Facebook推出的VR内容开发框架其核心渲染流程融合了React组件化思想与We前端3D渲染上一篇探索开放配置接口gNMI下一篇如何快速掌握Neo4j图数据库全栈开发者的终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表