文字到底能玩出多少花样(一) 炫酷文字粒子效果实现

简介: 文字到底能玩出多少花样(一) 炫酷文字粒子效果实现

前言


前几天在整理书签时,发现收藏了好多宝藏网站,宝藏项目,就光说文字效果,就让诸位大佬玩出了一万个花样,所以阿包准备跟大家一起来分享和学习这些异彩纷呈的创意和写法。


该文作为《文字到底能玩出多少花样》的第一篇文章,首先来带大家学习 文字粒子 的实现。


文字粒子这个创意最先源自于哪位大佬我也不知道,但我最早发现这个效果是 kennethcachia 写的巨炫酷的文字粒子效果,每次我打开这个 demo ,我都感觉我是个审美笨比,大佬做的真炫酷,真漂亮。


下面是 shape-shifter 效果的 github 地址和 demo 演示界面:



不多说了,一起进入阿包的文字粒子效果吧。


基础知识


文章最开始之前,先带大家了解两个 canvas 函数


fillText


语法


ctx.fillText(text, x, y, [maxWidth]);
复制代码


参数


  • text: 规定在画布上输出的文本。
  • x: 文本起点的 x 轴坐标。
  • y: 文本起点的 y 轴坐标。
  • maxWidth: 可选,绘制的最大宽度。


可以通过 font 属性来定义字体和字号,fillStyle 属性来定义字体颜色。


getImageData


语法


ctx.getImageData(sx, sy, sw, sh);
复制代码


参数


  • sx, sy: 要提取图像的左上角 x y 坐标
  • sw, sh: 要提取图像的宽高


返回值


  • 返回 ImageData 对象,该对象拷贝了指定图像区域的像素
  • 对于图像中每个像素点,都分别存放 RGBA 四方面的信息,所有的像素数据以一维数组形式存放在 data 属性中


绘制思路


在基础知识方面,我首先介绍了两个方法: fillTextgetImageDatafillText 可以在画布上绘制文字,getImageData 可以提取画布上一定矩形区域的像素点。也就是说,通过这两个方法就可以提取到我们绘制的文字的像素数据。那剩下的工作就是怎么处理这些像素数据,绘制对应运动粒子就可以。


下面来分析一下具体实现思路:


  1. 绘制主画布: 作为文字粒子的渲染画布
  2. 生成副画布: 作为绘制文字的画布,不需要添加到页面中,作为提取绘制文字像素的载体
  3. 生成文字粒子: 根据获取到的像素点,渲染粒子
  4. 文字粒子运动轨迹: 计算每个粒子的移动轨迹
  5. 启动动画


初始化工作


设立配置项 optionstextOptions ,分别存放画布的宽高、速度等信息和副画布文字的配置。


const options = {
    width: 400,
    height: 400,
    speed: 10
};
const textOptions = {
    words: "战场小包",
    font: "200px fangsong",
};
复制代码


绘制主画布


主画布已经通过  标签添加至页面中,因此只需要配置它的 widthheight ,为了方便展示,将 canvas 宽高设置为浏览器宽高


function pointCanvas(canvas, { width, height }) {
    canvas.width = width;
    canvas.height = height;
    ctx = canvas.getContext("2d");
    return ctx;
}
// pointCavas(canvas, options)
复制代码


创建副画布


副画布的创建也非常简单,只需要通过 JavaScript 创建一个 canvas 节点,配置副画布的宽高(与主画布相同),不需要添加到 dom 中。


副画布与主画布的宽高保持一致,这样副画布中的像素点,就可以对应到主画布中的像素位置,无需进行转换


function createVitualCvs({ width, height }) {
    const vitualCvs = document.createElement("canvas");
    vitualCvs.width = width;
    vitualCvs.height = height;
    let vitualCxt = vitualCvs.getContext("2d");
    initCanvas(vitualCxt, options, textOptions);
    return getFontInfo(vitualCxt, options);
}
复制代码


初始化副画布


设置文字属性,通过 fillText 绘制文字。通过 (canvas.width -  measure.width) / 2 保证在画布中间绘制文字。


measureText 可以获取到文字的宽高,更详细的参考链接: measureText


function initCanvas(ctx, { width, height }, { font, words }) {
    ctx.font = font;
    const measure = ctx.measureText(words);
    ctx.fillText(words, (width - measure.width) / 2, height / 2);
}
复制代码


构建粒子类


每个粒子有以下属性:


  • x: 粒子最终停留的位置 x 坐标
  • y: 粒子最终停留的位置 y 坐标
  • mx: 初始化时粒子的 x 坐标位置
  • my: 初始化时粒子的 y 坐标位置
  • radius: 粒子大小
  • speed: 粒子移动速度


同时还具备两个方法:


  • draw: 绘制粒子本身的方法
  • update: 更新粒子位置的方法


这里给出 drawupdate 方法代码


draw() {
    ctx.beginPath();
    ctx.fillStyle = this.color;
    ctx.arc(this.mx, this.my, this.radius, 0, Math.PI * 2, false);
    ctx.fill();
    this.update();
}
// 我这里的 update 比较简单,如果想要更复杂更炫酷的效果,可以使用贝塞尔曲线 
update() {
    this.mx = this.mx + (this.x - this.mx) / this.speed;
    this.my = this.my + (this.y - this.my) / this.speed;
}
复制代码


深入理解贝塞尔曲线


获取文字位置信息,绘制粒子


通过 getImageData 获取副画布的像素信息,getImageData 返回值中对每个像素点存储 RGBA 四方面信息,因此每四个数组元素代表一个像素点,可以通过 Alpha 来判断该像素点是否存在文字。


