「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」
背景
本人前几天写了一个vue3.0 + ts + threejs 实现简单的demo的文章,浏览量很高,但是点赞的人不多,个人觉得可能是讲的不够仔细,不够透彻,因为本人平时要上班,晚上还有带娃,写作的时间不多,所以上一篇文章讲的比较浅显,于是本人决定实现一个3D文字,并一步一步详细讲解,效果如下
技术
vue3.0
typescript
- threejs
实现
创建一个项目
这一步我们就略过了,因为这篇vue3.0 + ts + threejs 实现简单的demo已经讲过了,如果不会的可以看上篇文章,一步一步来就可以了。
创建一个demo
首先创建一个demo.vue
页面,然后在里面写入一下代码,并创建路由
<template>
<div class="demo"></div>
</template>
<script lang="ts">
import ThreeJs from "./index";
import { defineComponent, onMounted } from "vue";
export default defineComponent({
name: "Demo",
props: {},
setup() {
onMounted(() => {
new ThreeJs();
});
},
});
</script>
<style scoped lang="scss"></style>
引入 threejs和相关插件
- 在
demo.vue
文件夹内新建index.ts
文件; - 引入
threejs
; - 引入文字加载器和文字模型; 代码如下:
import * as THREE from "three";
import { FontLoader } from "three/examples/jsm/loaders/FontLoader";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry";
编写 ThreeJs
我们的index.ts
输出ThreeJs
编写,代码如下:
export default class ThreeJs {}
默认值和初始化
默认值:
scene: THREE.Scene | null = null;
camera: THREE.PerspectiveCamera | null = null;
renderer: THREE.WebGLRenderer | null = null;
ambientLight: THREE.AmbientLight | null = null;
mesh: THREE.Mesh | null = null;
初始化:
constructor() {
this.init();
}
init(): void {
this.setStats();
this.setScene();
this.setCamera();
this.setRenderer();
this.setCube();
this.render();
}
新建相机
setCamera(): void {
// 第二参数就是 长度和宽度比 默认采用浏览器 返回以像素为单位的窗口的内部宽度和高度
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this.camera.position.z = 10;
}
设置渲染器
setRenderer(): void {
this.renderer = new THREE.WebGLRenderer();
// 设置画布的大小
this.renderer.setSize(window.innerWidth, window.innerHeight);
//这里 其实就是canvas 画布 renderer.domElement
document.body.appendChild(this.renderer.domElement);
}
设置环境光
setLight(): void {
if (this.scene) {
this.ambientLight = new THREE.AmbientLight(0xffffff); // 环境光
this.scene.add(this.ambientLight);
}
}
创建网格模型
- 创建 文字加载器
const loader = new FontLoader();
- 引人字体
loader.load("/assets/fonts/helvetiker_regular.typeface.json",func,func, func)
- 成功回调,并渲染
(res) => {
if (this.scene) {
const font = new TextGeometry("hello juejin", {
font: res,
size: 0.8,
height: 0.1,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.1,
bevelSize: 0.05,
bevelSegments: 3,
});
font.center();
const material = new THREE.MeshNormalMaterial({
flatShading: true,
transparent: true,
opacity: 0.9,
});
this.mesh = new THREE.Mesh(font, material);
this.mesh.position.set(0, 0, 0);
this.scene.add(this.mesh);
}
});
- 完整代码,如下:
setCube(): void {
const loader = new FontLoader();
loader.load("/assets/fonts/helvetiker_regular.typeface.json", (res) => {
if (this.scene) {
const font = new TextGeometry("hello juejin", {
font: res,
size: 0.8,
height: 0.1,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.1,
bevelSize: 0.05,
bevelSegments: 3,
});
font.center();
const material = new THREE.MeshNormalMaterial({
flatShading: true,
transparent: true,
opacity: 0.9,
});
this.mesh = new THREE.Mesh(font, material);
this.mesh.position.set(0, 0, 0);
this.scene.add(this.mesh);
}
});
}
渲染函数
render(): void {
if (this.renderer && this.scene && this.camera) {
this.renderer.render(this.scene, this.camera);
}
}