【问题标题】:snapping to sections without window scrolling在不滚动窗口的情况下捕捉到部分
【发布时间】:2016-08-09 23:37:23
【问题描述】:

我想捕捉到 div 中的部分,但是我想在不滚动窗口的情况下执行此操作。我希望能够在该 div 内滚动。

我认为我对自己的解释不够好。当我滚动时,窗口滚动,然后文章被卡入到位,依此类推。我希望这样当我在#content 中滚动时,文章将被对齐到位。

有什么建议吗?

$(document).ready(function() {
  $("article").css("height", $(window).height() + "px");
  $("#content").sectionsnap({
    delay : 100
    , selector : 'article'
    , reference : 1
    , animationTime : 600
  });
});


(function($) {
$.fn.sectionsnap = function( options ) {

    var $wrapper = this
    , direction = 'down'
    , currentScrollTop = $("section").scrollTop()
    , scrollTimer
    , animating = false;

    // check the direction
    var updateDirection = function() {
        if ($("section").scrollTop() >= currentScrollTop)
            direction = 'down';
        else
            direction = 'up';
        currentScrollTop = $("section").scrollTop();
    }

    // return the closest element (depending on direction)
    var getClosestElement = function() {
        var $list = $wrapper.find(settings.selector)
        , wt = $("section").scrollTop()
        , wh = $("section").height()
        , refY = wh * settings.reference
        , wtd = wt + refY - 1
        , $target;

        if (direction == 'down') {
            $list.each(function() {
                var st = $(this).position().top;
                if ((st > wt) && (st <= wtd)) {
                    $target = $(this);
                    return false; // just to break the each loop
                }
            });
        } else {
            wtd = wt - refY + 1;
            $list.each(function() {
                var st = $(this).position().top;
                if ((st < wt) && (st >= wtd)) {
                    $target = $(this);
                    return false; // just to break the each loop
                }
            });
        }
        return $target;
    }

    // snap
    var snap = function() {
        var $target = getClosestElement();
        if ($target) {
            animating = true;
            $('html, body').animate({
                    scrollTop: ($target.offset().top)
                }, settings.animationTime, function() {
                    window.clearTimeout(scrollTimer);
                    animating = false;
                });
        }
    }
    // on window scroll
    $("section").scroll(windowScroll);
    return this;
};
})(jQuery);

非常感谢任何建议

【问题讨论】:

  • 我同意你解释得不够清楚
  • kuhl.pl/github/sectionsnap 当窗口滚动时,下一个元素立即进入视图。我想这样做,如果该部分(不是窗口)滚动,那么下一个元素就会出现。这说明清楚了吗?

标签: jquery html css scroll


【解决方案1】:
  1. 使用animate() 函数而不是scrollTop() 来生成动画,而不是立即从一个部分捕捉到另一个部分。

  2. 考虑使用缓动来实现平滑和非线性动画,如果你将使用 jQuery 做动画,你可以使用这个 jQuery easing plugin - [ CDN ]

  3. 对于更流畅的动画,您可以使用其他库,例如 GSAPVelocityjs,它们都带有内置的缓动功能,因此您无需使用外部包。

  4. 1234563滚动动画结束,然后我们重新开始。

示例 1: 使用带有缓动的 jQuery .animate() 函数

jsFiddle - editor

jsFiddle - fullscreen

var sections = $('.sections'),
  win = $(window),
  index = 0,
  isScrolling = false;  // will be used to check whether the page is scrolling or not


// on window scroll, we capture the scroll top and the current section's top
win.on('scroll', function() {
  var winTop = win.scrollTop(),
    secTop = $(sections[index]).offset().top;

  // if page is currently scrolling, we do nothing and wait until scrolling ends
  if (!isScrolling) {

    // if is scrolling is false, and window ".scrollTop()" is more than current
   // section ".offset().top" value, we set the "isScrolling" to true so that
   // we make any scrolling decisions until the animation ends, call the animation
   // function passing the value of the next next section's ".offset().top", also 
   // increase the "index" value.
    if (winTop > secTop) {
      isScrolling = true;
      animateScrolling($(sections[index + 1]).offset().top);
      index += 1;
    }

    // same as above except we check if the window ".scrollTop()" is *less* than
    // the current section's "scrollTop()", set "isScrolling = false" and animate the
    // scroll to the previous section's "offset().top", and decrease the index value.
    if (winTop < secTop) {
      isScrolling = 1;
      animateScrolling($(sections[index - 1]).offset().top);
      index -= 1;
    }
  }
});


// instead of "win.scrollTop()" we use ".animate()" function for smooth scrolling and
// making use of a the callback function, which get executed *after* the animation
// ends, we set our scrolling flag "isScrolling" to false for further animations.
   // we use easing too, "easeInOutCubic" here, for smooth animation

function animateScrolling(secTop) {
  $('html, body').animate({ scrollTop: secTop }, 500, 'easeInOutCubic', function() {
    isScrolling = false;
  });
}
body { margin: 0; padding: 0; }
.sections { width: 100%; height: 100vh; background-color: orange; display: block; }
.two { background-color: tomato; }
.three { background-color: skyblue; }
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js">
</script>
<div class="sections"></div>
<div class="sections two"></div>
<div class="sections three"></div>

示例 2: 使用带有内置缓动的 GSAP TweenMax 函数,虽然 GSAP 与 jQuery 配合得很好,但下面我使用纯 javascript 来选择元素而不是 jQuery。

CodePen - editor

CodePen - fullscreen

var sections = document.querySelectorAll('.sections'),
  HTMLbody = document.querySelectorAll('html, body'),
  index = 0,
  isScrolling = false;

window.addEventListener('scroll', function() {   
  // Get the window scrollTop value, from:
  // stackoverflow.com/questions/3464876/javascript-get-window-x-y-position-for-scroll
  var winTop = (window.pageYOffset || document.scrollTop) - (document.clientTop || 0),
  // ---------------------------------------------------------------------------------
    secTop = sections[index].offsetTop;

  if (!isScrolling) {
    if (winTop > secTop) {
      isScrolling = true;
      animateScrolling(sections[index + 1].offsetTop);
      index += 1;
    }
    if (winTop < secTop) {
      isScrolling = 1;
      animateScrolling(sections[index - 1].offsetTop);
      index -= 1;
    }
  }
});

function animateScrolling(secTop) {
  TweenMax.to(HTMLbody, 0.5, {
    scrollTop: secTop,
    ease: Power3.easeInOut,
    onComplete: setFlagToFalse
  });
}

function setFlagToFalse() {
  isScrolling = false;
}

【讨论】:

  • 感谢您的建议,但滚动不是很流畅,并且无法顺利滚动到下一部分。不过还是谢谢
  • @user1377298,很抱歉,我并没有真正尝试模仿您提供链接的库,它更像是我什至没有使用缓动的指南。
  • 但是,看看我更新的答案,平滑滚动和缓动,检查是窗口滚动,我还提供了另一个使用 GSAP 动画而不是 jQuery 动画的解决方案。
  • 我只是想说谢谢你的建议。我确实完成了你所做的事情,最终做了我需要做的事情。
  • 很好的答案、示例等。感谢您的时间和精力;)
猜你喜欢
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
  • 2012-08-24
  • 2016-09-13
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
  • 2021-02-20
相关资源
最近更新 更多