質問: ### 前提・実現したいこと 実現したいこと: ・上下スクロール時に複数設定したsectionのトリガー到達時に合致するサイドメニューを切り替える。 ・対象コンテンツを過ぎたらサイドメニューは隠す。 前提: ・フル画面ページではない。 ・sectionは縦並びで9個、うちサイドメニュー対象は上部5個。 ・スクロールを戻すとサイドメニューの内容も戻る。 ・サイドメニューはz-indexなどで重ねsectionと合致する内容のみ表示する。 ・レスポンシブ対応(※スマホ・タブレット時はサイドメニューは非表示) ・サイドメニューは上部固定。 近い動作をするサイト http://springsummer.dk/ ### 発生している問題 トリガー前にサイドメニューが切り替わる、もしくはトリガーを超えてから切り替わってしまう。 サイドメニュー対象外のエリアに入ってもサイドメニューが消えない。 ### 該当のソースコード HTML ``` 内容1:スライダー(bxslider) 内容2 内容3 内容4 内容5 内容6 内容7 内容8 内容9 内容1タイトル 内容2タイトル 内容3タイトル 内容4タイトル 内容5タイトル ``` ### 試したこと ソースの書き換え、他のプラグインの使用など 複数ブラウザでの動作確認(IE、Firefox、Chrome) 初めまして、Webページを作成していて、どうしても解決できないのでお力添えをいただければと思います。 プラグインや、ネットに掲載されているソースをほんの少し触る程度の実力です。 よろしくお願いいたします。
回答: これでいいでしょうか? サイドメニューの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'); } } }); ```