vue3.0 + ts + threejs 实现3D 文字(hello juejin)和demo详解

4,205 阅读2分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战

背景

本人前几天写了一个vue3.0 + ts + threejs 实现简单的demo的文章,浏览量很高,但是点赞的人不多,个人觉得可能是讲的不够仔细,不够透彻,因为本人平时要上班,晚上还有带娃,写作的时间不多,所以上一篇文章讲的比较浅显,于是本人决定实现一个3D文字,并一步一步详细讲解,效果如下 123.gif

技术

实现

创建一个项目

这一步我们就略过了,因为这篇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和相关插件

  1. demo.vue文件夹内新建 index.ts 文件;
  2. 引入 threejs
  3. 引入文字加载器和文字模型; 代码如下:
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);
    }
  }

创建网格模型

  1. 创建 文字加载器
const loader = new FontLoader();
  1. 引人字体
loader.load("/assets/fonts/helvetiker_regular.typeface.json",func,func, func)
  1. 成功回调,并渲染
(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);
      }
    });
  1. 完整代码,如下:
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);
    }
  }

效果图如下:

123.gif

相关文章