「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」
背景
本人前几天写了一个教你用3步代码实现360度全景图,超简单的文章,浏览量和点赞的人很多,而且有人留言想看更多的threejs
文章,于是我又写了一篇教你实现超级炫酷的粒子光,超级简单的文章,但是浏览量就不高,本人觉得可能是不够实用,于是本人决定用threejs
实现一个3D
效果的掘金红包封面,并一步一步详细讲解,并实现如下效果:
技术
typescript
- threejs
知识点
- 场景(Scene)
- 文本几何体(TextGeometry)
- 字体加载器(FontLoader)
- 轨道控制器(OrbitControls)
准备
- threejs
- vue-cli
- helvetiker_bold.typeface.json(字体)
红色背景实现
因为红包是红的,所以我们需要一个红色的背景。如下
1. 原理
场景(Scene)的属性有background
。文档描述如下:
若不为空,在渲染场景的时候将设置背景,且背景总是首先被渲染的。 可以设置一个用于的“clear”的Color(颜色)、一个覆盖canvas的Texture(纹理), 或是 a cubemap as a CubeTexture or an equirectangular as a Texture。默认值为null。
2. 代码
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0xe55439);
文字环实现
1. 加载字体
const loader = new FontLoader();
loader.load("/assets/fonts/helvetiker_bold.typeface.json", (res) => {
...
});
2. 创建文字
const text = "2022@JUEJIN@HAPPYNEWYEAR2022@JUEJIN@HAPPYNEWYEAR";
for (let i = 0; i < text.length; i++) {
const x = Math.floor(Math.cos((Math.PI / 24) * i) * -30);
const y = 0;
const z = Math.floor(Math.sin((Math.PI / 24) * i) * 30);
const font = new TextGeometry(text[i], {
font: res,
size: 4, //字体大小
height: 1, // 挤出文本的厚度
curveSegments: 12, // 曲线上点的数量。默认值为12
bevelEnabled: true, // 是否开启斜角,默认为false
bevelThickness: 0.5, // 文本上斜角的深度,默认值为20
bevelSize: 0.03, //斜角与原始文本轮廓之间的延伸距离。默认值为8
bevelSegments: 3, // 斜角的分段数。默认值为3
});
font.center();
const material = new THREE.MeshBasicMaterial({
color: 0xffcea3,
});
const textMesh = new THREE.Mesh(font, material);
textMesh.position.set(x, y, z);
textMesh.rotateY((Math.PI / 24) * i - Math.PI / 2);
}
3. 文字编组
this.textGroup = new THREE.Group();
this.textGroup && this.textGroup.add(textMesh);
this.scene.add(this.textGroup);
效果如下:
4.增加切斜角度
this.textGroup.rotateY(Math.PI * -0.2);
this.textGroup.rotateZ(Math.PI * -0.1);
效果如下:
5.增加旋转动画
if (this.textGroup) {
const axis = new THREE.Vector3(0, 1, 0); //向量axis
this.textGroup.rotateOnAxis(axis, -Math.PI / 200); //绕axis轴旋转π / 200
}
完整代码
setText(): void {
const loader = new FontLoader();
loader.load("/assets/fonts/helvetiker_bold.typeface.json", (res) => {
if (this.scene) {
this.textGroup = new THREE.Group();
const text = "2022@JUEJIN@HAPPYNEWYEAR2022@JUEJIN@HAPPYNEWYEAR";
for (let i = 0; i < text.length; i++) {
const x = Math.floor(Math.cos((Math.PI / 24) * i) * -30);
const y = 0;
const z = Math.floor(Math.sin((Math.PI / 24) * i) * 30);
const font = new TextGeometry(text[i], {
font: res,
size: 4, //字体大小
height: 1, // 挤出文本的厚度
curveSegments: 12, // 曲线上点的数量。默认值为12
bevelEnabled: true, // 是否开启斜角,默认为false
bevelThickness: 0.5, // 文本上斜角的深度,默认值为20
bevelSize: 0.03, //斜角与原始文本轮廓之间的延伸距离。默认值为8
bevelSegments: 3, // 斜角的分段数。默认值为3
});
font.center();
const material = new THREE.MeshBasicMaterial({
color: 0xffcea3,
});
const textMesh = new THREE.Mesh(font, material);
textMesh.position.set(x, y, z);
textMesh.rotateY((Math.PI / 24) * i - Math.PI / 2);
this.textGroup && this.textGroup.add(textMesh);
}
this.textGroup.rotateY(Math.PI * -0.2);
this.textGroup.rotateZ(Math.PI * -0.1);
this.scene.add(this.textGroup);
}
});
}
效果
总结
因为红包结构比较复杂,本人也是业余创作,所以一次很难完成,我将会分几期分开来实现掘金红包,大家也可以关注我以后的文章,谢谢大家。