Three.js中的3D文字效果

这篇具有很好参考价值的文章主要介绍了Three.js中的3D文字效果。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

对于一些设计网页中经常会出现一些3D的文字效果,本文将利用Three.js实现各种动画WebGL文本输入效果。

threejs渲染文字,threejs,javascript,3d,动画文章来源地址https://www.toymoban.com/news/detail-783638.html

示例效果
原文章

文本采样

通常情况下,文本网格是2D的平面形状,我们所要实现的3D文本形状则是要在2D的平面下,再生成z值形成一个立体的效果。

首先,我们创建一个canvas元素,对其应用一些与字体相关的样式,并确保其大小canvas足以容纳文本。

// 字体样式设置
const fontName = 'Verdana';
const textureFontSize = 100;

// 显示内容
let string = 'Some text' + '\n' + 'to sample' + '\n' + 'with Canvas';

// 创建canvas的2D上下文
const textCanvas = document.createElement('canvas');
const textCtx = textCanvas.getContext('2d');
document.body.appendChild(textCanvas);

设置样式后,我们在canvas上绘制文本。

function sampleCoordinates() {

    // 解析文本
    const lines = string.split(`\n`);
    const linesMaxLength = [...lines].sort((a, b) => b.length - a.length)[0].length;
    const wTexture = textureFontSize * .7 * linesMaxLength;
    const hTexture = lines.length * textureFontSize;

    // 绘制文本
    const linesNumber = lines.length;
    textCanvas.width = wTexture;
    textCanvas.height = hTexture;
    textCtx.font = '100 ' + textureFontSize + 'px ' + fontName;
    textCtx.fillStyle = '#2a9d8f';
    textCtx.clearRect(0, 0, textCanvas.width, textCanvas.height);
    for (let i = 0; i < linesNumber; i++) {
        textCtx.fillText(lines[i], 0, (i + .8) * hTexture / linesNumber);
    }

    // ...
}

接下来我们可以从中获取ImageData,该ImageData对象包含一个一维数组,其中包含每个像素的RGBA数据。通过canvas的大小,我们可以遍历该数组并检查已有像素颜色位置(即文本位置)。

    // 采样坐标
    textureCoordinates = [];
    const samplingStep = 4;
    if (wTexture > 0) {
        const imageData = textCtx.getImageData(0, 0, textCanvas.width, textCanvas.height);
        for (let i = 0; i < textCanvas.height; i += samplingStep) {
            for (let j = 0; j < textCanvas.width; j += samplingStep) {
                // 因为背景的RGBA是(0,0,0,0),所以可以通过判断r通道颜色来区分是否是文字
                if (imageData.data[(j + i * textCanvas.width) * 4] > 0) {
                    textureCoordinates.push({
                        x: j,
                        y: i
                    })
                }
            }
        }
    }

在采样步骤其实可以做一些比如添加随机性、对文本运用轮廓描边等工作。把点采样出来之后,可以在2d canvas上再绘制一遍检验效果。

threejs渲染文字,threejs,javascript,3d,动画

在Three.js的场景中绘制

设置一个基本的Three.js场景,创建一个Plane对象,我们可以使用上一步中的文本采样画布作为Plane的材质。

threejs渲染文字,threejs,javascript,3d,动画

生成粒子

我们可以使用相同的采样函数来对文字生成3D坐标。X、Y坐标是从画布中采集的,对于Z坐标,我们可以取一个随机数。我们可以用THREE.Points来展示这些例子

function createParticles() {
    const geometry = new THREE.BufferGeometry();
    const material = new THREE.PointsMaterial({
        color: 0xff0000,
        size: 2
    });
    const vertices = [];
    for (let i = 0; i < textureCoordinates.length; i ++) {
        vertices.push(textureCoordinates[i].x, textureCoordinates[i].y, 5 * Math.random());
    }
    geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    const particles = new THREE.Points(geometry, material);
    scene.add(particles);
}

因为纹理坐标和三维场景坐标y轴的不同,所以生成的粒子会发现上下颠倒。所以我们需要翻转每个粒子的Y值,为此我们需要计算文本的边界框。作为一种临时解决方案,我们可以将最大X、Y值作为文本的最大宽高值。

function refreshText() {
    sampleCoordinates();
    
    const maxX = textureCoordinates.map(v => v.x).sort((a, b) => (b - a))[0];
    const maxY = textureCoordinates.map(v => v.y).sort((a, b) => (b - a))[0];
    stringBox.wScene = maxX;
    stringBox.hScene = maxY;

    createParticles();
}

