【问题标题】:Having trouble getting the scroll animation to not trigger the scroll event无法让滚动动画不触发滚动事件
【发布时间】:2015-11-15 03:31:39
【问题描述】:

我目前有许多可以在下面看到的 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;
}

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

【问题讨论】:

  • 没有.current 元素出现在html 上?
  • @guest271314 不确定你的意思
  • html at Question 似乎不包含具有 class .current 的元素,在 scroll 事件处理程序中引用了该元素
  • 第一个div标签包含一个.current类
  • 是的,你是对的。 lastScrollTop 在初始滚动时会是 undefined 吗?

标签: javascript jquery html css scroll


【解决方案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() 以阻止滚动事件冒泡并因此变为递归。

编辑:

好的。所以我有一个更好的外观和基本问题:无限滚动是代码不检查 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 上的用户发生冲突。即您的代码将使其跳回之前的位置。

【讨论】:

  • 我有点不清楚如何实现这一点。我将.animate() 更改为.stop().animate() 并添加了event.preventDefault(),但它仍然无限滚动,只是随着时间的推移变慢。
【解决方案2】:

尝试将scroll 事件处理程序定义为命名函数;在 scroll 处理程序之外定义 lastScrollTop ;将 .one() 替换为 .on() 以允许动画在重新附加 scroll 事件之前完成;使用.promise(),它最多应该被调用一次,以避免.animate()complete回调被选择器"html, body"调用两次;替换单个if 来检查下一个或上一个元素.length.animate() 调用多个if..else 条件和语句,动画函数调用;动画完成后在.then() 重新附加scroll 事件.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>

【讨论】:

  • @Shikkediel 查看更新后的帖子;包括 "html" 选择器,用 .promise().then() 替换 .animate() complete 回调函数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 1970-01-01
  • 2015-02-09
  • 2016-06-23
相关资源
最近更新 更多