【问题标题】:ThreeJS / Angular - "scene is undefined"ThreeJS / Angular - “场景未定义”
【发布时间】:2019-01-16 23:14:50
【问题描述】:

我刚刚发现 ThreeJS,我正在尝试使用 ThreeJS 的 OBJLoader 加载一个 .obj 文件。

很遗憾,我遇到了一个错误

无法读取未定义的属性“场景”

此错误在this.scene.add( object ); 行产生

这是我的完整组件:

import { Component, OnInit } from '@angular/core';
import * as THREE from 'three';
import * as OBJLoader from 'three-obj-loader';
OBJLoader(THREE);



@Component({
  selector: 'app-items-catalog',
  templateUrl: './items-catalog.component.html',
  styleUrls: ['./items-catalog.component.css']
})
export class ItemsCatalogComponent implements OnInit {

  constructor() { 

  }

  private canEleId = 'renderCanvas';


  ngOnInit() {
    this.createScene(this.canEleId);
    this.animate();
  }

  canvas: HTMLCanvasElement;
  private renderer: THREE.WebGLRenderer;
  private camera: THREE.PerspectiveCamera;
  private scene: THREE.Scene =  new THREE.Scene();
  private light: THREE.AmbientLight;

  private cube: THREE.Mesh;


  createScene(elementId: string): void {
    //var scene = new THREE.Scene();
    // The first step is to get the reference of the canvas element from our HTML document
    this.canvas = <HTMLCanvasElement>document.getElementById(elementId);

    this.renderer = new THREE.WebGLRenderer({
      canvas: this.canvas,
      alpha: true,    // transparent background
      antialias: true // smooth edges
    });
    this.renderer.setSize(window.innerWidth, window.innerHeight);

    // create the scene


    this.camera = new THREE.PerspectiveCamera(
      75, window.innerWidth / window.innerHeight, 0.1, 1000
    );
    this.camera.position.z = 5;
    this.scene.add(this.camera);

    // soft white light
    this.light = new THREE.AmbientLight( 0x404040 );
    this.light.position.z = 10;
    this.scene.add(this.light);

    let geometry = new THREE.BoxGeometry(1, 1, 1);
    let material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    this.cube = new THREE.Mesh( geometry, material );
    //this.scene.add(this.cube);


/* HERE IS THE PART WHERE THE PROBLEM IS */ 
-----------------------------------------------------------------



    const objLoader = new THREE.OBJLoader();
    objLoader.setPath('../../assets/icon/threed/')
   // objLoader
  // var loader = new THREE.OBJLoader();

    objLoader.load(
      // resource URL
      'helicopter.obj',
      // called when resource is loaded
      function ( object ) {
        console.log(object);
        object.position.y -= 60;

       this.scene.add( object );

      },
      // called when loading is in progresses
      function ( xhr ) {

        console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

      },
      // called when loading has errors
      function ( error ) {

        console.log( 'An error happened' );

      }
    );
---------------------------------------------------------------

  }

  animate(): void {
    window.addEventListener('DOMContentLoaded', () => {
      this.render();
    });

    window.addEventListener('resize', () => {
      this.resize();
    });
  }

  render() {
    requestAnimationFrame(() => {
      this.render();
    });

    this.cube.rotation.x += 0.01;
    this.cube.rotation.y += 0.01;
    this.renderer.render(this.scene, this.camera);
  }

  resize() {
    let width = window.innerWidth;
    let height = window.innerHeight;

    this.camera.aspect = width / height;
    this.camera.updateProjectionMatrix();

    this.renderer.setSize( width, height );
  }

}

提前感谢您的帮助

【问题讨论】:

    标签: angular three.js


    【解决方案1】:

    因为objLoader.load的回调函数中的this指的是onload函数,而不是类实例。

    解决这个问题的一种方法是将this 实例化为createScene 函数中的变量,然后在加载函数中使用该变量而不是 this:

    createScene(elementId: string): void {
        let me = this;
        ...
    
        objLoader.load(
          // resource URL
          'helicopter.obj',
         // called when resource is loaded
         function ( object ) {
            console.log(object);
            object.position.y -= 60;
    
            me.scene.add( object );
    
         },
      ...
      );
    }
    

    另一种方法是使用箭头函数,其中this 将引用ItemsCatalogComponent 类:

    objLoader.load(
      // resource URL
      'helicopter.obj',
      // called when resource is loaded
      ( object ) => {
        console.log(object);
        object.position.y -= 60;
    
       this.scene.add( object );
    
      },
      // called when loading is in progresses
      ( xhr ) => {
    
        console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
    
      },
      // called when loading has errors
      ( error ) => {
    
        console.log( 'An error happened' );
    
      }
    );
    

    希望有所帮助。

    【讨论】:

    • 清晰准确!非常感谢。
    猜你喜欢
    • 2018-05-23
    • 2017-10-21
    • 2021-12-02
    • 2013-12-06
    • 2014-04-29
    • 2014-02-22
    • 1970-01-01
    • 2021-03-15
    • 2019-03-02
    相关资源
    最近更新 更多