← 記事一覧へ

CSS アニメーションと SVG で描くアート

CSS @keyframes による太陽系アニメーションと、SVG フィルター・リフレクションを使ったネオン都市の制作過程を解説します。

作品 1 — Solar System

CSS アニメーションだけで動く太陽系です。惑星・軌道・星空・太陽の光量変化をすべて CSS で実現しています。

Solar System — CSS animation & transform

軌道アニメーションの仕組み

各惑星は「軌道リング(div)が回転し、その端に惑星が貼りついている」という構造です。

/* 軌道リングが中心を原点に回転する */
.orbit-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  border-radius: 50%;
  animation: spin linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

惑星は軌道リングの上端(top: -半径px)に配置するだけ。リングが回れば惑星が円軌道を描きます。

// 4惑星のデータ定義
const planets = [
  { orbit: 55,  period: 2.5,  size: 7,  color: '#9ca3af' }, // 水星
  { orbit: 88,  period: 6,    size: 11, color: '#d97706' }, // 金星
  { orbit: 124, period: 11,   size: 12, color: '#00DC82' }, // 地球
  { orbit: 162, period: 19,   size: 9,  color: '#ef4444' }, // 火星
]

animationDelay に負の値を設定することで、ビルド時点での惑星の開始位置をずらせます。

animationDelay: p.delay + 's'  // 例: -4.5s → 4.5秒分進んだ状態から開始

太陽の脈動

radial-gradientfilter: blur の組み合わせで自然な光彩を表現し、 animation で明滅させています。

.sun-halo {
  background: radial-gradient(circle, rgba(255,180,0,0.35) 0%, transparent 70%);
  animation: pulse 3s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { transform: scale(1);   opacity: 0.5; }
  50%       { transform: scale(1.4); opacity: 1;   }
}

作品 2 — Neon City

SVG で描いたネオン都市です。<filter> によるウィンドウの発光と、変換行列で作る水面リフレクションが特徴です。

Neon City — SVG + filter + reflection

SVG フィルターでネオン発光

<feGaussianBlur> でぼかし画像を生成し、元画像と合成(feMerge)することでグロー効果を作ります。

<filter id="win-glow">
  <feGaussianBlur stdDeviation="2.5" result="blur" />
  <feMerge>
    <feMergeNode in="blur" />       <!-- ぼかした光 -->
    <feMergeNode in="SourceGraphic" /> <!-- 元のウィンドウ -->
  </feMerge>
</filter>

水面リフレクション

建物・窓を scale(1, -1) で上下反転し、地面ラインを軸に折り返すことで水面の映り込みを表現します。

<!-- translate(0, GROUND*2) で反転後の位置を地面ラインに揃える -->
<g transform="translate(0, 600) scale(1, -1)" mask="url(#reflect-fade)">
  <!-- 同じ建物・窓を再描画 -->
</g>

フェードマスクは linearGradient(白→透明)を <mask> で適用して、水面が下に向かうほど薄くなるように制御しています。

ウィンドウの決定論的生成

JavaScript の乱数(Math.random())は SSR とクライアントでズレてハイドレーションエラーになります。 そのため、ビルドインデックスから計算する決定論的な式でウィンドウの点灯パターンを決めています。

const seed = (buildingIndex * 31 + row * 17 + col * 7) % 100
const isLit = seed > 38  // 約 62% が点灯

技術比較

手法向いている表現難しい点
CSS animation繰り返し動作・軌道・脈動複雑な形状の制御
SVG filter発光・ぼかし・影フィルター定義の記述量
SVG transform反転・スケール・鏡像座標計算が必要
CSS radial-gradient光源・オーブ・背景ブラウザ差異がある場合も
✓ TIP

CSS と SVG を組み合わせると、互いの弱点を補い合えます。アニメーションは CSS、複雑なフィルターは SVG というように使い分けましょう。