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.