質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • JavaScript

    16442questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    6715questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

jQuery:sectionに対応したtriggerで変わるサイドメニュー

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 625

rayco

score 3

前提・実現したいこと

実現したいこと:
・上下スクロール時に複数設定したsectionのトリガー到達時に合致するサイドメニューを切り替える。
・対象コンテンツを過ぎたらサイドメニューは隠す。

前提:
・フル画面ページではない。
・sectionは縦並びで9個、うちサイドメニュー対象は上部5個。
・スクロールを戻すとサイドメニューの内容も戻る。
・サイドメニューはz-indexなどで重ねsectionと合致する内容のみ表示する。
・レスポンシブ対応(※スマホ・タブレット時はサイドメニューは非表示)
・サイドメニューは上部固定。

近い動作をするサイト
http://springsummer.dk/

発生している問題

トリガー前にサイドメニューが切り替わる、もしくはトリガーを超えてから切り替わってしまう。
サイドメニュー対象外のエリアに入ってもサイドメニューが消えない。

該当のソースコード

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="js/jquery.bxslider.min.js"></script>
<script>
$(function() {
    // 引き金となる要素を設定
    var triggerNode = $(".trigger");
    // 画面スクロール毎に判定を行う
    $(window).scroll(function(){
        // 引き金となる要素の位置を取得
        var triggerNodePosition = $(triggerNode).offset().top - $(window).height();    
        // 現在のスクロール位置が引き金要素の位置より下にあれば‥
        if ($(window).scrollTop() > triggerNodePosition) {
            // なんらかの命令を実行
            $('#sidenav').addClass('on');
        }
    });
});

$(function(){
    var margin = -250,
    sectionTop = new Array,
    current = -1;
    $('.trigger').each(function(i) {
        sectionTop[i] = $(this).offset().top;
    });
    $('#sidenav').append('<div id="#current"></div>');    //create #current
    changeNavCurrent(0);

    $(window).scroll(function(){
        scrollY = $(window).scrollTop();

        for (var i = sectionTop.length - 1 ; i >= 0; i--) {
            if (scrollY > sectionTop[i] - margin) {
                    changeNavCurrent(i);
                break;
            }
        };
    });
    //ナビの処理
    function changeNavCurrent(curNum) {
        if (curNum != current) {
            current = curNum;
            curNum2 = curNum + 1;
            $('#sidenav li').removeClass('on');
            $('#sidenav li:nth-child(' + curNum2 +')').addClass('on');
            /* 位置によって個別に処理をしたい場合 
            if (current == 0) {
                // 現在地がsection1の場合の処理
            } else if (current == 1) {
                // 現在地がsection2の場合の処理
            } else if (current == 2) {
                // 現在地がsection3の場合の処理
            }*/
        }
    };
});

$(function(){
   $(window).scroll(function(){
      var obj_t_pos = $('#moreContents').offset().top;
      var scr_count = $(document).scrollTop() + (window.innerHeight/2); // ディスプレイの半分の高さを追加
      if(scr_count > obj_t_pos){
         $('#sidenav').addClass('cle');
      }else{
         $('#sidenav').removeClass('cle');
      }
   })
});
</script>
</head>
<body>
<div id="Contents">
<div id="Main">
<div id="mainContents">
    <div class="trigger" id="section01">
        内容1:スライダー(bxslider)
    </div>
    <div class="trigger" id="section02">
        内容2
    </div>
    <div class="trigger" id="section03">
        内容3
    </div>
    <div class="trigger" id="section04">
        内容4
    </div>
    <div class="trigger" id="section05">
        内容5
    </div>
</div>

<div id="moreContents">
    <div class="otherContents" id="sub01">
        内容6
    </div>

    <div class="otherContents" id="sub02">
        内容7
    </div>

    <div class="otherContents" id="sub03">
        内容8
    </div>

    <div class="otherContents" id="sub04">
        内容9
    </div>
</div>

<ul id="sidenav">
<li><a href="#section01">内容1タイトル</a></li>
<li><a href="#section02">内容2タイトル</a></li>
<li><a href="#section03">内容3タイトル</a></li>
<li><a href="#section04">内容4タイトル</a></li>
<li><a href="#section05">内容5タイトル</a></li>
</ul>
</div>
</div>
</body>
</html>

試したこと

ソースの書き換え、他のプラグインの使用など
複数ブラウザでの動作確認(IE、Firefox、Chrome)

初めまして、Webページを作成していて、どうしても解決できないのでお力添えをいただければと思います。
プラグインや、ネットに掲載されているソースをほんの少し触る程度の実力です。
よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

これでいいでしょうか?
サイドメニューのidは'sideMenu'に変えました。

#Contents {
  position : relative;
  left : 0px;
  top : 0px;
}

#Main {
  position : relative;
  left : 0px;
  top : 0px;
}

.trigger, .otherContents {
  left : 100px;
  height : 100%;
  margin-top : 10px;
  margin-bottom : 20px;
}

#sideMenu {
  /* サイドメニューの位置は固定 */
  position : fixed;
  left : 0px;
  top : 60px;
}

#sideMenu li {
  /* サイドメニューの全項目は原則非表示 */
  display : none;
}

#sideMenu li.on {
  /* サイドメニューのCSSクラス'on'が追加されている項目は表示 */
  display : block;
}
$(function() {
    // ブラウザの画面幅がこの値より狭くなると、サイドメニューは非表示
    var discontinuousWidth = 760;
    // 引き金となる要素
    var triggerNode = $(".trigger");
    // 引き金となる各要素の(marginを含む)範囲(上、下)の配列
    var triggerNodeRange = new Array();
    // サイドメニューで現在表示されている項目のsection番号(nullならば非表示)
    var currentSection = null;


    // 引き金となる各要素の範囲を一つずつ取得して配列に保存
    triggerNode.each(function(index) {
        var marginTop = $(this).css('margin-top');
        // 'px'を取り去って数値に変換
        marginTop = marginTop.replace(/px$/, '') - 0;

        var top    = $(this).offset().top - marginTop;
        // marginを含む高さを取得
        var height = $(this).outerHeight() + marginTop;
        var bottom = top + height - 1;

        // 引き金要素の範囲(上と下をセットで)を配列要素に保存
        triggerNodeRange[index] = {
            'top' : top,
            'bottom' : bottom
        };
    });


    // サイドメニューに項目を初期表示
    selectItemFromSideMenu(1);


    // 画面スクロール時に動作
    $(window).on('scroll', function() {
        // 現在のスクロール位置
        var scrollY = $(window).scrollTop();

        for (var sectionNum = 1;
                 sectionNum <= triggerNodeRange.length;
                 sectionNum++)
        {
            // 引き金となる各要素の範囲の配列から要素を取り出して比較
            // (配列のindexは0から始まるので、section番号から1を引く)
            var range = triggerNodeRange[sectionNum - 1];
            if (range.top <= scrollY && scrollY <= range.bottom) {
                // 現在のスクロール位置が、引き金要素の上と下の間ならば、
                // サイドメニューにsection番号の項目を表示
                selectItemFromSideMenu(sectionNum);
                return;
            }
        }

        // どの引き金要素の範囲内になければ、
        // サイドメニューの項目を非表示
        selectItemFromSideMenu(null);
    });


    // 画面幅変化時に動作
    $(window).on('resize', function() {
        selectItemFromSideMenu(currentSection);
    });


    /**
     * サイドメニューにsection番号の項目を表示
     * @param sectionNum  項目を表示するsection番号(nullならば非表示)
     */
    function selectItemFromSideMenu(sectionNum) {
        currentSection = sectionNum;

        // 全ての項目からCSSクラス'on'を削除
        $('#sideMenu li').removeClass('on');

        if ($(window).width() >= discontinuousWidth &&
                currentSection !== null) {
            // ブラウザの画面幅が広く、nullでなければ、
            // currentSection番目の項目にCSSクラス'on'を追加
            $('#sideMenu li:nth-child(' + currentSection + ')').addClass('on');
        }
    }
});

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/21 15:09

    ご回答ありがとうございました。思っていた動作できました!
    コメントを入れていただいているおかげで、勉強にもなります。
    本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    16442questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    6715questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。