Blog

ブログ

IonicでMasonryレイアウト

Yuko Hashimoto
Yuko Hashimoto デザイナー

IonicでMasonryレイアウトを使いたいなあと思って試してみたメモです。
javascriptプラグインを入れて使ってみたことがなかったので、ちょこちょこ引っかかりました。

作りたいMasonryレイアウト

こんな感じの仕上がりを目指します。
Pinterestとかで見るレイアウトです。

Masonry.jsを使う

Masonryレイアウトを作るのに一番有名なプラグインMasonryを使った場合。

JSを設置

公式サイトからmasonry.pkgd.min.jsをダウンロードし、Ionicのassetsフォルダにpluginとか適当な名前のフォルダを作って入れておきます。

index.htmlに読み込む

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    ・・・
  </head>
  <body>
    ・・・
    <script src="build/main.js"></script>

    <!-- main.js読み込んだ後あたりに -->
    <script src="assets/plugin/masonry.pkgd.min.js"></script>

  </body>
</html>

html,cssを用意

<div class="grid">
  <div class="grid-item"><img src="./assets/images/image01.jpg"></div> 
  <div class="grid-item" ><img src="./assets/images/image02.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image03.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image04.jpg"></div> 
  <div class="grid-item"><img src="./assets/images/image05.jpg"></div> 
  <div class="grid-item"><img src="./assets/images/image06.jpg"></div> 
  <div class="grid-item"><img src="./assets/images/image07.jpg"></div> 
  <div class="grid-item"><img src="./assets/images/image08.jpg"></div>
</div>

横幅固定にした理由は後述。

.grid-item {
  width: 150px;
}

tsで呼び出し

公式サイトのVanilla JSに設置するコードを参考にします。

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

declare var Masonry: any; // ←型定義する

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})

export class HomePage {
  constructor(public navCtrl: NavController) {
  }

  ionViewDidEnter() {
    setTimeout(() => {
      var elem = document.querySelector('.grid');
      var msnry = new Masonry(elem, {
        columnWidth: 150,
        itemSelector: '.grid-item',
      });
    }, 100);
  }
}

横幅150pxにしましたが、何故か横幅を%で指定すると表示が崩れます。
オプションをどう指定してもダメでした。何かいい方法あるんでしょうか・・・。

Ionic案件ではレスポンシブ対応することも多いし、次のプラグインの方が扱いやすいかも。

Macy.jsを使う

Masonryレイアウトが作れる軽量プラグインMacy
表示するだけならMasonry.jsよりシンプルで扱いやすい感じがします。
ブレイクポイントごとに横に何列表示するかを設定できます。
Masonryと設置方法はほとんど同じです。

JSを設置

公式サイトからmacy.jsをダウンロードし、Ionicのassetsフォルダに入れます(先ほどのMasonryと同じようにpluginフォルダとします)。

index.htmlに読み込む

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    ・・・
  </head>
  <body>
    ・・・
    <script src="build/main.js"></script>

    <!-- main.js読み込んだ後あたりに -->
    <script src="assets/plugin/macy.js"></script>

  </body>
</html>

htmlを用意

<div class="grid">
  <div class="grid-item"><img src="./assets/images/image01.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image02.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image03.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image04.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image05.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image06.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image07.jpg"></div>
  <div class="grid-item"><img src="./assets/images/image08.jpg"></div>
</div>

tsで呼び出し

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

declare var Macy: any; // ←型定義

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})

export class HomePage {
  constructor(public navCtrl: NavController) {
  }

  ionViewDidEnter() {
    setTimeout(() => {
      var macy = Macy({
        container: '.grid',
        trueOrder: false,
        waitForImages: false,
        columns: 6,
        margin: {
          x: 20,
          y: 10,
        },
        breakAt: {
          1200: 5,
          940: 4,
          520: 3,
          400: 2
        }
      });
    }, 100);
  }
}

オプションは公式サイトをご覧ください。
ブレイクポイントごとに細かく設定できて好きだなー。

MiniMasonry.jsでも試してみた

MiniMasonryも同じように設置できます。
しかし要素ごとにheightを指定しないとうまく表示できないようです。要素の高さがバラバラだと厳しい。

他にも色々可能性がありそう

IonicでjQuery/jQueryプラグインを従来通り使う方法というQiitaを参考にしました。
今回はjQueryを使わないプラグインばかりでしたが、jQueryも使えるともっとできることが増えそうです。

……あんまり使わない方がいいんだろうな…とは…思う……。