使用threejs来渲染一个基础效果。因为自己一直是用vue开发项目,所以项目框架选为vue vite js nodejs 14
安装依赖
pnpm i three
版本选择
既然要学就选择最新版本,2023年08月02日,threejs的最新版本是155,但是在项目开发过程中155下的网格模型光源照射后仍然是黑色的不清楚是什么原因,所以这里使用154版本
"three": "^0.154.0",
实例演示地址
项目关键要素
场景
首先创建一个场景,场景可以理解为一个盒子,一个房间。
const scene = new THREE.Scene();
加入物品
如果只有房间,里面空空如也的话,那么就什么都看不到,我们需要往房间里加东西,比如放一张桌子,椅子,这里我们创建一个立方体放入到场景中。
// 创建一个立方体几何对象,并创建网格模型对象
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh); // 将网格模型添加到场景中
相机
有了房间,房间里有了椅子,我们还需要一双眼睛来看,这里的眼睛就是相机了,添加一个相机,让我们来看东西。threejs 相机有几种分别是什么?
const width = window.innerWidth;
const height = window.innerHeight;
const k = width / height;
const s = 200;
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(200, 300, 200); // 设置相机位置
camera.lookAt(scene.position); // 设置相机方向
光源
白天看东西很清楚,但是晚上没有光源的话就看不到东西了,所以我们还需要添加光源,光源的种类有很多。可以点此了解光源:threejs 光源有哪些?
// 创建光源
const point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300);
scene.add(point);
const ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient);
渲染器
房子 房子里的东西 相机都有了,那么就需要一个渲染器,把这些东西渲染出来。类似于相机的拍照功能。
// 创建渲染器,设置大小和背景颜色
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.setClearColor(0xb9d3ff, 1);
// 将渲染器的dom元素添加到我们的HTML页面中
rendererDom.value.appendChild(renderer.domElement);
// 执行渲染操作
renderer.render(scene, camera);
效果截图
代码实例
<template>
<!-- 定义一个用于承载Three.js渲染结果的div元素 -->
<div class="rendererDom" ref="rendererDom"/>
</template>
<script>
import {onMounted, ref} from "vue";
import * as THREE from "three";
export default {
name: "ThreeScene",
setup() {
// 创建一个响应式引用,用于获取模板中的div元素
const rendererDom = ref(null);
// 在组件挂载完成后执行
onMounted(() => {
// 创建场景
const scene = new THREE.Scene();
// 创建一个立方体几何对象,并创建网格模型对象
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh); // 将网格模型添加到场景中
// 创建并添加点光源
const point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300);
scene.add(point);
// 创建并添加环境光
const ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient);
// 创建相机
const width = window.innerWidth;
const height = window.innerHeight;
const k = width / height;
const s = 200;
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(200, 300, 200); // 设置相机位置
camera.lookAt(scene.position); // 设置相机方向
// 创建渲染器,设置大小和背景颜色
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.setClearColor(0xb9d3ff, 1);
// 将渲染器的dom元素添加到我们的HTML页面中
rendererDom.value.appendChild(renderer.domElement);
// 执行渲染操作
renderer.render(scene, camera);
});
// 返回一个包含我们创建的ref的对象,使其可以在模板中被访问
return {rendererDom};
},
};
</script>
<style lang="scss">
.rendererDom {
width: 100%;
height: 100%;
position: relative;
}
</style>
画布大小调整
上面我们完成了我们想要的效果,在数据可视化大屏 项目开发中,我们的效果可能只会在某个div内显示,并不是整个页面,这需要我们进行调整,让其跟随div的宽和高进行适配。
threejs的画布大小为div rendererDom的大小而不是整个页面的大小,我们需要调整代码
// 获取渲染元素的宽度和高度
const width = rendererDom.value.clientWidth;
const height = rendererDom.value.clientHeight;
// 创建渲染器,设置大小和背景颜色
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
监听div大小变化
当rendererDom大小变化的时候,three需要重新调整以进行适配
// 设置初始尺寸
renderer.setSize(rendererDom.value.clientWidth, rendererDom.value.clientHeight);
rendererDom.value.appendChild(renderer.domElement);
// 创建一个 ResizeObserver 实例并监听 rendererDom 的尺寸变化
const resizeObserver = new ResizeObserver(entries => {
// 更新渲染器的尺寸
for (let entry of entries) {
renderer.setSize(entry.contentRect.width, entry.contentRect.height);
camera.aspect = entry.contentRect.width / entry.contentRect.height;
camera.updateProjectionMatrix();
}
});
resizeObserver.observe(rendererDom.value);
onUnmounted(() => {
// 停止监听
resizeObserver.unobserve(rendererDom.value);
});
完整实例代码
<template>
<!-- 定义一个用于承载Three.js渲染结果的div元素 -->
<div class="rendererDom" ref="rendererDom"/>
</template>
<script>
import { onMounted, onUnmounted, ref } from 'vue';
import * as THREE from 'three';
export default {
setup() {
const rendererDom = ref(null);
onMounted(() => {
// 创建场景
const scene = new THREE.Scene();
// 创建立方体
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 创建光源
const point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300);
scene.add(point);
const ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient);
// 创建相机
const aspect = rendererDom.value.clientWidth / rendererDom.value.clientHeight;
const camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
camera.position.set(200, 300, 200);
camera.lookAt(scene.position);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(rendererDom.value.clientWidth, rendererDom.value.clientHeight);
renderer.setClearColor(0xb9d3ff, 1);
rendererDom.value.appendChild(renderer.domElement);
// 渲染
const animate = function () {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();
// 创建一个 ResizeObserver 实例并监听 rendererDom 的尺寸变化
const resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
renderer.setSize(entry.contentRect.width, entry.contentRect.height);
camera.aspect = entry.contentRect.width / entry.contentRect.height;
camera.updateProjectionMatrix();
}
});
resizeObserver.observe(rendererDom.value);
onUnmounted(() => {
resizeObserver.unobserve(rendererDom.value);
});
});
return { rendererDom };
},
};
</script>
<style lang="scss">
.rendererDom {
width: 100%;
height: 100%;
position: fixed;
}
</style>
视频教程地址
今天学习视频教程 《WebGL/Three.js前端高薪3D可视化》-大屏3D地图可视化-通过Three.js实现一个基础渲染代码
地图Web3D可视化-WebGL/Three.js 课程介绍
下一节
下一节我们来学习指定threejs画布大小 threejs 渲染非全屏(相机和渲染器)自定义画布大小
实例代码下载
当前学习笔记演示实例代码
项目运行环境 vue3 vite js nodejs 14