스크롤 이벤트가 너무 많이 발생합니다. 초당 최대 한 번만 발사하고 싶습니다.
"무한 스크롤"페이지가 있습니다. 페이지 끝과 현재 페이지의 차이를 계산하고이 차이가 충분히 작 으면 더 많은 콘텐츠를로드합니다. 코드는 jQuery를 사용하여 다음과 같습니다.
$(window).on('scroll', function() {
if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
# load more content via ajax
}
이제 문제는 스크롤 할 때마다이 이벤트가 스크롤 당 여러 번 발생한다는 것입니다. 나는 기껏해야 x 밀리 초마다 발사하고 싶습니다. 어떻게해야합니까?
Underscore.js 라이브러리의 "throttle"메소드를 확인하십시오.
http://underscorejs.org/#throttle
이것이 제공하는 예제는 스크롤 이벤트를 처리해야하는 빈도를 제한하는 것입니다.
이 문제를 해결하는 한 가지 방법은 시간 간격을 정의하고 해당 시간 간격 내에서 스크롤 이벤트를 한 번만 처리하는 것입니다. 해당 시간 간격 동안 스크롤 이벤트가 두 개 이상 들어 오면 무시하고 해당 시간 간격이 지난 경우에만 처리합니다.
var scrollTimer, lastScrollFireTime = 0;
$(window).on('scroll', function() {
var minScrollTime = 100;
var now = new Date().getTime();
function processScroll() {
console.log(new Date().getTime().toString());
}
if (!scrollTimer) {
if (now - lastScrollFireTime > (3 * minScrollTime)) {
processScroll(); // fire immediately on first scroll
lastScrollFireTime = now;
}
scrollTimer = setTimeout(function() {
scrollTimer = null;
lastScrollFireTime = new Date().getTime();
processScroll();
}, minScrollTime);
}
});
이렇게하면 첫 번째 스크롤 이벤트가 즉시 발생하고 스크롤바가 이동하는 동안 약 100ms마다 한 번씩 스크롤 이벤트가 발생하고 스크롤바가 이동을 멈춘 후 마지막 이벤트가 하나 발생합니다. 인수를 setTimeout
(현재 100으로 설정된 값) 으로 변경하여 이벤트 빈도를 조정할 수 있습니다 .
여기에 데모가 있습니다. http://jsfiddle.net/jfriend00/EBEqZ/ 디버그 콘솔 창을 열고 콘텐츠 창에서 스크롤바를 이동 한 다음 디버그 콘솔 창에서 각 스크롤 이벤트의 시간을 확인해야합니다. . 내 버전의 Chrome에서는 최소 간격이 100ms로 설정되어 있으며 100-200ms마다 발생하는 것 같습니다.
이 상황을 해결하기 위해 jQuery를 만든 John Resig의 멋진 설명이 있습니다.
var outerPane = $details.find(".details-pane-outer"),
didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
setInterval(function() {
if ( didScroll ) {
didScroll = false;
// Check your page position and then
// Load in more results
}
}, 250);
출처 : http://ejohn.org/blog/learning-from-twitter/
var isWorking = 0;
$(window).on('scroll', function()
{
if(isWorking==0)
{
isWorking=1;
if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
# load more content via ajax
setTimeout(function(){isWorking=0},1000);
}
}
var now = new Date().getTime();
$(window).scroll( function () {
if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
{
if (new Date().getTime() - now > 1000)
{
console.log("Task executed once per second");
now = new Date().getTime();
}
}
});
또는
Throttling fonction calls를 사용할 수 있습니다. throttling-function-calls
function throttle(fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last,
deferTimer;
return function () {
var context = scope || this;
var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
}
다음과 같이 부를 수 있습니다.
$('body').on('mousemove', throttle(function (event) {
console.log('tick');
}, 1000));
다음은 단순성을 목표로하는 추가 JS 라이브러리 또는 플러그인을 사용할 필요가없는 솔루션입니다. 다른 구현만큼 효율적이지 않을 수 있지만 스크롤 할 때마다 메인 이벤트를 시작하는 것보다 확실히 한 단계 더 올라갑니다.
이것은 Danny Van Kooten 의이 블로그 게시물 에서 가져온 것입니다 . onscroll()
내 블로그의 back-to-top 버튼에 대한 내 이벤트를 지연시키는 데 사용했습니다 .
var timer;
$(window).scroll(function() {
if(timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout(function() {
// actual code here. Your call back function.
console.log( "Firing!" );
}, 100);
});
또한 $(window).height()
페이지가로드되면 변경되지 않는 일부 정적 div 요소 의 값 또는 높이와 같은 불필요한 재 계산을 피하기 위해 콜백 함수에서 변수를 이동하여 성능을 더욱 향상시킬 수 있습니다 .
다음은 제 사용 사례에서 적용한 예입니다.
var scrollHeight = $("#main-element").height(); //never changes, no need to recalculate.
$(window).on('scroll', function() {
if (timer)
window.clearTimeout(timer);
timer = window.setTimeout(function() {
var scrollPosition = $(window).height() + $(window).scrollTop();
if ($(window).scrollTop() < 500)
$(".toggle").fadeIn(800);
else
$(".toggle").fadeOut(800);
}, 150); //only fire every 150 ms.
});
이것은 실제 기능이 150ms마다 실행되도록 제한하거나 150ms가 지나지 않은 경우 타이머를 0으로 재설정합니다. 필요한 것에 맞게 값을 조정하십시오.
스크롤이 여러 번 발생하면 매번 스크롤 위치를 다르게 얻을 수 있습니다. 언급 한 것처럼 스크롤 이벤트에 처음 들어갈 때 타이머를 설정하고 타임 스탬프를 기록한 다음 다음에 스크롤 이벤트가 발생하면 마지막 트리거 시간을 확인하고 x 밀리 초 이내에 있으면 무시해야한다고 생각합니다. , 타이머 작업에서 실제 작업을 수행하십시오.
적절한 스로틀 기능을 위해 많은 지역 변수가 필요하지 않습니다. 스로틀 기능의 목적은 더 많이 사용하는 오버 헤드를 너무 많이 적용하는 것이 아니라 브라우저 리소스를 줄이는 것입니다. 이 주장의 증거로서, 나는 그 범위에 단지 5 개의 '매달려있는'변수 리퍼 렌을 갖는 스로틀 함수를 고안했습니다. 또한 스로틀 기능에 대한 저의 다른 용도에는 여러 가지 상황이 필요합니다. 여기에 '좋은'스로틀 기능이 필요하다고 생각하는 것들의 목록이 있습니다.
- 마지막 호출 이후 간격 MS 이상이면 즉시 함수를 호출합니다.
- 다른 간격 MS에 대한 기능 실행을 피합니다 .
- 이벤트를 모두 삭제하는 대신 과도한 이벤트 발생을 지연합니다.
- 연속 호출에서 지연된 이벤트 개체를 업데이트하여 '부실'상태가되지 않도록합니다.
그리고 다음의 스로틀 기능이이 모든 것을 만족한다고 생각합니다.
function throttle(func, alternateFunc, minimumInterval) {
var executeImmediately = true, freshEvt = null;
return function(Evt) {
if (executeImmediately) { // Execute immediatly
executeImmediately = false;
setTimeout(function(f){ // handle further calls
executeImmediately = true;
if (freshEvt !== null) func( freshEvt );
freshEvt = null;
}, minimumInterval);
return func( Evt );
} else { // Delayed execute
freshEvt = Evt;
if (typeof alternateFunc === "function") alternateFunc( Evt );
}
};
}
그런 다음이 조절 함수를 DOM 이벤트 리스너 주변에 래핑하려면 다음을 수행합니다.
var ltCache = [];
function listen(obj, evt, func, _opts){
var i = 0, Len = ltCache.length, lF = null, options = _opts || {};
a: {
for (; i < Len; i += 4)
if (ltCache[i] === func &&
ltCache[i+1] === (options.alternate||null) &&
ltCache[i+2] === (options.interval||200)
) break a;
lF = throttle(func, options.alternate||null, options.interval||200);
ltCache.push(func, options.alternate||null, options.interval||200, lF);
}
obj.addEventListener(evt, lF || ltCache[i+3], _opts);
};
function mute(obj, evt, func, options){
for (var i = 0, Len = ltCache.length; i < Len; i += 4)
if (ltCache[i] === func &&
ltCache[i+1] === (options.alternate||null) &&
ltCache[i+2] === (options.interval||200)
) return obj.removeEventListener(evt, ltCache[i+3], options);
}
사용 예 :
function throttle(func, alternateFunc, minimumInterval) {
var executeImmediately = true, freshEvt = null;
function handleFurtherCalls(f){
executeImmediately = true;
if (freshEvt !== null) func( freshEvt );
freshEvt = null;
};
return function(Evt) {
if (executeImmediately) { // Execute immediatly
executeImmediately = false;
setTimeout(handleFurtherCalls, minimumInterval);
return func( Evt );
} else { // Delayed execute
freshEvt = Evt;
if (typeof alternateFunc === "function") alternateFunc( Evt );
}
};
}
var ltCache = [];
function listen(obj, evt, func, _opts){
var i = 0, Len = ltCache.length, lF = null, options = _opts || {};
a: {
for (; i < Len; i += 4)
if (ltCache[i] === func &&
ltCache[i+1] === (options.alternate||null) &&
ltCache[i+2] === (options.interval||200)
) break a;
lF = throttle(func, options.alternate||null, options.interval||200);
ltCache.push(func, options.alternate||null, options.interval||200, lF);
}
obj.addEventListener(evt, lF || ltCache[i+3], _opts);
};
function mute(obj, evt, func, options){
for (var i = 0, Len = ltCache.length; i < Len; i += 4)
if (ltCache[i] === func &&
ltCache[i+1] === (options.alternate||null) &&
ltCache[i+2] === (options.interval||200)
) return obj.removeEventListener(evt, ltCache[i+3], options);
}
var numScrolls = 0, counter = document.getElementById("count");
listen(window, 'scroll', function whenbodyscrolls(){
var scroll = -document.documentElement.getBoundingClientRect().top;
counter.textContent = numScrolls++;
if (scroll > 900) {
console.log('Body scrolling stoped!');
mute(window, 'scroll', whenbodyscrolls, true);
}
}, true);
<center><h3>\/ Scroll Down The Page \/</h3></center>
<div style="position:fixed;top:42px"># Throttled Scrolls: <span id="count">0</span></div>
<div style="height:192em;background:radial-gradient(circle at 6em -5em, transparent 0px, rgba(128,0,0,.4) 90em),radial-gradient(circle at 10em 40em, rgba(255,255,255,.8) 0px, rgba(128,0,0,.02) 50em),radial-gradient(circle at 4em 80em, rgba(0,192,0,.75) 0px,rgba(0,128,0,.56) 10em,rgba(255,0,96,.03125) 30em),radial-gradient(circle at 86em 24em, rgba(255,0,0,.125) 0px,rgba(0,0,255,.0625) 60em,transparent 80em);"></div>
<style>body{margin:0}</style>
기본적으로 이는 200ms마다 최대 한 번의 호출로 함수를 제한합니다. 간격을 다른 밀리 초 수로 변경하려면 옵션 인수에 "interval"이라는 키를 전달하고 원하는 밀리 초로 설정합니다.
'Programing' 카테고리의 다른 글
Aptana Studio 3에서 jQuery 지원을 활성화하는 방법 (0) | 2020.12.12 |
---|---|
상속되는 CSS 속성은 무엇입니까? (0) | 2020.12.12 |
Spring에서 예약 된 작업을 조건부로 활성화 또는 비활성화하는 방법은 무엇입니까? (0) | 2020.12.12 |
부모 활동을 동적으로 설정 (0) | 2020.12.12 |
SBT에서 Scala 프로젝트에 Java 버전을 적용합니까? (0) | 2020.12.12 |