ThreeJs新手入门不完全教学指南 快速入门篇(三)

在前两节课程中,向大家介绍了ThreeJs中一些基本的概念和一些常用的Api,今天的教程更加偏向实战,在这半个月的实战练习中反复遇到的,希望大家牢牢掌握。

还有大家在学习的过程中请务必注意当前使用的ThreeJs版本,开发与学习过程中结合官方提供的文档与案例效果最佳。

开发模块化拆分

在前两节的铺调后,相信大家已经可以在threejs中创建一些简单的几何模型。实际开发中,我们尽量将代码进行拆分,保证代码整洁方便维护。

大家跟着我一步步来操作

  1. model.ts
ts 复制代码
import * as THREE from 'three';


const geometry = new THREE.BoxGeometry(50, 50, 50);

const material = new THREE.MeshLambertMaterial({
  color: 0xcccccc
})

const mesh = new THREE.Mesh(geometry, material);

const model = new THREE.Group()

model.add(mesh)

export { model }
  1. scene.ts
ts 复制代码
import * as THREE from 'three';
import { model } from './model'

const scene = new THREE.Scene();
scene.add(model)

const amibient = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(amibient);

const dirLight1 = new THREE.DirectionalLight(0xffffff, 1);
dirLight1.position.set(400, 400, 400);
scene.add(dirLight1);

const dirLight2 = new THREE.DirectionalLight(0xffffff, 1);
dirLight2.position.set(-400, -400, -400);
scene.add(dirLight2);

const axesHelper = new THREE.AxesHelper(100);
scene.add(axesHelper);

export { scene }
  1. renderCamera.ts
ts 复制代码
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

const width = window.innerWidth;
const height = window.innerHeight;
const camera = new THREE.PerspectiveCamera(45, width / height, 0.25, 2000);
camera.position.set(200, 200, 200);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.setPixelRatio(window.devicePixelRatio);

window.onresize = function () {
  renderer.setSize(window.innerWidth, window.innerHeight); 
  camera.aspect = window.innerWidth / window.innerHeight; 
  camera.updateProjectionMatrix();
};



const controls = new OrbitControls(camera, renderer.domElement);
controls.update()
export { renderer, camera }
  1. render.ts
ts 复制代码
import { renderer, camera } from "./renderCamera";
import { scene } from "./scene";

function render() {
  renderer.render(scene, camera);
  requestAnimationFrame(render)
}

render()

export { renderer }
  1. index.vue
ts 复制代码
<script lang="ts" setup>
import { renderer } from './render';

const initRender = () => {
  document.body.appendChild(renderer.domElement);
};

onMounted(() => {
  initRender();
});
</script>

经过以上操作,我们在画布中间创建了一个方形模型,并且有着清晰的代码结构。后面我们可以根据需求添加模型文件,引入到scene文件add添加即可。

场景信息标注

实际开发中,经常会有这样一个需求,在产品模型上标注产品的名称、价格等一系列信息,这时就需要将我们前端常用的HTML代码与ThreeJs结合来实现。

CSS2DObject、CSS2DRenderer

首先我们来添加2D模型查看效果 创建css2D.ts

js 复制代码
const create2DObject = () => {
const div = document.createElement("div")
div.classList.add("flex", "justify-around",
  "py-2", "w-40", "border", "border-yellow-300", "absolute", "text-light-50")
div.innerHTML = ` <span>花西子</span>
<span>79</span>`

const tag = new CSS2DObject(div)
tag.position.y += 40
return tag
}

export { create2DObject }

这里用了windicss,没有使用的根据语义添加css属性即可

model.ts中引入

ts 复制代码
import { create2DObject } from './css2D'


const tag = create2DObject()
model.add(tag)

renderCamera.ts添加

ts 复制代码
const css2Renderer = new CSS2DRenderer();
css2Renderer.setSize(window.innerWidth, window.innerHeight);
css2Renderer.domElement.style.position = 'absolute';
css2Renderer.domElement.style.top = '0';
css2Renderer.domElement.style.left = '0';
css2Renderer.domElement.style.pointerEvents = 'none';

导出css2Renderer

render.ts引入 render函数内添加

js 复制代码
 css3Renderer.render(scene, camera);

index.vue

js 复制代码
const initRender = () => {
  document.body.appendChild(renderer.domElement);
  document.body.appendChild(css2Renderer.domElement);
};

效果如图,并且旋转视角时,标签内容始终平铺在画布上

CSS3DObject、CSS3DRenderer

操作其实与2D类似,大家把相应的CSS2DObject换成CSS3DObject CSS2DRenderer换成CSS3DRenderer即可 这里贴下关键代码

ts 复制代码
import { CSS3DObject } from "three/examples/jsm/renderers/CSS3DRenderer.js"

const create3DObject = () => {
const div = document.createElement("div")
div.classList.add("flex", "justify-around",
  "py-2", "w-40", "border", "border-yellow-300", "absolute", "text-light-50")
div.innerHTML = ` <span>花西子</span>
<span>79</span>`

const tag = new CSS3DObject(div)
tag.position.y += 40
return tag
}

export { create3DObject }
ts 复制代码
const css3Renderer = new CSS3DRenderer();
css3Renderer.setSize(window.innerWidth, window.innerHeight);
css3Renderer.domElement.style.position = 'absolute';
css3Renderer.domElement.style.top = '0';
css3Renderer.domElement.style.left = '0';
css3Renderer.domElement.style.pointerEvents = 'none';

其余方法都是一样的

这时候转动视角,会发现标签会随着视角发生变化,具有了3D属性。 在实际项目中,根据需求,选择适合你的模型对象

结语

好了,今天就先介绍到这里,下一篇会向大家介绍射线拾取来对画布中的模型添加相关事件,欢迎大家点赞收藏~

相关推荐
前端 贾公子1 分钟前
Monorepo + vite 怎么热更新
前端
然我37 分钟前
不用 Redux 也能全局状态管理?看我用 useReducer+Context 搞个 Todo 应用
前端·javascript·react.js
前端小巷子42 分钟前
Web 实时通信:从短轮询到 WebSocket
前端·javascript·面试
神仙别闹1 小时前
基于C#+SQL Server实现(Web)学生选课管理系统
前端·数据库·c#
web前端神器1 小时前
指定阿里镜像原理
前端
枷锁—sha1 小时前
【DVWA系列】——CSRF——Medium详细教程
android·服务器·前端·web安全·网络安全·csrf
枷锁—sha1 小时前
跨站请求伪造漏洞(CSRF)详解
运维·服务器·前端·web安全·网络安全·csrf
群联云防护小杜1 小时前
深度隐匿源IP:高防+群联AI云防护防绕过实战
运维·服务器·前端·网络·人工智能·网络协议·tcp/ip
汉得数字平台2 小时前
【鲲苍提效】全面洞察用户体验,助力打造高性能前端应用
前端·前端监控
花海如潮淹2 小时前
前端性能追踪工具:用户体验的毫秒战争
前端·笔记·ux