【JavaScript】桜舞うプログラム

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>桜舞うプログラム</title>
<style>
body {
margin: 0;
background: linear-gradient(to bottom, #FFEEFF, #ffffff);
height: 100vh;
position: relative;
}
.sakura {
position: fixed;
pointer-events: none;
/* transform-origin を中心に設定 */
transform-origin: center center;
}
/* 花びらが落下しながら左右にゆらゆら揺れるアニメーション */
@keyframes fall {
0% {
transform: translateX(0) translateY(-100px) rotate(0deg);
opacity: 1;
}
25% {
transform: translateX(50px) translateY(25vh) rotate(90deg);
}
50% {
transform: translateX(0) translateY(50vh) rotate(180deg);
}
75% {
transform: translateX(-50px) translateY(75vh) rotate(270deg);
}
100% {
transform: translateX(0) translateY(110vh) rotate(360deg);
opacity: 0;
}
}
</style>
</head>
<body>
<script>
function createSakura() {
const xmlns = "http://www.w3.org/2000/svg";
const svg = document.createElementNS(xmlns, "svg");
svg.setAttribute("viewBox", "0 0 40 40");
svg.setAttribute("class", "sakura");
// ランダムなサイズ設定(scale 0.5~1.25倍、40pxを基準)
const scale = Math.random() * 0.75 + 0.5;
const size = 40 * scale;
svg.style.width = `${size}px`;
svg.style.height = `${size}px`;
// 横方向の初期位置(画面全体からランダムに)
svg.style.left = Math.random() * window.innerWidth + "px";
// 垂直方向は画面外上部から開始
svg.style.top = "-50px";
// SVG内にパス要素を作成
const path = document.createElementNS(xmlns, "path");
path.setAttribute("d", "M20.1,11.6l-2.5,3.1-2.5-3.1c-2.2,1.8-3.7,6-3.7,10.7s6.2,11.8,6.2,11.8c0,0,6.2-5.3,6.2-11.8s-1.5-8.9-3.7-10.7Z");
path.setAttribute("fill", "#FFC3E7");
svg.appendChild(path);
// ランダムなアニメーション設定(5~10秒、開始遅延もランダム)
const duration = Math.random() * 5 + 5;
const delay = Math.random() * -20;
svg.style.animation = `fall ${duration}s linear ${delay}s infinite`;
document.body.appendChild(svg);
// アニメーション終了後に削除してパフォーマンス対策
setTimeout(() => { svg.remove(); }, duration * 1000);
}
function generateSakura() {
setInterval(createSakura, 150);
}
generateSakura();
</script>
</body>
</html>CSS によるスタイル設定とアニメーション
背景と全体レイアウト
body {
margin: 0;
background: linear-gradient(to bottom, #FFEEFF, #ffffff);
height: 100vh;
position: relative;
}- 背景: ページ全体の背景には、ピンクのグラデーションを設定します。
- レイアウト: height: 100vh により、画面全体を使い、position: relative により内部要素(花びら)の配置の基準にします。
花びら(.sakura クラス)のスタイル
.sakura {
position: fixed;
pointer-events: none;
transform-origin: center center;
}- 位置指定: position: fixed を使用して、画面上で固定された位置に表示。これにより、スクロールなどの影響を受けずにアニメーションが継続します。
- ポインター無効: pointer-events: none; でマウスイベントを無効にします。
- 変形の基準: transform-origin: center center; により、花びらの回転や移動の基準を中央に設定。
アニメーション (keyframes)
@keyframes fall {
0% {
transform: translateX(0) translateY(-100px) rotate(0deg);
opacity: 1;
}
25% {
transform: translateX(50px) translateY(25vh) rotate(90deg);
}
50% {
transform: translateX(0) translateY(50vh) rotate(180deg);
}
75% {
transform: translateX(-50px) translateY(75vh) rotate(270deg);
}
100% {
transform: translateX(0) translateY(110vh) rotate(360deg);
opacity: 0;
}
}- 初期状態: 上部(-100px)から開始し、透明度は1(完全に表示)です。
- 途中の動き:
- 25% で右に50px移動し、画面下部の 25vh まで移動、同時に90度回転。
- 50% で中央に戻り、50vh の位置に到達し、180度回転。
- 75% では、左へ50px移動し、75vh に到達、270度回転。
- 終了状態: 100% で元の横位置に戻りながら、110vh の位置に到達し、360度回転。透明度は0になり、フェードアウトします。
- この一連の動きが、花びらが「落下しながら左右に揺れる」効果を生み出しています。
JavaScript による動的生成
JavaScript 部分では、一定間隔で花びらを生成し、各花びらにランダムなパラメーターを設定しています。
SVG を用いた花びらの生成
function createSakura() {
const xmlns = "http://www.w3.org/2000/svg";
const svg = document.createElementNS(xmlns, "svg");
svg.setAttribute("viewBox", "0 0 40 40");
svg.setAttribute("class", "sakura");- SVG 要素の作成:
インライン SVG を使用することで、clip-path ではなく、正しいスケーリングと座標系が適用されます。
viewBox="0 0 40 40" により、花びらのパスが 40px を基準に描画されます。
サイズ・位置・アニメーションのランダム設定
// ランダムなサイズ設定(scale 0.5~1.25倍、40pxを基準)
const scale = Math.random() * 0.75 + 0.5;
const size = 40 * scale;
svg.style.width = `${size}px`;
svg.style.height = `${size}px`;
// 横方向の初期位置(画面全体からランダムに)
svg.style.left = Math.random() * window.innerWidth + "px";
// 垂直方向は画面外上部から開始
svg.style.top = "-50px";- サイズ: ランダムなスケールで各花びらの大きさを変化させ、自然なバリエーションを実現しています。
- 位置: 横位置は画面全体からランダムに選ばれ、縦位置は画面外上部から開始することで、徐々に下へ落ちるアニメーションが始まります。
SVG パスの設定とアニメーションの適用
// SVG内にパス要素を作成
const path = document.createElementNS(xmlns, "path");
path.setAttribute("d", "M20.1,11.6l-2.5,3.1-2.5-3.1c-2.2,1.8-3.7,6-3.7,10.7s6.2,11.8,6.2,11.8c0,0,6.2-5.3,6.2-11.8s-1.5-8.9-3.7-10.7Z");
path.setAttribute("fill", "#FFC3E7");
svg.appendChild(path);- パスの定義:
事前に用意された桜の花びらの形状(SVG の path データ)を設定しています。 - 塗りの色: 桜らしい淡いピンク(#FFC3E7)で塗り、柔らかい印象を与えています。
アニメーションのランダム適用とパフォーマンス対策
// ランダムなアニメーション設定(5~10秒、開始遅延もランダム)
const duration = Math.random() * 5 + 5;
const delay = Math.random() * -20;
svg.style.animation = `fall ${duration}s linear ${delay}s infinite`;
document.body.appendChild(svg);
// アニメーション終了後に削除してパフォーマンス対策
setTimeout(() => { svg.remove(); }, duration * 1000);- ランダムなアニメーション:
各花びらは 5~10 秒間のランダムな持続時間でアニメーションが実行され、開始遅延もランダムに設定されています。 - パフォーマンス対策:
アニメーションが終了したら SVG 要素を削除することで、メモリ消費の増大やパフォーマンス低下を防ぎます。
花びらの生成ループ
function generateSakura() {
setInterval(createSakura, 150);
}
generateSakura();- 定期生成:
setInterval を用いて、150ミリ秒ごとに createSakura 関数を呼び出し、画面に次々と花びらを追加していきます。 - このループにより、常に新しい花びらが舞うような効果が生み出されています。
まとめ
今回のプログラムでは、以下の技術を組み合わせて実装しています。
- HTML:ページの基本構造とコンテンツの配置。
- CSS:背景、花びらのスタイル、及び複雑なアニメーション(落下、左右の揺れ、回転)を定義。
- SVG:花びらの形状を正確に再現するために、インライン SVG と viewBox を活用。
- JavaScript:花びらの動的生成、ランダムなサイズ・位置・アニメーションのパラメーター設定、及び生成後の削除によるパフォーマンス最適化。
この仕組みにより、桜の花びらが風に揺れながら、自然な動きで舞うアニメーションが実現されています。コードをカスタマイズすることで、色や動き、生成間隔などを変更できるため、より好みに合わせた桜舞うエフェクトに仕上げることが可能です。

