534 Stimmen

Wie lässt sich eine Änderung der DIV-Dimension erkennen?

Ich habe die folgende Beispiel-HTML, gibt es eine DIV, die 100% Breite hat. Es enthält einige Elemente. Bei der Größenänderung von Windows können die inneren Elemente neu positioniert werden, und die Größe des DIVs kann sich ändern. Ich frage, ob es möglich ist, die div's Dimension Änderung Ereignis Haken? und wie man das tun? Ich binde derzeit die Callback-Funktion an das jQuery-Resize-Ereignis auf dem Ziel-DIV, jedoch wird kein Konsolenprotokoll ausgegeben, siehe unten:

Before Resize enter image description here

<html>
<head>
    <script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
    <script type="text/javascript" language="javascript">
            $('#test_div').bind('resize', function(){
                console.log('resized');
            });
    </script>
</head>
<body>
    <div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
        <input type="button" value="button 1" />
        <input type="button" value="button 2" />
        <input type="button" value="button 3" />
    </div>
</body>
</html>

638voto

Daniel Herr Punkte 17315

Ein neuerer Standard hierfür ist die Resize Observer api, mit guter Browserunterstützung.

function outputsize() {
 width.value = textbox.offsetWidth
 height.value = textbox.offsetHeight
}
outputsize()

new ResizeObserver(outputsize).observe(textbox)

Width: <output id="width">0</output><br>
Height: <output id="height">0</output><br>
<textarea id="textbox">Resize me</textarea><br>

Größe des Beobachters ändern

Dokumentation: https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API

Spez: https://wicg.github.io/ResizeObserver

Aktuelle Unterstützung: http://caniuse.com/#feat=resizeobserver

Polyfills: https://github.com/pelotoncycle/resize-observer https://github.com/que-etc/resize-observer-polyfill https://github.com/juggle/resize-observer

297voto

Marc J. Schmidt Punkte 8082

Es gibt eine sehr effiziente Methode, um festzustellen, ob die Größe eines Elements geändert wurde.

http://marcj.github.io/css-element-queries/

Diese Bibliothek hat eine Klasse ResizeSensor die zur Erkennung der Größenänderung verwendet werden kann.
Es verwendet einen ereignisbasierten Ansatz, ist also verdammt schnell und verschwendet keine CPU-Zeit.

Beispiel:

new ResizeSensor(jQuery('#divId'), function(){ 
    console.log('content dimension changed');
});

Bitte verwenden Sie nicht die jQuery onresize plugin denn es verwendet setTimeout() in Kombination mit dem Lesen des DOM clientHeight / clientWidth Eigenschaften in einer Schleife, um auf Änderungen zu prüfen.
Das ist unglaublich langsam und ungenau denn sie verursacht Layout-Durchforstung .

Offenlegung: Ich bin direkt mit dieser Bibliothek verbunden.

58voto

nkron Punkte 17828

Langfristig werden Sie die Möglichkeit haben, die ResizeObserver .

new ResizeObserver(callback).observe(element);

Leider wird sie derzeit von vielen Browsern nicht standardmäßig unterstützt.

In der Zwischenzeit können Sie eine Funktion wie die folgende verwenden. Da die meisten Änderungen der Elementgröße von der Größenänderung des Fensters oder von Änderungen im DOM kommen. Sie können auf die Größenänderung des Fensters mit der Funktion Größe ändern Ereignis und Sie können auf DOM-Änderungen hören, indem Sie MutationObserver .

Hier ist ein Beispiel für eine Funktion, die Sie zurückruft, wenn sich die Größe des bereitgestellten Elements aufgrund eines dieser Ereignisse ändert:

var onResize = function(element, callback) {
  if (!onResize.watchedElementData) {
    // First time we are called, create a list of watched elements
    // and hook up the event listeners.
    onResize.watchedElementData = [];

    var checkForChanges = function() {
      onResize.watchedElementData.forEach(function(data) {
        if (data.element.offsetWidth !== data.offsetWidth ||
            data.element.offsetHeight !== data.offsetHeight) {
          data.offsetWidth = data.element.offsetWidth;
          data.offsetHeight = data.element.offsetHeight;
          data.callback();
        }
      });
    };

    // Listen to the window's size changes
    window.addEventListener('resize', checkForChanges);

    // Listen to changes on the elements in the page that affect layout 
    var observer = new MutationObserver(checkForChanges);
    observer.observe(document.body, { 
      attributes: true,
      childList: true,
      characterData: true,
      subtree: true 
    });
  }

  // Save the element we are watching
  onResize.watchedElementData.push({
    element: element,
    offsetWidth: element.offsetWidth,
    offsetHeight: element.offsetHeight,
    callback: callback
  });
};

