用threejs实现掘金红包封面-实现中文和SVG(3)

1,004 阅读1分钟

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

背景

上一篇文章(用three.js实现掘金红包封面-3D旋转LOGO)我们实现了3D旋转LOGO,本篇文章我准备实现中文和titleSVG,接下来我就来实现它吧!

image.png

技术

threejs知识点

  1. SVGLoader
  2. TTFLoader
  3. Font
  4. Group

实现 掘金title

为了实现掘金title我们要获取title.svg文件,这个很好获取,加开掘金首页,打开控制台,找到logoimg就可以看见了,如下图:

image.png

准备

  1. 掘金title.svg

代码

1. 引入SVGLoader加载器

import { SVGLoader } from "three/examples/jsm/loaders/SVGLoader";

2. 实现 掘金title

setTitleGroup(): void {
    const loader = new SVGLoader();
    loader.load(
      "/assets/imgs/title.svg",
      (data) => {
        const paths = data.paths;
        this.titleGroup = new THREE.Group();
        for (let i = 0; i < paths.length; i++) {
          const path = paths[i];

          const material = new THREE.MeshLambertMaterial({
            // color: path.color,
            color: 0xffcea3,
            side: THREE.DoubleSide,
            depthWrite: false,
          });

          const shapes = SVGLoader.createShapes(path);

          for (let j = 0; j < shapes.length; j++) {
            const shape = shapes[j];
            const geometry = new THREE.ShapeGeometry(shape);

            const mesh = new THREE.Mesh(geometry, material);
            this.titleGroup && this.titleGroup.add(mesh);
          }
        }
        this.scene && this.titleGroup && this.scene.add(this.titleGroup);
      },
      // called when loading is in progresses
      function (xhr) {
        console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
      },
      // called when loading has errors
      function (error) {
        console.log("An error happened", error);
      }
    );
  }

3. 居中方法

setCenter(group: THREE.Group): void {
    const box = new THREE.Box3();
    //通过传入的object3D对象来返回当前模型的最小大小,值可以使一个mesh也可以使group
    box.expandByObject(group);

    const mdlen = box.max.x - box.min.x;
    const mdwid = box.max.z - box.min.z;
    const mdhei = box.max.y - box.min.y;
    const x1 = box.min.x + mdlen / 2;
    const y1 = box.min.y + mdhei / 2;
    const z1 = box.min.z + mdwid / 2;

    group.position.set(-x1, -y1, -z1);
 }

4. 位子设置

this.titleGroup.scale.set(0.2, 0.2, 0.2);
this.titleGroup.rotateX(Math.PI);
this.setCenter(this.titleGroup);
this.titleGroup.position.y = 70;

效果

image.png

实现中文("恭喜发财,大吉大利")

threejs显示中文,首先你要有一个拥有中文的字体,比如我用的是STHeiti.ttf,你有字体后还要加载字体,这个时候就要用TTFLoader加载器。

准备

  1. STHeiti.ttf字体

代码

1. 引入TTFLoader加载器

import { TTFLoader } from "three/examples/jsm/loaders/TTFLoader";

2. 引入ttffont

import { Font, FontLoader } from "three/examples/jsm/loaders/FontLoader";

3. 实现文字

setTitle(): void {
    const loader = new TTFLoader();
    loader.load("/assets/fonts/STHeiti.ttf", (res) => {
      if (this.scene) {
        const json = new Font(res);
        const text = "恭喜发财,大吉大利";
        const font = new TextGeometry(text, {
          font: json,
          size: 4, //字体大小
          height: 0.01, // 挤出文本的厚度
          curveSegments: 12, // 曲线上点的数量。默认值为12
          bevelEnabled: true, // 是否开启斜角,默认为false
          bevelThickness: 0.5, // 文本上斜角的深度,默认值为20
          bevelSize: 0.03, //斜角与原始文本轮廓之间的延伸距离。默认值为8
          bevelSegments: 3, // 斜角的分段数。默认值为3
        });
        font.center();
        const material = new THREE.MeshLambertMaterial({
          color: 0xffcea3,
        });
        this.title = new THREE.Mesh(font, material);
        this.title.position.set(0, 50, 0);
        this.scene.add(this.title);
      }
    });
  }

效果

image.png

本文效果

image.png

整体效果

结合上两篇文章的旋转文字环,整体效果如下:

动画1.gif