使用 JavaScript 实现矩阵下雨代码效果
动机
执行
结论
您可以从哪里向我了解更多信息?
CMatrix - JavaScript 中的矩阵效应
动机
新电影《黑客帝国》今年上映,我太期待了,所以不得不用我的工具来制作这个标志性的效果。实现过程本身非常简单,我只用了 HTML、CSS 和原生 JavaScript。
如果您更喜欢视频格式,您可以在 YouTube 上查看我的教程:
执行
我将使用 HTML 画布来创建“数字雨”效果,并且我们将在 javascript 中进行所有登录。
HTML
HTML 文件非常简单。在 body 中我们只有一个<canvas>
,并且我在底部添加了 javascript 文件,你也可以使用defer
属性将其添加到 head 中。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./styles.css">
<title>Matrix digital rain</title>
</head>
<body>
<canvas id="Matrix"></canvas>
<script src="./index.js"></script>
</body>
</html>
CSS
这部分内容应该很短。在 CSS 中,我基本上只是让 body 填充整个视口,并为其设置黑色背景颜色。
html {
background: black;
height: 100%;
overflow: hidden;
}
body {
margin: 0;
padding: 0;
height: 100%;
}
JavaScript
这个实现将是这个项目🦁的重头戏。
首先,我们必须用 2D 上下文初始化画布。我还通过设置画布的宽度和高度,让它占据整个视口:
const canvas = document.getElementById('Matrix');
const context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
接下来,我要创建一个字母表,从中挑选雨滴的字符。我会使用片假名(《黑客帝国》电影里就用到了片假名符号的变体)、拉丁字母和阿拉伯数字。将这些字母组合起来,就组成了完整的字母表。
const katakana = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン';
const latin = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const nums = '0123456789';
const alphabet = katakana + latin + nums;
我们必须计算屏幕上可以容纳多少个“雨列”,为此我将设置一个固定的字体大小,并用窗口的内部宽度除以宽度以获得精确的列数。
const fontSize = 16;
const columns = canvas.width/fontSize;
我将使用一个数组来存储和渲染雨滴。给定元素的索引将保存雨滴在 X 轴上的坐标,给定元素的值将保存其在 Y 轴上的坐标。这样我们就不需要二维数组了。为了初始化数组,我将它填充为 1,因此初始化后,每一列的高度都将完全相同:1。
const rainDrops = [];
for( let x = 0; x < columns; x++ ) {
rainDrops[x] = 1;
}
现在是时候实现效果的核心——绘制函数了。首先,我们将用透明的黑色覆盖整个画布。这将为雨滴添加拖尾效果,当雨滴落下时,原本被淹没的字符会慢慢淡出。接下来,我将设置字体大小和颜色(当然是绿色😎)。现在到了🔑键。我将循环遍历雨滴数组,为每个元素从字母表中随机选取一个字符,并将其渲染到该列的下一个位置。这里重要的是,您必须将坐标(元素值和索引)乘以字体大小才能获得完美的间距。最后,我们必须将落入视口高度以下的雨滴移动到该列的顶部。为了实现下雨效果,我不会立即将其放置在顶部,而是通过增加一个随机概率来增加一点随机性。
const draw = () => {
context.fillStyle = 'rgba(0, 0, 0, 0.05)';
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = '#0F0';
context.font = fontSize + 'px monospace';
for(let i = 0; i < rainDrops.length; i++)
{
const text = alphabet.charAt(Math.floor(Math.random() * alphabet.length));
context.fillText(text, i*fontSize, rainDrops[i]*fontSize);
if(rainDrops[i]*fontSize > canvas.height && Math.random() > 0.975){
rainDrops[i] = 0;
}
rainDrops[i]++;
}
};
最后一步,我需要每隔一段时间调用一次绘制函数,这将每 30 毫秒调用一次绘制函数。
setInterval(draw, 30);
结论
这个项目真的很有趣,我尽量让实现过程尽可能地方便新手。希望你喜欢。如果你想寻找 Web 开发的教育内容,可以关注我。我也会制作 YouTube 上的教育视频和 Instagram 帖子。
快乐黑客!
您可以从哪里向我了解更多信息?
我创建了涵盖多个平台上的 Web 开发的教育内容,请随意查看。
我还创建了一个简报,分享我创作的一周或两周的教育内容。不废话💩,只讲教育内容。
🔗 链接:
- 🍺 支持免费教育,请我喝杯啤酒
- 💬 加入我们的Discord 社区
- 📧在此订阅新闻通讯
- 🎥 YouTube JavaScript 学院
- 🐦推特:@dev_adamnagy
- 📷 Instagram @javascriptacademy