webentwicklung-frage-antwort-db.com.de

Wie warte ich auf das "Ende" des "Größenänderungs" -Ereignisses und führe erst dann eine Aktion aus?

Also benutze ich momentan so etwas wie:

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

Dies wird jedoch viele Male aufgerufen, während der Größenänderungsprozess fortgesetzt wird. Ist es möglich, ein Ereignis zu erfassen, wenn es endet?

220
Rella

Ich hatte Glück mit der folgenden Empfehlung: http://forum.jquery.com/topic/the-resizeend-event

Hier ist der Code, damit Sie nicht den Link und die Quelle seines Posts durchsuchen müssen:

var rtime;
var timeout = false;
var delta = 200;
$(window).resize(function() {
    rtime = new Date();
    if (timeout === false) {
        timeout = true;
        setTimeout(resizeend, delta);
    }
});

function resizeend() {
    if (new Date() - rtime < delta) {
        setTimeout(resizeend, delta);
    } else {
        timeout = false;
        alert('Done resizing');
    }               
}

Danke sime.vidas für den Code!

162
Dolan Antenucci

Sie können setTimeout() und clearTimeout() verwenden

function resizedw(){
    // Haven't resized in 100ms!
}

var doit;
window.onresize = function(){
  clearTimeout(doit);
  doit = setTimeout(resizedw, 100);
};

Codebeispiel auf jsfiddle .

491
Mark Coleman

Dies ist der Code, den ich nach @ Mark Coleman Antwort schreibe:

$(window).resize(function() {
    clearTimeout(window.resizedFinished);
    window.resizedFinished = setTimeout(function(){
        console.log('Resized finished.');
    }, 250);
});

Danke Markus!

74
Roy Shoa

Internet Explorer bietet ein resizeEnd -Ereignis. Andere Browser lösen das Größenänderungsereignis mehrmals aus, während Sie die Größe ändern.

Es gibt hier andere großartige Antworten, die zeigen, wie setTimeout und die Methoden . Throttle , . Debounce von lodash und Underscore verwendet werden, also ich Erwähnen wir Ben Almans jQuery-Plug-in mit Gaspedal, das das schafft, wonach Sie suchen.

Angenommen, Sie haben diese Funktion, die Sie nach einer Größenänderung auslösen möchten:

function onResize() {
  console.log("Resize just happened!");
};

Beispiel für eine Drosselklappe
Im folgenden Beispiel wird onResize() während einer Fenstergrößenänderung nur einmal alle 250 Millisekunden aufgerufen.

$(window).resize( $.throttle( 250, onResize) );

Debounce-Beispiel
Im folgenden Beispiel wird onResize() nur einmal am Ende einer Fenstergrößenänderung aufgerufen. Dies führt zu dem gleichen Ergebnis, das @Mark in seiner Antwort präsentiert.

$(window).resize( $.debounce( 250, onResize) );
34
jessegavin

Es gibt eine elegante Lösung, die nderscore.js verwendet. Wenn Sie sie also in Ihrem Projekt verwenden, können Sie Folgendes tun:

$( window ).resize( _.debounce( resizedw, 500 ) );

Das sollte reichen :) Aber wenn du mehr darüber lesen möchtest, kannst du meinen Blog-Beitrag lesen - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using-underscore-debounce(Deadlink)

24
Rifat

Sie können eine Referenz-ID für jedes setInterval oder setTimeout speichern. So was:

var loop = setInterval(func, 30);

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

Um dies ohne eine "globale" Variable zu tun, können Sie der Funktion selbst eine lokale Variable hinzufügen. Ex:

$(window).resize(function() {
    clearTimeout(this.id);
    this.id = setTimeout(doneResizing, 500);
});

function doneResizing(){
  $("body").append("<br/>done!");   
}
7
Xman Classical

Eine Lösung ist, jQuery um eine Funktion zu erweitern, z. B .: resized

$.fn.resized = function (callback, timeout) {
    $(this).resize(function () {
        var $this = $(this);
        if ($this.data('resizeTimeout')) {
            clearTimeout($this.data('resizeTimeout'));
        }
        $this.data('resizeTimeout', setTimeout(callback, timeout));
    });
};

Beispielnutzung:

$(window).resized(myHandler, 300);

7
Jone Polvora

Sie können setTimeout() und clearTimeout() in Verbindung mit jQuery.data :

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

Update

Ich habe eine Erweiterung geschrieben, um den Standard-Event-Handler on (& bind) von jQuery zu verbessern. Es hängt eine Ereignishandlerfunktion für ein oder mehrere Ereignisse an die ausgewählten Elemente an, wenn das Ereignis für ein bestimmtes Intervall nicht ausgelöst wurde. Dies ist nützlich, wenn Sie einen Rückruf erst nach einer Verzögerung auslösen möchten, z. B. nach dem Größenänderungsereignis. https://github.com/yckart/jquery.unevent.js

;(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));

Verwenden Sie es wie jeden anderen on oder bind -Ereignishandler, mit der Ausnahme, dass Sie als letztes einen zusätzlichen Parameter übergeben können:

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

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

3
yckart

Mark Colemans Antwort ist sicherlich weitaus besser als die ausgewählte Antwort. Wenn Sie jedoch die globale Variable für die Zeitüberschreitungs-ID (die Variable doit in Marks Antwort) vermeiden möchten, können Sie eine der folgenden Aktionen ausführen:

(1) Verwenden Sie einen sofort aufgerufenen Funktionsausdruck (IIFE), um einen Abschluss zu erstellen.

$(window).resize((function() { // This function is immediately invoked
                               // and returns the closure function.
    var timeoutId;
    return function() {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function() {
            timeoutId = null; // You could leave this line out.
            // Code to execute on resize goes here.
        }, 100);
    };
})());

(2) Verwenden Sie eine Eigenschaft der Event-Handler-Funktion.

$(window).resize(function() {
    var thisFunction = arguments.callee;
    clearTimeout(thisFunction.timeoutId);
    thisFunction.timeoutId = setTimeout(function() {
        thisFunction.timeoutId = null; // You could leave this line out.
        // Code to execute on resize goes here.
    }, 100);
});
2
John S

Dies ist eine Modifikation von Dolans Code oben. Ich habe eine Funktion hinzugefügt, die die Fenstergröße zu Beginn der Größenänderung überprüft und mit der Größe am Ende der Größenänderung vergleicht, wenn die Größe entweder größer oder kleiner als der Rand ist ( zB 1000) dann wird nachgeladen.

var rtime = new Date(1, 1, 2000, 12,00,00);
var timeout = false;
var delta = 200;
var windowsize = $window.width();
var windowsizeInitial = $window.width();

$(window).on('resize',function() {
    windowsize = $window.width();
    rtime = new Date();
    if (timeout === false) {
            timeout = true;
            setTimeout(resizeend, delta);
        }
});

function resizeend() {
if (new Date() - rtime < delta) {
    setTimeout(resizeend, delta);
    return false;
} else {
        if (windowsizeInitial > 1000 && windowsize > 1000 ) {
            setTimeout(resizeend, delta);
            return false;
        }
        if (windowsizeInitial < 1001 && windowsize < 1001 ) {
            setTimeout(resizeend, delta);
            return false;
        } else {
            timeout = false;
            location.reload();
        }
    }
    windowsizeInitial = $window.width();
    return false;
}
2
Sami A.

ich habe selbst eine kleine Wrapper-Funktion geschrieben ...

onResize  =   function(fn) {
    if(!fn || typeof fn != 'function')
        return 0;

    var args    = Array.prototype.slice.call(arguments, 1);

    onResize.fnArr    = onResize.fnArr || [];
    onResize.fnArr.Push([fn, args]);

    onResize.loop   = function() {
        $.each(onResize.fnArr, function(index, fnWithArgs) {
            fnWithArgs[0].apply(undefined, fnWithArgs[1]);
        });
    };

    $(window).on('resize', function(e) {
        window.clearTimeout(onResize.timeout);
        onResize.timeout    = window.setTimeout("onResize.loop();", 300);
    });
};

Hier ist die Verwendung:

var testFn  = function(arg1, arg2) {
    console.log('[testFn] arg1: '+arg1);
    console.log('[testFn] arg2: '+arg2);
};

