jQuery

見出しを自動で目次化して クリックするとスムーズにスクロールさせる(スムーズスクロール編)

N114 hikkurikaerukabocya Fotor

今回は 前記事 見出しを自動で目次化して クリックするとスムーズにスクロールさせる(見出し→目次編) | LogicA の続きです。
目次の項目をクリックすると、該当箇所までスムーズスクロールさせる方法です。

実際の動作はこの記事の頭にある目次欄をクリックとかしてみてください。

サンプルコードです

[javascript]

/* =========================================================
【ページ内リンク】 と 【目次】 を自動生成
========================================================= */
 
 
var list;  // 目次を入れる変数
 
jQuery("h3").each(function(i){
    var idName = "mokuji" + i;
    jQuery(this).attr("id", idName);
    list += ‘<li><a href="#’ + idName + ‘">’ + jQuery(this).text() + ‘</a></li>’;
});
 
if (jQuery("h3").length){
    jQuery("p:first").append(‘<ul id="mokuji"><strong>- 目次 -</strong>’ + list + ‘</ul>’);
}
 
/* =========================================================
スムーススクロール
========================================================= */
//クリックイベント発火
jQuery("[href^=’#’]").click(function() {
// ID取得
var t = jQuery(this).attr("href");
var off = jQuery(t).offset().top;
// ブラウザ判定
var w = jQuery(window).scrollTop();
if (jQuery(‘html’).scrollTop() > 0) {
    var targetBody = jQuery(‘html’);
}
else if (jQuery(‘body’).scrollTop() > 0) {
    var targetBody = jQuery(‘body’);
}
// アニメーション
targetBody.animate({
scrollTop: off
});
return false;
});

[/javascript]

今回は【スムーススクロール】のコメントアウト以下から解説します。

目次にクリックイベントを発生させる

目次にはリンクが付いています。(前回記事参照)全ての目次のリンクにはページ内リンクさせるため、【#】を頭に付けています。なので、#付きのリンクを抽出します。

[javascript]

jQuery("[href*=’#’]").click(function() {

[/javascript]

【href*=’#’】は、【URL内に #を含むhref】という条件になります。ページ内リンクは必ず頭に#が付いているので、これで記事内の全ての#付きリンクが抽出できます。
(ページ内リンクは必ず頭に#が付くので、【href^=’#’】でもOKです)

スクロールする目的地の【高さ】を取得する

目的地の高さ、つまり、アニメーションさせるゴール地点のポイントの【topの座標】を取得します。

[javascript]

var t = jQuery(this).attr("href");
var off = jQuery(t).offset().top;

[/javascript]

一行目の【変数 t】で、まずはクリックした目次のリンクURLを取得します。このブログどおりのコードを使用していると、【#mokuji2】といった値が取得できるはずです。数字は連番で見出しの(0から始まる)順番どおりに振られているはず。

二行目の【変数 off】は、先ほど取得した【変数 t】の値を要素として指定することで、目的地の見出しのIDとなります。
つまり実際はjQuery(“#mokuji2”).offset().top;と、IDで指定しているのと同じ内容になります。これで、【〜番目の見出し】の高さが取得できます。

あとはアニメーション!…の前にブラウザ判定を

jQuery得意のアニメーションでラストです!が、その前に

[javascript]

var w = jQuery(window).scrollTop();
if (jQuery(‘html’).scrollTop() > 0) {
    var targetBody = jQuery(‘html’);
}
else if (jQuery(‘body’).scrollTop() > 0) {
var targetBody = jQuery(‘body’);
}

[/javascript]

コツは、アニメーションをさせる要素を【html】と【body】どちらにするか、です。
片方だけだとブラウザによって挙動が変わって、スクロールしないブラウザが出て来ます。例えば(2013年5月20日現在だと)【html】を指定しないとFirefoxで動かなく、逆に【body】を指定しないとWebKit系(ChromeやSafariとか)で動きません。
しかし、両方指定する(jQuery(‘html,body’) みたいな)のはNGとのこと。コールバックが発生したときに2重で動作してしまうようです。詳しくは
ページ内で気持ち良いスムーススクロールをするためのjQueryプラグイン作った。 | モンキーレンチ
こちらの記事を参照させていただきました。そして対策もそのままさせていただきました!アザス(*´꒳`*)

これで【変数 targetBody】に html、body をブラウザに合わせて必要な方を入れられました。

あとはアニメーション!

さきほど作成した【変数 targetBody】にアニメーションをかけます。

[javascript]

targetBody.animate({
scrollTop: off
});
return false;

[/javascript]

アニメーションは普通のanimateメソッドなので、特に説明はありません。【変数 targetBody】を指定し、【scrollTop】で 先ほど取得したゴールの座標【変数 off】を指定してます。

あとはスクロールアニメのアレンジなんかで個性は出せますよ。例えばこのブログでは

[javascript]

targetBody.animate({
scrollTop: off
}, 800, "easeOutQuart");

[/javascript]

で、スピードやエフェクト(イージング)を指定してます。あんまり個性を出し過ぎると濃ゆくなってくどくなるのでほどほどで気持ちよいくらいでとどめましょう。

ちなみにjQueryのイージングはプラグインが無いとほぼ無意味です。こちらの記事
jQueryアニメーションにイージング(easing)処理をつけるプラグイン【イージング動作サンプル一覧】 | BlackFlag
はいつもイージング利用のときにお世話になってます。サンプル付きリンク先付きなのでありがたいです。

今回の記事と前回の記事とを併せてブログへ入れて頂くと、いつも通り記事を書くだけで 勝手に目次を作ってくれて、クリックすると各見出しへスルスルスルっとスクロールしてくれるようになりますよ。是非!

以上、@dutchisover でした!