54voto

GorvGoyl Punkte 32029

Ich empfehle NICHT setTimeout() hacken, da es die Leistung verlangsamt! Stattdessen können Sie DOM ResizeObserver Methode zum Abhören von Div-Größenänderungen.

const myObserver = new ResizeObserver(entries => {
 // this will get called whenever div dimension changes
  entries.forEach(entry => {
    console.log('width', entry.contentRect.width);
    console.log('height', entry.contentRect.height);
  });
});

const someEl = document.querySelector('.some-element');

// start listening to changes
myObserver.observe(someEl);

// later, stop listening to changes
myObserver.disconnect();

Alte Antwort mit MutationObserver :

Zum Abhören von HTML-Elementattributen, Teilbaum- und Klassenänderungen:

JS:

    var observer = new MutationObserver(function(mutations) {
        console.log('size changed!');
      });
      var target = document.querySelector('.mydiv');
      observer.observe(target, {
        attributes: true,
        childList: true,
        subtree: true
      });

HTML:

    <div class='mydiv'>
    </div>

Hier ist die fiddle.. Versuchen Sie, die Div-Größe zu ändern.


Sie können Ihre Methode weiter in die debounce Methode zur Verbesserung der Effizienz. debounce wird Ihre Methode alle x Millisekunden auslösen, anstatt jede Millisekunde, in der die Größe des DIVs geändert wird.

38voto

Martin Wantke Punkte 3753

ResizeSensor.js ist Teil einer großen Bibliothek, aber ich habe seine Funktionalität auf DIESE :

function ResizeSensor(element, callback)
{
    let zIndex = parseInt(getComputedStyle(element));
    if(isNaN(zIndex)) { zIndex = 0; };
    zIndex--;

    let expand = document.createElement('div');
    expand.style.position = "absolute";
    expand.style.left = "0px";
    expand.style.top = "0px";
    expand.style.right = "0px";
    expand.style.bottom = "0px";
    expand.style.overflow = "hidden";
    expand.style.zIndex = zIndex;
    expand.style.visibility = "hidden";

    let expandChild = document.createElement('div');
    expandChild.style.position = "absolute";
    expandChild.style.left = "0px";
    expandChild.style.top = "0px";
    expandChild.style.width = "10000000px";
    expandChild.style.height = "10000000px";
    expand.appendChild(expandChild);

    let shrink = document.createElement('div');
    shrink.style.position = "absolute";
    shrink.style.left = "0px";
    shrink.style.top = "0px";
    shrink.style.right = "0px";
    shrink.style.bottom = "0px";
    shrink.style.overflow = "hidden";
    shrink.style.zIndex = zIndex;
    shrink.style.visibility = "hidden";

    let shrinkChild = document.createElement('div');
    shrinkChild.style.position = "absolute";
    shrinkChild.style.left = "0px";
    shrinkChild.style.top = "0px";
    shrinkChild.style.width = "200%";
    shrinkChild.style.height = "200%";
    shrink.appendChild(shrinkChild);

    element.appendChild(expand);
    element.appendChild(shrink);

    function setScroll()
    {
        expand.scrollLeft = 10000000;
        expand.scrollTop = 10000000;

        shrink.scrollLeft = 10000000;
        shrink.scrollTop = 10000000;
    };
    setScroll();

    let size = element.getBoundingClientRect();

    let currentWidth = size.width;
    let currentHeight = size.height;

    let onScroll = function()
    {
        let size = element.getBoundingClientRect();

        let newWidth = size.width;
        let newHeight = size.height;

        if(newWidth != currentWidth || newHeight != currentHeight)
        {
            currentWidth = newWidth;
            currentHeight = newHeight;

            callback();
        }

        setScroll();
    };

    expand.addEventListener('scroll', onScroll);
    shrink.addEventListener('scroll', onScroll);
};

Wie man es benutzt:

let container = document.querySelector(".container");
new ResizeSensor(container, function()
{
    console.log("dimension changed:", container.clientWidth, container.clientHeight);
});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X