function getWordPxInfo(ctx, { width, height }) {
    let imageData = ctx.getImageData(0, 0, width, height).data;
    const particles = [];
    for (let x = 0; x < width; x += 4) {
        // 为了粒子效果出现,间隔选点
        for (let y = 0; y < height; y += 4) {
        // 判断当前像素点是否有文字
        const pxAlphaIndex = (x + y * width) * 4 + 3;
        if (imageData[pxAlphaIndex] > 0) {
            particles.push(
            new Particle({
                x,
                y,
            })
            );
        }
        }
    }
    return particles;
}
复制代码


启动动画


动画是通过 requestAnimationFrame 实现,每一帧清空画布,重新绘制所有的粒子。


requestAnimationFrame学习: 【今天你更博学了么】一个神奇的前端动画 API requestAnimationFrame


function init(points, { width, height }) {
    ctx.clearRect(0, 0, width, height);
    points.forEach((value) => {
        value.draw();
    });
    const timer = window.requestAnimationFrame(function () {
        init(points, options);
    });
}
复制代码


大功告成


大功告成,摸鱼成功。


源码仓库


传送门: 文字粒子



相关文章
|
数据安全/隐私保护
全球免费编程教育网站:Code.org
你还在为小朋友的编程教育而发愁吗? 你还在为小朋友放假无聊而头疼吗? 他来了他来了,全球免费编程教育网站来了。 2013年成立的Code.org是一个非营利组织。 它致力于为年轻女子、学生从来自少数民族提供机会。 其愿景是:每所学校的每位学生都有机会学习计算机科学,就像学习生物、化学和代数。 提供了最广泛讲授的中小学计算机科学课程,也会每年组织编程一小时活动。 这已吸引了全世界约 10% 的学生来参与。 Code.org 得到了亚马逊、脸书、谷歌、印孚瑟斯基金会、微软等更多慷慨捐助者的支持。
3303 0
|
Web App开发
如何搭建 Scratch 官方网页版?真正意义上的一键安装部署
功能介绍 Scratch 是一款由麻省理工学院(MIT) 设计开发的一款面向少年的简易编程工具,Scratch 已经是少儿编程行业的基础软件。使用 Scratch,你可以编写属于你的互动媒体,像是故事、游戏、动画,然后你可以将你的创意分享给全世界。
9657 0
|
1月前
|
人工智能 弹性计算 数据可视化
Hermes Agent 是什么?被戏称 “爱马仕” 的自主 AI 智能体,不止是 OpenClaw 平替!
OpenClaw“龙虾”神话还未降温,Hermes Agent “爱马仕”已经悄然登上了王座!
1574 0
|
存储 监控 网络协议
服务器压力测试是一种评估系统在极端条件下的表现和稳定性的技术
【10月更文挑战第11天】服务器压力测试是一种评估系统在极端条件下的表现和稳定性的技术
778 32
|
编解码 监控 网络协议
RTSP协议规范与SmartMediaKit播放器技术解析
RTSP协议是实时流媒体传输的重要规范,大牛直播SDK的rtsp播放器基于此构建,具备跨平台支持、超低延迟(100-300ms)、多实例播放、高效资源利用、音视频同步等优势。它广泛应用于安防监控、远程教学等领域,提供实时录像、快照等功能,优化网络传输与解码效率,并通过事件回调机制保障稳定性。作为高性能解决方案,它推动了实时流媒体技术的发展。
683 5
|
机器学习/深度学习 人工智能
Qwen2VL-Flux:开源的多模态图像生成模型,支持多种生成模式
Qwen2VL-Flux 是一个开源的多模态图像生成模型,结合了 Qwen2VL 的视觉语言理解和 FLUX 框架,能够基于文本提示和图像参考生成高质量的图像。该模型支持多种生成模式,包括变体生成、图像到图像转换、智能修复及 ControlNet 引导生成,具备深度估计和线条检测功能,提供灵活的注意力机制和高分辨率输出,是一站式的图像生成解决方案。
1738 4
Qwen2VL-Flux:开源的多模态图像生成模型,支持多种生成模式
|
机器学习/深度学习 人工智能 安全
合合信息在视觉内容安全领域的创新与应用-应对伪造挑战的前沿进展
在2024年中国图象图形学学会青年科学家会议上,上海合合信息科技股份有限公司图像算法研发总监郭丰俊博士分享了“视觉内容安全技术的前沿进展与应用”。随着AI技术的发展,尤其是深度学习和生成对抗网络(GANs)的成熟,视觉内容伪造技术日益复杂,给传统审核手段带来挑战。郭博士介绍了合合信息在图像、视频篡改检测及人脸鉴伪等领域的创新解决方案,强调了大模型如ForgeryGPT的应用前景,并指出未来视觉内容安全将趋向多模态检测和智能化防护,以应对不断演化的伪造手段。合合信息通过自研AI算法,实现了对篡改区域的精确识别,具备较强的跨域泛化能力,已在金融、政府监管等领域广泛应用。
|
存储 数据处理 Kotlin
Kotlin Flow背后的神秘力量:背压、缓冲与合并策略的终极揭秘!
【9月更文挑战第13天】Kotlin Flow 是 Kotlin 协程库中处理异步数据流的强大工具,本文通过对比传统方法,深入探讨 Flow 的背压、缓冲及合并策略。背压通过 `buffer` 函数控制生产者和消费者的速率,避免过载;缓冲则允许数据暂存,使消费者按需消费;合并策略如 `merge`、`combine` 和 `zip` 则帮助处理多数据源的整合。通过这些功能,Flow 能更高效地应对复杂数据处理场景。
689 2
|
移动开发 前端开发 JavaScript
学习Particles.js 给网页来点粒子特效
学习Particles.js 给网页来点粒子特效
994 0