もうね、エンジニアの存在意義が問われる時代になってしまったのを痛感してます。なかなか再現が難しかった映画マトリックスのあのエフェクト(通称、Matrix text rain)をどうやって表現しているのか気になってChatGPTに効いてみたんですよ。単純に仕組みを知りたかっただけなんですけど、いろいろ改良点を指摘していったらほぼほぼ完成版として動作するものが出来てしまったんです……
とりあえずできたエフェクトを掲載しておきます。
初稿(最初に出来上がったJavaScriptのコード)でも十分仕組みが理解出来たのですが、突き詰めていくとちょこちょこ不具合があったのでそれを少しずつ直していきました。たった30分くらいですよ……で、この仕上がり。
とりあえず、文字の描画がコンテンツの幅の100%までされなかったことを指摘して、そのあとレスポンシブにも対応するようにしていきました。
これはChatGPTの上手い使い方なのだろうか……それとも禁断の扉を開けてしまったのだろうか……
とりあえず動作確認済のコードを掲載しておきます泣
サンプルコード
<div id="canvas-container">
<canvas id="canvas"></canvas>
</div>
#canvas-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 60%;
/* キャンバスの縦横比は 5:3 とする */
background-color: black;
}
#canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const fontFamily = 'Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace';
let fontSize = 10;
let columns = Math.floor(canvas.width / fontSize);
let drops = [];
function draw() {
// 背景を描画
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 文字列を描画
ctx.font = `${fontSize}px ${fontFamily}`;
ctx.fillStyle = '#0f0';
for (let i = 0; i < drops.length; i++) {
const text = String.fromCharCode(Math.random() * (0x30a0 - 0x3040) + 0x3040);
const x = i * fontSize;
const y = drops[i] * fontSize;
ctx.fillText(text, x, y);
if (y > canvas.height && Math.random() > 0.975) {
drops[i] = 0;
}
drops[i]++;
}
}
function resizeCanvas() {
const container = document.getElementById('canvas-container');
canvas.width = container.clientWidth;
canvas.height = canvas.width * 0.6; // キャンバスの縦横比は 5:3 とする
columns = Math.floor(canvas.width / fontSize);
drops.length = columns;
drops.fill(0);
}
function loop() {
draw();
requestAnimationFrame(loop);
}
window.addEventListener('resize', () => {
fontSize = Math.max(Math.floor(canvas.width / 100), 5); // 100px未満にはしない
resizeCanvas();
});
resizeCanvas();
loop();