import { AfterViewInit , Component , ElementRef , Input , ViewChild } from '@angular/core' ; import * as THREE from 'three' ; @ Component ( { selector : 'geometry-cube' , templateUrl : './cube.component.html' , styleUrls : [ './cube.component.css' ] } ) export class CubeComponent implements AfterViewInit { private camera : THREE . PerspectiveCamera ; private get canvas ( ) : HTMLCanvasElement { return this . canvasRef . nativeElement ; } @ ViewChild ( 'canvas' ) private canvasRef : ElementRef ; private cube : THREE . Mesh ; private renderer : THREE . WebGLRenderer ; private scene : THREE . Scene ; @ Input ( ) public rotationSpeedX : number = 0.005 ; @ Input ( ) public rotationSpeedY : number = 0.01 ; @ Input ( ) public size : number = 200 ; @ Input ( ) public texture : string = '/assets/textures/crate.gif' ; @ Input ( ) public cameraZ : number = 400 ; @ Input ( ) public fieldOfView : number = 70 ; @ Input ( 'nearClipping' ) public nearClippingPane : number = 1 ; @ Input ( 'farClipping' ) public farClippingPane : number = 1000 ; constructor ( ) { } /**
     * Animate the cube
     */ private animateCube ( ) { this . cube . rotation . x += this . rotationSpeedX ; this . cube . rotation . y += this . rotationSpeedY ; } /**
     * Create the cube
     */ private createCube ( ) { let texture = new THREE . TextureLoader ( ) . load ( this . texture ) ; let material = new THREE . MeshBasicMaterial ( { map : texture } ) ; let geometry = new THREE . BoxBufferGeometry ( this . size , this . size , this . size ) ; this . cube = new THREE . Mesh ( geometry , material ) ; this . scene . add ( this . cube ) ; } /**
     * Create the scene
     */ private createScene ( ) { this . scene = new THREE . Scene ( ) ; let aspectRatio = this . getAspectRatio ( ) ; this . camera = new THREE . PerspectiveCamera ( this . fieldOfView , aspectRatio , this . nearClippingPane , this . farClippingPane ) ; this . camera . position . z = this . cameraZ ; } private getAspectRatio ( ) { return this . canvas . clientWidth / this . canvas . clientHeight ; } /**
     * Start the rendering loop
     */ private startRenderingLoop ( ) { this . renderer = new THREE . WebGLRenderer ( { canvas : this . canvas } ) ; this . renderer . setPixelRatio ( devicePixelRatio ) ; this . renderer . setSize ( this . canvas . clientWidth , this . canvas . clientHeight ) ; let component = this ; ( function render ( ) { requestAnimationFrame ( render ) ; component . animateCube ( ) ; component . renderer . render ( component . scene , component . camera ) ; } ( ) ) ; } /**
     * Update scene after resizing.
     */ public onResize ( ) { this . camera . aspect = this . getAspectRatio ( ) ; this . camera . updateProjectionMatrix ( ) ; this . renderer . setSize ( this . canvas . clientWidth , this . canvas . clientHeight ) ; } /**
     * We need to wait until template is bound to DOM, as we need the view
     * dimensions to create the scene. We could create the cube in a Init hook,
     * but we would be unable to add it to the scene until now.
     */ public ngAfterViewInit ( ) { this . createScene ( ) ; this . createCube ( ) ; this . startRenderingLoop ( ) ; } }