欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

angular10+threejs搭建3D

程序员文章站 2024-03-24 11:46:46
...

以前用纯js+threejs开发了3D。现在用angular试试。会展示部分代码。流程如下

 1.搭建项目环境
	ng new 项目名
	引入需要的3d包,并且要加类型的说明,否则无法调用,如下:
	cnpm i three --save
	cnpm i three-full --save
	cnpm i gsap --save
	cnpm i stats.js --save
	---------------------------
	cnpm i @types/three -s
	cnpm i @types/three-full -s
	cnpm i @types/gsap -s
	cnpm i @types/stats.js -s
	以上安装完成需要的3D支持和环境库。
2.展示代码
	在src目录下建立conf/modul.ts
		import {
  Scene,
  AmbientLight,
  PointLight,
  WebGLRenderer,
  PerspectiveCamera,
  GridHelper,
  Vector2,
  Raycaster,
  Color
} from 'three';

import {
   CSS2DRenderer
} from 'node_modules/three/examples/jsm/renderers/CSS2DRenderer';
// @ts-ignore
import * as Stats from 'node_modules/stats.js/build/stats.min.js';

import {
  FXAAShader, UnrealBloomPass, ShaderPass, FilmPass, OutlinePass, GeometryUtils, CopyShader, ColorifyShader, SepiaShader,
  OrbitControls, GLTFLoader, EffectComposer, RenderPass, SMAAShader, SMAAPass, ClearMaskPass, MaskPass,
} from 'three-full';

//  渲染器
export const RENDERER = new WebGLRenderer(); //  渲染器(去据此){ antialias: true }
// @ts-ignore
export const CSS2DRENDER = new CSS2DRenderer();

// tslint:disable-next-line:typedef
export function initRenderer(doc) {
  RENDERER.setSize(
    doc.clientWidth,
    doc.clientHeight
  );
  RENDERER.shadowMap.enabled = true; // 辅助线
  doc.appendChild(RENDERER.domElement);

  CSS2DRENDER.setSize(
    doc.clientWidth,
    doc.clientHeight
  );
  CSS2DRENDER.domElement.style.position = 'absolute';
  CSS2DRENDER.domElement.style.top = '0' ;
  CSS2DRENDER.domElement.className  = 'Css2DRenderDiv';
  doc.appendChild(CSS2DRENDER.domElement);

}


// 场景
export const SCENE = new Scene();

export const MOUSE = new Vector2();
export const raycaster = new Raycaster();

// tslint:disable-next-line:typedef
export function initScene() {
  SCENE.background = new Color(0xcccccc);
}

//  灯光
// tslint:disable-next-line:typedef
export function initLight() {
  const ambientLight = new AmbientLight(0xffffff, 0.2);    // 全局光
  ambientLight.position.set(10, 20, 55);   // 灯光
  SCENE.add(ambientLight);

  // 点光源
  const pointLight = new PointLight(0xffffff);
  pointLight.distance = 0;
  CAMERA.add(pointLight);
  SCENE.add(CAMERA);
}

//  相机
export let CAMERA;
export let CONTROLS;
// tslint:disable-next-line:typedef
export function initCamera(doc) {
  const d = {
    fov: 30, // 拍摄距离  视野角值越大,场景中的物体越小
    near: 1, //  最小范围
    far: 1000, //  最大范围
  };
  CAMERA = new PerspectiveCamera(
    d.fov,
    doc.clientWidth / doc.clientHeight,
    d.near,
    d.far)
  ;
  const p = {
    x: 0,
    y: 600,
    z: 200,
  };
  CAMERA.position.set(p.x, p.y, p.z);
  CAMERA.lookAt(0, 0, 0);
  CONTROLS = new OrbitControls(CAMERA, CSS2DRENDER.domElement);  // 控制镜头
}


//  网格
// tslint:disable-next-line:typedef
export function initGrid() {
  const gridHelper = new GridHelper(100, 50);
  SCENE.add(gridHelper);
}


//  性能检测
export const STATS = new Stats();
// tslint:disable-next-line:typedef
export function initStats(doc) {
  STATS.setMode(0);
  STATS.domElement.style.position = 'absolute';
  STATS.domElement.left = '0px';
  STATS.domElement.top = '0px';
  doc.appendChild(STATS.domElement);
}

//  动画混合器组(把模型的动画混合器都push到这里面,在canvas.ts里面更新动画   )
export const MIXER = [];
3.在app-module.ts调用conf下配置的ts
	import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { EventManager } from '@angular/platform-browser';
import {
  initRenderer,
  initCamera,
  initScene, initLight,
  initGrid, initStats, MOUSE, raycaster, CSS2DRENDER,
  RENDERER, CAMERA, SCENE, CONTROLS, STATS, MIXER
} from '../../src/config/base';

