スクラッチ風に擦ると文字が浮かび上がってくるデザインの改良版です。
本コードでは要素が見えたら自動的にスクラッチが削れて見えるようにしております。
文字が見える!
document.addEventListener('DOMContentLoaded', () => { // 初期設定 const canvas = document.getElementById("mask"); const ctx = canvas.getContext("2d"); const container = document.getElementById("container"); // キャンバスのサイズをコンテナに合わせる canvas.width = container.offsetWidth; canvas.height = container.offsetHeight; // キャンバスを黒で塗りつぶし ctx.fillStyle = "#959595"; ctx.fillRect(0, 0, canvas.width, canvas.height); // 削る範囲(1回のスクラッチ幅) const size = 35; // 円形で削るため小さめに // 初期位置設定(画面左端からスタート) let x = 0; // 左端から開始 let y = canvas.height / 2; // 画面中央からスタート let dx = 1.5; // 横方向の移動速度 let dy = -1.5; // 縦方向の移動速度 // 中央付近を削る範囲を設定 const centralRange = 10; // 上下10pxの範囲で動かす // スムーズに動かすための変数 let speed = 10; // 動きの速さ(速すぎず遅すぎず) // 方向変更のフラグ let movingUp = true; // アニメーションの実行フラグ let isAnimating = false; // 自動スクラッチ削りの処理 function animate() { // 背景を削る(透明化) ctx.globalCompositeOperation = "destination-out"; ctx.beginPath(); ctx.arc(x, y, size, 0, Math.PI * 2, false); // 円形で削る ctx.fill(); // 右に進みながら斜め上/下に動く x += dx; y += dy; // 上下の範囲を制限する let offset = Math.random() * 10; if (y <= canvas.height / 2 - centralRange) { y = canvas.height / 2 - centralRange - offset; // 上限に達したら中央付近で止める movingUp = false; // 下方向に切り替える } else if (y >= canvas.height / 2 + centralRange) { y = canvas.height / 2 + centralRange + offset; // 下限に達したら中央付近で止める movingUp = true; // 上方向に切り替える } // movingUp フラグに基づいて dy を決定 if (movingUp) { dy = -1.5; // 上方向 } else { dy = 1.5; // 下方向 } // アニメーションを再帰的に呼び出す if (isAnimating) { setTimeout(animate, speed); // 指定した速度で動く } } // IntersectionObserverの設定 const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { // キャンバスが表示されたらアニメーション開始 isAnimating = true; animate(); // アニメーション開始 observer.disconnect(); // 監視停止 } }); }, { threshold: 0.5 }); // 要素が50%表示されたら // キャンバスがビューポートに表示されたらアニメーションを開始 observer.observe(canvas); });
<div id="container"> <div style="z-index: 1; position: relative;">文字が見える!</div> <canvas id="mask"></canvas> </div>
#container { position: relative; width: 50%; height: 200px; font-size: 4.0rem; font-weight: 900; text-align: center; color: #000000; background: #FFFFFF; overflow: hidden; user-select: none; display: flex; justify-content: center; align-items: center; margin: 0 auto; } #mask { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 2; }