続いて、目次からリンクしている記事パネルを作成します。記事のパネルは、先ほど作成した目次と同じHTML内につなげて記述します。非常に長いHTMLになりますが、コンテンツを一気に読み込むことでサーバーとの通信頻度を少なくし、パネル間の移動をスムーズにできます。
記述するHTMLは次のとおりです。内容は自由で構いませんが、パネル全体をdiv要素で囲んで、目次と一致したid属性を付加しておきます。これで、ページ内リンクが機能するようになります。
positionプロパティにabsoluteを設定して幅と高さに100%をするとパネルが画面いっぱいに表示されるので、すべてのパネルが以下のように重なった状態になります。
この状態でdisplayプロパティをnoneにしてすべてのパネルをいったん非表示にし、目次パネルだけをdisplay:blockで表示状態に切り替えます。目次パネルには「active」というクラスを設定してあるので、以下のように記述します。
スライドパネルのJavaScriptを作成する
HTMLとCSSの用意ができたので、いよいよスライドのスクリプトを作成します。スクリプトは以下のようになります。
$(function() {
var winWidth = window.innerWidth;
/**
* ページ内リンクのクリックイベント
*/
$('a[href^=#]').click(function() {
if ($(this).attr('href') == '#index') {
goIndex();
} else {
$('#index').animate({
left: (winWidth * -1) + 'px'
}, 500, function() { $(this).removeClass('active') });
$($(this).attr('href')).css('left', winWidth).addClass('active').animate({
left: 0
}, 500);
return false;
}
});
/**
* 戻る
*/
function goIndex() {
if ($('div.active').attr('id') == 'index') return false;
$('div.active').animate({
left: winWidth + 'px'
}, 500, function() { $(this).removeClass('active'); });
$('#index').css('left', (winWidth * -1) + 'px').addClass('active').animate({
left: 0
}, 500);
}
});
前に説明した通り、jQueryを使ったスクリプトでは対象の要素に続けてメソッドやイベントを記述していくのが基本です。まず、7行目に注目します。
$('a[href^=#]').click(function() {
...
a[href=^#]は、a要素でかつhref属性が「#」から始まる要素、つまりページ内リンクを指定したリンク要素を表します。click()は「クリックされたとき」という意味のイベントですので、ページ内リンクがクリックされたときに{ }内のプログラムが実行されます。
パネルを動かすプログラムの本体は、11行目からになります。
$('#index').animate({
left: (winWidth * -1) + 'px'
}, 500, function() { $(this).removeClass('active') });
$($(this).attr('href')).css('left', winWidth).addClass('active').animate({
left: 0
}, 500);
animate()は、任意のCSSプロパティの値を徐々に変化させて、さまざまなアニメーション効果を表現するメソッドです。ここでは、「id属性がindexの要素」=目次に対して、「leftプロパティを左方向に徐々に変更して左端までずらす」というアニメーションを設定しています。
画面幅は、あらかじめスクリプトの2行目で取得しています。
var winWidth = window.innerWidth;
window.innerWidthでは、スマートフォンの端末ごとの画面幅を取得できます。たとえば、iPhoneの画面幅は320pxなので、320×-1=-320pxまでずらすことになります。
目次パネルのアニメーションが終わったら、removeClass('active') を実行します。class属性から「active」が取り除かれ、目次パネルが非表示になります。
続いて、以下のプログラムを見ていきます。
$($(this).attr('href')).css('left', winWidth).addClass('active').animate({
left: 0
}, 500);
セレクター部分がやや複雑ですが、まずは $(this).attr('href') だけに注目してください。attr()は「属性を取得する」というメソッドで、ここではクリックされたリンクのhref属性(「#vol01」などの文字列)を取得します。前のプログラムを展開すると次のようになります。
$('#vol01').css('left...
セレクターの対象が分かったので、各メソッドを確認していきましょう。css()メソッドは任意のCSSプロパティの値を変更します。ここでは「leftプロパティを画面の右端に」と指定し、記事パネルを右側に隠しておきます。
addClass()はclass属性を追加するメソッドで、「active」を追加するとdisplay: blockが適用されてパネルが画面に表示されます。最後に、animate()メソッドでleftプロパティを0に変更し、記事パネルを画面の左端に移動させます。
以上、解説がかなり長くなりましたが、一連のプログラムが同時に実行されることで、以下のようになります。
- 目次で項目がタップされる
- 目次が徐々に画面左端に消えていく。 同時に記事パネルが右端から現れる
- 目次が左端に消えたあと表示が消え、代わりに記事パネルが表示される
これで、パネルが左にスライドして切り替わったように見えるわけです。
「戻る」ボタンをタップしたときは逆の動きをします。表示されている記事パネルを右方向に画面幅分だけスライドさせ、目次パネルを左端から表示させます。「戻る」のプログラムは、次のページで紹介するフリック操作で再利用できるように、goIndex()というファンクションにまとめています。
フリックでの移動
前のページまでの解説でスライドパネルの機能が一通り完成しましたが、今度はスマートフォンならではの操作として、フリック操作でも戻れるようにします。次のようなスクリプトを追加します。
/**
* フリックでの戻る
*/
document.addEventListener("touchstart", start, false);
document.addEventListener("touchmove", move, false);
document.addEventListener("touchend", end, false);
var startX, endX;
function start() {
startX = event.touches[0].pageX;
}
function move(e) {
endX = event.touches[0].pageX;
}
function end(e) {
if (endX - startX > 100) {
goIndex();
}
}
先ほどclick()イベントを紹介しましたが、スマートフォンには特有のイベントとして「タッチした」「(タッチしたまま)指を動かした」「指を離した」というイベントが用意されています。
本来は「フリックした」というイベントがあれば簡単なのですが、用意されていないので、複数のイベントを組み合わせて疑似的に「フリックイベント」を作ります。フリック操作を分解すると、次のようなイベントになります。
- 画面をタッチする
- そのまま指を右(または左)に動かす
- 指を離す
実際のプログラムを分解して見ていきましょう。
タッチイベントが発生すると、タッチされた地点のX座標を記録します。
function start() {
startX = event.touches[0].pageX;
}
プログラムでは指が動くたびにX座標を記録し続けます。
function move(e) {
endX = event.touches[0].pageX;
}
指が画面から離れると、最後の位置と最初の位置を比較し、100px以上離れていると「フリックした」とみなします。
function end(e) {
if (endX - startX > 100) {
goIndex();
}
}
呼び出しているgoIndex()は自作のファンクション(関数)で、前に解説した「目次に戻る」という動作を定義しています。
/**
* 戻る
*/
function goIndex() {
if ($('div.active').attr('id') == 'index') return false;
$('div.active').animate({
left: winWidth + 'px'
}, 500, function() { $(this).removeClass('active'); });
$('#index').css('left', (winWidth * -1) + 'px').addClass('active').animate({
left: 0
}, 500);
}
なお、ここで「100px」としている数字は特に決まった数値ではありません。小さな値にすれば敏感に反応するようになり、大きな数字にすれば反応しづらくなります。実際に試しながら最適な数値にチューニングしたり、ユーザーが自由に設定できるようにしたりするとよいでしょう。
今回紹介したサンプルコードは以下からダウンロードできます。一覧と詳細ページに分かれているニュースやブログ、カタログなど、さまざまなサイトで活用できますので、ぜひ組み込んで試してみてください。