繁体   English   中英

在等待滚动选择动画完成时禁用滚动

[英]Disable scroll while waiting to for scroll selection animation to complete

我正在尝试自定义section-scroll ,其中在动画运行时禁用滚动事件。 我尝试在滚动动画正在进行时应用溢出隐藏和其他类似的功能,但没有运气。

JS小提琴示例

CSS

.stop-scrolling {
  height: 100%;
  overflow: hidden;
}

JS示例:

$('html').on('wheel', function(event) {
  if (event.originalEvent.deltaY > 0) {
//scroll down
    counter++;


    $('body').addClass('stop-scrolling');
    console.log("Start animacije");
    setTimeout(function () {
      $('body.stop-scrolling').removeClass('stop-scrolling');
      console.log("End animation");
    }, 800);



    if (!(counter > maxSections)) {
      $('html, body').animate({
        scrollTop: $( $("#sect-"+counter) ).offset().top
      }, 800);
    }

  } else {
//scroll up
    counter--;


    $('body').addClass('stop-scrolling');
    console.log("Start animation");
    setTimeout(function () {
      $('body.stop-scrolling').removeClass('stop-scrolling');
      console.log("End animation");
    }, 800);


    if (!(counter < 1)) {
      $('html, body').animate({
        scrollTop: $( $("#sect-"+counter) ).offset().top
      }, 800);
    }

  }

  if (counter <= 0) {
    counter = 1;
  }
  else if (counter >= 3) {
    counter = maxSections;
  }

  console.log(counter);
});

如果您在动画播放时滚动,滚动将继续,直到您到达部分末尾。

是否可以在动画进行时禁用滚动事件?

您可以使用脚本来阻止滚动事件,而不是使用 CSS。

您可以使用.animate方法onComplete参数在动画结束后运行回调。

有了这个,您可以使用标志变量来确定页面是否正在滚动。

整个过程大概是这样的:

  1. 动画开始了。
  2. 标记动画 = 真。
  3. 阻止滚动。
  4. 动画结束。
  5. 标记动画 = false。
  6. 取消阻止滚动。

这是一个最小且可重复的示例。 它可能有一些错误,但它应该可以解决您的主要问题。

 $(document).ready(function(){ 'use strict'; // Flag to decide whether or not scroll is allowed. let animating = false; $(window).on('scroll', (e) => { if (animating){ // Block scroll e.preventDefault(); } }); $('.section').on('wheel', e => { e.stopPropagation(); // Do not run this function again when animation is happening. if (animating){ return; } const $target = $(e.target); const isScrollDown = e.originalEvent.deltaY > 0; // Choose whether to scroll to next or previous section. const $targetSection = isScrollDown ? $target.next('.section') : $target.prev('.section'); // Check whether or not there is a target const hasTargetSection = $targetSection.length > 0; // Only animate when there is a target. if (hasTargetSection){ // Flag animation start animating = true; $('html, body').animate( // Animation properties { scrollTop: $targetSection.offset().top }, // Animation duration 800, // Function to run after animation ends () => { // Flag animation ended animating = false; } ); } }); });
 html, body, #app { width: 100%; height: 100%; padding: 0; margin: 0; } .section { width: 100%; height: 100%; font-size: 3em; display: flex; justify-content: center; align-items: center; } .a { background-color: #f008; } .b { background-color: #0f08; } .c { background-color: #00f8; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="app"> <div class="section a">Section A</div> <div class="section b">Section B</div> <div class="section c">Section C</div> </div>

这是具有较少代码修改的简单修复。

只需声明一个代表滚动状态的变量。 如果当前正在滚动,则使用此状态您可以忽略传入的滚动事件。

let scrolling = false;

$('html').on('wheel', function(event) {
  if (scrolling) {
    return;
  } else {
    scrolling = true;
    setTimeout(function () {
      scrolling = false;
    }, 800 /* animation duration */);
  }

  ...

这是最后的小提琴链接

使用setTimeout函数可以将滚动状态重置为false以便接收新事件。

您所要求的称为节流。 我建议您阅读此链接以更好地理解它。

所以要修复你的代码,你只需要为你的wheel事件监听器启用节流。

像这样:

let throttle = (fn, timedelay) => {
  let pass = true;
  return function () {
    if (pass) {
      setTimeout(() => {
        fn.apply(this, arguments);
        pass = true;
      }, timedelay);

      pass = false;
    }
  };
};

let scrollFunction = throttle(function(event) {
  // your code
}, 200); // 200 miliseconds sounds good

$('html').on('wheel', scrollFunction);

这是一个工作代码: https : //jsfiddle.net/d1fcL5en/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM