一、3D 开关首先是能力选择器“三维预览”开关不应只控制一个组件的显示与隐藏。开启后页面需要确认载体有可用模型、资源能加载、场景对象能创建、材质能绑定任一步失败都要回到用户能理解的状态。关闭后则应立即使用稳定的二维预览不能因为三维资源异常而阻断生成与导出主流程。页面因此维护两层选择外层use3DPreview决定使用三维还是二维渲染三维组件内部再用sceneMode区分自动场景和自定义场景。自动场景直接交给Component3D加载原始 GLB适合快速展示自定义场景显式创建相机、灯光和材质适合贴图与手势控制。模式场景来源交互能力失败后的去向二维预览Canvas/图片渲染稳定展示、可导出继续保留二维结果自动 3D原始 GLB 资源平台默认旋转缩放可切回二维或自定义自定义 3DScene.load()结果自定义相机、贴图、手势显示错误并提供重试二、页面分支必须由领域条件共同决定自定义照片载体没有固定 GLB不能因为开关为真就强行进入三维组件。渲染分支需要同时检查载体类型和开关状态让自定义载体走专用图片渲染固定载体才进入三维。if (isCustomCarrier(this.workshop.productId)) { CustomCarrierRenderer({ carrierImageUri: this.customCarrierUri, patternId: this.workshop.patternId, aiImageUrl: this.aiImageUrl }) } else if (this.workshop.use3DPreview) { Carrier3DViewer({ productId: this.workshop.productId, patternId: this.workshop.patternId, aiImageUrl: this.aiImageUrl }) } else { CanvasRenderer({ patternId: this.workshop.patternId, productId: this.workshop.productId, aiImageUrl: this.aiImageUrl }) }这种判断顺序避免“自定义照片 开启 3D”落入不存在资源的分支。组件 ID 仍由纹样和载体稳定 ID 组成导出服务不用理解当前是二维还是三维只消费页面已经确认的预览结果。三、自动场景和自定义场景必须使用不同生命周期自动场景只需把资源交给组件页面不持有Scene。切到自定义模式后才清理旧引用并异步加载随后创建SceneOptions。模式切换时主动释放引用防止旧相机和材质状态污染下一次加载。private toggleSceneMode(): void { if (this.sceneMode auto) { this.sceneMode custom this.loadCustomScene() return } this.sceneMode auto this.sceneRef null this.sceneOpt null this.cameraRef null this.textureApplied false } private loadCustomScene(): void { this.sceneRef null this.sceneOpt null this.cameraRef null this.textureApplied false this.loadScene() }状态清理必须发生在新请求开始前。如果先加载再清理异步回调可能把新Scene写入后又被旧逻辑置空表现为偶现黑屏。四、加载状态要覆盖所有退出路径三维加载最常见的问题不是抛错而是某条提前返回没有恢复loading。组件需要在未知载体、资源工厂为空、加载成功和 Promise 拒绝四条路径中都写入明确状态。private loadScene(): void { this.loading true this.errorMsg const product getProductById(this.productId) if (product undefined || product.glbPath.length 0) { this.loading false this.errorMsg 当前载体不支持三维预览 return } Scene.load($rawfile(product.glbPath)) .then(async (scene: Scene) { const factory scene.getResourceFactory() if (factory null) { this.loading false this.errorMsg 三维资源工厂不可用 return } await this.setupCustomScene(scene, factory) this.sceneRef scene this.sceneOpt { scene, modelType: ModelType.TEXTURE } this.loading false }) .catch((error: Error) { this.loading false this.errorMsg error.message }) }错误态应包含重试和切回二维两个动作。重试负责处理瞬时资源问题切回二维确保用户仍能完成业务。自动静默切换虽然更顺滑却会掩盖设备差异因此界面应保留“当前使用二维预览”的可见提示。五、自定义相机手势需要边界约束单指拖动映射为绕模型旋转双指缩放映射为相机距离。若不限制俯仰角和距离相机会进入模型内部、翻转到地面下方或者缩到浮点精度不稳定的范围。private updateOrbit(dx: number, dy: number): void { this.orbitAngleY dx * 0.01 this.orbitAngleX dy * 0.01 this.orbitAngleX Math.max( -Math.PI / 3, Math.min(Math.PI / 3, this.orbitAngleX) ) this.updateCameraPosition() } private updateZoom(scale: number): void { if (scale 0) { return } this.cameraDist this.cameraDist / scale this.cameraDist Math.max(1.5, Math.min(10, this.cameraDist)) this.updateCameraPosition() } private updateCameraPosition(): void { if (this.cameraRef null) return this.cameraRef.position { x: this.cameraDist * Math.sin(this.orbitAngleY) * Math.cos(this.orbitAngleX), y: this.cameraDist * Math.sin(this.orbitAngleX), z: this.cameraDist * Math.cos(this.orbitAngleY) * Math.cos(this.orbitAngleX) } }手势层只修改相机不重新加载模型。资源生命周期与交互状态分离后拖动和缩放不会触发昂贵的场景重建。六、运行证据要区分“容器出现”和“模型可用”灰色矩形出现只能证明Component3D占位布局已创建不能证明模型加载成功。有效证据至少包括模型轮廓真实可见自动/自定义模式标签正确拖动后观察角度变化双指缩放后距离受限切回二维后业务预览仍存在。Builder ViewerState() { if (this.loading) { LoadingProgress() } else if (this.errorMsg.length 0) { Column() { Text(this.errorMsg) Button(重新加载).onClick(() this.loadScene()) Button(使用二维预览).onClick(() this.onFallback()) } } else { this.ViewerContent() } }截图中的模型主体、模式按钮和“自动场景”状态共同构成运行证据。若只截取开关不足以判断三维内容是否真正渲染。七、失败语义和降级矩阵故障点三维组件状态页面动作业务是否可继续载体无 GLB明确提示不支持切到二维可以Scene.load失败保存错误文本重试或二维可以资源工厂为空停止加载切到二维可以材质绑定失败模型仍可见、贴图状态为否使用原材质可以相机创建失败自定义模式失败切回自动场景可以手势越界相机参数被钳制继续拖动可以设备不支持 3D开关回退并提示使用二维可以页面退出清理场景引用再进入重新加载可以降级的原则是“缩减表现能力不改变用户已经选择的纹样和载体”。切回二维时不应清空patternId、productId或生成图 URL否则一个渲染问题会扩大成业务数据丢失。八、验证步骤1. 固定载体开启三维预览确认真实模型出现而不是只有空容器。 2. 在自动场景和自定义场景之间往返两次确认没有旧模型叠加或黑屏。 3. 单指拖动到上下边界确认俯仰角停止在限制范围内双指缩放确认不会进入模型内部。 4. 注入不存在的载体 ID确认加载结束并显示“不支持”页面仍可切换二维。 5. 模拟 GLB 加载失败确认只影响预览不影响已选纹样、载体与导出格式。 6. 关闭三维开关后返回页面确认二维预览稳定出现再次开启时重新建立场景。 7. 在不具备三维能力的设备上确认降级提示真实可见且没有无限 Loading。九、总结三维预览的可靠性来自明确的能力边界页面先判断载体是否适配再由开关选择二维或三维三维内部把自动场景与自定义场景分开管理加载、相机、材质和错误各有独立状态。即使 GLB、资源工厂或设备能力失败业务仍能退回二维继续完成生成和导出。平台三维图形能力可参考ArkGraphics 3D 概述。