mirror of
https://github.com/QIDITECH/QIDIStudio.git
synced 2026-01-31 00:48:41 +03:00
82 lines
2.4 KiB
JavaScript
82 lines
2.4 KiB
JavaScript
|
|
// 侧边导航:导轨 + 活动短竖条
|
|||
|
|
(function($){
|
|||
|
|
function positionIndicator(){
|
|||
|
|
var $nav = $('#sideNav');
|
|||
|
|
var $active = $nav.find('.nav-item.active');
|
|||
|
|
if (!$active.length) return;
|
|||
|
|
var top = $active.position().top;
|
|||
|
|
var height = $active.outerHeight();
|
|||
|
|
$nav.find('.indicator').css({ top: top + 'px', height: height + 'px' });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function scrollToAnchor($item){
|
|||
|
|
var href = $item.find('a').attr('href');
|
|||
|
|
if (href && href.charAt(0) === '#'){
|
|||
|
|
var $target = $(href);
|
|||
|
|
if ($target.length){
|
|||
|
|
var offset = 70; // 顶部预留,避免顶到视口边缘
|
|||
|
|
$('html,body').animate({ scrollTop: Math.max(0, $target.offset().top - offset) }, 300);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$(function(){
|
|||
|
|
positionIndicator();
|
|||
|
|
$('#sideNav').on('click', '.nav-item', function(e){
|
|||
|
|
e.preventDefault();
|
|||
|
|
var $it = $(this);
|
|||
|
|
$it.addClass('active').siblings('.nav-item').removeClass('active');
|
|||
|
|
positionIndicator();
|
|||
|
|
scrollToAnchor($it);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 滚动联动(ScrollSpy)
|
|||
|
|
var ticking = false;
|
|||
|
|
function computeActiveByScroll(){
|
|||
|
|
var scrollTop = $(window).scrollTop();
|
|||
|
|
var viewportOffset = 100; // 判定阈值,提前一点触发
|
|||
|
|
var $items = $('#sideNav .nav-item');
|
|||
|
|
var currentId = null;
|
|||
|
|
$items.each(function(){
|
|||
|
|
var href = $(this).find('a').attr('href');
|
|||
|
|
if (!href || href.charAt(0) !== '#') return;
|
|||
|
|
var $sec = $(href);
|
|||
|
|
if (!$sec.length) return;
|
|||
|
|
var top = $sec.offset().top;
|
|||
|
|
if (top <= scrollTop + viewportOffset){
|
|||
|
|
currentId = href;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if (currentId){
|
|||
|
|
var $cur = $items.filter(function(){
|
|||
|
|
return $(this).find('a').attr('href') === currentId;
|
|||
|
|
}).first();
|
|||
|
|
if ($cur.length && !$cur.hasClass('active')){
|
|||
|
|
$cur.addClass('active').siblings('.nav-item').removeClass('active');
|
|||
|
|
positionIndicator();
|
|||
|
|
} else {
|
|||
|
|
// 位置可能变化,仍然校准指示条
|
|||
|
|
positionIndicator();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function onScroll(){
|
|||
|
|
if (!ticking){
|
|||
|
|
ticking = true;
|
|||
|
|
requestAnimationFrame(function(){
|
|||
|
|
computeActiveByScroll();
|
|||
|
|
ticking = false;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
$(window).on('scroll', onScroll);
|
|||
|
|
$(window).on('resize', function(){
|
|||
|
|
positionIndicator();
|
|||
|
|
computeActiveByScroll();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 初始根据当前滚动位置激活一次
|
|||
|
|
computeActiveByScroll();
|
|||
|
|
});
|
|||
|
|
})(jQuery);
|