目次兼ページャー兼現在位置表示みたいな感じで。
こんな感じ
- <select>で選んだ項目とリンクするidにスムーススクロール
- ページをスクロールして該当idが出てきたら<select>のselected位置を切り替える。
- 見えないと分からんので<select>は固定表示(cssでやる)
<select id="nav">
<option value="#ttl01">#ttl01</option>
<option value="#ttl02">#ttl02</option>
<option value="#ttl03">#ttl03</option>
<option value="#ttl04">#ttl04</option>
</select>
<article>
<h2 id="ttl01">ttl01</h2>
⋮
<h2 id="ttl02">ttl02</h2>
⋮
<h2 id="ttl03">ttl03</h2>
⋮
<h2 id="ttl04">ttl04</h2>
⋮
</article>
select{
position:fixed;
bottom: 0;
}
$(function(){
//select用スムーススクロール
$('select').on('change',function() {
if($(this).val() != ''){
let speed = 500;
let href= $(this).val();
let target = $(href === "#" || href === "" ? 'html' : href);
let position = target.offset().top;
$('body,html').animate({scrollTop:position}, speed, 'swing');
return false;
}
});
//select切り替え
$(window).on('load scroll resize',function(){
$('article').find('h2').each(function(){
let windowHeight = Number($(window).height());
let nowPosition = Number($(window).scrollTop());
let targetPosition = Number($(this).offset().top);
let targetId = $(this).attr('id');
if(nowPosition >= Number(targetPosition - windowHeight / 2)){
$('select option').prop('selected',false);
$('select option[value="#'+targetId+'"]').prop('selected',true);
}
})
})
})
ちょっと詰まったところ
見出しの座標を拾いたくて.scrollTop()を入れたら通らなかったので.offset().topに変更。
記述がミスってるのかと思って弄ってたけど解決せず、console.log()で各種数値を引っ張ったら取得できてなかったことが分かった。
Number()は無くてもいいんだけど、あったほうがいい。
状況によるのかもだけど、文字列連結の+に四則演算を続けるとおかしいことになった。
なので、今回の内容では数値として取得できてるから取扱的には問題ないんだけど、他との兼ね合いがあるので明示的にするためにNumber()を使うとか、変数を作ってそっちで計算して引っ張ってくるとかしたほうが無難。
自動切り替えについて
ifはselected付与のタイミングで調整すること。
画面内に入った瞬間は気が早すぎるし、一番上まで行ってからもなんか微妙。
サンプルでは画面の半分くらいまで来たら、って感じにしてある。
スムーススクロールとselect切り替えはケンカしない
組んでる最中に気になってたんだけど、jsでselectを切り替えることによってスムーススクロールが発火することはなかった。
とても嬉しい。
コメント