代码结构
参考郭隆邦老师的代码结构
项目文件夹test
项目内模块代码必须为.js结尾 此时如果写成.ts 参数导出取不到
test/scene/index.js(初始化场景)
import * as THREE from "three";
import { model } from "./model";
let scene = new THREE.Scene();
/**
* 添加模型
*/
scene.add(model);
/**
* 光源设置
*/
// 平行光1
let directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(400, 200, 300);
scene.add(directionalLight);
// 平行光2
let directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight2.position.set(-400, -200, -300);
scene.add(directionalLight2);
//环境光
var ambient = new THREE.AmbientLight(0xffffff, 0.3);
scene.add(ambient);
// Three.js三维坐标轴 三个坐标轴颜色RGB分别对应xyz轴
let axesHelper = new THREE.AxesHelper(250);
scene.add(axesHelper);
export { scene };
test/scene/model,js(加载模型)
import * as THREE from "three";
// 模型组
let model = new THREE.Group();
// 添加正方体模型
let geometry = new THREE.BoxGeometry(50, 50, 50);
let material = new THREE.MeshLambertMaterial({
color: 0x00ffff,
});
let mesh = new THREE.Mesh(geometry, material);
model.add(mesh);
export { model };
test/RendererCamera.js(初始化渲染器及相机)
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// width和height用来设置Three.js输出Canvas画布尺寸,同时用来辅助设置相机渲染范围
let width = window.innerWidth; //窗口文档显示区的宽度
let height = window.innerHeight; //窗口文档显示区的高度
/**
* 透视投影相机设置
*/
// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面
let camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
camera.position.set(292, 223, 185); //相机在Three.js三维坐标系中的位置
camera.lookAt(0, 0, 0); //相机指向Three.js坐标系原点
/**
* 创建渲染器对象
*/
let renderer = new THREE.WebGLRenderer({
antialias: true, //开启锯齿
});
renderer.setPixelRatio(window.devicePixelRatio); //设置设备像素比率,防止Canvas画布输出模糊。
renderer.setSize(width, height); //设置渲染区域尺寸
// renderer.setClearColor(0xffffff, 1); //设置背景颜色
//创建控件对象 控件可以监听鼠标的变化,改变相机对象的属性
let controls = new OrbitControls(camera, renderer.domElement);
controls.mouseButtons = {
LEFT: THREE.MOUSE.PAN,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.ROTATE,
};
//限制最大仰视角和俯视角 controls.minPolarAngle = 0; controls.maxPolarAngle = 1.5;
//禁止缩放 controls.enableZoom=false
//缩放限制 controls.minDistance = 50; controls.maxDistance = 450;
//是否使用键盘 controls.enableKeys = false;
//修改鼠标按键
// onresize 事件会在窗口被调整大小时发生
window.onresize = function () {
// 重置渲染器输出画布canvas尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
// 全屏情况下:设置观察范围长宽比aspect为窗口宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源)
// 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
camera.updateProjectionMatrix();
};
export { renderer, camera };
test/RenderLoop.js(渲染方法)
import { scene } from "./scene/index";
import { renderer, camera } from "./RendererCamera";
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
// console.log(camera.position);
}
render();
export { renderer };
test/index.vue(将渲染结果添加到结果容器内)
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { renderer } from "./RenderLoop.js";
// 场景容器
const ThreeDom = ref(null);
onMounted(() => {
(ThreeDom as any)._value.appendChild(renderer.domElement);
});
</script>
<template>
<div id="ThreeContainer" ref="ThreeDom"></div>
</template>
<style scoped lang="less">
#ThreeContainer {
width: 100%;
height: 100%;
}
</style>
感想
个人觉得 此结构更加清晰 专注于业务逻辑的书写 而不是繁琐的参数传递
渲染效率比将参数赋予vue内的data里存储,再渲染的方式 要高些