简体   繁体   English

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

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

I'm trying to make customize section-scroll where scroll event is disabled while animation is in motion.我正在尝试自定义section-scroll ,其中在动画运行时禁用滚动事件。 I tried with overflow hidden and other similar functions to apply while scroll animation is in progress but no luck.我尝试在滚动动画正在进行时应用溢出隐藏和其他类似的功能,但没有运气。

JS fiddle example JS小提琴示例

CSS CSS

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

JS example: 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);
});

If you scroll while animation is in progress, scroll will continue until you reach end of sections.如果您在动画播放时滚动,滚动将继续,直到您到达部分末尾。

Is possible to disable scroll event while animation is in progress?是否可以在动画进行时禁用滚动事件?

Instead of using CSS, you can use your script to block scroll events .您可以使用脚本来阻止滚动事件,而不是使用 CSS。

You can use the onComplete parameter of the .animate method to run a callback after animation ends.您可以使用.animate方法onComplete参数在动画结束后运行回调。

With this, you can use a flag variable to determine whether or not the page is scrolling.有了这个,您可以使用标志变量来确定页面是否正在滚动。

The whole process would be something like:整个过程大概是这样的:

  1. Animation started.动画开始了。
  2. Flag animating = true.标记动画 = 真。
  3. Block scrolling.阻止滚动。
  4. Animation ended.动画结束。
  5. Flag animating = false.标记动画 = false。
  6. Unblock scrolling.取消阻止滚动。

Here's a minimal and reproducible example.这是一个最小且可重复的示例。 It may have some bugs, but it should solve your main problem.它可能有一些错误,但它应该可以解决您的主要问题。

 $(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>

Here's simple fix with less code modification.这是具有较少代码修改的简单修复。

Just declare a variable that represents scrolling state.只需声明一个代表滚动状态的变量。 And using this state you can ignore incoming scroll events if currently scrolling.如果当前正在滚动,则使用此状态您可以忽略传入的滚动事件。

let scrolling = false;

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

  ...

Here's final fiddle link .这是最后的小提琴链接

Using setTimeout function you can reset scrolling state to false so, new events will be received.使用setTimeout函数可以将滚动状态重置为false以便接收新事件。

What you are asking for is called throttling.您所要求的称为节流。 I recommend you read this link to understand it better.我建议您阅读此链接以更好地理解它。

So to fix your code, you only need to enable throttling for your wheel event listener.所以要修复你的代码,你只需要为你的wheel事件监听器启用节流。

Like this:像这样:

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);

Here is a working code: https://jsfiddle.net/d1fcL5en/这是一个工作代码: https : //jsfiddle.net/d1fcL5en/

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

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