JavaScript / JQuery : $ (window) .resize 크기 조정이 완료된 후 실행하는 방법은 무엇입니까?


235

JQuery를 다음과 같이 사용하고 있습니다.

$(window).resize(function() { ... });

그러나 사용자가 창 가장자리를 드래그하여 브라우저 창의 크기를 조정하여 더 크거나 작게 만들면 .resize위 의 이벤트가 여러 번 발생합니다.

질문 : 브라우저 창의 크기 조정이 완료된 후 함수를 호출하는 방법 (이벤트가 한 번만 발생하도록)?


이 답변을 참조하십시오 : stackoverflow.com/questions/667426/… 시간 초과를 사용하여 함수 실행을 지연시킵니다.
Alastair Pitts

그게 가능하다면하지만,이 플러그인을 시도 할 수 모른다 benalman.com/projects/jquery-resize-plugin
BrunoLM에게

그건 그렇고, 이것은 사용자가 아래로 스크롤 할 때 주소 표시 줄을 점차 숨기고 화면 크기를 조정하는 모바일 브라우저에서 매우 유용하다는 것을 알았습니다. 또한 화면 크기가 데스크톱에서만 발생할 것으로 예상했습니다.
MakisH

답변:


299

코드의 여러 위치에서 호출 할 수있는 CMS 솔루션의 수정 사항은 다음과 같습니다.

var waitForFinalEvent = (function () {
  var timers = {};
  return function (callback, ms, uniqueId) {
    if (!uniqueId) {
      uniqueId = "Don't call this twice without a uniqueId";
    }
    if (timers[uniqueId]) {
      clearTimeout (timers[uniqueId]);
    }
    timers[uniqueId] = setTimeout(callback, ms);
  };
})();

용법:

$(window).resize(function () {
    waitForFinalEvent(function(){
      alert('Resize...');
      //...
    }, 500, "some unique string");
});

CMS의 솔루션은 한 번만 호출하면 괜찮지 만 여러 번 호출하면 (예 : 코드의 다른 부분이 창 크기 조정에 대해 별도의 콜백을 설정 한 경우) timer변수 를 공유하는 데 실패 합니다.

이 수정을 통해 각 콜백에 고유 ID를 제공하고 해당 고유 ID를 사용하여 모든 시간 초과 이벤트를 개별적으로 유지합니다.


2
나는 <3 u, 나는 이것을 전체 화면 (html5가 아닌) Highcharts 그래프의 크기를 조정하면서 결합했으며 훌륭하게 작동합니다.
Michael J. Calkins

절대적으로 믿어지지 않는다!
Starkers

2
귀하의 답변에서 많은 이점을 얻었으므로 나머지 커뮤니티를 위해 제공된 코드의 작동 프로토 타입을 공유한다고 생각했습니다 : jsfiddle.net/h6h2pzpu/3 . 모두 즐기세요!
Jonas Stawski

1
이것은 모두 완벽하지만 실제 함수 실행을 밀리 초 (ms)만큼 지연시킵니다. 이는 매우 바람직하지 않을 수 있습니다.
Tomas M

이것은 마지막 크기를 잡아서 밀리 초 동안 릴레이 할 필요가없는 방법입니까? 어쨌든 이것은 방금 내 하루를 구했습니다 : ') 감사합니다.
Leo

138

이벤트를 만들고 싶습니다.

$(window).bind('resizeEnd', function() {
    //do something, window hasn't changed size in 500ms
});

작성 방법은 다음과 같습니다.

 $(window).resize(function() {
        if(this.resizeTO) clearTimeout(this.resizeTO);
        this.resizeTO = setTimeout(function() {
            $(this).trigger('resizeEnd');
        }, 500);
    });

전역 자바 스크립트 파일에서이를 가질 수 있습니다.


이 솔루션을 사용했습니다. 그러나 장기적으로 brahn의 솔루션과 동일하게 구현하고 싶습니다.
Bharat Patil

이것은 물론 별도의 반응이 필요한 여러 페이지 / .js 파일이 있다고 가정 할 때 하나의 기능뿐만 아니라 모든 이벤트에 바인딩 할 수 있습니다.
hanzolo

이것은 나를 위해 작동하지 않았다하지만 DusanV의 대답은 작업 한
lightbyte

123

반복 동작을 지연시키기 위해 다음 기능을 사용합니다. 귀하의 경우에는 효과가 있습니다.

var delay = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

용법:

$(window).resize(function() {
    delay(function(){
      alert('Resize...');
      //...
    }, 500);
});

전달 된 콜백 함수는 지정된 시간 후에 지연에 대한 마지막 호출이 이루어진 경우에만 실행됩니다. 그렇지 않으면 타이머가 재설정됩니다. 사용자가 입력을 중지 한 시점을 감지하는 등 다른 목적으로 유용합니다. ..


5
이 접근법은 여러 번 사용하면 (예 : 코드 설정 콜백의 다른 부분이에 $(window).resize) timer변수 가 모두 공유되므로 실패 할 수 있습니다 . 제안 된 솔루션에 대해서는 아래 답변을 참조하십시오.
brahn

아주 좋아요! 매력처럼 작동합니다! 답처럼 ... 간단하고 우아합니다!
Mr. Pumpkin

74

Underscore.js를 설치 한 경우 다음을 수행 할 수 있습니다.

$(window).resize(_.debounce(function(){
    alert("Resized");
},500));

1
Underscore를 포함하고 싶지 않더라도 최소한 이것에 대한 소스를 확보하십시오. underscorejs.org/docs/underscore.html#section-67
tybro0103

Debounce는 올바른 기술이며 구현의 문제입니다. Underscore / Lodash가 이미 프로젝트 종속성 인 경우 이는 우수한 구현입니다.
팩터 미스틱

이것은 지금 내가 사용하고있는 것입니다
Bharat Patil

20

앞에서 언급 한 솔루션 중 일부는 더 일반적인 사용법이지만 작동하지 않았습니다. 또는 창 크기 조정 작업을 수행 한이 것을 발견했습니다 .

$(window).bind('resize', function(e){
    window.resizeEvt;
    $(window).resize(function(){
        clearTimeout(window.resizeEvt);
        window.resizeEvt = setTimeout(function(){
        //code to do after window is resized
        }, 250);
    });
});

1
당신의 모범 만이 나를 위해 일했습니다 ... 위의 다른 사람들은 그렇지 않았습니다! 귀하의 답변이 선택되지 않은 이유가 확실하지 않습니다.
Mumbo Jumbo 2016 년

나는 resize 이벤트 안에서 resize 이벤트를 잡아야하는 이유를 이해하지 못하지만 나에게도 효과가있다.
lightbyte

Mumbo Jumbo, 다른 사람들은 일반화에 중점을 두어 그러한 문제 (여러 함수 호출)에 대한 해결책을 찾고 있기 때문에 생각합니다.
DusanV

lightbyte는 함수가 호출 될 때마다 이전 이벤트를 중지해야하기 때문입니다.
DusanV

13

David Walsh에게 감사를 표합니다. 여기에 밑줄 디 바운스의 바닐라 버전이 있습니다.

암호:

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

간단한 사용법 :

var myEfficientFn = debounce(function() {
    // All the taxing stuff you do
}, 250);

$(window).on('resize', myEfficientFn);

참조 : http://davidwalsh.name/javascript-debounce-function


6

실제로, 내가 아는 것처럼, 향후 사용자의 동작을 모르기 때문에 크기 조정이 해제되어 있으면 정확히 몇 가지 동작을 수행 할 수 없습니다. 그러나 두 크기 조정 이벤트 사이에 시간이 경과했다고 가정 할 수 있으므로이 시간보다 조금 더 기다렸다가 크기를 조정하지 않으면 함수를 호출 할 수 있습니다.
아이디어는 우리가 사용 setTimeout하고 저장하거나 삭제하기 위해 ID라는 것입니다. 예를 들어 두 크기 조정 이벤트 사이의 시간이 500ms이므로 750ms를 기다립니다.

