JQuery : 크기 조정이 완료된 후에 만 ​​RESIZE 이벤트를 호출하는 방법은 무엇입니까?


109

브라우저 창 크기 조정이 완료되면 함수를 어떻게 호출합니까?

그렇게하려고하는데 문제가 있습니다. JQuery Resize 이벤트 함수를 사용하고 있습니다.

$(window).resize(function() {
  ... // how to call only once the browser has FINISHED resizing?
});

그러나 사용자가 브라우저 창의 크기를 수동으로 조정하는 경우이 함수는 계속 호출 됩니다 . 즉, 짧은 시간 간격으로이 함수를 수십 번 호출 할 수 있습니다.

어떻게 난 단지 크기 조정 함수를 호출 할 수있는 하나의 시간 (브라우저 창은 완성 된 크기 조정이되면)?

최신 정보

또한 전역 변수를 사용할 필요가 없습니다.


당신이 어떻게 나를 보여줄 수 있다면, @BGerrissen jsfiddle.net/Zevan/c9UE5/1를 전역 변수없이, 나는 확실히 :) 것이다
nickb

위의 cleartimeout / settimeout 메서드는 훌륭하게 작동합니다.
kris-o3 2013

답변:


129

다음은 thejh의 지침을 사용한 예입니다.

setInterval 또는 setTimeout에 참조 ID를 저장할 수 있습니다. 이렇게 :

var loop = setInterval(func, 30);

// some time later clear the interval
clearInterval(loop);

이 코드가 매우 간단하다는 점이 마음에 듭니다. 전역 변수를 사용 하지 않고도이 작업을 수행 할 수있는 방법이 있습니까?
nickb 2010

내가 전역 변수없이이 작업을 수행하는 방법을 참조하면, 나는 "허용 대답"고 만들거야
nickb

문제 없어요. 몇 가지 방법이 있습니다. 나는 내가 생각할 수있는 가장 간단한 것을 반영하기 위해 답을 편집했다.
Zevan 2010

업데이트에 감사하지만 여전히 전역 변수를 사용하는 것으로 보입니다. 전역 변수 (var id)가 필요하지 않도록 업데이트 할 수 있습니다. 감사합니다
nickb 2010

4
게시물 끝에서 링크를 놓친 것 같습니다 ... 확인해 보세요
Zevan

85

디 바운스 .

function debouncer( func , timeout ) {
   var timeoutID , timeout = timeout || 200;
   return function () {
      var scope = this , args = arguments;
      clearTimeout( timeoutID );
      timeoutID = setTimeout( function () {
          func.apply( scope , Array.prototype.slice.call( args ) );
      } , timeout );
   }
}


$( window ).resize( debouncer( function ( e ) {
    // do stuff 
} ) );

디 바운스하려는 모든 항목 (키 이벤트 등)에이 방법을 사용할 수 있습니다.

최적의 원하는 효과를 위해 타임 아웃 매개 변수를 조정합니다.


1
나는 이것을 실행하려고 시도했고 그것은 TWICE 를 실행하는 것처럼 보인다 . 나는 대체 "// 물건을 할""$ ("몸 ") (DONE <BR/>!") APPEND를. ";" 그리고 그것은 브라우저 크기 조정에서 TWICE라고 부릅니다
nickb

죄송합니다 ... 다소 중요한 부분을 잊어 버렸습니다 (실제로 timeoutID 설정) ... 지금 수정되었습니다. 다시 시도해주세요;)
BGerrissen

3
@ user43493 : func내부 this포인터가를 가리키는 cuntion을 호출하고 인수로 scopewith Array.prototype.slice.call(args)(의 표준 배열을 생성 함 args)
Eric

4
이것은 재사용 가능한 추상화이므로 타임 아웃을 직접 코딩하거나 글로벌 타임 아웃 ID를 직접 추적 할 필요가 없습니다. 예를 들어 더 높은 시간 제한 매개 변수를 전달하여 제출 버튼을 디 바운스하기 위해 창 크기를 조정하는 것보다 더 많이 사용할 수 있습니다. 적은 코드 솔루션을 선택할 수 있지만이 코드 조각을 키트에 보관하는 것이 좋습니다. 나중에 감사하겠습니다.;)
BGerrissen

2
Underscore.js는 이미 해당 lib를 사용하고 있다면이를 잘 구현했습니다. underscorejs.org/#debounce
twmulloy

22

setTimeout()및 다음 clearTimeout()과 함께 사용할 수 있습니다 jQuery.data.

$(window).resize(function() {
    clearTimeout($.data(this, 'resizeTimer'));
    $.data(this, 'resizeTimer', setTimeout(function() {
        //do something
        alert("Haven't resized in 200ms!");
    }, 200));
});

최신 정보

jQuery의 기본 (& ) 이벤트 처리기 를 향상시키기 위해 확장 을 작성했습니다 . 이벤트가 지정된 간격 동안 트리거되지 않은 경우 하나 이상의 이벤트에 대한 이벤트 처리기 함수를 선택한 요소에 연결합니다. 이는 resize 이벤트 등 지연 후에 만 ​​콜백을 실행하려는 경우에 유용합니다. https://github.com/yckart/jquery.unevent.jsonbind

