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



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

JS fiddle示例

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

如果在动画进行时滚动,则滚动将继续,直到到达节的末尾。

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

这里有一个简单的修复程序,代码修改较少。

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

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

这是最后一个小提琴环节。

使用setTimeout功能,您可以将滚动状态重置为false,以便接收新的事件。

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

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

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

整个过程大概是这样的:

  1. 动画开始
  2. 标志动画设置为true
  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>

您所要求的叫做节流。我建议你阅读这个链接以更好地理解它。

因此,要修复代码,只需要为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/

最新更新