// document ready
$(function() {
    onResize(testFn, 'argument1', 'argument2');
});
1
user2123506

Hier ist SEHR einfaches Skript, um sowohl ein 'resizestart'- als auch ein' resizeend'-Ereignis für das Fensterobjekt auszulösen.

Es ist nicht nötig, sich mit Daten und Uhrzeiten zu beschäftigen.

Die Variable d gibt die Anzahl der Millisekunden zwischen Größenänderungsereignissen an, bevor das Größenänderungsendereignis ausgelöst wird. Sie können damit spielen, um die Empfindlichkeit des Endereignisses zu ändern.

Um diese Ereignisse anzuhören, müssen Sie nur Folgendes tun:

resizestart: $(window).on('resizestart', function(event){console.log('Resize Start!');});

größe ändern: $(window).on('resizeend', function(event){console.log('Resize End!');});

(function ($) {
    var d = 250, t = null, e = null, h, r = false;

    h = function () {
        r = false;
        $(window).trigger('resizeend', e);
    };

    $(window).on('resize', function (event) {
        e = event || e;
        clearTimeout(t);

        if (!r) {
            $(window).trigger('resizestart', e);
            r = true;
        }

        t = setTimeout(h, d);
    });
}(jQuery));
1
Neaox

Nun, für den Fenstermanager ist jedes Größenänderungsereignis eine eigene Meldung mit einem unterschiedlichen Anfang und Ende. Technisch gesehen ist es also bei jeder Größenänderung des Fensters . das Ende.

Vielleicht möchten Sie Ihre Fortsetzung verzögern? Hier ist ein Beispiel.

var t = -1;
function doResize()
{
    document.write('resize');
}
$(document).ready(function(){
    $(window).resize(function(){
        clearTimeout(t);
        t = setTimeout(doResize, 1000);
    });
});
1
Demian Brecht
(function(){
    var special = jQuery.event.special,
        uid1 = 'D' + (+new Date()),
        uid2 = 'D' + (+new Date() + 1);

    special.resizestart = {
        setup: function() {
            var timer,
                handler =  function(evt) {
                    var _self = this,
                        _args = arguments;
                    if (timer) {
                        clearTimeout(timer);
                    } else {
                        evt.type = 'resizestart';
                        jQuery.event.handle.apply(_self, _args);
                    }

                    timer = setTimeout( function(){
                        timer = null;
                    }, special.resizestop.latency);
                };
            jQuery(this).bind('resize', handler).data(uid1, handler);
        },
        teardown: function(){
            jQuery(this).unbind( 'resize', jQuery(this).data(uid1) );
        }
    };

    special.resizestop = {
        latency: 200,
        setup: function() {
            var timer,
                handler = function(evt) {
                    var _self = this,
                        _args = arguments;
                    if (timer) {
                        clearTimeout(timer);
                    }
                    timer = setTimeout( function(){
                        timer = null;
                        evt.type = 'resizestop';
                        jQuery.event.handle.apply(_self, _args);
                    }, special.resizestop.latency);
                };

            jQuery(this).bind('resize', handler).data(uid2, handler);
        },
        teardown: function() {
            jQuery(this).unbind( 'resize', jQuery(this).data(uid2) );
        }
    };
})();

$(window).bind('resizestop',function(){
    //...
});
1
lazer

Ich weiß nicht, ob mein Code für andere funktioniert, aber es macht wirklich einen tollen Job für mich. Ich bin auf diese Idee gekommen, als ich Dolan Antenucci-Code analysiert habe, da seine Version für mich nicht geeignet ist und ich hoffe wirklich, dass sie jemandem hilft.

var tranStatus = false;
$(window).resizeend(200, function(){
    $(".cat-name, .category").removeAttr("style");
    //clearTimeout(homeResize);
    $("*").one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",function(event) {
      tranStatus = true;
    });
    processResize();
});

function processResize(){
  homeResize = setInterval(function(){
    if(tranStatus===false){
        console.log("not yet");
        $("*").one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",function(event) {
            tranStatus = true;
        }); 
    }else{
        text_height();
        clearInterval(homeResize);
    }
  },200);
}
0

