マトリックスレイン
カタカナや数字が緑の軌跡で流れ落ちる映画風デジタルレイン。残像合成と先頭の発光で雰囲気を出します。テック系の演出やイントロに。
ライブデモ
使用例(お題: SaaS FlowDesk)
この技法を「SaaS FlowDesk」というテーマのダミーサイトで実際に使った例です。
<!-- FlowDesk:セキュリティ機能セクション(マトリックスレイン背景) -->
<section class="fd-sec">
<!-- 主役:デジタルレイン背景 -->
<canvas class="fd-sec__rain" id="fdMatrix"></canvas>
<!-- 前景UI:セキュリティ訴求カード -->
<div class="fd-sec__inner">
<span class="fd-sec__tag">ENTERPRISE SECURITY</span>
<h1 class="fd-sec__title">データは、つねに暗号化。</h1>
<p class="fd-sec__lead">保存時・通信時ともに AES-256 / TLS1.3 で保護。SOC2 Type II 準拠の堅牢な基盤で、チームの情報を守ります。</p>
<ul class="fd-sec__list">
<li><span class="fd-dot"></span>エンドツーエンド暗号化</li>
<li><span class="fd-dot"></span>シングルサインオン(SAML)</li>
<li><span class="fd-dot"></span>監査ログ・権限管理</li>
</ul>
<a class="fd-sec__btn" href="#">セキュリティ詳細</a>
</div>
</section>
/* FlowDesk:マトリックスレイン背景のセキュリティ訴求 */
:root {
--navy: #0f1b34;
--blue: #4f7cff;
--white: #ffffff;
}
* { box-sizing: border-box; }
body {
margin: 0;
height: 400px;
font-family: "Hiragino Kaku Gothic ProN", "Segoe UI", system-ui, sans-serif;
overflow: hidden;
}
.fd-sec {
position: relative;
height: 400px;
overflow: hidden;
background: linear-gradient(160deg, #0c1730, #070d1d);
}
/* 主役:流れ落ちる文字(背景) */
.fd-sec__rain {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
display: block;
z-index: 1;
opacity: 0.55;
}
/* 前景UI:右からのグラデで読みやすく */
.fd-sec__inner {
position: relative;
z-index: 2;
padding: 38px 32px;
max-width: 440px;
height: 100%;
background: linear-gradient(90deg, rgba(10,18,38,0.92) 55%, transparent);
}
.fd-sec__tag {
display: inline-block;
font-size: 10px;
letter-spacing: 0.28em;
color: #6fe0a8;
font-weight: 800;
}
.fd-sec__title {
margin: 13px 0 12px;
font-size: 26px;
line-height: 1.4;
font-weight: 800;
color: var(--white);
}
.fd-sec__lead {
margin: 0 0 18px;
font-size: 13px;
line-height: 1.8;
color: rgba(255,255,255,0.76);
}
.fd-sec__list { list-style: none; margin: 0 0 22px; padding: 0; }
.fd-sec__list li {
display: flex;
align-items: center;
gap: 10px;
font-size: 13px;
color: rgba(255,255,255,0.88);
padding: 5px 0;
}
.fd-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: #6fe0a8;
box-shadow: 0 0 10px rgba(111,224,168,0.8);
}
.fd-sec__btn {
display: inline-block;
padding: 11px 22px;
border-radius: 9px;
background: var(--blue);
color: var(--white);
font-size: 13px;
font-weight: 700;
text-decoration: none;
box-shadow: 0 10px 24px rgba(79,124,255,0.4);
transition: transform 0.2s ease;
}
.fd-sec__btn:hover { transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) {
.fd-sec__btn { transition: none; }
}
// FlowDesk:マトリックスレイン(背景演出)
(() => {
const canvas = document.getElementById('fdMatrix');
if (!canvas) return; // null安全
const ctx = canvas.getContext('2d');
if (!ctx) return;
let w = 0, h = 0, raf = 0, running = true, cols = 0, drops = [];
const dpr = Math.min(window.devicePixelRatio || 1, 2);
const fontSize = 14;
// カタカナ+数字+記号
const glyphs = 'アカサタナハマヤラワabcdef0123456789{}<>$#@'.split('');
function resize() {
const r = canvas.getBoundingClientRect();
w = r.width; h = r.height;
canvas.width = Math.max(1, w * dpr);
canvas.height = Math.max(1, h * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
cols = Math.floor(w / fontSize);
// 各列の先頭位置(ランダムな開始でばらけさせる)
drops = Array.from({ length: cols }, () => Math.random() * -h / fontSize);
}
resize();
function step() {
// 残像(軌跡を残す)
ctx.fillStyle = 'rgba(7,13,29,0.12)';
ctx.fillRect(0, 0, w, h);
ctx.font = `${fontSize}px monospace`;
for (let i = 0; i < cols; i++) {
const ch = glyphs[Math.floor(Math.random() * glyphs.length)];
const x = i * fontSize;
const y = drops[i] * fontSize;
// 先頭は明るく、それ以外は緑系
ctx.fillStyle = '#cfffe6';
ctx.fillText(ch, x, y);
ctx.fillStyle = 'rgba(79,224,150,0.85)';
ctx.fillText(glyphs[Math.floor(Math.random() * glyphs.length)], x, y - fontSize);
// 列をリセット(ランダムで間隔をばらす)
if (y > h && Math.random() > 0.975) drops[i] = 0;
drops[i]++;
}
raf = requestAnimationFrame(step);
}
function start() {
if (running) return;
running = true;
raf = requestAnimationFrame(step);
}
function stop() {
running = false;
cancelAnimationFrame(raf);
}
window.addEventListener('resize', resize);
document.addEventListener('visibilitychange', () => {
document.hidden ? stop() : start();
});
running = false;
start();
})();
実装ガイド
使いどころ
テック系・サイバーパンク系サイトのイントロやヒーロー背景、ローディング演出、映画風の雰囲気を出したい場面に向きます。カタカナと数字が緑の軌跡で流れ落ちるレトロな質感で、印象的なファーストビューを作れます。
実装時の注意点
列ごとに落下位置(drops配列)を持ち、毎フレーム半透明の黒(rgba(0,0,0,0.08))で全面を覆うことで残像のフェードを作ります。先頭文字を明るい色、後続を緑にして発光感を出し、列数は canvas 幅÷フォントサイズで決めます。下端を越えた列はランダムなタイミングで上へ戻し、流れが揃わないようにしています。
対応ブラウザ
Canvas 2D(fillText / font 指定 / 半透明塗り)と requestAnimationFrame のみで、全モダンブラウザで標準対応です。カタカナ・半角カナ・記号を含むため、monospace フォントが該当グリフを持つ環境で意図通り表示されます(一部環境では字形が異なる可能性があります)。
よくある失敗
残像用の半透明塗りの不透明度が低すぎると過去の文字が消えずに画面が緑で埋もれ、高すぎると残像感が失われます。フォントサイズに対して列数の計算がずれると右端に隙間や重なりが出ます。高DPIで dpr スケールを忘れると文字がぼやけます。タブ非表示中も rAF が回り続けるとモバイルで無駄に電力を消費します。
応用例
文字セット・色・落下速度・フォントサイズを変えて、青系のデータストリームや任意の言語のレインへ差し替えられます。マウス位置に反応させて近くの列を加速する、ロゴや単語を文字の流れの中に浮かび上がらせる、prefers-reduced-motion で速度を落とす(本デモ対応済み)といった発展が定番です。
コード
<!-- マトリックスレイン -->
<div class="stage">
<canvas id="matrixCanvas"></canvas>
</div>
/* マトリックスレイン(漆黒背景) */
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
.stage {
position: relative;
width: 100%;
height: 360px;
overflow: hidden;
background: #000;
}
#matrixCanvas {
display: block;
width: 100%;
height: 100%;
}
// マトリックス風デジタルレインデモ
(() => {
const canvas = document.getElementById('matrixCanvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
// 描画文字(カタカナ+数字+記号)
const glyphs = 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホ0123456789@#$%&*+=<>'.split('');
const fontSize = 16;
let w = 0, h = 0, cols = 0, drops = [];
const dpr = Math.min(window.devicePixelRatio || 1, 2);
function resize() {
const r = canvas.getBoundingClientRect();
w = r.width; h = r.height;
canvas.width = w * dpr;
canvas.height = h * dpr;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
cols = Math.ceil(w / fontSize);
// 各列の落下位置をランダムに初期化
drops = Array.from({ length: cols }, () => Math.random() * -h);
}
resize();
window.addEventListener('resize', resize);
function step() {
// 残像を作るために半透明の黒で覆う
ctx.fillStyle = 'rgba(0,0,0,0.08)';
ctx.fillRect(0, 0, w, h);
ctx.font = `${fontSize}px monospace`;
for (let i = 0; i < cols; i++) {
const ch = glyphs[(Math.random() * glyphs.length) | 0];
const x = i * fontSize;
const y = drops[i];
// 先頭は明るく、後続は緑のグラデ
ctx.fillStyle = '#cfffd6';
ctx.fillText(ch, x, y);
ctx.fillStyle = '#19c34a';
ctx.fillText(ch, x, y - fontSize);
drops[i] += fontSize * (reduced ? 0.3 : 1);
// 下端を越えたらランダムに上へ戻す
if (drops[i] > h && Math.random() > 0.975) drops[i] = Math.random() * -40;
}
requestAnimationFrame(step);
}
requestAnimationFrame(step);
})();
🤖 AIエージェント用プロンプト
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「マトリックスレイン」の効果を追加してください。
# 追加してほしい効果
マトリックスレイン(Canvas エフェクト)
カタカナや数字が緑の軌跡で流れ落ちる映画風デジタルレイン。残像合成と先頭の発光で雰囲気を出します。テック系の演出やイントロに。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- マトリックスレイン -->
<div class="stage">
<canvas id="matrixCanvas"></canvas>
</div>
【CSS】
/* マトリックスレイン(漆黒背景) */
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
.stage {
position: relative;
width: 100%;
height: 360px;
overflow: hidden;
background: #000;
}
#matrixCanvas {
display: block;
width: 100%;
height: 100%;
}
【JavaScript】
// マトリックス風デジタルレインデモ
(() => {
const canvas = document.getElementById('matrixCanvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
// 描画文字(カタカナ+数字+記号)
const glyphs = 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホ0123456789@#$%&*+=<>'.split('');
const fontSize = 16;
let w = 0, h = 0, cols = 0, drops = [];
const dpr = Math.min(window.devicePixelRatio || 1, 2);
function resize() {
const r = canvas.getBoundingClientRect();
w = r.width; h = r.height;
canvas.width = w * dpr;
canvas.height = h * dpr;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
cols = Math.ceil(w / fontSize);
// 各列の落下位置をランダムに初期化
drops = Array.from({ length: cols }, () => Math.random() * -h);
}
resize();
window.addEventListener('resize', resize);
function step() {
// 残像を作るために半透明の黒で覆う
ctx.fillStyle = 'rgba(0,0,0,0.08)';
ctx.fillRect(0, 0, w, h);
ctx.font = `${fontSize}px monospace`;
for (let i = 0; i < cols; i++) {
const ch = glyphs[(Math.random() * glyphs.length) | 0];
const x = i * fontSize;
const y = drops[i];
// 先頭は明るく、後続は緑のグラデ
ctx.fillStyle = '#cfffd6';
ctx.fillText(ch, x, y);
ctx.fillStyle = '#19c34a';
ctx.fillText(ch, x, y - fontSize);
drops[i] += fontSize * (reduced ? 0.3 : 1);
// 下端を越えたらランダムに上へ戻す
if (drops[i] > h && Math.random() > 0.975) drops[i] = Math.random() * -40;
}
requestAnimationFrame(step);
}
requestAnimationFrame(step);
})();
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。