DigiPress

Highly Flexible WordPress Theme

スクロールでWebページの背景カラーをフェードしながら変化させる方法

Webデザイン・アプリ開発

現在開発中の新しい WordPress テーマの機能として、ページを下方にスクロールすると背景カラーが徐々に変化するギミックを考えてみたので、ご紹介します。

CSS のみで実現する方法

要件から少しはずれますが、まずは CSS のみで簡単に実現する方法をご紹介します。
CSS のみで実現するには、ページの背景要素に CSS グラデーション(linear-gradient)を指定するのみです。
めちゃくちゃ単純です。。

サンプル

See the Pen Change Background Color by Scrolling with Pure CSS by digistate (@digistate) on CodePen.

ただ、上記の CSS のみの方法の場合は、スクロールするほどのコンテンツがない場合は、当然ですが一見でページ全体が単純にグラデーションがかかった見た目になってしまいます。

また、グラデーションに利用する背景カラーの数だけカラーコードを個別に用意する必要があります。
これでは要件を満たせません。

そこで、JavaScript を利用してスクロール量に対して背景カラーを動的に変更する方法を考えてみます。

JavaScript で実現する方法

JavaScript の場合、スクロールのイベントリスナーを利用して、スクロール量に応じて元の背景カラーを基準にして対象要素の背景カラー( background-color )を少しずつ動的に書き換えることができます。

正確には、HEX 値や RGB 値ではなく 色相(hue)のみを変化させることで色が遷移しています。

サンプル

See the Pen Change Background Color by Scrolling with JavaScript by digistate (@digistate) on CodePen.

対象要素の取得

まず、背景要素から背景カラーを取得します。
サンプルでは .container という要素を想定しています。

const container = document.querySelector('.container');

RGB形式のコード(文字列)を配列に変換

getComputedStyle で取得されるカラーコードは hex 値ではなくrgba 形式の文字列なので、これを余分な文字列(rgba)を削除して RGB(Red, Green, Blue) 形式の色空間としての配列(Red, Green, Blue)に変換します。

let bgColor = getComputedStyle(container);
bgColor = bgColor.backgroundColor.replace(/[()rgba ]/g,"").split(",");

RGB形式の配列をHSL形式の配列に変換

背景カラーの遷移は、色相(Hue)の変化によって表現するため、得られた RGB 形式のカラーコード(配列)から、HSL(Hue, Saturation, Luminance) 形式の色空間にさらに変換する関数を用意します。

RGBからHSLに変換する関数
rgbToHsl = (r, g, b) => {

  // Make r, g, and b fractions of 1
  r /= 255;
  g /= 255;
  b /= 255;

  // Find greatest and smallest channel values
  let cmin = Math.min(r,g,b),
    cmax = Math.max(r,g,b),
    delta = cmax - cmin,
    h = 0,
    s = 0,
    l = 0;

  // Calculate hue
  // No difference
  if (delta == 0)
    h = 0;
  // Red is max
  else if (cmax == r)
    h = ((g - b) / delta) % 6;
   // Green is max
  else if (cmax == g)
    h = (b - r) / delta + 2;
  // Blue is max
  else
    h = (r - g) / delta + 4;
    h = Math.round(h * 60);

  // Make negative hues positive behind 360°
  if (h < 0)
    h += 360;

  // Calculate lightness
  l = (cmax + cmin) / 2;

  // Calculate saturation
  s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));

  // Multiply l and s by 100
  s = +(s * 100).toFixed(1);
  l = +(l * 100).toFixed(1);

  return [h, s, l];
}

この関数を利用して、RGB形式の配列をHSL形式の配列に変換します。

const hsl = rgbToHsl( bgColor[0], bgColor[1], bgColor[2] );

スクロール量に応じて色相(Hue)を変更

あとは、スクロールのイベントリスナーでスクロール量を取得し、基準となる値を算出して色相(Hue)となる数値を変更したものを対象要素の background-colorHSL 形式でセットします。

window.addEventListener( 'scroll', () => {
  let y = ( window.scrollY || window.pageYOffset ) / 100;
  y = y < 0 ? 0 : y;  // Sarari でのエラスティック(マイナス方向への)スクロール対策
  
  // スクロール量を元に適度な Hue 値を求める
  const hue = hsl[0] + y * 10,
         [ h, s, l ] = [ hue, hsl[1], hsl[2] ];

  // 対象要素の background-color を HSL 形式で Hue だけ変更
  container.style.backgroundColor = `hsl(${h}, ${s}%, ${l}%)`
 } );

背景カラーが #ffffff (白)または #000000 (黒)の場合は、Hue 値を変更しても変化がないため、その場合は RGB の値を少し調整して書き換えるなどの対応が必要となります。


Share / Subscribe
Facebook Likes
Tweets
Hatena Bookmarks
Pinterest
Pocket
Feedly
Send to LINE