我在StackOverflow上进行了一些挖掘,希望找到一个答案,但是我遇到了。我正在尝试根据滚动以及元素是否在视图内来触发事件(通过从DOM顶部计算元素的顶部)。
现在,我可以在所有主流浏览器上使用它,但是由于某些原因,我绊倒了IE / Edge怪癖。
I've put together a codepen,希望有助于加快故障排除过程。要重点关注的代码行是Codepen JS的41和42。
const self = this;
const debug = true;
const parent = document.getElementById('js-data-count');
let scrolling = false;
let touchmoving = false;
let inView = false;
// Create a constant that should only fire ONCE
const animateOnce = (function() {
let executed = false;
return function() {
if (!executed) {
executed = true;
$(document.getElementsByClassName('data-points__stat')).each(function() {
let $this = $(this);
let countTo = $this.attr('data-count-to');
$({
countNum: $this.text()
}).animate({
countNum: countTo
}, {
duration: 1500,
easing: 'linear',
step: function() {
$this.text(Math.floor(this.countNum));
},
complete: function() {
$this.text(this.countNum);
}
});
});
}
};
})();
// If on load the area is in view but the user hasn't scrolled to it (refresh the page for example)
window.onload = function() {
if (parent) {
window.addEventListener('scroll', function() {
scrolling = true;
});
window.addEventListener('touchmove', function() {
touchmoving = true;
});
const fromTop = parent.offsetTop + 50;
const element = window.innerHeight + document.documentElement.scrollTop;
const visible = fromTop <= element;
if (visible) {
inView = true;
animateOnce();
if (debug) {
console.log("Target(s) ARE within viewport AND user hasn't scrolled")
}
}
}
};
// Set an interval to fire the desired functions on scroll but prevent excessive recalculations
setInterval(function() {
// If the parent element is present on the page
if (parent) {
const fromTop = parent.offsetTop + 50;
const element = window.innerHeight + document.documentElement.scrollTop;
const visible = fromTop <= element;
const notVisible = fromTop > element;
// If the user is actively scrolling
if (scrolling) {
scrolling = false;
// If the target area is NOT within the viewport
if (notVisible) {
if (debug) {
console.log("Target(s) ARE NOT within viewport AND user has scrolled")
}
inView = false;
return;
}
// If the target area IS within the viewport
if (visible) {
if (debug) {
console.log('Target(s) ARE within viewport AND user scrolled')
}
inView = true;
animateOnce();
}
}
}
}, 1000); // set a delay to avoid event spamming
// Change the value below to test the scroll conditions
.artificial-spacer {
background-color: #c0c0c0;
height: 95vh;
position: relative;
&:before {
content: 'Scroll down please!';
font-weight: bold;
width: 50%;
margin: auto;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
}
<section class="artificial-spacer"> </section>
<section class="data-points">
<div class="data-points__wrapper">
<h1 class="data-points__title">Nam id nibh urna. Aenean sollicitudin in felis sit amet ornare. Donec scelerisque tellus urna, ac dignissim sem varius id.</h1>
<ul class="data-points__list multiple" id="js-data-count">
<li class="data-points__item">
<a href="#random-link1" class="data-points__link" aria-label="View the Link" title="View the Link">
<div class="data-points__bubble">
<span class="data-points__stat" data-count-to="24">0</span>
<span class="data-points__type">%</span>
</div>
</a>
<p class="data-points__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</li>
<li class="data-points__item">
<a href="#random-link2" class="data-points__link" aria-label="View the Link" title="View the Link">
<div class="data-points__bubble">
<span class="data-points__stat" data-count-to="60">0</span>
<span class="data-points__type">%</span>
</div>
</a>
<p class="data-points__text">Quisque fringilla tellus sed ipsum euismod, a laoreet nisl blandit.</p>
</li>
<li class="data-points__item">
<a href="#random-link3" class="data-points__link" aria-label="View the Link" title="View the Link">
<div class="data-points__bubble">
<span class="data-points__stat" data-count-to="55">0</span>
<span class="data-points__type">%</span>
</div>
</a>
<p class="data-points__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</li>
</ul>
</div>
</section>
我已经尝试过:
window
事件以定位document
body
没有height: 100%
,与滚动事件行为发生冲突overflow