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

结语

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

相关推荐
GIS程序媛—椰子几秒前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山23 分钟前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享1 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果1 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
从兄1 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
凉辰2 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
清灵xmf3 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨3 小时前
VUE+Vite之环境文件配置及使用环境变量
前端
GDAL3 小时前
npm入门教程1:npm简介
前端·npm·node.js
小白白一枚1114 小时前
css实现div被图片撑开
前端·css