var a;
$(window).resize(function(){
  clearTimeout(a);
  a = setTimeout(function(){
    // call your function
  },750);
});


3

전역 지연 리스너 선언 :

var resize_timeout;

$(window).on('resize orientationchange', function(){
    clearTimeout(resize_timeout);

    resize_timeout = setTimeout(function(){
        $(window).trigger('resized');
    }, 250);
});

그리고 아래에서 리스너를 사용하여 resized원하는대로 이벤트하십시오.

$(window).on('resized', function(){
    console.log('resized');
});

고마워, 그것은 현재 최고의 솔루션입니다. 또한 250ms가 창 크기를 조정할 때 가장 좋은 방법으로 작동하는지 테스트했습니다.
AlexioVay


2

지연된 창 크기 조정 이벤트를위한 간단한 jQuery 플러그인.

통사론:

이벤트 크기를 조정하는 새로운 기능 추가

jQuery(window).resizeDelayed( func, delay, id ); // delay and id are optional

앞에서 추가 한 함수를 제거하십시오 (ID를 선언하여)

jQuery(window).resizeDelayed( false, id );

모든 기능 제거

jQuery(window).resizeDelayed( false );

용법:

// ADD SOME FUNCTIONS TO RESIZE EVENT
jQuery(window).resizeDelayed( function(){ console.log( 'first event - should run after 0.4 seconds'); }, 400,  'id-first-event' );
jQuery(window).resizeDelayed( function(){ console.log('second event - should run after 1.5 seconds'); }, 1500, 'id-second-event' );
jQuery(window).resizeDelayed( function(){ console.log( 'third event - should run after 3.0 seconds'); }, 3000, 'id-third-event' );

// LETS DELETE THE SECOND ONE
jQuery(window).resizeDelayed( false, 'id-second-event' );

// LETS ADD ONE WITH AUTOGENERATED ID(THIS COULDNT BE DELETED LATER) AND DEFAULT TIMEOUT (500ms)
jQuery(window).resizeDelayed( function(){ console.log('newest event - should run after 0.5 second'); } );

// LETS CALL RESIZE EVENT MANUALLY MULTIPLE TIMES (OR YOU CAN RESIZE YOUR BROWSER WINDOW) TO SEE WHAT WILL HAPPEN
jQuery(window).resize().resize().resize().resize().resize().resize().resize();

사용 출력 :

first event - should run after 0.4 seconds
newest event - should run after 0.5 second
third event - should run after 3.0 seconds

플러그인:

