JavaScript

画像の明度をアニメーションで変化させる

  1. 最終更新日:
  2. 公開日:

CSSのfilterプロパティbrightnessメソッドで指定した画像の明度をアニメーションで変化させる方法について解説します。

この記事のポイント

  • 画像の明度はfilterプロパティbrightnessメソッドを使う
  • アニメーションはtransitionプロパティanimationプロパティを使う
  • JavaScriptでclass属性を編集することでアニメーションを実行する

画像の明度の変化をアニメーションにする

CSSではimg要素で読み込んだ画像の明度をfilterプロパティbrightnessメソッドで調整することができます。
このプロパティはtransitionプロパティanimationプロパティを使ってアニメーションにすることができます。

明度の調整例

今回はこの2つのプロパティとJavaScriptによるclass属性の編集操作を組み合わせることで、数パターンの明度調整をアニメーションさせていきます。

以下の例は5つのボタン「すごく明るい」「明るめ」「デフォルト」「暗め」「真っ暗」のいずれかを押すと、表示している画像のうち2枚目のimg要素class属性を切り替えて、明度の変化をアニメーションで表現します。

サンプルページはこちら

HTML コード例

<article id="content1">
  <h1>JavaScriptレシピ</h1>
  <ul id="btn_change">
    <li><a id="btn1" href="#">すごく明るい</a></li>
    <li><a id="btn2" href="#">明るめ</a></li>
    <li><a id="btn3" href="#" class="active">デフォルト</a></li>
    <li><a id="btn4" href="#">暗め</a></li>
    <li><a id="btn5" href="#">真っ暗</a></li>
  </ul>
  <div>
    <figure><img id="pic1" src="./image/bear.png" alt="元画像"><figcaption>元の状態</figcaption></figure>
    <figure><img id="pic2" src="./image/bear.png" alt="加工画像"><figcaption>調整後</figcaption></figure>
  </div>
  
</article>

CSSは下の方の「明度の調整」に記述した明度を調整するスタイルが非常に重要になってきます。
ここではtransitionプロパティを使ってアニメーションの設定も行います。

CSS コード例

article {
  padding: 20px;
  background-color: #bedef7;
}
h1 {
  margin: 0 0 20px;
  padding: 0;
  font-size: 100%;
}

/* 明度の切り替えボタン
------------------------------ */
ul {
  overflow: hidden;
  margin: 0;
  padding: 0;
}
ul li {
  float: left;
  margin: 0 20px 0 0;
  display: inline-block;
  padding: 0;
}
ul li a {
  display: inline-block;
  margin-bottom: 20px;
  padding: 10px 20px;
  color: #fff;
  font-size: 86%;
  text-decoration: none;
  border-radius: 5px;
  background-color: #4a93cb;
}
ul li a:hover,
ul li a.active {
  background-color: #71b2e4;
}

/* 画像エリア
------------------------------ */
div {
  overflow: hidden;
}
figure {
  float: left;
  margin: 0 20px 0 0;
  padding: 0;
}
figure img {
  width: 400px;
  height: auto;
}

/* 明度の調整
------------------------------ */
#pic2 {
  filter: brightness(1);
  transition-property: filter;
  transition-duration: .5s;
  transition-timing-function: ease;
}
#pic2.white {
  filter: brightness(2);
}
#pic2.brite {
  filter: brightness(1.5);
}
#pic2.dark {
  filter: brightness(0.6);
}
#pic2.black {
  filter: brightness(0.3);
}

brightnessメソッド1は初期状態で元画像と同じ状態です。
それ以外の値とボタンとの関係は以下のように設定します。

クラス名対応するボタンbrightnessメソッドの値
.whiteすごく明るい2
.brite明るめ1.5
.dark暗め0.6
.black真っ暗0.3

最後にJavaScriptのコードです。

JavaScript コード例

window.addEventListener('DOMContentLoaded', function(){

  const pic2 = document.getElementById('pic2');    
  const btn_change = document.getElementById('btn_change');
  const btns = document.querySelectorAll('#btn_change li a');

  for(var btn of btns) {

    btn.addEventListener('click', (e)=> {

    const btns2 = document.querySelectorAll('#btn_change li a');
    for(var i_btn of btns2) {
      i_btn.classList.remove('active');
    }

    e.preventDefault(); 
    e.target.classList.add('active');
      
    switch(e.target.textContent) {
      case 'すごく明るい':
        pic2.setAttribute('class','white');
        break;

      case '明るめ':
        pic2.setAttribute('class','brite');
        break;

      case '暗め':
        pic2.setAttribute('class','dark');
        break;

      case '真っ暗':
        pic2.setAttribute('class','black');
        break;

      default:
        pic2.removeAttribute('class');
        break;
    }

  });
  }
});

switch文の条件式で指定している「e.target.textContent」は押されたボタンのテキストを取得して、case文で押されたボタンによって処理を切り分けます。

case文ではimg要素に対してsetAttributeメソッドremoveAttributeメソッドを使ってclass属性を書き換えます。
適用するクラスが切り替わることで、CSSに記述したtransitionプロパティのアニメーションが実行されます。

animationプロパティを使った明度のアニメーション

上記のコードではtransitionプロパティを使ってアニメーションの設定を行いましたが、animationプロパティに置き換えるとCSSは以下の内容になります。
HTMLとJavaScriptについては変更は必要ありません。

1点だけtransitionプロパティと異なる点があり、animationプロパティのアニメーションを設定する@keyframesでは現在適用されているプロパティの値を引き継ぐことができません。
そのため、何かボタンを押してアニメーションを実行した後の状態から、他のボタンが押されたときに次のアニメーションを開始するときは初期値「brightness(0)」からのスタートになります。

CSS コード例

article {
  padding: 20px;
  background-color: #bedef7;
}
h1 {
  margin: 0 0 20px;
  padding: 0;
  font-size: 100%;
}

/* 明度の切り替えボタン
------------------------------ */
ul {
  overflow: hidden;
  margin: 0;
  padding: 0;
}
ul li {
  float: left;
  margin: 0 20px 0 0;
  display: inline-block;
  padding: 0;
}
ul li a {
  display: inline-block;
  margin-bottom: 20px;
  padding: 10px 20px;
  color: #fff;
  font-size: 86%;
  text-decoration: none;
  border-radius: 5px;
  background-color: #4a93cb;
}
ul li a:hover,
ul li a.active {
  background-color: #71b2e4;
}

/* 画像エリア
------------------------------ */
div {
  overflow: hidden;
}
figure {
  float: left;
  margin: 0 20px 0 0;
  padding: 0;
}
figure img {
  width: 400px;
  height: auto;
}

/* 明度の調整
------------------------------ */
#pic2 {
  animation: a1 .5s ease forwards;
}
#pic2.white {
  animation: a2 .5s ease forwards;
}
#pic2.brite {
  animation: a3 .5s ease forwards;
}
#pic2.dark {
  animation: a4 .5s ease forwards;
}
#pic2.black {
  animation: a5 .5s ease forwards;
}

@keyframes a1 {
  100% {filter: brightness(1);}
}
@keyframes a2 {
  100% {filter: brightness(2);}
}
@keyframes a3 {
  100% {filter: brightness(1.5);}
}
@keyframes a4 {
  100% {filter: brightness(0.6);}
}
@keyframes a5 {
  100% {filter: brightness(0.3);}
}

記事一覧

関連記事