水位が引いて景色が現れる、水のようなオープニング

IXcode

IXcode

Opening study / Water

Code that moveslike water.

Frontend coding partner for studios and designers.

Quiet on the surface.

Precise underneath.

Your design,

carried over without a ripple.

Let it flow.

A fill, a ripple, a calm surface — built with one shader and a few numbers.

More from the blog
← ブログ一覧へ

水位が引いて景色が現れる、水のようなオープニング

要点

  • 画面全体を、1 枚の板(WebGL)に貼った画像として描く
  • 「水位」は、2 つの色を混ぜる割合で作り、揺れはサイン波で作る
  • スクロールでは、同じ仕組みを、もう一度使う

仕組み

  1. 板に、画像を貼って描く:絵をテクスチャとして使い、ピクセルごとの色を、フラグメントシェーダーで計算します。
  2. 画像を、横に揺らす:見る位置を、横方向にだけ、サイン波でずらします(sin(x * 24 + time) * amp)。左上ほど強く揺れるよう、位置ごとの重みも付けます。
  3. 水位は、混ぜる割合で作る:境目の上は水色、下は画像、境目の中は混ぜます。smoothstep(mix - blur, mix + blur, y) で、境目を下から上へ動かします。
  4. 登場の間に、3 つの値を同時に動かす:揺れの強さ 0.012 → 0、波の進み 0 → 4、ぼかし 0 → 0.3 を約 2.8 秒(ease-out)。水位は約 2.2 秒で上げ切ります。
  5. 文字は、水位が動き出してから浮かせる:ロゴは 1 文字ずつ 0.16 秒おき、キャッチコピーは行ごとに 0.2 秒おきに、水の色から白へ変えながら出します。
  6. スクロールで、同じ仕組みをもう一度:position: sticky で貼りつけ、進み具合(0〜1)に合わせて、揺れ・ぼかし・暗い色を足します。進み具合は、少し遅れて追わせます。
  7. 文章は、1 文字ずつ:回転と移動を付けた状態から、0.03 秒ずつずらして戻します。

シェーダー(要部)

// 水位と画像を混ぜる(GLSL の一部)
float wave = sin(v.x * 24.0 + time) * amp * (pow(1.0 - v.x, 2.0) + 1.5 * pow(1.0 - v.y, 2.0));
vec2 uv = vec2(v.x + wave * 3.5, v.y + wave * 1.5);
vec3 img = texture(tex, uv * scale + offset).rgb;

float level = mix + sin(v.x * 5.0 + time) * 0.012;
float m = smoothstep(level - blur, level + blur, v.y);
color = mix(img, baseColor, m);   // 境目の上は水色、下は画像

こだわり・気をつけたこと

  • 登場のあいだだけ、スクロールを止めます。約 3 秒で、6 秒たったら必ず解除します。
  • 動きを減らす設定には、揺れ・水位・スクロールの演出を省きます。完成した状態の絵と文字を、最初から見せます。
  • WebGL2 が使えなくても、完成した見た目を出します。
  • 画面サイズが変わったら、描き直します。縦横比が崩れないよう、見せる範囲を計算し直します(cover と同じ考え方)。
  • スマホでは、揺れとぼかしを少し強めます。画面が小さいと、同じ強さでは伝わりにくいためです。
  • 画像ファイルがないので、読み込みを待ちません。覆いは、フォントを待つ間(最長 1.5 秒)だけです。
  • 1 文字に分けた文字も、読み上げは元の文のままです。

背景の水中の景色は、コードで描いています。英字フォントを、Google Fonts から読み込んでいます。