Angular 14集成Three.js遇阻,求GLB/OBJ模型加载解决方案
Angular 14 集成 @angular-three 加载GLB模型失败排查与解决
问题概述
用Angular CLI开发Web应用,想通过Three.js做产品交互效果,但Angular 14里死活搞不定@angular-three集成:
- GLB/OBJ格式模型加载不进场景
- 弹出Angular TypeScript错误
- 已经用
ng add @angular-three/core装了依赖,同样代码在Angular 13里能正常跑
用户提供代码
组件类代码
/* I used the three Library by installing the dependencies using ng add @angular-three/core */ // And I included everything even with the new way of including a file but still the same result, nothing. Plus errors from angular typescript. import { NgtSobaOrbitControls } from '@angular-three/soba/controls'; import { NgtGLTFLoaderService } from '@angular-three/soba/loaders'; import { Component, Input, OnInit } from '@angular/core'; import { MeshStandardMaterial, Object3D, Mesh, PerspectiveCamera } from 'three'; @Component({ selector: 'app-product-preview', templateUrl: './three.component.html', styleUrls: ['./three.component.scss'] }) export class ThreeComponent implements OnInit { @Input() set color(value: string) { this.#color = value; this.applyColorToMaterial(value); } #color = ''; cupMaterial: MeshStandardMaterial | undefined; constructor(private gltfLoaderService: NgtGLTFLoaderService) {} cup$ = this.gltfLoaderService.load('assets/toyota.glb'); cupLoaded(object: Object3D) { this.cupMaterial = <MeshStandardMaterial>(<Mesh>object.getObjectByName('Object_2')).material; this.applyColorToMaterial(this.#color); } ngOnInit() { } controlsReady(controls: NgtSobaOrbitControls) { const orbitControls = controls.controls; orbitControls.enableZoom = false; // orbitControls.autoRotate = true; // orbitControls.autoRotateSpeed = 10; const camera = orbitControls.object as PerspectiveCamera; camera.zoom = 10.5; camera.position.setY(2); camera.position.setX(30); } applyColorToMaterial(color: string) { if (this.cupMaterial) { this.cupMaterial.color.setHex(parseInt(color.substring(1), 16)); } } }
冲突的HTML脚本
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
问题排查与解决步骤
1. 删掉冲突脚本
上面的AngularJS 1.7.5脚本和Angular 14完全不兼容,直接删掉这行,不然会导致框架冲突,啥都跑不起来。
2. 对齐@angular-three版本
Angular 14必须用对应v14版本的@angular-three包,版本不匹配是常见坑,重新安装:
# 先卸载现有依赖 npm uninstall @angular-three/core @angular-three/soba # 装Angular14适配版本 npm install @angular-three/core@14 @angular-three/soba@14 three @types/three
3. 补全组件模板
@angular-three靠模板渲染场景、相机这些核心元素,你没给模板代码肯定显示不了,给你适配的three.component.html示例:
<ngt-canvas [camera]="{ position: [0, 2, 30], zoom: 10.5 }"> <ngt-scene> <!-- 环境光,没光模型会黑 --> <ngt-ambient-light [intensity]="0.5"></ngt-ambient-light> <ngt-directional-light [position]="[5, 5, 5]" [intensity]="1"></ngt-directional-light> <!-- 加载GLB模型,用async管道订阅Observable --> <ngt-mesh *ngIf="cup$ | async as cup" (ready)="cupLoaded(cup.scene)"> <ngt-primitive [object]="cup.scene"></ngt-primitive> </ngt-mesh> <!-- 轨道控制器 --> <ngt-soba-orbit-controls (ready)="controlsReady($event)"></ngt-soba-orbit-controls> </ngt-scene> </ngt-canvas>
4. 修复类型安全问题
原代码里直接断言对象存在,容易触发TypeScript错误,改一下cupLoaded方法:
cupLoaded(object: Object3D) { const targetMesh = object.getObjectByName('Object_2') as Mesh | undefined; if (targetMesh && targetMesh.material instanceof MeshStandardMaterial) { this.cupMaterial = targetMesh.material; this.applyColorToMaterial(this.#color); } else { console.error('找不到目标网格,或者材质类型不对'); } }
5. 检查资产配置
确保src/assets/toyota.glb文件存在,并且angular.json里配置了资产目录:
{ "projects": { "你的项目名": { "architect": { "build": { "options": { "assets": [ "src/favicon.ico", "src/assets" ] } } } } } }
6. 模块导入要全
在组件所属的NgModule里导入@angular-three相关模块:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ThreeComponent } from './three.component'; import { NgtCoreModule } from '@angular-three/core'; import { NgtSobaControlsModule } from '@angular-three/soba/controls'; import { NgtSobaLoadersModule } from '@angular-three/soba/loaders'; @NgModule({ declarations: [ThreeComponent], imports: [ CommonModule, NgtCoreModule, NgtSobaControlsModule, NgtSobaLoadersModule ], exports: [ThreeComponent] }) export class ThreeModule { }
验证
重启开发服务器ng serve,打开浏览器看控制台有没有错误,检查模型是否渲染、颜色修改功能是否正常。
内容的提问来源于stack exchange,提问作者pandit mckenzie
相关产品推荐
相关产品推荐