对于每个点,Y坐标变为boxTotalHeight-Y。将整个粒子系统移动盒子的一半宽度和一半高度可以解决居中问题。

function createParticles() {
    
    // ...
    for (let i = 0; i < textureCoordinates.length; i ++) {
       // 将Y进行翻转
       vertices.push(textureCoordinates[i].x, stringBox.hScene - textureCoordinates[i].y, 5 * Math.random());
    }
    // ...
    
    // 将文字居中
    particles.position.x = -.5 * stringBox.wScene;
    particles.position.y = -.5 * stringBox.hScene;
}

到目前为止,我们是借助文本canvas直接从3D场景中收集的像素坐标。但是假设我们需要3D文本的高度等于10个单位。如果我们将字体大小设置为10,则canvas分辨率将太低而无法进行适当的采样。为了避免这种情况(并且更灵活地使用粒子密度),我们可以添加一个额外的缩放因子(在3D空间中使用它们之前,我们将与画布坐标相乘的值)。

// ...
const textureFontSize = 30;
const fontScaleFactor = .3;
// ...
function refreshText() {
    // ...
    textureCoordinates = textureCoordinates.map(c => {
        return { x: c.x * fontScaleFactor, y: c.y * fontScaleFactor }
    });
    // ...
}

切换到InstancedMesh

THREE.Points的主要限制是粒子大小。THREE.PointsMaterial是基于WebGL的gl_PointSize,它可以以大约50 到 100 的最大像素大小进行渲染,具体取决于显卡。如果我们想要用3D形状来作为粒子形状的话,只能用THREE.InstancedMesh

首先根据粒子数量创建InstancedMesh,然后添加要用于每个实例的几何体和材质,再创建一个虚拟对象,帮助我们为每个粒子生成一个 4×4 变换矩阵。使用setMatrixAt方法将变换矩阵应用于每个实例

function updateParticlesMatrices() {
    let idx = 0;
    textureCoordinates.forEach(p => {

        // we apply samples coordinates like before + some random rotation
        dummy.rotation.set(2 * Math.random(), 2 * Math.random(), 2 * Math.random());
        dummy.position.set(p.x, stringBox.hScene - p.y, Math.random());

        dummy.updateMatrix();
        instancedMesh.setMatrixAt(idx, dummy.matrix);

        idx ++;
    })
    instancedMesh.instanceMatrix.needsUpdate = true;
}

基本动画

我们可以为文字做一些基本的动画。我们可以添加一个额外的Particle对象数组来存储每个实例的参数,仍然需要textureCoordinates数组来存储以像素为单位的2D坐标,但现在我们将它们重新映射到particles数组。然后粒子变换更新放到主render循环中。

每个Particle对象都包含一个属性列表和一个grow()更新其中一些属性的函数。

首先,我们定义位置、旋转和缩放。每个粒子的位置都是静态的,创建粒子时比例会从零增加到一,并且旋转将始终设置动画。

function Particle([x, y]) {
    this.x = x;
    this.y = y;
    this.z = 0;
    this.rotationX = Math.random() * 2 * Math.PI;
    this.rotationY = Math.random() * 2 * Math.PI;
    this.rotationZ = Math.random() * 2 * Math.PI;
    this.scale = 0;
    this.deltaRotation = .2 * (Math.random() - .5);
    this.deltaScale = .01 + .2 * Math.random();
    this.grow = function () {
        this.rotationX += this.deltaRotation;
        this.rotationY += this.deltaRotation;
        this.rotationZ += this.deltaRotation;
        if (this.scale < 1) {
            this.scale += this.deltaScale;
        }
    }
}
// ...
function updateParticlesMatrices() {
    let idx = 0;
    // textureCoordinates.forEach(p => {
    particles.forEach(p => {
        // update the particles data
        p.grow();
        // dummy.rotation.set(2 * Math.random(), 2 * Math.random(), 2 * Math.random());
        dummy.rotation.set(p.rotationX, p.rotationY, p.rotationZ);
        dummy.scale.set(p.scale, p.scale, p.scale);
        dummy.position.set(p.x, stringBox.hScene - p.y, p.z);
        dummy.updateMatrix();
        instancedMesh.setMatrixAt(idx, dummy.matrix);
        idx ++;
    })
    instancedMesh.instanceMatrix.needsUpdate = true;
}

其他扩展

我们也可以利用上述流程做一些气泡、云朵、花草的文字效果。

threejs渲染文字,threejs,javascript,3d,动画

