こんにちは。前回から引き続き、JavaScriptによるUIを実装する方法を紹介していきます。
基本のタブメニュー
ウェブアプリでよく使われるインタフェースのひとつ、タブメニューを実装してみましょう。まず、骨組みとなる基本のHTMLは以下のとおりです。
そして、CSSは次のとおりです。ひとまず今回はサイズを固定にして、特に凝ったスタイルは使っていません。あえて言えば、li要素をinlineにして横に並べている点と、リンクに対してアクティブなとき・マウスを乗せたときで、スタイルを変えている点がポイントです。
さて、このHTMLを操作するJavaScriptです。まずはなるべくシンプルに実装してみます。
タブを切り替えるには、クリックしたリンクに対応するコンテンツを表示するだけでなく、それまで表示されていたコンテンツを非表示にする必要があります(ついでにリンクのスタイルも変更)。今回は現在表示されているコンテンツ・リンク自体を変数(current)に入れておき、現在のコンテンツを非表示に変更してから、次のコンテンツを表示する、という方法で実装しました。
なお、for文でのループの中でtab_init関数を呼び出していますが、この関数の中身をfor文の中に直接書いても問題ないように見えると思います。しかし、実際には直接書いてしまっては意図通りに動作しなくなります。その理由はもちろんクロージャーです。
上記コードにおいて、tab_init内のlink・pageなどの変数はtab_init内のローカル変数であり、同時にtab_init内部のonclickに設定された関数からもlinkとpageは参照可能です。
つまり、変数のスコープは次のようになっています(こちらは実際に動くコードではありません)。
変数pageとlinkがそれぞれ3つ存在する点がポイントです。
クロージャーの復習はこれくらいにして、実際の動作サンプルは次のとおりです。
機能的には問題ありませんが、リンクの間の隙間が気になると思います。これは、(li要素をインラインにしているので)li要素の間にある改行が空白文字列として認識されてしまうためです。
これを回避する方法はいくつかあり、単純にliとliの間の改行を取り除くというのが手軽な方法です。
または、HTMLではli要素は終了タグを省略できること、タグを省略した場合に改行がその前のタグの中身になる点を利用する方法もあります(加えて、li要素をinlineではなくinline-blockにする必要があります)。ただ、今回のケースではIEでリンクの後ろに空白が残ってしまいます。
というわけで、今回は改行の位置を工夫してリンクの中に空白を入れるようにしてみます。
タブメニューのアニメーション
さて、タブメニューの切り替えを簡単なアニメーションにしてみます。
まず、HTMLはほぼ同じです。変更点はひとつだけで、コンテンツ部分のdivを増やしました。
CSSも概ね同じですが、tab_contentはposition:relativeに、追加したinnerとpageはposition:absoluteにしています。
さらに、innerはwidthを1350pxと大きく取りました。このinnerの中に各pageを横に並べて配置した状態でinnerを左右に動かせば、表示されるpageが切り替わるという仕組みです。
最後にJavaScriptで450px動かすようにするだけです。とてもシンプルですね。
あとは、このleftの値をアニメーションさせるだけです。第17回で作ったMiniTweenerを使ってアニメーションさせましょう。
タブメニューの汎用化
ここまで、幅や高さなどの値が決め打ちで、汎用的ではありませんでした。最後に少しだけ汎用化してみましょう。
まず、HTMLはこれまで通りです。CSSはtab_content、inner、pageに指定していたwidthとheightを取り除き、代わりに各ページごとにバラバラなサイズを指定します。
あとはJavaScriptで各pageごとのサイズを取得し、それをtab_contentとinnerに反映・調整してあげるだけです。
要素のサイズを取得するにはclientHeight, clientWidthを用います。ほかにgetBoundingClientRectメソッドを利用するという方法もあります。getBoundingClientRectは要素のサイズや位置情報をまとめて取得できる便利なメソッドです。元々IEが独自に実装したメソッドでCSSOM View Moduleで標準化されており、ほとんどのブラウザで利用できます(万が一、Firefox 2をサポートしなければいけない場合、getBoundingClientRectをサポートしていないので、ほかの方法で代替する必要があります)。ただし、IEのgetBoundingClientRectはtop, right, bottom, leftの4つのプロパティしかサポートしていません。今回のように幅と高さを取得したい場合はbottom-topのように計算が必要になります。
まとめ
今回はJavaScriptを使ったUIとしてタブメニューの作り方を取り上げました。こういったUIはまだまだつくり込む余地がたくさんあります。是非、自分なりの改良を加えてみてください。
次回も引き続きJavaScriptを使ったクロスブラウザなUIの実装を見ていきたいと思います。