通过Three.js实现一个基础渲染代码

threejs yekong

使用threejs来渲染一个基础效果。因为自己一直是用vue开发项目,所以项目框架选为vue vite js nodejs 14

安装依赖

pnpm i three

版本选择

既然要学就选择最新版本,2023年08月02日,threejs的最新版本是155,但是在项目开发过程中155下的网格模型光源照射后仍然是黑色的不清楚是什么原因,所以这里使用154版本

"three": "^0.154.0",

实例演示地址

通过Three.js实现一个基础渲染代码

项目关键要素

场景

首先创建一个场景,场景可以理解为一个盒子,一个房间。

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

相关文件下载地址
此资源需支付 ¥1 后下载
支付宝购买扫右侧红包码购买更优惠,如无法下载请联系微信:17331886870
喜欢
通过Three.js实现一个基础渲染代码