我目前有一个脚本,我在其中跟踪元素的.offset()位置。当此元素到达窗口的顶部,左侧,底部或右侧边缘时,我需要调用一个函数,该函数只应调用一次,然后在下次到达窗口边缘时再次调用。 / p>
现在我有这个:
var exceededBounds = false
function checkPosition(element) {
var pos = element.offset();
var maxBoundsX = $(window).width();
var maxBoundsY = $(window).height();
var minBoundsX = 0
var minBoundsY = 0
// if the element hits one of the edges of the window
if (pos.left >= maxBoundsX || pos.top >= maxBoundsY || pos.left <= minBoundsX || pos.top <= minBoundsY) {
if (!exceededBounds) {
exceededBounds = true
}
else {
exceededBounds = false
}
}
else {
exceededBounds = exceededBounds;
}
}
function something() {
// do something here, which only happens once
}
function init() {
checkPosition(element);
if (exceededBounds) {
something()
}
requestAnimationFrame(init);
}
requestAnimationFrame(init);
问题是,something()函数被多次调用,我相信由于requestanimationframe()的帧速率?我需要使用requestanimationframe,但是我只想在变量exceededBounds发生变化时调用something()函数。我想过尝试在这里实现某种观察,但是对于我真正需要的东西来说感觉太复杂了。
由于
答案 0 :(得分:1)
你需要保留两个布尔值:
exceeding
以了解您的元素目前是否已超出范围。changed
知道最后一次检查是否已经超过。
var element = $('#el');
var changed = false;
var exceeding = false;
function checkPosition(element) {
var pos = element.offset();
var maxBoundsX = $(window).width();
var maxBoundsY = $(window).height();
var minBoundsX = 0
var minBoundsY = 0
// if the element hits one of the edges of the window
if (pos.left >= maxBoundsX || pos.top >= maxBoundsY || pos.left <= minBoundsX || pos.top <= minBoundsY) {
if (!exceeding) {
changed = true
} else {
changed = false;
}
exceeding = true;
} else {
if (exceeding) {
changed = true;
} else {
changed = false;
}
exceeding = false;
}
}
function something() {
console.log('changed:', exceeding ? 'hidden' : 'visible');
// do something here, which only happens once
}
function init() {
checkPosition(element);
if (changed) {
something()
}
requestAnimationFrame(init);
}
requestAnimationFrame(init);
&#13;
#el {
margin-top: calc(100vh - 30px);
margin-bottom: 100vh;
}
#cont {
width: 100vw;
height: 100vh;
overflow: auto;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cont">
<div id="el">Scroll me</div>
</div>
&#13;
现在,我不知道是什么原因导致你的元素在你的场景中移动,但不要那样轮询。相反,请听取可能导致此更改的事件。 E.G,在我的片段中,你会听到受限制的scroll
事件。
var element = $('#el');
var changed = false;
var exceeding = false;
cont.onscroll = throttle(init);
function checkPosition(element) {
var pos = element.offset();
var maxBoundsX = $(window).width();
var maxBoundsY = $(window).height();
var minBoundsX = 0
var minBoundsY = 0
// if the element hits one of the edges of the window
if (pos.left >= maxBoundsX || pos.top >= maxBoundsY || pos.left <= minBoundsX || pos.top <= minBoundsY) {
// our if else blocks can also be replaced by
changed = !exceeding;
exceeding = true;
} else {
changed = !!exceeding;
exceeding = false;
}
}
function something() {
console.log('changed:', exceeding ? 'hidden' : 'visible');
// do something here, which only happens once
}
function init() {
checkPosition(element);
if (changed) {
something()
}
}
// wait for next screen refresh before triggering event's callback
function throttle(callback) {
if (typeof callback !== 'function')
throw 'A callback function must be passed';
var active = false;
var evt;
function handler() {
active = false;
callback(evt);
};
return function handleEvent(e) {
evt = e;
if (!active) {
active = true;
requestAnimationFrame(handler);
}
};
}
&#13;
#el {
margin-top: calc(100vh - 30px);
margin-bottom: 100vh;
}
#cont {
width: 100vw;
height: 100vh;
overflow: auto;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cont">
<div id="el">Scroll me</div>
</div>
&#13;
答案 1 :(得分:0)
如果元素曾经有exceededBounds
,那么将多次调用 ,除非你的something
立即立即更改元素以使其在界限范围内 - 这就是如何递归调用requestAnimationFrame会起作用,它会不断被反复调用。
我建议改变something
,以便立即改变元素,使其再次进入边界 - 然后,something
只会运行一次(直到它再次超出界限)。