jQuery.fn.resizeDelayed = (function(){

    // >>> THIS PART RUNS ONLY ONCE - RIGHT NOW

    var rd_funcs = [], rd_counter = 1, foreachResizeFunction = function( func ){ for( var index in rd_funcs ) { func(index); } };

    // REGISTER JQUERY RESIZE EVENT HANDLER
    jQuery(window).resize(function() {

        // SET/RESET TIMEOUT ON EACH REGISTERED FUNCTION
        foreachResizeFunction(function(index){

            // IF THIS FUNCTION IS MANUALLY DISABLED ( by calling jQuery(window).resizeDelayed(false, 'id') ),
            // THEN JUST CONTINUE TO NEXT ONE
            if( rd_funcs[index] === false )
                return; // CONTINUE;

            // IF setTimeout IS ALREADY SET, THAT MEANS THAT WE SHOULD RESET IT BECAUSE ITS CALLED BEFORE DURATION TIME EXPIRES
            if( rd_funcs[index].timeout !== false )
                clearTimeout( rd_funcs[index].timeout );

            // SET NEW TIMEOUT BY RESPECTING DURATION TIME
            rd_funcs[index].timeout = setTimeout( rd_funcs[index].func, rd_funcs[index].delay );

        });

    });

    // <<< THIS PART RUNS ONLY ONCE - RIGHT NOW

    // RETURN THE FUNCTION WHICH JQUERY SHOULD USE WHEN jQuery(window).resizeDelayed(...) IS CALLED
    return function( func_or_false, delay_or_id, id ){

        // FIRST PARAM SHOULD BE SET!
        if( typeof func_or_false == "undefined" ){

            console.log( 'jQuery(window).resizeDelayed(...) REQUIRES AT LEAST 1 PARAMETER!' );
            return this; // RETURN JQUERY OBJECT

        }

        // SHOULD WE DELETE THE EXISTING FUNCTION(S) INSTEAD OF CREATING A NEW ONE?
        if( func_or_false == false ){

            // DELETE ALL REGISTERED FUNCTIONS?
            if( typeof delay_or_id == "undefined" ){

                // CLEAR ALL setTimeout's FIRST
                foreachResizeFunction(function(index){

                    if( typeof rd_funcs[index] != "undefined" && rd_funcs[index].timeout !== false )
                        clearTimeout( rd_funcs[index].timeout );

                });

                rd_funcs = [];

                return this; // RETURN JQUERY OBJECT

            }
            // DELETE ONLY THE FUNCTION WITH SPECIFIC ID?
            else if( typeof rd_funcs[delay_or_id] != "undefined" ){

                // CLEAR setTimeout FIRST
                if( rd_funcs[delay_or_id].timeout !== false )
                    clearTimeout( rd_funcs[delay_or_id].timeout );

                rd_funcs[delay_or_id] = false;

                return this; // RETURN JQUERY OBJECT

            }

        }

        // NOW, FIRST PARAM MUST BE THE FUNCTION
        if( typeof func_or_false != "function" )
            return this; // RETURN JQUERY OBJECT

        // SET THE DEFAULT DELAY TIME IF ITS NOT ALREADY SET
        if( typeof delay_or_id == "undefined" || isNaN(delay_or_id) )
            delay_or_id = 500;

        // SET THE DEFAULT ID IF ITS NOT ALREADY SET
        if( typeof id == "undefined" )
            id = rd_counter;

        // ADD NEW FUNCTION TO RESIZE EVENT
        rd_funcs[id] = {
            func : func_or_false,
            delay: delay_or_id,
            timeout : false
        };

        rd_counter++;

        return this; // RETURN JQUERY OBJECT

    }

})();

1

창 크기를 조정 한 후 마우스 커서가 문서로 돌아 가야한다고 가정하면 onmouseover 이벤트로 콜백과 유사한 동작을 만들 수 있습니다. 이 솔루션은 터치 지원 화면에서 예상대로 작동하지 않을 수 있습니다.

var resizeTimer;
var resized = false;
$(window).resize(function() {
   clearTimeout(resizeTimer);
   resizeTimer = setTimeout(function() {
       if(!resized) {
           resized = true;
           $(document).mouseover(function() {
               resized = false;
               // do something here
               $(this).unbind("mouseover");
           })
       }
    }, 500);
});

마우스 기반 데스크톱 전용 사이트에는 적합하지만 예를 들어 사용자가 모바일 환경에서 가로 방향에서 세로 방향으로 변경하거나 터치 스크린 데스크톱에서 창 크기를 조정 한 경우 마우스 오버 이벤트가 발생하지 않습니다.
user56reinstatemonica8

Win-Arrow-Left Win-Arrow-Right 등과 같은 최신 창에서 키보드를 사용하여 브라우저 창 크기를 조정할 수 있습니다.
Lu4

0

이것이 내가 구현 한 것입니다.

$ (window) .resize (function () {setTimeout (someFunction, 500);});

크기 조정이 다음보다 작을 것으로 예상 되면 setTimeout을 지울 수 있습니다.500ms

행운을 빕니다...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.