Angular ThreeJS |如何正确创建自定义画布
Posted
技术标签:
【中文标题】Angular ThreeJS |如何正确创建自定义画布【英文标题】:Angular ThreeJS | How do I correctly create a custom canvas 【发布时间】: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 @
【参考方案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);
);
<canvas #rendererCanvas></canvas>
【讨论】:
以上是关于Angular ThreeJS |如何正确创建自定义画布的主要内容,如果未能解决你的问题,请参考以下文章