Masonry.jsでフィルターを実装する

Masonry.jsでフィルターを実装する

Masonry.jsとは

可変グリッドレイアウトに整列させる時に便利なjQueryプラグインです。
同じようなプラグインには「Isotope.js」「MixItUp.js」などが挙げられます。
今回は「Masonry.js」を使用します。

ダウンロード

こちらから

特徴とライセンス

特徴 ライセンス
Masonry.js 中央配置しやすい
画像読み込み後のコールバックがある
商用利用無料
Isotope.js レイアウトモデルが豊富
ソート、フィルター機能付き
商用利用有料
MixItUp.js アニメーションが豊富
ソート、フィルター機能付き
商用利用有料

Masonry.jsでフィルターを実装する

「Masonry.js」にはフィルター機能が付いていません。
個人使用なら問題ないのですが、商用でフィルターを使いたいとなると他の有料プラグインか、自分で実装するしかありません。
ここでは自分で実装する方法を紹介します。デモは下記です。

デモ

DEMO

ソース

主要な部分だけ抜粋しています。

<body class="category-all">
  <main>
    <!-- ボタン -->
    <ul class="category-btn">
      <li><a href="" class="all is-current">All</a></li>
      <li><a href="" class="sea">Sea</a></li>
      <li><a href="" class="mountain">Mountain</a></li>
      <li><a href="" class="river">River</a></li>
    </ul>
    <!-- 写真 -->
    <ul class="photo">
      <li class="photo-block item-all item-sea"><img src="" width="100%" alt="sea01"></li>
      <li class="photo-block item-all item-mountain"><img src="" width="100%" alt="mountain01"></li>
      <li class="photo-block item-all item-river"><img src="" width="100%" alt="river01"></li>
      <li class="photo-block item-all item-sea"><img src="" width="100%" alt="sea02"></li>
      <li class="photo-block item-all item-mountain"><img src="" width="100%" alt="mountain02"></li>
      <li class="photo-block item-all item-river"><img src="" width="100%" alt="river02"></li>
    </ul>
  </main>
</body>
.category-btn li a.is-current {
  pointer-events: none;
}
.photo {
  margin: 0 auto;
  padding: 0;
}
.photo .photo-block {
  display: none;
  opacity: 0;
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
  width: 300px;
  height: 225px;
}
body.category-all .item-all,
body.category-sea .item-sea,
body.category-mountain .item-mountain,
body.category-river .item-river {
  display: block;
  -webkit-animation: show .5s linear 0s forwards;
          animation: show .5s linear 0s forwards;
}
@-webkit-keyframes show {
  from {
    opacity: 0;
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
  }
  to {
    opacity: 1;
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
  }
}
@keyframes show {
  from {
    opacity: 0;
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
  }
  to {
    opacity: 1;
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
  }
}
$(function(){
  categoryBtn = $('.category-btn').find('a');
  categoryBtn.each(function() {
    $(this).click(function(e){
      var selected = $(this).attr('class');
      e.preventDefault();
      categoryBtn.removeClass('is-current');
      $(this).addClass('is-current');
      $('body').removeClass(function(index, className) {
      return (className.match(/\bcategory-\S+/g) || []).join(' ');
      }).addClass('category-' + selected);
      $('.photo').masonry({
        itemSelector: '.photo-block',
        columnWidth: 300,
        isFitWidth: true
      });
    });
  });
  $('.photo').masonry({
    itemSelector: '.photo-block',
    columnWidth: 300,
    isFitWidth: true
  });
});

解説

まずは「Masonry.js」で真ん中寄せのグリッドレイアウトを作っていきます。

ボタンを押した後の流れは下記です。

  1. ボタンをクリックする
  2. 変数「selected」に押したボタンのclassを格納する
  3. class「is-current」がついているボタンからclassを外す
  4. 押したボタンにclass「is-current」を追加
  5. bodyについているclassのうち、「category-」から始まるクラスを削除
  6. bodyに「(category-)+(変数selected)」のclassを追加
  7. 「Masonry.js」のレイアウトを成形し直す

 

わかりづらいので、もしボタンを「All」から「Sea」に押した場合で考えてみましょう。

  1. 「Sea」ボタンをクリックする
  2. 変数「selected」にclass「sea」を格納する
  3. ボタン「All」からclass「is-current」を外す
  4. 「Sea」ボタンにclass「is-current」を追加(ボタンが緑になる)
  5. bodyからclass「category-all」を削除
  6. bodyにclass「category-sea」を追加
  7. 「Masonry.js」のレイアウトを成形し直す

という流れになります。
「category-」から始まるクラスを削除する部分では正規表現を使っています。

あとはCSSでbodyにclass「category-sea」が付いている時はclass「item-sea」がついている写真が表示されるようになり、「category-river」のときには「item-river」が表示されるようになります。
表示の切り替えには「display:none;」から「display:block;」に変えているだけですが、「display」に対してtransitionは効かないので、keyframeで「opacity」を使用したアニメーションを設定しています。

さいごに

見てわかる通り、かなりアナログなやり方です。
これを作った背景には
「グリッドデザインにして、カテゴリー表示もしたい、ただお金はかけれない」というのがありました。
もし購入できるのであれば有料プラグインの方がいいこと間違いなしですが、一つの方法として参考になればと思います。