马黑PHP整站系统

ThreeJS :给立方体各面加上文字

位置: 首页 > 前端三套件[ 发布时间: 2025.6.18  作者: 马黑  阅读: 58 ]

ThreeJS 对文本的处理相对薄弱,它提供有一个扩展几何体 TextGeometry,需要加载字体,且对非英文字体一点都不友好。故此,若需要给立方体每一个面都添加文本,需要另辟蹊径,其中,通过离线 canvas 绘制文本然后作为纹理贴图贴到立方体的每一个面,是个很常见的实现方法。

ThreeJS 本身就是通过 canvas 标签在2d平面上绘制3d效果,它对 canvas 的支持度非常好,核心库内置有canvas纹理,一个 CanvasTexture 类,构造器复杂无比(CanvasTexture),不过没关系,通常用到的参数主要只是一个 canvas 标签,像这样:

const texture = new THREE.CanvasTexture(canvasElement);

canvasElement 即为canvas画布元素,其上应该是已经绘制好了所需文本。为此,需要熟悉 canvas 绘制文本功能,可以参阅 canvas绘制文本 加以学习掌握,主要学习其上介绍的 fillText 方法,因为 ThreeJS 貌似对 strokeText 支持不好。

为方便复用,我编写了一个在 canvas 画布上绘制文本的函数:

function mkText(txt, font, color, bg, w, h) {
	const canv = document.createElement('canvas');
	canv.width = w;
	canv.height = h;
	const ctx = canv.getContext('2d');
	ctx.fillStyle = bg;
	ctx.fillRect(0, 0, w, h); // 绘制矩形(面的背景色)
	ctx.font = font;
	ctx.textAlign = 'center';
	ctx.textBaseline = 'middle';
	ctx.fillStyle = color;
	ctx.fillText(txt, w/2, h/2); // 绘制文本
	return canv;
};
	

参数解释:

1. txt : 输出的文本,文本型
2. font : 字体设置,字符型,例如,'bold 20px "宋体"'
3. color : 文本颜色,字符型
4. bg : 背景色,字符型
5. w : 宽度,数值型
6. h : 高度,数值型

可以根据需要修改绘制文本的函数。这是离线创建的 canvas 标签,它没有添加到文档中,不会显示出来。函数返回(return)所创建的 canvas 画布 canv,所以,下一步,以其返回值创建 ThreeJS 纹理:

const texture = new THREE.CanvasTexture(
	mkText(
		'文字', // 1. 输出的文本
		'bold 24px "微软雅黑"', // 2. 字体设置
		'white', // 3. 前景色
		'purple', // 4. 背景色
		100, // 5. 宽度
		50 // 6. 高度
	)
);
// 代码可以写在一行
// const texture = mkText('文字', '24px "微软雅黑"', 'white', 'purple', 100, 50)
	

最后创建立由方体几何体 BoxGeometry 和六个面的基础材质 MeshBasicMaterial 构建而成的 Mesh 网格,再初始化 Mesh 的 Pose,加上旋转动画,就大功告成。下面是完整代码,可在线运行:

<script type="module">
	import { THREE, scene, camera, renderer, clock, basic3, click3 } from 'https://638183.freep.cn/638183/3dev/3/3basic.js';

	basic3();

	const texts = ['1', '2', '3', '4', '5', '6'];
	let faces = [];

	texts.forEach(text => {
		const texture = new THREE.CanvasTexture(mkText(text, 'bold 24px "微软雅黑"', 'white', 'purple', 100, 50));
		faces.push(new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff, map: texture}));
	});

	const mesh = new THREE.Mesh(new THREE.BoxGeometry(), faces);
	mesh.rotateY(Math.PI / 4);

	scene.add(mesh);

	animate();

	function animate() {
		requestAnimationFrame(animate);
		const delta = clock.getDelta();
		mesh.rotation.x -= delta / 2;
		renderer.render(scene, camera);
	};

	function mkText(txt, font, color, bg, w, h) {
		const canv = document.createElement('canvas');
		canv.width = w;
		canv.height = h;
		const ctx = canv.getContext('2d');
		ctx.fillStyle = bg;
		ctx.fillRect(0, 0, w, h);
		ctx.font = font;
		ctx.textAlign = 'center';
		ctx.textBaseline = 'middle';
		ctx.fillStyle = color;
		ctx.fillText(txt, w/2, h/2);
		return canv;
	};
</script>
	

前一篇: ThreeJS 直管道
下一篇: ThreeJS点材质着色问题

发表评论:

       

评论列表 [1条]

#1 | 飞飞 于 2025-6-19 11:29 发布: 这样添加上文字跟骰子似的

Copyright © 2023 All Right Reserved 马黑PHP文章管理整站系统v1.8
联系我们: gxblk@163.com