;(function ($) {
    var methods = { on: $.fn.on, bind: $.fn.bind };
    $.each(methods, function(k){
        $.fn[k] = function () {
            var args = [].slice.call(arguments),
                delay = args.pop(),
                fn = args.pop(),
                timer;

            args.push(function () {
                var self = this,
                    arg = arguments;
                clearTimeout(timer);
                timer = setTimeout(function(){
                    fn.apply(self, [].slice.call(arg));
                }, delay);
            });

            return methods[k].apply(this, isNaN(delay) ? arguments : args);
        };
    });
}(jQuery));

추가 매개 변수를 마지막으로 전달할 수 있다는 점을 제외하고는 다른 on또는 bind-event 핸들러 와 같이 사용하십시오 .

$(window).on('resize', function(e) {
    console.log(e.type + '-event was 200ms not triggered');
}, 200);

http://jsfiddle.net/ARTsinn/EqqHx/


1
말 그대로 매일 동일한 Google 검색을 수행합니다. 이 코드에 대해 동일한 페이지로 이동합니다. 내가 그것을 기억할 수 있으면 좋겠어 하하.
Dustin Silk

7
var lightbox_resize = false;
$(window).resize(function() {
    console.log(true);
    if (lightbox_resize)
        clearTimeout(lightbox_resize);
    lightbox_resize = setTimeout(function() {
        console.log('resize');
    }, 500);
});

나는 이것을 가장 좋아하지만 조건문에 중괄호를 사용하지 않는 이유는 무엇입니까? 나는 그것이 그들 없이도 작동한다는 것을 알고 있지만 다른 개발자들이보기에는 고통
스럽

7

위에 추가하기 만하면 스크롤 막대가 튀어 나와서 원치 않는 크기 조정 이벤트가 발생하는 것이 일반적입니다.이를 방지하기위한 몇 가지 코드는 다음과 같습니다.

function registerResize(f) {
    $(window).resize(function() {
        clearTimeout(this.resizeTimeout);
        this.resizeTimeout = setTimeout(function() {
            var oldOverflow = document.body.style.overflow;
            document.body.style.overflow = "hidden";
            var currHeight = $(window).height(),
                currWidth = $(window).width();
            document.body.style.overflow = oldOverflow;

            var prevUndefined = (typeof this.prevHeight === 'undefined' || typeof this.prevWidth === 'undefined');
            if (prevUndefined || this.prevHeight !== currHeight || this.prevWidth !== currWidth) {
                //console.log('Window size ' + (prevUndefined ? '' : this.prevHeight + "," + this.prevWidth) + " -> " + currHeight + "," + currWidth);
                this.prevHeight = currHeight;
                this.prevWidth = currWidth;

                f(currHeight, currWidth);
            }
        }, 200);
    });
    $(window).resize(); // initialize
}

registerResize(function(height, width) {
    // this will be called only once per resize regardless of scrollbars changes
});

jsfiddle 참조


5

Underscore.js는 이 작업을위한 좋은 방법 중 몇 가지를 가지고 throttledebounce. Underscore를 사용하지 않더라도 이러한 함수의 소스를 살펴보십시오. 예를 들면 다음과 같습니다.

var redraw = function() {'redraw logic here'};
var debouncedRedraw = _.debounce(redraw, 750);
$(window).on('resize', debouncedRedraw);

2

이것이 내 접근 방식입니다.

document.addEventListener('DOMContentLoaded', function(){
    var tos = {};
    var idi = 0;
    var fn  = function(id)
    {
        var len = Object.keys(tos).length;

        if(len == 0)
            return;

        to = tos[id];
        delete tos[id];

        if(len-1 == 0)
            console.log('Resize finished trigger');
    };

    window.addEventListener('resize', function(){
        idi++;
        var id = 'id-'+idi;
        tos[id] = window.setTimeout(function(){fn(id)}, 500);
    });
});

resize-event-listener는 수신되는 모든 크기 조정 호출을 포착하고, 각각에 대한 시간 초과 기능을 생성하고 'id-', tos-array에 ( 배열 키로 사용할 수 있도록) 앞에 추가되는 반복 번호와 함께 시간 초과 식별자를 저장합니다 .

시간 초과가 트리거 될 때마다 -function을 호출하여 이것이 배열 fn의 마지막 시간 초과인지 확인합니다 tos(fn- 함수는 실행 된 모든 시간 초과를 삭제함). true (= if(len-1 == 0))이면 크기 조정이 완료됩니다.


당신은 어떤 의견이나 당신이 무슨 일을하는지에 관해서는 설명이 있다면 그것은 좋은 것입니다
브렛 그렉 슨을

1

jQuery는 off이벤트 핸들러를 제거 하는 방법을 제공 합니다.

$(window).resize(function(){
    if(magic == true) {
        $(window).off('resize', arguments.callee);
    }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.