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 );
}
}
不出意外肯定是可以跑起来了。案例里面也实现了部分的模型交互,动画以及对接数据库,剩下的就看你们想怎么弄。总直。重点还是模型,代码难度不大。到这里吧
推荐阅读
-
angular10+threejs搭建3D
-
Nehe教程第10课3D世界
-
Win10系统从源码构建3D Slicer
-
Win10 RS3版 删除资源管理器中的“3D 对象”
-
从Windows中移除文档、下载、图片、视频、桌面、音乐、3D对象(Windows10/Windows2016/Windows2019)
-
删除win10 3D库
-
如何删除Win10文件管理器中的3D对象/音乐/视频/下载/文档等文件夹
-
appium+java+selenium环境搭建和使用方法
-
【Android开发学习00】Windows下Android开发环境搭建
-
windows10下搭建appium+python+android自动化测试环境启动真机