JavaScriptでスクロールに合わせてナビゲーションメニューのアクティブを変更する

ワンカラムレイアウトでスクロールに合わせてグローバルナビゲーションのアクティブが変わるページ多いですよね。
このアクティブを変更するライブラリは多く存在しますが弊社サイトでも導入するとのことだったので作ってみました。

(デモ)

 

(弊社活用事例)

 

 

 

使い方

 

  1. jQueryと、Waypoints.jsを読み込みます。
    1. <script type="text/javascript" src="/PATH/jquery-1.11.3.min.js"></script>
    2. <script src="/PATH/noframework.waypoints.min.js"></script>
  2. ChangeScroll.jsをダウンロードし、読み込み込みます。
    1. <script src="/PATH/ScrollChange.js"></script>
  3. ページ内リンクを作成し、リンクの飛び先に「active-func」クラスを付与します。
    1. <a href="#contents1">大幅アップデート</a>
    2. <a href="#contents2">選ばれる理由</a>
    3.  
    4. <section id="contents1" class="active-func">
    5. <p>大幅アップデート</p>
    6. </section>
    7. <section id="contents2" class="active-func">
    8. <p>選ばれる理由</p>
    9. </section>
  4. 設定は以上です。スクロールとリンクに対応して aリンクに「active」クラスが付与されます。
    ScrollChange.jsを開き、下記を変更することでオフセットの位置、active-funcやactiveクラス名などの設定を変更することが可能です。

    1. /**********************
    2. * Settings
    3. **********************/
    4. // Target class name
    5. target_name:'active-func',
    6.  
    7. // Add class name
    8. active_class_name:'active',
    9.  
    10. // Scroll offset
    11. header_offset:155,
    12.  
    13. // 検出位置の差分(大きいほどターゲットより下にActive変更ポイントが来る)
    14. // 0は正しく動作しません。
    15.   header_offset2:10,
    16.  
    17. // Smooth scroll setting(On:1 Off:0)
    18. smooth_scroll:1,
    19.  
    20. // Scroll speed
    21. scroll_speed:800,
    22. /**********************
    23. * End settings
    24. **********************/

 

検証ブラウザ

 

動作するブラウザ

IE10+ 、Chrome、Safari、Firefox

検証環境は下記の通りで全てで動作確認済

Windows7 IE10、IE11、Chrome、Firefox
Windows8 IE10
Windows8.1 IE11
Windows10 IE11

MacOS10.9 Chrome、Safari、Firefox

iPhone5 標準ブラウザ
iPhone6 標準ブラウザ

Xperia Z3 標準ブラウザ(Android5)
Xperia Z3 タブレット 標準ブラウザ(Android5)
 

 

解説

 

せっかくですのでどのような仕組みでこの機能が動作しているかを解説します。
JavaScriptに興味がある方のみお読みください。

 

スクロール検知について

スクロールの検知はWaypoints.jsで行っています。

  1. Waypoints.jsを読み込みます。
  2. new Waypointで、Waypointのインスタンスを起動
  3. element: にターゲットを指定します。ここでは idに basic-waypoint が付与された箇所を取得しています。
  4. handler:function(){ ここに処理を書く } に スクロールがbasic-waypointに来たときの処理を書きます。
  1. var waypoint = new Waypoint({
  2. element: document.getElementById('basic-waypoint'),
  3. handler: function() {
  4. notify('Basic waypoint triggered')
  5. }
  6. })

とても簡単に使うことができます。今回はスクロール位置を検出しactiveクラスを付与していますが、その他にも画面スクロールを検出し、なにかアニメーションを加えることなどできます。
 

クリック検知について

スクロールに合わせてactiveも変化しますが、アンカーをクリックした時にもActiveが変化します。
一般的にアクティブが変わるグローバルナビゲーションにはヘッダーの高さがあり、アンカーをクリックしたときにヘッダーの高さを足した分だけ下げる必要があります。(例では100px分下げています)

ヘッダーの高さ分下げないと、ヘッダーに対象のコンテンツが隠れてしまいあまりよろしくないですね。

