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

结语

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

相关推荐
zhougl9961 小时前
html处理Base文件流
linux·前端·html
花花鱼1 小时前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
HBR666_1 小时前
marked库(高效将 Markdown 转换为 HTML 的利器)
前端·markdown
careybobo3 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
杉之4 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端4 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡4 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木5 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!6 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
難釋懷6 小时前
JavaScript基础-移动端常见特效
开发语言·前端·javascript