Material Desgin Lightでいろいろ困る。iframeとかスクロールとか

 Material Design Lite
を試している。最新のデザインとUIをカンタンなコーディングで得られる、Bootstrapよりも軽い(サイズが小さい)、とかそういうのが利点だろうか(そういう比較は各所で見れる)。
 COMPONENTSのページにはUIで使えるコンポーネントみたいなやつが、デモとコードで示されている。これをコピペすればそれなりにいい感じできあがる。わかりやすい。
 しかし、実際に動かしてみると困ったことがいくつか。まず、iframeを使ったウィジェットなどの挙動が変。たとえば、はてなブックマークボタンが表示されないのだ。

はてなブックマークボタンなどが表示されない問題

 はてなブックマークボタンが一瞬表示されるのだけど、すぐ消える。そんな感じ。余計な画面リフレッシュが走ってるような気もする。Chromeの開発ツールを見ると、消えたタイミングでiframeの中身が空になるのだ。
 これは「mdl-js-layout」というclassが一番外側のdivで指定されてると発生する(menu関連のサンプルのコードを見ればわかる)。消せばはてなブックマークは問題なく表示される。しかし、このclassの指定がないと、メニューまわりの動作がおかしくなる。ドロワーが出なくなったりとか。そういう動作を司っているのが「mdl-js-xxxx」みたいなclassなのだろう。各コンポーネントは見た目と動きを司る別々のclassが存在するっぽい。
 で、どうするかというと、はてなブックマークボタンを表示するためのJavaScriptのロードを遅らせること。Material Desgin Liteが、「mdl-componentupgraded」というイベントを発生させているのでこれをイベントリスナーでキャッチすればいい。このイベントはUIが更新されるたびに発生するのだけど、1回目だけをチェックすればいい(というわけで、キャッチしたらイベントリスナーを削除でいいらしい)。


 こんな感じだ。まずはうまく表示されない状態。はてブボタンがおかしいことになってるのがわかるはず。

 対策を施した例。

 これなら表示される。
 同じような状況はTwitterのタイムラインを表示するウィジェットでも発生している。上の実働サンプルにも入れてある。
 この現象について詳しくは以下にある。
 MDL Javascript conflict with Twitter widget #1369

Google Adsenseでも問題

 似たような状況ではGoogle Adsenseでも不具合が発生している。こちらもiframeを使ったコードだ。なぜか、中身がリロードされる。
 ページが表示されると、ちゃんとAdsenseの広告が表示されるのだが、中身がリロードされ、別の広告に切り替わるのだ。なぜ? 表示されなりはまし、という考え方もあるのだけど、気持ち悪い。
 先の例と同じようにJavaScriptのコードを遅れてロードするようにすればいい。具体的にいうと「/pagead2.googlesyndication.com/pagead/js/adsbygoogle.js」というファイル。
 しかし、Google Adsenseの規約的にどうなのだろう? 実際に試したのだけど、公開用にはどうだろうなあ、と思い、やめてしまった。
 とりあえず、この例については以下が詳しい。
 Material Design Lite and Adsense, make them play together in harmony

/pagead2.googlesyndication.com/pagead/js/adsbygoogle.js

スクロールの制御ができない

 スクロールの制御ができないという話。jQueryのwow.js、jquery lazyload、smoothscrollといったプラグインが動かないとのこと。これについては以下が詳しい。
 【新サイト開発不定期日誌】Material Design Liteがなんかおかしい件 – 文系プログラマによるTIPSブログ
 これも「mdl-js-layout」があると動かないそうだ。で、「html,body」にスクロールイベントを設定するのではなく、「.mdl-layout__content」に設定すればよいとか。
 試す。ほんとだ。確かに動く。しかし、問題がまたも発生。

「.mdl-layout__content」に対してスクロール設定すると確かに位置も取得できてスクロールもできたんですが、タイミングによっておかしな値が取れたりして、正直挙動がよく解りませんでした。

 まさしくこれ!
 この問題。いろいろテストしてみると、スクロールして移動したあとに位置を取得するとおかしくなるということらしい。位置をあらかじめ取得して変数に記憶。あとはそれを参照するという方法にした。
 最初に使おうとしてたのはこれ。
 ページ内を自在にスクロール | よく使うjQuery
 このコード、メニュー項目が増えても自動で対応できる(いちいちid指定も不要)ので、すごいと思ったのだけど(こういう書き方はjQueryでは定番だったりするのだろうか? 自分では到底思い浮かばないなあ、と思った)。残念ながら、Material Desgin Liteではそのままではうまくいかなかった。
 上記ページのコードでは、メニュー項目のクリックのタイミングで、ジャンプ先の位置を取得しているのだけど、いったん移動してからだと取得した値がおかしくなる。
 もう少し具体的に言うと、メニュー a、b、c のクリックで、ページ内の A、B、C にそれぞれ飛ぶという構成。A、B、Cの位置(上からの座標)がそれぞれ、0、100、200だとする。
 aのあとに、bまたはcをクリックした場合はちゃんとB、Cにそれぞれ移動する。
 しかし、メニューbのクリックでBに移動。その時点でcを押すとCに移動できない。Cの位置を100と検出してしまっているから、という感じだ。
 前述のとおり、位置の取得のタイミングを変えればなんとか問題解決。ウィンドウのリサイズとか、スマホやタブレットなら回転とかするとかするとおかしくなりそうだけど。まあ、最悪、スクロールすればいいので今回はそれ以上追求しないことにする。まだ先に進まないとならないので。

結局のところ

 とりあえず、Material Desgin Liteについてわかったことのメモでした。
 いろいろ問題を回避しようとしているうちに、Material Desgin Liteのコンポーネントの例にあるものからちょっと離れてきたところもいろいろ。
  たとえば、ヘッダーの表示がうまいこと制御できてない。これは自分の理解がまだ足りてないからだと思うのだけど、スクリーンサイズで制御される部分と、スクロールとかウォーターフォール、さらにドロワー表示の組み合わせが思ったとおりにいかない。
 ドロワーとヘッダーの動きまったく個別に指定できてない(このへんがドキュメントで理解できてない)。そんなことでヘッダーはheaderタグを使わず、書いた。これにドロワー用のメニューボタンを重ねる(いわゆるハンバーガーアイコン、これはヘッダーなしの例で挙げられている)。でも、ドロワーを表示しようとすると、最初に挙げiframeのウィジェットの挙動が変になる。結局、これもやめてMENU(more_vertアイコン、3つの点が縦に並ぶのやつ)を使うことにした。縦全体に出るドロワーとは違って小さい。
 Material Desgin LiteのGitHubを見ると、まだまだ進化の途中、バグを出し切れてない&修正しきれてないという状態にも見える。つい最近も1.0.4から1.0.5にバージョンアップしたばかりだ(でも、上で挙げた問題点はまだ残されたままだ)。
 それでもPolymerよりは導入のハードルがだいぶ低いと思うので、試さない手はないと思う。なんといっても、ライブラリをローカルにダウンロードする必要がない、CDNのURLを指定するだけでいいというのはすごい楽(jQuery本体と同じ感じですぐ試せる状態になる)。
 Material Desgin Liteの記事をいろいろ探したのだけど、日本では単なる紹介記事ばかりで、実際に使っているという人はまだまだ少ないという印象。で、実際に使った人は問題点を挙げており、べた褒めしてる人はまだいないという感じか。いや、今回挙げた問題にひっかからなければ、すんげー楽!便利!って感じで使えてるのだろう。
 しばらくは使いながら、いろいろ記録していくことにしよう。なんかできたら公開します。
 
 

コメント

タイトルとURLをコピーしました