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属性。 在实际项目中,根据需求,选择适合你的模型对象

结语

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

相关推荐
真滴book理喻几秒前
Vue(四)
前端·javascript·vue.js
蜜獾云3 分钟前
npm淘宝镜像
前端·npm·node.js
dz88i83 分钟前
修改npm镜像源
前端·npm·node.js
Jiaberrr7 分钟前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook
程序员_三木25 分钟前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
顾平安1 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网1 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工1 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
沈剑心2 小时前
如何在鸿蒙系统上实现「沉浸式」页面?
前端·harmonyos
一棵开花的树,枝芽无限靠近你2 小时前
【PPTist】组件结构设计、主题切换
前端·笔记·学习·编辑器