<template>
<div class="webgl-container">
<div id="webglDom" ref="webglDom" style="height: 1080px;"></div>
</div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
export default {
name:'',
data(): {
return {
// 场景 相机 渲染器 控制器
scene: undefined,
camera: undefined,
renderer: undefined,
controls: undefined,
// 容器宽高
containerWidth: 0,
containerHeight: 0,
// requestAnimationFrame
requestAnimationId: undefined,
// 平行光 环境光
directionalLight: undefined,
ambient: undefined,
// 相机参数
// fov — 摄像机视锥体垂直视野角度
fov: 45,
// far — 摄像机视锥体远端面
far: 10000,
// near — 摄像机视锥体近端面
near: 0.01,
},
mounted() {
this.$nextTick(() => {
this.init();
});
},
// 在页面卸载时或重新加载场景时调用 clearCache 方法
beforeDestroy() {
// 页面卸载前清除内存,定时器,渲染器等
cancelAnimationFrame(this.requestAnimationId);
new THREE.Cache.clear();
window.removeEventListener("resize", this.onWindowResize);
window.removeEventListener("mousewheel", this.mousewheel);
},
methods: {
// 初始化场景
initScene() {
this.scene = new THREE.Scene();
// 背景
this.scene.background = new THREE.Color(0xeaeaea);
},
// 初始化相机
initCamera() {
this.camera = new THREE.PerspectiveCamera(
this.fov,
this.containerWidth / this.containerHeight,
this.near,
this.far
);
// 相机位置
this.camera.position.set(-4000, 8000, 6400);
this.scene.add(this.camera);
// 摄像头朝向
this.camera.lookAt(this.scene.position);
},
// 初始化灯光
initLight() {
// 平行光 类似太阳的光源
this.directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
this.directionalLight.color.setHSL(0.1, 1, 0.95);
this.directionalLight.position.set(0, 1000, 0).normalize();
this.scene.add(this.directionalLight);
// 环境光 影响整个场景的光源
this.ambient = new THREE.AmbientLight(0xffffff, 1);
this.ambient.position.set(0, 0, 0);
this.scene.add(this.ambient);
},
// 初始化渲染器
initRenderer() {
this.renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true,
});
this.renderer.setSize(this.containerWidth, this.containerHeight);
this.renderer.setClearColor(0x4682b4, 1.0);
document
.getElementById("webglDom")
.appendChild(this.renderer.domElement);
},
// 实时渲染
animate() {
// 不要同时使用 requestAnimationFrame()和controls.addEventListener('change', render)调用同一个函数,这样会冲突。
this.requestAnimationId = requestAnimationFrame(this.animate);
this.renderer.render(this.scene, this.camera);
this.update();
},
// 初始化轨迹球控件
initControls() {
this.controls = new OrbitControls(
this.camera,
this.renderer.domElement
);
this.controls.enableDamping = true;
this.controls.dampingFactor = 0.5;
// 视角最小距离
this.controls.minDistance = 2000;
// 视角最远距离
this.controls.maxDistance = 5500;
// 最大角度
this.controls.maxPolarAngle = Math.PI / 2.2;
},
// 更新控件
update() {
this.controls.update();
},
// 窗口变动触发的方法
onWindowResize() {
this.camera.aspect = this.containerWidth / this.containerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.containerWidth / this.containerHeight);
},
// 鼠标滑轮 放大缩小
mousewheel(e) {
e.preventDefault();
//e.stopPropagation();
if (e.wheelDelta) {
//判断浏览器IE,谷歌滑轮事件
if (e.wheelDelta > 0) {
//当滑轮向上滚动时
this.fov -= this.near < this.fov ? 1 : 0;
}
if (e.wheelDelta < 0) {
//当滑轮向下滚动时
this.fov += this.fov < this.far ? 1 : 0;
}
} else if (e.detail) {
//Firefox滑轮事件
if (e.detail > 0) {
//当滑轮向上滚动时
this.fov -= 1;
}
if (e.detail < 0) {
//当滑轮向下滚动时
this.fov += 1;
}
this.camera.fov = this.fov;
this.camera.updateProjectionMatrix();
this.renderer.render(this.scene, this.camera);
}
},
//初始化
init() {
//获取div盒子
const container = this.$refs.webglDom;
//div盒子的宽高
this.containerWidth = container.offsetWidth;
this.containerHeight = container.offsetHeight;
// 场景
this.initScene();
// 相机
this.initCamera();
// 渲染器
this.initRenderer();
// 灯光
this.initLight();
// 控制器
this.initControls();
// 实时渲染
this.animate();
// 事件监听
document
.getElementById("webglDom")
.addEventListener("resize", this.onWindowResize, false);
document
.getElementById("webglDom")
.addEventListener("mousewheel", this.mousewheel, {
passive: false,
});
},
},
}
</script>
<style scoped>
#webglDom,
.webgl-container {
width: 100%;
height: 98%;
overflow: hidden;
}
</style>
THREE初始化(场景 相机 渲染器 控制器等)
于 2022-08-16 15:56:55 首次发布