n要素毎に高さ揃えができる自作プラグイン(といっても、前職在籍時の2010年頃にライブラリのコードリーディングをして勉強したことがあるので、よく似ているのですが)を使っていて、オプションで{ groupBy: 3 }
のように要素数を指定をしているのですが、レスポンシブWebデザインのサイトを設計・実装する際、画面幅によってnの値を変えたい場合が時々出てきます。
以前MJLで高さ揃えをする際、ビューポートの幅に応じて何個ごとに高さ揃えをするか変えることを検討してみたに書いたように.matchMedia()
も使ったりしたのですが、どうも手間がかかります。同じことを繰り返すならもっと楽をしたいと思案したところ、groupBy
の値に画面幅とグルーピングする要素数を書けば良いかと思いつき、実装したところ上手くいきました。
コードの改善ポイント
オプションは次のように配列で指定します。
{
groupBy: [
{
maxWidth: 479,
groupBy: 0 // 高さ揃えをキャンセル
},
{
maxWidth: 767,
groupBy: 2
},
{
maxWidth: 99999,
groupBy: 3
},
]
}
プラグインでは、まずgroupBy
の値がオブジェクト(JavaScriptなので、配列もtypeof
の結果はオブジェクト)の場合、ブレークポイントを収集しておきます。
defineGroupByVal: function () {
var groupBySetting = this.options.groupBy,
breakPoints = [];
groupBySetting.forEach(function (setting) {
breakPoints.push(setting.maxWidth);
});
breakPoints.sort(
function compareNumbers(a, b) {
return a - b;
}
);
this.breakPoints = breakPoints;
},
そして、load・resizeイベントが発火して高さ揃えをする際、ブレークポイントが格納されている場合は画面サイズをチェックして、設定にマッチするgroupBy
の値を抽出するようにしました。
doEqualize: function () {
var height = [],
nElem = this.target.length,
i = 0,
matchFlag = false,
groupBy;
// 省略
// 高さ揃えのグループ単位を取得
if (this.breakPoints) {
this.breakPoints.forEach(mylib.util.proxy(this, function (breakPoint) {
if (!matchFlag && window.innerWidth < breakPoint) {
this.options.groupBy.filter(function (item) {
if (item.maxWidth === breakPoint) {
groupBy = item.groupBy;
}
});
matchFlag = true;
}
}));
} else {
groupBy = this.options.groupBy;
}
// 揃える高さを算出
if (groupBy === 0) {
// 高さ揃えをキャンセル
height = [];
} else {
height = this._getArrangeHeight(height, nElem, groupBy);
}
// 要素に高さを設定
this._setHeight(height, nElem);
},
テストで作成したファイルのレンダリング結果は次のようになりました。
- ビューポートが680px以上の場合
- ビューポートが480px〜679pxの場合
- ビューポートが479px以下の場合
揃える要素数はプラグイン内で算出しても良いかもしれませんが、予め分かっているのでそこまでしなくてもよいかなと考えました。