JavaScript Canvas 实现字符雨动画效果详解
作者:流萤时间:2026-10-25 12:43:16浏览:533
本文详细解析了利用 JavaScript Canvas 实现字符雨下落效果的原理与代码。通过控制黑色半透明背景的重绘频率实现字符渐隐,并结合随机概率算法控制各列字符的刷新节奏,从而营造出参差不齐的下落视觉体验。文章提供了从 HTML 结构、CSS 样式到核心 JS 类实现的完整代码示例,帮助开发者快速掌握该特效的制作技巧。
本文提供了使用 JavaScript Canvas 实现字符雨动画效果的具体代码示例,供读者参考学习。
字符雨效果

实现原理分析
- 字符雨从上往下逐渐消失的原理:在
canvas中绘制字符时,每次循环都会重绘一层带有透明度的黑色背景。该黑色背景的透明度设置为 0.08(经测试此数值较为合适,也可调整以观察不同效果)。由于字符从上往下依次出现,上方字符先绘制,下方字符后绘制。程序重复绘制半透明黑色背景,使得上方先出现的字符逐渐被覆盖变暗,而下方后出现的字符保持相对清晰,从而形成字符逐渐消失的视觉错觉。 - 部分列出现字符的控制逻辑:若不进行控制,
canvas的每一列都会同时出现字符,导致效果整齐划一而非参差不齐。因此,引入一个代表出现机率的变量进行控制。当字符落到canvas底部时,程序生成一个随机数与出现机率进行比较。若随机数大于该阈值,则允许该列从顶部重新生成字符;否则,该列在当前循环中不生成新字符,需等待下一次循环再次比较随机数。通过这种机制,实现了部分列有字符、部分列无字符的随机分布效果。
实例创建步骤
let charRain = new CharRain("canvas_id");HTML 结构搭建
<canvas id="canvas"></canvas>CSS 样式设置
body{
margin: 0;
padding: 0;
overflow: hidden;
}
#canvas{
background-color: #111;
}JavaScript 核心源码
;(function(win){
/**
* 创造字符雨
*/
class CharRain
{
/**
* @description CharRain 类的构造函数
* @constructs
* @param {string} canvas_id - canvas 元素的 id
*/
constructor(canvas_id){
this.canvas = document.getElementById(canvas_id);
this.context = this.canvas.getContext("2d");
this.bg_alpha = 0.08; // canvas背景的透明度,也是字符消失的速度;取值范围:0 - 1
this.appearRate = 0.95; // canvas中每一列字符下落到底部后再次出现字符的机率;取值范围:0 - 1
this.dropSpeed = 30; // 字符下落速度
this.fontSize = 17; // 字符大小;也确定了字符列的数目,列之间的间距
this.colunm = 0; // 画布中的字符列的数目
this.isColorful = false; // 是否呈现彩色字符雨,默认为经典黑底绿字
this.drops = []; // 记录每一列的字符下落的 y 值
this.timer = null; // 定时器
this.chars = "abcdefghijklmnopqrstuvwxyz0123456789"; // 可选字符
this.init();
}
/**
* @description 初始化类
*/
init(){
let _this = this;
this.setAttr();
win.addEventListener("resize", function (){ // 添加浏览器窗口变化监听,重新设置相关属性
_this.setAttr();
});
this.timer = setInterval(function (){ // 添加定时器,下落
_this.draw();
}, _this.dropSpeed);
}
/**
* @description 设置类的一些属性
*/
setAttr(){
this.canvas.width = win.innerWidth;
this.canvas.height = win.innerHeight; // 重新设置 canvas 的宽度和高度
this.colunm = Math.ceil(win.innerWidth / this.fontSize); // 重新设置列数
for (let i=0; i<this.colunm; i++) {
if(!this.drops[i]) { // 已经存在下落字符的列不用设置
this.drops[i] = win.innerHeight; // 字符瀑布流直接开始下落
}
}
}
/**
* @description 随机一个颜色
* @return {string} rgba 颜色值
*/
randomColor(){
let r = Math.floor(Math.random()*256);
let g = Math.floor(Math.random()*256);
let b = Math.floor(Math.random()*256);
return "rgba("+r+","+g+","+b+", 1)";
}
/**
* @description 在画布上画出下落的字符
*/
draw(){
this.context.fillStyle = "rgba(1,1,1," + this.bg_alpha + ")"; // 叠加画黑色背景,通过不透明度,形成字符逐渐消失的效果
this.context.fillRect(0, 0, win.innerWidth, win.innerHeight); // 画矩形以清除之前画的字符
this.context.font = this.fontSize + "px Consolas"; // 设置字符的大小、样式
if(this.isColorful) {
this.context.fillStyle = this.randomColor(); // 呈现彩色字符雨
} else {
this.context.fillStyle = "#00cc33"; // 经典黑底绿字
}
for(let i=0; i<this.colunm; i++) { // 在每一列上画出字符
let index = Math.floor(Math.random() * this.chars.length); // 随机一个字符
let x = i * this.fontSize;
let y = this.drops[i] * this.fontSize; // 字符在 y 轴方向上的距离
this.context.fillText(this.chars[index], x, y); // 画字符
if (y>=this.canvas.height && Math.random()>this.appearRate) { // 字符落到底部 && 有再次出现的机率
this.drops[i] = 0; // 0 代表每一列的字符位置回到顶部
} else {
this.drops[i]++; // 字符逐渐下落,字符在 y 轴上的距离增加一
}
}
}
}
win.CharRain = CharRain;
}(window));以上内容为本文的全部代码与解析,希望对读者学习有所帮助。欢迎继续支持本站获取更多技术资源。
作者最新文章
JavaScript将图片转换为Base64编码的两种途径
2026-11-05 16:43:05
怎么在 Vue 或 React 项目中正确集成 animate.js
2026-11-05 10:23:38
JS注册事件:addEventListener基础语法与参数详解
2026-11-05 08:44:56
JSP和JS的区别:运行环境与服务端/客户端职责解析
2026-11-04 23:34:36
pdf.js 官方下载地址:GitHub Release 获取预编译包
2026-11-04 23:07:27
