お待たせしました!
「れーとーびーむの作り方」実践編!

……これまでの前座はなんだったのか。

今回は、「ページ内リンク」を瞬間移動ではなく、するするーっとスクロールするように改造しちゃおうのコーナー。

ついでに、ページ内リンクを踏んでもURLが変わらず、「戻る履歴」にも残らないようにしてしまう。

今回紹介する方法は、このブログでも使っているのだ。多少アレンジしてるけど。

jQueryを使ったJavaScriptでできるよ。

サンプル

とりあえず、以下のページ内リンクを踏んでみな。

※スムーズスクロールは負荷が高いので、スマホとかではカクついてスムーズにならない可能性大。

※帰りは自分でスクロールしてくれ。

とりあえずソース

jQueryを使ったスクリプトだから、しかるべき場所に書くように。

$(function() {
    $('a[href^="#"]:not([href$="#"])').click(function() {
        var href = $(this).attr('href');
        var pos = $(href).offset().top;
        ver duration = 600;
        $('body, html').animate({ scrollTop: pos }, duration, 'linear');
        return false;
    });
});

たったこれだけ!

解説

まず前提条件だが、このサイトのjQueryのバージョンは1.11.2であり、特に古いバージョンではどうなるかわからない。

また、ページ内リンクは <a href="#hoge"> のようにhref属性値は # から始めること。

ちなみに、ページ内リンクのリンク先は、すぐ上の例では id="hoge" をもつ要素になる。

それでは中身を見ていこう。

まず2行目では、「#で始まり、かつ#のみでないhref属性値を持つ<a>要素がクリックされたとき、以降の処理を行う」という意味だ。

3行目では、クリックされた要素のhref属性値を取得し、変数 href に代入している。例:'#hoge'

4行目では、クリックされた要素の、ページ上端からの距離を取得し、変数 pos に代入している。単位はピクセル。

5行目では、スムーズスクロールの所要時間を変数 duration に代入している。単位はミリ秒。

そして6行目で、これまでの処理の結果を利用して、実際にスムーズスクロールを実行している。

7行目は、おまじないに近いが、<a>要素をクリックしたときにブラウザが本来行う処理を無効にしている。つまり、URLは変わらないし、「戻る」で元の位置に戻ったりせず、前のページに戻るようになる。

次に、6行目では何をしているのかを確認しよう。

animate() では、これを設定した要素(上のコードでは<body>と<html>)の属性値を時間変化させることができる。

なぜ<body>と<html>の両方なのかというと、たぶんブラウザの種類によって設定すべき要素が違うんだと思う。

第1引数では、アニメーションさせたいプロパティとその値を、object形式で指定する。

ここでは scrollTop というプロパティ(ページ上端からのスクロール量)と変数 pos を指定している。

第2引数では、アニメーションの所要時間をミリ秒で指定する。

ここでは変数 duration を指定している。

第3引数では、イージングといって、アニメーションの時間変化の加速度を指定する。

指定できるのは 'linear' (常時等速)と 'swing' (徐々に加速し、徐々に減速)という2種類の文字列値だけだ。

アレンジ

移動先の表示位置を調整する

ページ内リンクは、標準の方法でも今回の方法でも、リンク先の要素が画面の上端に来るように移動する。

このサイトをPCで閲覧すると、画面上端にメインメニューが固定表示されるので、リンク先がメニューにかぶってしまわないように位置を調整している。

ということで、4行目を以下のように変えよう。

        var pos = $(href).offset().top - 50;

-50することで、通常より50ピクセル上がスクロールの目的地になる。

移動距離によって所要時間を変える

ページ内リンクと一口に言っても、移動距離は長かったり短かったりする。

上記のソースでは、どんな距離を移動しても所要時間が一定なので、移動速度が距離に比例することになる。

つまり、移動距離が短い時は遅すぎるかもしれないし、長い時は速すぎるかもしれない。

そこで、速度を一定にするというのも一つの手だ。

5行目を以下のように変えてみる。

        ver duration = Math.abs($(window).scrollTop() - pos) / 2;

Math.abs() は“絶対値”を返す関数で、 $(window).scrollTop() は現在のページ上端からの位置だ。

ここでどんな計算をしているのかというと、「時間=距離÷速度」ということで、「現在の位置」-「目的地の位置」の絶対値が移動距離だから、これを速度「2」で割って所要時間を求めているのだ。

ちなみに「2」とは、2ピクセル/ミリ秒、つまり2000ピクセル/秒ということだ。

この速度を各自調整してくれたらいいんだけど……

実際にやってみればわかるが、上の例では移動距離が200ピクセルしかないとたった0.1秒で移動してしまい、ほぼ瞬間移動だ。

逆に、移動距離が10000ピクセルもあれば、移動に5秒もかかってしまい、かなり鬱陶しい。

いずれも極端な例だが、俺はけっこう気になったので、移動距離に応じて速度を変えるようにif文をたくさん書いた。

結局、速度を一定にするより、所要時間を一定にしたほうがナチュラルかもしれない……

終わりに

今回はjQueryを使ってページ内リンクをスムーズスクロールにする方法を紹介した。

やっぱり動きがあるWEBサイトはかっこいいもんね!

ところで「れーとーびーむの作り方」とはどういうことなのかというと……

※れーとーびーむ:このブログ『れいぶろぐ』を含む俺のサイトの名前

俺が独学でWEBデザインを学び、このサイトを作って培った技術やノウハウを、多くの人と共有したい。

それで、こうやってこのサイトで実際に使っているコードを紹介している、つまりこのサイトの作り方を公開しているわけだ。

「れーとーびーむの作り方」シリーズで紹介したこと、これから紹介することを全部真似していけば、このサイトと同じようなサイトが完成する。

もちろん、ただコピペするだけじゃなくて、応用し、アレンジし、自分だけのサイトを作ってほしいと思っているわけだけど。

俺としては自信を持っているこの立派でかっこいい(?)サイトも、こうやって簡単に作れるんだよと、そういう思いを込めて「れーとーびーむの作り方」と名付けた次第だ。

一応創作クラスタだから、タイトルはそれなりに考えてるんだよーっと。

あ、配置や配色や画像のデザインは苦手だから、見た目はかっこよくないよ。

WEBデザインは技術だし、見た目のデザインはセンスだからなー。

デザインのセンスが欲しい。ついでに絵もうまくなりたい。

欲張りだね。

今回はこの辺にしとこう。

それでは、次回をお楽しみに。