Angular-CLI& ThreeJS

时间:2016-10-26 22:44:23

标签: angular three.js angular-cli

我一直在尝试添加正确的npm依赖项来将THREE添加到我的Angular-CLI项目中。随着CLI在过去几个月里变化如此之快,我找不到工作来源。

以下是一些想法......

  • 带脚本的Piggyback

    这是我的第一次尝试,只需将<script src="three.js"></script>添加到index.html文件即可。但是我在打字稿界面中使用javascript时遇到了麻烦。

  • 的WebPack

    这是我的第二次尝试,但我遇到了几个文档问题。 Angular-cli似乎没有使用webpacks的一致方法。实现webpack有四种不同的方法。我无法与三人合作。

  • 捆绑

    这似乎是一个黑客,一个穷人/冗长的人。将捆绑包添加到THREE库中,以便可以将其解释为角度2。

我目前仍在制作Angluar-CLI + THREE.js项目。如果我在下周没有看到进展,我可能会放弃角度cli。任何建议/来源将不胜感激。

1 个答案:

答案 0 :(得分:23)

从angular-cli 1.0.0开始:

  1. npm install three --save
  2. npm install @types/three
  3. 在AppComponent.html中添加div元素:<div #rendererContainer></div>
  4. 在AppComponent.ts中导入three.js:import * as THREE from 'three';
  5. 使用@ViewChild('rendererContainer') rendererContainer: ElementRef;
  6. 获取div元素的句柄
  7. 在构造函数/生命周期方法中进行必要的设置。注意:ViewChild之后才能使用ngAfterViewInit
  8. 完整AppComponent:

    import {Component, ViewChild, ElementRef} from '@angular/core';
    import * as THREE from 'three';
    
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    })
    export class AppComponent {
        @ViewChild('rendererContainer') rendererContainer: ElementRef;
    
        renderer = new THREE.WebGLRenderer();
        scene = null;
        camera = null;
        mesh = null;
    
        constructor() {
            this.scene = new THREE.Scene();
    
            this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
            this.camera.position.z = 1000;
    
            const geometry = new THREE.BoxGeometry(200, 200, 200);
            const material = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
            this.mesh = new THREE.Mesh(geometry, material);
    
            this.scene.add(this.mesh);
        }
    
        ngAfterViewInit() {
            this.renderer.setSize(window.innerWidth, window.innerHeight);
            this.rendererContainer.nativeElement.appendChild(this.renderer.domElement);
            this.animate();
        }
    
        animate() {
            window.requestAnimationFrame(() => this.animate());
            this.mesh.rotation.x += 0.01;
            this.mesh.rotation.y += 0.02;
            this.renderer.render(this.scene, this.camera);
        }
    }
    

    完整AppComponent.html:

    <div #rendererContainer></div>
    

    如果您想使用其他一些脚本:

    您可能最终想要使用一些其他脚本,例如加载器和控件。其中大部分都没有作为模块编写,而是在加载时在THREE上添加window命名空间的功能。因此,我最终通过将以下内容添加到我的.angular-cli.json文件中来告诉angular-cli手动加载我的脚本:

    {
      "apps": [
        {
          "scripts": [
            "../node_modules/tween.js/src/Tween.js",
            "../node_modules/three/build/three.js",
            "../node_modules/stats.js/build/stats.min.js",
            "../vendor/VRMLLoader.js",
            "../vendor/OrbitControls.js"
          ],
          ...
    

    请注意,您还需要处理这样的事实:您的three.js @types文件没有为这些附加脚本定义任何类型。理想情况下,我想扩展现有的类型定义,但暂时我只是通过在我使用three.js的文件顶部添加declare const THREE: any来提示三个错误来解决错误。如果您找到了一种从@types/three扩展现有定义的好方法,请报告回来!

    要处理调整窗口大小:

    虽然我在这里,但我还会提到调整window的大小可能会导致raycasting(我用它来决定是否点击某个对象)不再正常工作。要解决这个问题,请执行以下操作:

    @HostListener('window:resize', ['$event'])
    onWindowResize(event) {
        this.renderer.setSize(event.target.innerWidth, event.target.innerHeight)
    }