das hat bei mir funktioniert, da ich keine Plugins verwenden wollte.

$(window).resize(function() {
    var originalWindowSize = 0;
    var currentWidth = 0;

    var setFn = function () {
        originalWindowSize = $(window).width();
    };

    var checkFn = function () {
        setTimeout(function () {
            currentWidth = $(window).width();
            if (currentWidth === originalWindowSize) {
                console.info("same? = yes") 
                // execute code 
            } else {
                console.info("same? = no"); 
                // do nothing 
            }
        }, 500)
    };
    setFn();
    checkFn();
});

Bei einer Größenänderung des Fensters rufen Sie "setFn" auf, das die Breite des Fensters abruft und als "originalWindowSize" speichert. Rufen Sie dann "checkFn" auf, das nach 500 ms (oder Ihrer Präferenz) die aktuelle Fenstergröße erhält und das Original mit der aktuellen vergleicht. Wenn diese nicht identisch sind, wird die Größe des Fensters immer noch geändert. Vergessen Sie nicht, Konsolenmeldungen in der Produktion zu entfernen, und (optional) kann "setFn" selbstausführend machen.

0
Byron Wong

Ich habe eine Funktion geschrieben, die eine Funktion übergibt, wenn sie in ein Größenänderungsereignis eingeschlossen wird. Es wird ein Intervall verwendet, damit die Größenänderung nicht ständig Zeitüberschreitungsereignisse erzeugt. Auf diese Weise kann unabhängig vom Größenänderungsereignis ein anderer Protokolleintrag ausgeführt werden, der in der Produktion entfernt werden soll.

https://github.com/UniWrighte/resizeOnEnd/blob/master/resizeOnEnd.js

        $(window).resize(function(){
            //call to resizeEnd function to execute function on resize end.
    //can be passed as function name or anonymous function
            resizeEnd(function(){



    });

        });

        //global variables for reference outside of interval
        var interval = null;
        var width = $(window).width();
    var numi = 0; //can be removed in production
        function resizeEnd(functionCall){
            //check for null interval
            if(!interval){
                //set to new interval
                interval = setInterval(function(){
        //get width to compare
                    width2 = $(window).width();
        //if stored width equals new width
                    if(width === width2){
                        //clear interval, set to null, and call passed function
                        clearInterval(interval);
                        interval = null; //precaution
                        functionCall();

                    }
        //set width to compare on next interval after half a second
                    width = $(window).width();
                }, 500);

            }else{
                //logging that should be removed in production
                console.log("function call " + numi++ + " and inteval set skipped");

            }

}

0
David Kamer

da die ausgewählte antwort nicht funktioniert hat .. und wenn du jquery nicht verwendest, ist hier eine einfache drosselfunktion mit einem beispiel wie man sie mit fenstergrößenänderung benutzt

    function throttle(end,delta) {

    var base = this;

    base.wait = false;
    base.delta = 200;
    base.end = end;

    base.trigger = function(context) {

        //only allow if we aren't waiting for another event
        if ( !base.wait ) {

            //signal we already have a resize event
            base.wait = true;

            //if we are trying to resize and we 
            setTimeout(function() {

                //call the end function
                if(base.end) base.end.call(context);

                //reset the resize trigger
                base.wait = false;
            }, base.delta);
        }
    }
};

var windowResize = new throttle(function() {console.log('throttle resize');},200);

window.onresize = function(event) {
    windowResize.trigger();
}
0
Chad Brown

Das ist, was ich benutze, um wiederholte Aktionen zu verzögern. Es kann an mehreren Stellen in Ihrem Code aufgerufen werden:

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);
    };
};

Verwendungszweck:

$(window).resize(function () { 
   debounce(function() {
          //...
    }, 500);
});
0
Hil
var flag=true;
var timeloop;

$(window).resize(function(){
    rtime=new Date();
    if(flag){
        flag=false;
        timeloop=setInterval(function(){
            if(new Date()-rtime>100)
                myAction();
        },100);
    }
})
function myAction(){
    clearInterval(timeloop);
    flag=true;
    //any other code...
}
0
babak iran