// @ts-ignore
import {
  CSS2DObject
} from 'node_modules/three/examples/jsm/renderers/CSS2DRenderer';
import {
  FXAAShader, UnrealBloomPass, ShaderPass, FilmPass, OutlinePass, GeometryUtils, CopyShader, ColorifyShader, SepiaShader,
  OrbitControls, GLTFLoader, EffectComposer, RenderPass, SMAAShader, SMAAPass, ClearMaskPass, MaskPass,
} from 'three-full';
import { Vector2, Group, Scene, SphereGeometry, ImageUtils, AnimationMixer, MeshBasicMaterial, Mesh } from 'three';
import { fromEvent } from 'rxjs';
import {TweenMax} from 'gsap';
// import {ServerProcessService} from './share/server-process.service';


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

  @ViewChild('canvasFrame', { static: true }) canvasContainer: ElementRef;
  thing;
  constructor(private eventManager: EventManager) { }
  title = 'datacenter';

  ngOnInit(): void {
    console.log('数据库获取值');
    // console.log(this.serverDataSource.getdata());
    this.init();
    // @ts-ignore
    this.eventManager.addGlobalEventListener('window', 'click', (e) => {
      this.checkisModelsection( e );

    });
    this.eventManager.addGlobalEventListener('window', 'resize', (e) => {
      const width = window.innerWidth;
      const height = window.innerHeight;

      CAMERA.aspect = width / height;
      CAMERA.updateProjectionMatrix();

      RENDERER.setSize( width, height );

      RENDERER.setPixelRatio(window.devicePixelRatio);
      RENDERER.setSize(window.innerWidth, window.innerHeight);

      CSS2DRENDER.setSize(window.innerWidth, window.innerHeight);
    });
    this.eventManager.addGlobalEventListener('window', 'touchend', (e) => {
      console.log(e);
    });

  }
  // tslint:disable-next-line:typedef
  onResize(){
    console.log('888');
  }
  // tslint:disable-next-line:typedef
  checkisModelsection( event ) {
    // tslint:disable-next-line:one-variable-per-declaration prefer-const
    let x, y, z, selectedObj ;
    if ( event.changedTouches ) {
      x = event.changedTouches[ 0 ].pageX;
      y = event.changedTouches[ 0 ].pageY;

    } else {
      x = event.clientX;
      y = event.clientY;
    }
    MOUSE.x = ( x / window.innerWidth ) * 2 - 1;
    MOUSE.y = - ( y / window.innerHeight ) * 2 + 1;

    raycaster.setFromCamera( MOUSE, CAMERA );
    const inter = raycaster.intersectObjects( [ SCENE ], true );
    if (inter.length > 0){
      selectedObj = inter[ 0 ].object;
      console.log(selectedObj);

      const parentDiv = document.createElement('div');

      parentDiv.className = 'modelLabel';

      const asName = '55';
      const sonDiv = document.createElement('div');
      sonDiv.className =  'power-child';
      sonDiv.innerText = asName;
      parentDiv.appendChild(sonDiv);


      // @ts-ignore
      const parentLabel = new CSS2DObject( parentDiv );
      parentLabel.visible = true;
      parentLabel.name = 'biaoqian';
      parentLabel.position.set( 0, 0, 0 );
      selectedObj.add(parentLabel);

      TweenMax.to(selectedObj.position, 1.5, {
        y: '60',
        x: '10',
        z: '60',
        delay: 1
      });
      TweenMax.to(selectedObj.scale, 1.5, {
        y: '5',
        x: '5',
        z: '5',
        delay: 2
      });
    }
  }
  // tslint:disable-next-line:typedef
  init() {
    initRenderer(this.canvasContainer.nativeElement);
    initCamera(this.canvasContainer.nativeElement);
    initScene();
    initLight();
    initGrid();
    initStats(this.canvasContainer.nativeElement);
    //  加载模型-star
    this.importantModel();
    //  加载模型-end

    // const delta = new Clock();
    const rendererOut = () => {
      requestAnimationFrame(rendererOut);
      RENDERER.render(SCENE, CAMERA);
      CSS2DRENDER.render(SCENE, CAMERA);
      CONTROLS.update();
      STATS.update();
      if (MIXER) {
        MIXER.map(r => {
          // r.update(delta.getDelta());
        });
      }
    };

    rendererOut();

  }
  // tslint:disable-next-line:typedef
  importantModel() {
    const rollOverGeo = new SphereGeometry( 5, 5, 5 );
    const rollOverMaterial = new MeshBasicMaterial( { color: 0xff0000, opacity: 0.5, transparent: true } );
    const rollOverMesh = new Mesh( rollOverGeo, rollOverMaterial );
    rollOverMesh.visible = true;
    rollOverMesh.position.set(20, 10, 0);
    rollOverMesh.name = 'robotMesh';
    SCENE.add( rollOverMesh );
  }
}

	
 不出意外肯定是可以跑起来了。案例里面也实现了部分的模型交互,动画以及对接数据库,剩下的就看你们想怎么弄。总直。重点还是模型,代码难度不大。到这里吧
相关标签: 前端3D javascript