threejs渲染文字,threejs,javascript,3d,动画

到了这里,关于Three.js中的3D文字效果的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Three.js--》实现图片转3D效果展示

    目录 项目搭建 初始化three.js基础代码 加载图片纹理 设置着色器 今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。 项目搭建 本案例还是借助框架书写three项目,借用vite构建工具搭建vue项目

    2024年02月08日
    浏览(60)
  • Three.js--》实现3D汽车展厅效果展示

    目录 项目搭建 初始化three.js基础代码 加载汽车模型 设置展厅效果 设置GUI面板动态控制车身操作 车门操作与车身视角展示 设置手动点击打开关闭车门 设置图片背景 今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起

    2024年02月09日
    浏览(60)
  • WEB 3D技术 three.js 3D贺卡(3) 点光源灯光动画效果

    经过 上文 WEB 3D技术 three.js 3D贺卡(2) 加入天空与水面效果 我们将水面 和 天空的效果搭建了一下 那么 我们将四周 点光源的效果做一下 首先 我们将 renderer.toneMappingExposure 的值 改为 0.1 让效果看着明显一点 这样 整个界面就会暗下来 然后 我们在任意位置 加入代码 创建一个点

    2024年01月19日
    浏览(58)
  • WEB 3D技术 three.js 3D贺卡(2) 加入天空与水面效果

    上文 WEB 3D技术 three.js 3D贺卡(1) 搭建基本项目环境 我们简单搭了一个贺卡雏形 然后 我们要引入一个hdr的一个天空的效果 所以 我们需要在代码中导入 RGBELoader 这里 大家可以选择下载我的hdr资源 WEB 3D技术 three.js 3D贺卡 天空 hdr资源 下载好之后呢 我们在外面套一个 xhdr 文件夹

    2024年01月18日
    浏览(68)
  • vue 项目使用three.js 实现3D看房效果

    0.前言 该教程能帮助直接写出vue项目的3D看房效果!!! 先上效果图 1.安装依赖 2.vue代码 这里文件名为three.vue 代码非原创,出处 vue3+threejs实现全景看房 (异步加载 BOLLROOM 部件为对原代码的修改) 注意这里的hdr 文件必须要放在assets文件夹中,且要通过import模块的形式导入!

    2024年02月13日
    浏览(56)
  • web上构建3d效果 基于three.js的实例

    web页面上提供3D效果,可以为页面提供不少色彩,H5之后canvas 为webgl提供了基础,使得在web页面使用JS也能写出3D的效果,其中three.js作为封装了图形函数 的框架,为入门提供了方便,效果图如下。   以上是官方例子中其中的三个,没接触过的朋友肯定会觉得很神奇,事实上

    2024年02月05日
    浏览(50)
  • vue2+three.js实现类似VR、3D全景效果

    效果图: 俩图标是我自己加的前进后退按钮,也是百度了好久,再加上GPT的帮助,才给搞出来。因为需求急,都不看官方文档,百度到一个能跑的demo之后改吧改吧,就先用着了。 下面是代码: 这里 代码有很多用不到的地方和需要优化的地方,我是来不及改了,就先这样吧

    2024年02月15日
    浏览(54)
  • vue2+three.js+blender(实现3d 模型引入并可点击效果)

    2023.9.13今天我学习了如何把3d建模里面的模型引入到vue中,并可以实现拖动,点击的效果: 首先安装: npm install three 相关代码如下:  如果没有图片可以去 Three.js--》建模软件如何加载外部3D模型?_threejs加载3d模型_亦世凡华、的博客-CSDN博客

    2024年02月03日
    浏览(64)
  • 【THREE.JS】网页中的炫酷3D

    概述 :基于 WebGL 的三维引擎,目前是国内资料最多、使用最广泛的 三维引擎 ,可以制作一些 3D 可视化项目 目前随着 元宇宙 概念的爆火, THREE 技术已经深入到了物联网、VR、游戏、数据可视化等多个平台。 最近一段时间主要对之前学习three.js的总结和记录,记录只对自己

    2024年02月03日
    浏览(50)
  • 探索微信小程序中的3D世界:Three.js Mini Program

    项目地址:https://gitcode.com/wechat-miniprogram/threejs-miniprogram 在当今的移动应用领域,3D图形已经逐渐成为提升用户体验的重要手段。微信小程序作为一个轻量级的应用平台,也在逐步引入高级功能以满足开发者的需求。现在,借助于Three.js Mini Program,开发者可以在微信小程序中轻

    2024年04月25日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包