ResizeStart und ResizeEnd Ereignisse für das Fenster

http://jsfiddle.net/04fLy8t4/

Ich habe eine Funktion implementiert, die zwei Ereignisse auf dem Benutzer-DOM-Element auslöst:

  1. resizestart
  2. Größe ändern

Code:

var resizeEventsTrigger = (function () {
    function triggerResizeStart($el) {
        $el.trigger('resizestart');
        isStart = !isStart;
    }

    function triggerResizeEnd($el) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function () {
            $el.trigger('resizeend');
            isStart = !isStart;
        }, delay);
    }

    var isStart = true;
    var delay = 200;
    var timeoutId;

    return function ($el) {
        isStart ? triggerResizeStart($el) : triggerResizeEnd($el);
    };

})();

$("#my").on('resizestart', function () {
    console.log('resize start');
});
$("#my").on('resizeend', function () {
    console.log('resize end');
});

window.onresize = function () {
    resizeEventsTrigger( $("#my") );
};
0
WebBrother

AKTUALISIEREN!

Eine bessere Alternative, die auch von mir erstellt wurde, ist hier: https://stackoverflow.com/a/23692008/28296 (unterstützt " Funktionen löschen ")

ORIGINAL POST:

Ich habe diese einfache Funktion für die Behandlung von Verzögerungen bei der Ausführung geschrieben, die in jQuery .scroll () und .resize () nützlich ist. Daher wird callback_f nur einmal für eine bestimmte ID-Zeichenfolge ausgeführt.

function delay_exec( id, wait_time, callback_f ){

    // IF WAIT TIME IS NOT ENTERED IN FUNCTION CALL,
    // SET IT TO DEFAULT VALUE: 0.5 SECOND
    if( typeof wait_time === "undefined" )
        wait_time = 500;

    // CREATE GLOBAL ARRAY(IF ITS NOT ALREADY CREATED)
    // WHERE WE STORE CURRENTLY RUNNING setTimeout() FUNCTION FOR THIS ID
    if( typeof window['delay_exec'] === "undefined" )
        window['delay_exec'] = [];

    // RESET CURRENTLY RUNNING setTimeout() FUNCTION FOR THIS ID,
    // SO IN THAT WAY WE ARE SURE THAT callback_f WILL RUN ONLY ONE TIME
    // ( ON LATEST CALL ON delay_exec FUNCTION WITH SAME ID  )
    if( typeof window['delay_exec'][id] !== "undefined" )
        clearTimeout( window['delay_exec'][id] );

    // SET NEW TIMEOUT AND EXECUTE callback_f WHEN wait_time EXPIRES,
    // BUT ONLY IF THERE ISNT ANY MORE FUTURE CALLS ( IN wait_time PERIOD )
    // TO delay_exec FUNCTION WITH SAME ID AS CURRENT ONE
    window['delay_exec'][id] = setTimeout( callback_f , wait_time );
}


// USAGE

jQuery(window).resize(function() {

    delay_exec('test1', 1000, function(){
        console.log('1st call to delay "test1" successfully executed!');
    });

    delay_exec('test1', 1000, function(){
        console.log('2nd call to delay "test1" successfully executed!');
    });

    delay_exec('test1', 1000, function(){
        console.log('3rd call to delay "test1" successfully executed!');
    });

    delay_exec('test2', 1000, function(){
        console.log('1st call to delay "test2" successfully executed!');
    });

    delay_exec('test3', 1000, function(){
        console.log('1st call to delay "test3" successfully executed!');
    });

});

/* RESULT
3rd call to delay "test1" successfully executed!
1st call to delay "test2" successfully executed!
1st call to delay "test3" successfully executed!
*/
0
var resizeTimer;
$( window ).resize(function() {
    if(resizeTimer){
        clearTimeout(resizeTimer);
    }
    resizeTimer = setTimeout(function() {
        //your code here
        resizeTimer = null;
        }, 200);
    });

Dies funktionierte für das, was ich in Chrom zu tun versuchte. Dadurch wird der Rückruf erst 200ms nach dem letzten Größenänderungsereignis ausgelöst.

0
frost287