无法使滚动动画触发滚动事件

时间:2015-11-15 03:31:39

标签: javascript jquery html css scroll

我目前在下面可以看到一些div标签,每个标签都是视口的高度。

<!-- .current represents the div the user is currently viewing -->
<div class="full-height current" id="id1">
    <div class="container">

    </div>
</div>

<div class="full-height" id="id2">
    <div class="container">
    </div>
</div>

<div class="full-height" id="id3">
    <div class="container">
    </div>
</div>

<div class="full-height" id="id4">
    <div class="container">
    </div>
</div>

<div class="full-height" id="id5">
    <div class="container">
    </div>
</div>

我正在尝试实现一个功能,在用户滚动时,窗口将滚动到下一个div标签,一次只能在视图中使用一个div。我实现它的方式很有效,除了动画再次触发滚动事件这一事实,一旦用户滚动,导致页面无限循环滚动。我尝试通过使用一个变量来解决这个问题,如果动画正在进行中,该变量将阻止事件触发,但它似乎不起作用。我知道我没有为向上滚动做这件事,但我只是想看看它是否适用于首先。

$(window).scroll(function(event) {
    var scrollTop = $(this).scrollTop();

    // If user scrolls down
    if ((scrollTop > lastScrollTop) && $(".current").next("div").length > 0) {
        if (animating == false) {
            console.log("down");

            $(".current").next("div").addClass("current");
            $(".current").first().removeClass("current");

            animating = true;
            $("html, body").animate({
                scrollTop: $(".current").offset().top    
            }, 1000, function() {animating = false});   
        }
    // If user scrolls up
    } else {
        if ($(".current").prev("div").length > 0) {
            console.log("up");

            $(".current").prev("div").addClass("current");
            $(".current").last().removeClass("current");

            $("html, body").animate({
                scrollTop: $(".current").offset().top    
            }, 1000);
        }            
    }

    lastScrollTop = scrollTop;
});

CSS包含以防万一。 100vh - 111px是由于顶部固定的导航栏高111px

/* Makes the element take up the entire height of the screen */
.full-height{
    height: -o-calc(100vh - 111px); /* opera */
    height: -webkit-calc(100vh - 111px); /* google, safari */
    height: -moz-calc(100vh - 111px); /* firefox */
}

#id1 {
    background-color: red;
}
#id2 {
    background-color: blue;
}

#id3 {
    background-color: yellow;
}
#id4 {
    background-color: green;
}

#id5 {
    background-color: purple;
}

如果有人能给我任何解决问题的想法,那就太棒了。

2 个答案:

答案 0 :(得分:1)

您需要停止活动并阻止默认。以下是当前着陆页中的一些代码:

 $(document).ready(function () {
        $('a.page-scroll').on('click', function(event) {
            var link = $(this);
            $('html, body').stop().animate({
                scrollTop: $(link.attr('href')).offset().top - 50
            }, 500);
            event.preventDefault();
        });
        $('body').scrollspy({
            target: '.navbar-fixed-top',
            offset: 80
        });

    });

它使用bootstrap scrollspy所以只是忽略它。但请注意,它会停止任何可能正在运行的滚动动画,然后调用event.preventDefault()来阻止滚动事件冒泡,从而变为递归。

编辑:

O.k。所以我有一个更好的外观和基本问题:无限滚动是代码不检查scrollTop是否已经在'它需要的地方'。您需要额外检查以使滚动短路:

if (animating == false) {

        if ($(this).scrollTop() == lastScrollTop) return;

        if (($(this).scrollTop() > lastScrollTop) && $(".current").next("div")) {
        console.log("down");

        $(".current").next("div").addClass("current");
        $(".current").first().removeClass("current");

        animating = true;
        $("html, body").stop().animate({
            scrollTop: $(".current").offset().top
        }, 1000,
        function () { lastScrollTop = $(this).scrollTop(); animating = false; });

        // If user scrolls up
    } else {
        if ($(".current").prev("div").length > 0) {
            console.log("up");

            $(".current").prev("div").addClass("current");
            $(".current").last().removeClass("current");

            $("html, body").stop().animate({
                scrollTop: $(".current").offset().top
            }, 1000, function () { lastScrollTop = $(this).scrollTop(); animating = false; });
        }
    }
}

否则,它始终向上或向下滚动,永远不会安定下来。那说“工作”这是一个糟糕的用户体验。它将跳转,因为滚动到代码将在当前scrollTop上与用户保持滚动。即你的代码会让它跳回到以前的位置。

答案 1 :(得分:1)

尝试将scroll事件处理程序定义为命名函数;在lastScrollTop处理程序之外定义scroll;将.one()替换为.on()以允许动画在重新附加scroll事件之前完成;使用最多应调用一次的.promise(),以避免使用选择器.animate()调用complete "html, body"次回调。替换单if来检查下一个或上一个元素.length.animate()是否需要调用多个if..else条件和语句,动画函数调用;动画完成scroll

后,.then()重新附加.promise()个事件

var lastScrollTop = 0;

function scroller(event) {

  var scrollTop = $(this).scrollTop();
  var direction = scrollTop > lastScrollTop ? "next" : "prev";
  var el = $(".current")[direction](".full-height");
  console.log(direction === "next" ? "down" : "up");
  if (el.is("*")) {
    $("html, body").animate({
      scrollTop: el.offset().top
    }, 1000).promise().then(function() {
      console.log(this)
      lastScrollTop = $(window).scrollTop();
      $(".current")
      .removeClass("current")[direction]("div")
      .addClass("current")
      setTimeout(function() {
        $(window).one("scroll", scroller)
      })
    });
  } else {
    lastScrollTop = scrollTop;
    $(window).one("scroll", scroller)
  }
}

$(window).one("scroll", scroller);
/* Makes the element take up the entire height of the screen */

.full-height {
  height: -o-calc(100vh - 111px);
  /* opera */
  height: -webkit-calc(100vh - 111px);
  /* google, safari */
  height: -moz-calc(100vh - 111px);
  /* firefox */
}
#id1 {
  background-color: red;
}
#id2 {
  background-color: blue;
}
#id3 {
  background-color: yellow;
}
#id4 {
  background-color: green;
}
#id5 {
  background-color: purple;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- .current represents the div the user is currently viewing -->
<div class="full-height current" id="id1">
  <div class="container">

  </div>
</div>

<div class="full-height" id="id2">
  <div class="container">
  </div>
</div>

<div class="full-height" id="id3">
  <div class="container">
  </div>
</div>

<div class="full-height" id="id4">
  <div class="container">
  </div>
</div>

<div class="full-height" id="id5">
  <div class="container">
  </div>
</div>

相关问题