Canvas实例篇:黑客帝国-3D字幕雨

发布于:2025-05-29 ⋅ 阅读:(23) ⋅ 点赞:(0)

Canvas实例篇:黑客帝国-3D字幕雨

前言

在之前的文章中,我们介绍了如何通过Canvas实现黑客帝国-字母矩阵(字幕雨),在该篇文章中,我们使用的是普通文字(2D效果),本文将讲述如何通过阴影、模糊、渐变等特效,形成3D文字,营造3D字幕雨下落的效果。

效果预览

黑客帝国-3D字幕雨

代码实现

<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>黑客帝国-3D立体字幕矩阵</title>
		<style>
			body {
				overflow: hidden;
				background: #000;
			}

			#canvas {
				display: block;
			}
		</style>
	</head>

	<body>
		<canvas id="canvas"></canvas>
		<script>
			const canvas = document.getElementById('canvas');
			const ctx = canvas.getContext('2d');
			const screen = window.screen;
			canvas.width = screen.width;
			canvas.height = screen.height;

			// 3D参数配置
			const FONT_SIZE = 24; // 字体大小
			const COLUMN_WIDTH = FONT_SIZE + 12; // 列间距
			const FALL_SPEED = 24; // 下落速度
			const Z_DEPTH = 300; // 立体深度
			const BLUR_STRENGTH = 2; // 高斯模糊强度
			const COLOR_STEPS = ['#0f0', '#0ff', '#f0f', '#ff0', '#0f0']; // 彩虹渐变色彩

			// 列数据结构:包含z轴深度和垂直位置
			const columns = Array(Math.floor(canvas.width / COLUMN_WIDTH)).fill().map(() => ({
				z: Math.random() * Z_DEPTH,
				y: -Math.random() * 1000
			}));

			// 立体投影转换函数
			function project(z) {
				return Z_DEPTH / (Z_DEPTH + z);
			}

			// 绘制3D文字
			function draw3DText(text, x, y, z) {
				const scale = project(z);
				const offset = (1 - scale) * FONT_SIZE * 0.5; // 深度偏移量

				// 绘制底部阴影层
				ctx.filter = `blur(${BLUR_STRENGTH}px)`;
				ctx.fillStyle = `rgba(0, 255, 0, ${0.2 + 0.8 * scale})`;
				ctx.font = `${FONT_SIZE * scale}px Arial`;
				ctx.fillText(text, x + offset, y + offset);

				// 绘制立体主体层
				ctx.filter = 'none';
				ctx.fillStyle = COLOR_STEPS[Math.floor(z / (Z_DEPTH / COLOR_STEPS.length))];
				ctx.shadowColor = `rgba(0, 255, 0, ${0.1 + 0.4 * scale})`;
				ctx.shadowOffsetX = 2 * scale;
				ctx.shadowOffsetY = 2 * scale;
				ctx.shadowBlur = 2 * scale;
				ctx.font = `${FONT_SIZE * scale}px Arial`;
				ctx.fillText(text, x, y);
			}

			// 主绘制函数
			function animate() {
				requestAnimationFrame(animate);

				// 背景模糊擦除
				ctx.globalCompositeOperation = 'source-over';
				ctx.fillStyle = 'rgba(0, 0, 0, 0.03)';
				ctx.fillRect(0, 0, canvas.width, canvas.height);

				columns.forEach((col, index) => {
					const x = index * COLUMN_WIDTH;
					const z = col.z;
					const y = col.y;

					// 生成随机字符
					const char = 'QWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*'.charAt(Math.random() * 32);

					// 绘制3D文字
					draw3DText(char, x, y, z);

					// 更新位置和深度
					col.y += FALL_SPEED * project(z);
					if (y > canvas.height + FONT_SIZE * 10) {
						col.y = -Math.random() * 1000;
						col.z = Math.random() * Z_DEPTH;
					}
				});
			}

			// 启动动画
			animate();
		</script>
	</body>

</html>

思路解析

  1. 准备工作:获取 Canvas 元素及其 2D 绘图上下文,并设置画布的宽高与屏幕一致,确保字母雨能够覆盖整个页面。
  2. 数据初始化:定义3D文字的相关属性,如字体大小、模糊层度、渐变色等。
  3. 3D效果:通过两层绘制和阴影效果,实现文字的立体效果,并根据深度应用不同颜色。
  4. 绘制字母:在每次绘制时,先使用半透明黑色填充画布,模拟背景的深邃感,然后遍历字母位置数组,随机选择字母并绘制在相应位置,并用3D属性渲染。
  5. 动画实现:通过requestAnimationFrame函数不断调用绘制函数,实现字母的连续下落动画,同时更新字母的位置,当字母超出屏幕底部时,将其重置到顶部,形成循环下落的效果。

网站公告

今日签到

点亮在社区的每一天
去签到