【问题标题】:Angular ThreeJS | How do I correctly create a custom canvasAngular ThreeJS |如何正确创建自定义画布
【发布时间】:2020-05-14 19:02:35
【问题描述】:

我正在尝试使用 ThreeJS 和 Angular 8 正确设置一个非常基本的示例。

当我尝试修改画布的大小以移除滚动条时,我收到错误“无法读取 null 的属性 'width'”

这是因为画布,但我不知道为什么。

Component.html:

<canvas id="myCanvas"></canvas>

Component.css:

body { 
    margin: 0; 
}

canvas { 
    width: 100vw; 
    height: 100vh; 
    display: block; 
}

Component.ts:

export class Scene3dComponent implements OnInit {

  scene = new THREE.Scene()

  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)

  canvas = document.querySelector("canvas")
  renderer = new THREE.WebGLRenderer({antialias: true, canvas: this.canvas})

  constructor() { }

  ngOnInit() {
    this.startScene();
  }

  startScene() {
    this.renderer.setClearColor('#E5E5E5')
    this.renderer.setSize(window.innerWidth, window.innerHeight)
    this.renderer.render(this.scene, this.camera)

    document.body.appendChild(this.renderer.domElement)

    window.addEventListener('resize', () => {
      this.renderer.setSize(window.innerWidth, window.innerHeight)
      this.camera.aspect = window.innerWidth / innerHeight
      this.camera.updateProjectionMatrix();
    })
  }
}

我很确定我没有理解某些东西,但我不知道是什么。

【问题讨论】:

  • 我在您发布的代码中看不到任何会产生错误“无法读取 null 的属性'width'”的地方......但我确实看到this.camera.aspect = window.innerWidth / innerHeight 可能应该是@987654325 @

标签: angular three.js html5-canvas


【解决方案1】:

我认为这不是在 angular 中实现threejs 的最佳方式。

  • 所以在我的建议中,您首先可以使用 ElementRef 和 @ViewChild 来获取画布

  • 创建包含您的功能的服务(创建场景、动画...)

    import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
    
    /**
     * Engine 3D
     */
    @Component({
      selector: 'app-engine-frame',
      templateUrl: './engine-frame.component.html',
      styleUrls: ['./engine-frame.component.css'],
    })
    export class EngineFrameComponent implements OnInit {
      @ViewChild('rendererCanvas', {static: true})
      public rendererCanvas: ElementRef<HTMLCanvasElement>;
      /**
       * Contructor
       * @param engService
       */
      constructor(private engService: EngineFrameService) {
      }
    
      ngOnInit(): void {
        this.engService.createScene(this.rendererCanvas);
        this.engService.animate();
      }
    }
    
    /**
    * Engine service
    */
    import * as THREE from 'three';
    import {ElementRef, Inject, Injectable, NgZone, OnDestroy} from '@angular/core';
    @Injectable({
      providedIn: 'root'
    })
    export class EngineFrameService implements OnDestroy {
      canvas: HTMLCanvasElement;
      renderer: THREE.WebGLRenderer;
      scene: THREE.Scene;
      frameId: number = null;
      constructor(private ngZone: NgZone, private rendererService: RendererService ) {
      }
    
      public ngOnDestroy(): void {
      }
      createScene(canvas: ElementRef<HTMLCanvasElement>): void {
        this.scene = new THREE.Scene(); 
        this.canvas = canvas.nativeElement;
        this.renderer = this.rendererService.create(this.canvas); // Create service for renderer
        // create your camera
      }
    public animate(): void {
        this.ngZone.runOutsideAngular(() => {
          window.addEventListener('resize', () => {
            this.resize();
          });
      }
      public render(): void {
        this.frameId = requestAnimationFrame(() => {
          this.render();
        });
        this.renderer.render(this.scene, this.camera);
      }
    
      public resize(): void {
          this.ngZone.runOutsideAngular(() => {
            const width = this.canvas.offsetWidth;
            const height = this.canvas.offsetHeight;
            this.renderer.setSize(width, height);
          });
      }
    &lt;canvas #rendererCanvas&gt;&lt;/canvas&gt;

【讨论】:

    猜你喜欢
    • 2020-01-10
    • 2019-09-21
    • 2021-02-05
    • 1970-01-01
    • 1970-01-01
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    相关资源
    最近更新 更多