使用javascript/jquery自动滚动到固定点

Scroll to fixed points automatically using javascript/jquery

本文关键字:滚动 javascript jquery 使用      更新时间:2023-09-26

我有一个正在开发的应用程序,我希望它能在用户向上或向下滚动时将其锁定到最近的锚点。

有什么已知的方法可以做到这一点吗?如果有人在iPhone上有"circa"应用程序,你就会知道我在说什么。

我有一个简单的破解解决方案,可以检测卷轴并做到这一点:

var nearestAnchorOffset = calculateNearestAnchorOffset();
$('body').scrollTop(nearestAnchorOffset);

然而,它并不理想,因为它有时会很紧张和不可预测。

一个问题似乎是,当滚动开始时,滚动事件会触发,是否存在在滚动结束时触发的等效事件?

这是我试图让它工作的网站:

http://supi.hmp.is.it

请注意,这种效果只在小屏幕上触发(在台式机上并不真正需要)。我在滚动上使用了jQuery去抖动,这样它只在用户停止滚动时触发。它在桌面上非常流畅,但当你在iPhone上看的时候,50%的时间都不会正确,而且会滚动到错误的地方。

到目前为止,这是我的完整解决方案:

if($( document ).width() <= 768){
    var offsets = {};
    $( window ).scroll($.debounce(function(data) {
        if(isActive !== false){          
            // different scrollable points
            offsets.todaytitle      = $('.row.today.title').offset();
            offsets.todaywind       = $('.row.today.result .wind').offset();
            offsets.todaytemp       = $('.row.today.result .temp').offset();
            offsets.tomorrowtitle   = $('.row.tomorrow.title').offset();
            offsets.tomorrowwind    = $('.row.tomorrow.result .wind').offset();
            offsets.tomorrowtemp    = $('.row.tomorrow.result .temp').offset();
            offsets.form            = $('#postcodeForm').offset();
            offsets.nav             = $('#nav-bottom').offset();
            offsets.top             = {top: 0};
            var current = $(window).scrollTop();
            var closest = "";
            var curDiff = 99999;
            $.each(offsets, function( key, value ) {
                var diff = Math.abs(offsets[key].top - current);
                if(diff < curDiff){
                    curDiff = diff;
                    closest = key;
                }
            });
            animatedScroll(offsets[closest].top);
        }
    },350));
}
function animatedScroll(offset){
    $("body").animate({ scrollTop: offset },200, function() {
        scrollingOn = false;
    });
}

任何帮助都将不胜感激!

您没有包括您已经尝试过的内容,但我可以向您展示我最近针对这类问题制定的解决方案。

单独使用scroll()函数处理它不会很顺利,因为拖动滚动条可能是一个大问题,我建议您使用鼠标滚轮事件。

通过将其与'DOMMouseScroll mousewheel'事件绑定来进行锚定。然后使用originalEvent.wheelDelta获取鼠标滚轮的方向,向下滚动将返回负值,向上滚动将返回正值。

$('body').bind('DOMMouseScroll mousewheel', function(e){
    var $anchored = $('section.anchored');      
    if(e.originalEvent.wheelDelta < 0) { //mousewheel down
        $next = $anchored.next();
        if($next.length){
            $('body').stop().animate({scrollTop:$next.offset().top},'slow');
            $anchored.removeClass('anchored')
            $next.addClass('anchored')     
        } 
    }else{ //mousewheel up
        $prev = $anchored.prev();
        if($prev.length){
            $('body').stop().animate({scrollTop:$prev.offset().top},'slow'); 
            $anchored.removeClass('anchored')
            $prev.addClass('anchored')   
        }
    }
    e.preventDefault();
});

现在,如果用户通过拖动滚动条进行滚动,则还需要将'anchored'类指示符移动到视口中最可见的<section>

$(window).scroll(function(){
    var st = $(this).scrollTop();
    $('section').each(function(){
        var offset = $(this).offset();
        if(st >= offset.top && st < offset.top + $(this).outerHeight()){
            $(this).addClass('anchored');
        }else{
            $(this).removeClass('anchored');
        }
    });
});

这是我的样品jsfiddle。