クリックイベントを取得しスクロールするコードは下記です。

  1. // #を含むリンクがクリックされた場合
  2. // href属性に#が入っているリンクを .click() イベントハンドラで取得
  3. $('a[href^=#]').click(function() {
  4.  
  5. // href属性の内容を取得
  6. var href= $(this).attr('href');
  7.  
  8. // href属性が # のみか、空だった場合は、htmlのDOM(トップ)をtargetに入れます。
  9. // 上記以外の場合href属性の値をDOMで取得します。
  10. var target = $(href == '#' || href == '' ? 'html' : href);
  11.  
  12. // 移動先スクロール位置を数値で取得
  13. // target.offset().top Topから対象までのピクセル数
  14. // ScrollChange.header_offset プロパティにヘッダーの高さ
  15. // -5 は、ブラウザ間で多少移動位置がずれるのでその範囲を吸収するために
  16. // 「-5」を指定しています。コーディングした内容に合わせて調整ください。
  17. var position = target.offset().top - (ScrollChange.header_offset - 5);
  18.  
  19. // jQueryのanimate() メソッドで対象位置までスクロール
  20. $('body,html').animate({scrollTop:position}, ScrollChange.scroll_speed);
  21. return false;
  22. });

 

コメント付き全量コード

 

  1. var ScrollChange = new Object();
  2. ScrollChange = {
  3. /**********************
  4. * Settings
  5. **********************/
  6. // Target class name
  7. target_name:'active-func',
  8.  
  9. // Add class name
  10. active_class_name:'active',
  11.  
  12. // Scroll offset
  13. header_offset:155,
  14.  
  15. // 検出位置の差分(大きいほどターゲットより下にActive変更ポイントが来る)
  16. // 0は正しく動作しません。
  17. header_offset2:10,
  18.  
  19. // Smooth scroll setting(On:1 Off:0)
  20. smooth_scroll:1,
  21.  
  22. // Scroll speed
  23. scroll_speed:800,
  24. /**********************
  25. * End settings
  26. **********************/
  27.  
  28. CheckActiveClass:function(ei){
  29. // 現状 activeが付与されているかどうかチェック
  30. if($('.'+this.active_class_name+':eq(0)') == undefined){
  31. // ターゲットにクラス付与
  32. this.AddClass(ei);
  33. }else{
  34. // 現在のactiveを削除後、クラス付与
  35. this.RemoveClass().AddClass(ei);
  36. }
  37. },
  38. RemoveClass:function(){
  39. // activeが存在したら、クラスを削除
  40. $('.'+this.active_class_name).removeClass(this.active_class_name);
  41. return this;
  42. },
  43. AddClass:function(sp){
  44. // スクロールポイントのIDを取得する sp:スクロールポイント
  45. var target_class= 'a[href*="' + sp + '"]';
  46. // ターゲットのDOMを取得し、クラス追加
  47. $(target_class).addClass(this.active_class_name);
  48.  
  49. }
  50. }
  51.  
  52. $(function(){
  53. // active-funcが付いている箇所をn個取得する
  54. var w = $('.' + ScrollChange.target_name);
  55. var offset2 = ScrollChange.header_offset-ScrollChange.header_offset2;
  56. // active-funcの回数分ループ
  57. for (var i = 0; i < w.length; i++) {
  58. new Waypoint({
  59. element: w[i],
  60. handler: function() {
  61. ScrollChange.CheckActiveClass(this.element.id);
  62. },offset:ScrollChange.header_offset
  63. });
  64. new Waypoint({
  65. element: w[i],
  66. handler: function() {
  67. ScrollChange.CheckActiveClass(this.element.id);
  68. },offset:offset2
  69. });
  70. }
  71.  
  72. // #で始まるアンカーをクリックした場合に処理
  73. if(ScrollChange.smooth_scroll){
  74. $('a[href^=#]').click(function() {
  75. // アンカーの値取得
  76. var href= $(this).attr('href');
  77.  
  78. // 移動先を取得
  79. var target = $(href == '#' || href == '' ? 'html' : href);
  80.  
  81. // 移動先スクロール位置を数値で取得
  82. var position = target.offset().top - (ScrollChange.header_offset - 5);
  83.  
  84. $('body,html').animate({scrollTop:position}, ScrollChange.scroll_speed);
  85. return false;
  86. });
  87. }
  88. });

 

以上です。せっかく作ったので公開してみました。

 

関連タグ:

この記事をシェアする

次へ
前へ