resizesensor resizeobserver event ejemplo div javascript jquery html

javascript - resizeobserver - ¿Cómo detectar la dimensión de DIV cambiada?



resize js (21)

Tengo el siguiente html de muestra, hay un DIV que tiene 100% de ancho. Contiene algunos elementos. Mientras se realiza el cambio de tamaño de las ventanas, los elementos internos pueden reubicarse y la dimensión del div puede cambiar. Estoy preguntando si es posible enganchar el evento de cambio de dimensión del div? ¿y como hacer eso? Actualmente vinculo la función de devolución de llamada al evento de cambio de tamaño jQuery en el DIV de destino, sin embargo, no se genera ningún registro de consola, consulte a continuación:

<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>


¡NO recomiendo hackear setTimeout () ya que ralentiza el rendimiento! En su lugar, puede usar observadores de mutación DOM para escuchar el cambio de tamaño de Div.

JS:

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

HTML:

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

Aquí está el violín https://jsfiddle.net/JerryGoyal/uep7nse1/
Intenta cambiar el tamaño de div.

Puede ajustar aún más su método en el método de debounce para mejorar la eficiencia. debounce desencadenará su método por x milisegundos en lugar de desencadenar cada milisegundos que se está redimensionando el DIV.


A largo plazo, podrá utilizar el https://wicg.github.io/ResizeObserver .

new ResizeObserver(callback).observe(element);

Desafortunadamente, actualmente no está soportado por defecto en muchos navegadores.

Mientras tanto, puedes usar una función como la siguiente. Desde entonces, la mayoría de los cambios en el tamaño del elemento provendrán del cambio de tamaño de la ventana o de cambiar algo en el DOM. Puede escuchar el cambio de tamaño de la ventana con el evento de cambio de tamaño de la ventana y puede escuchar los cambios de DOM usando MutationObserver .

Este es un ejemplo de una función que le devolverá la llamada cuando el tamaño del elemento proporcionado cambie como resultado de cualquiera de esos eventos:

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


Debe vincular el evento de cambio de resize en el objeto de la window , no en un elemento html genérico.

Entonces podrías usar esto:

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

y dentro de la función de devolución de llamada puede verificar el nuevo ancho de su llamada div

$(''.a-selector'').width();

Entonces, la respuesta a su pregunta es no , no puede vincular el evento de cambio de resize a un div.


Eche un vistazo a este http://benalman.com/code/projects/jquery-resize/examples/resize/

Tiene varios ejemplos. Intente redimensionar su ventana y ver cómo se ajustan los elementos dentro de los elementos del contenedor.

Ejemplo con js fiddle para explicar cómo hacer que funcione.
Echa un vistazo a este violín http://jsfiddle.net/sgsqJ/4/

En ese evento resize (), el evento está vinculado a un elemento que tiene la clase "prueba" y también al objeto de ventana y en la devolución de llamada de cambio de tamaño del objeto de ventana $ (''. Test''). Se llama a resize ().

p.ej

$(''#test_div'').bind(''resize'', function(){ console.log(''resized''); }); $(window).resize(function(){ $(''#test_div'').resize(); });


Encontré esta biblioteca para trabajar cuando la solución de MarcJ no:

https://github.com/sdecima/javascript-detect-element-resize

Es muy ligero y detecta incluso tamaños naturales a través de CSS o simplemente la carga / renderización de HTML.

Ejemplo de código (tomado del enlace):

<script type="text/javascript" src="detect-element-resize.js"></script> <script type="text/javascript"> var resizeElement = document.getElementById(''resizeElement''), resizeCallback = function() { /* do something */ }; addResizeListener(resizeElement, resizeCallback); removeResizeListener(resizeElement, resizeCallback); </script>


Esta publicación del blog me ayudó a detectar de manera eficiente los cambios de tamaño en los elementos DOM.

http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/

Cómo usar este código ...

AppConfig.addResizeListener(document.getElementById(''id''), function () { //Your code to execute on resize. });

Código empaquetado utilizado por el ejemplo ...

var AppConfig = AppConfig || {}; AppConfig.ResizeListener = (function () { var attachEvent = document.attachEvent; var isIE = navigator.userAgent.match(/Trident/); var requestFrame = (function () { var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || function (fn) { return window.setTimeout(fn, 20); }; return function (fn) { return raf(fn); }; })(); var cancelFrame = (function () { var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.clearTimeout; return function (id) { return cancel(id); }; })(); function resizeListener(e) { var win = e.target || e.srcElement; if (win.__resizeRAF__) cancelFrame(win.__resizeRAF__); win.__resizeRAF__ = requestFrame(function () { var trigger = win.__resizeTrigger__; trigger.__resizeListeners__.forEach(function (fn) { fn.call(trigger, e); }); }); } function objectLoad(e) { this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__; this.contentDocument.defaultView.addEventListener(''resize'', resizeListener); } AppConfig.addResizeListener = function (element, fn) { if (!element.__resizeListeners__) { element.__resizeListeners__ = []; if (attachEvent) { element.__resizeTrigger__ = element; element.attachEvent(''onresize'', resizeListener); } else { if (getComputedStyle(element).position === ''static'') element.style.position = ''relative''; var obj = element.__resizeTrigger__ = document.createElement(''object''); obj.setAttribute(''style'', ''display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;''); obj.__resizeElement__ = element; obj.onload = objectLoad; obj.type = ''text/html''; if (isIE) element.appendChild(obj); obj.data = ''about:blank''; if (!isIE) element.appendChild(obj); } } element.__resizeListeners__.push(fn); }; AppConfig.removeResizeListener = function (element, fn) { element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); if (!element.__resizeListeners__.length) { if (attachEvent) element.detachEvent(''onresize'', resizeListener); else { element.__resizeTrigger__.contentDocument.defaultView.removeEventListener(''resize'', resizeListener); element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__); } } } })();

Nota: AppConfig es un espacio de nombres / objeto que utilizo para organizar funciones reutilizables. Siéntase libre de buscar y reemplazar el nombre con cualquier cosa que desee.


Esto es prácticamente una copia exacta de la respuesta principal, pero en lugar de un enlace, es solo la parte del código lo que importa, traducido a IMO más legible y más fácil de entender. Algunos otros pequeños cambios incluyen el uso de cloneNode (), y no poner html en una cadena js. Cosas pequeñas, pero puedes copiar y pegar esto como está y funcionará.

La forma en que funciona es haciendo que dos divs invisibles llenen el elemento que está viendo, y luego colocando un disparador en cada uno, y estableciendo una posición de desplazamiento que llevará a un cambio de desplazamiento si el tamaño cambia.

Todo el crédito real está para Marc J, pero si solo está buscando el código relevante, aquí está:

window.El = {} El.resizeSensorNode = undefined; El.initResizeNode = function() { var fillParent = "display: block; position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;"; var triggerStyle = "position: absolute; left: 0; top: 0; transition: 0s;"; var resizeSensor = El.resizeSensorNode = document.createElement("resizeSensor"); resizeSensor.style = fillParent; var expandSensor = document.createElement("div"); expandSensor.style = fillParent; resizeSensor.appendChild(expandSensor); var trigger = document.createElement("div"); trigger.style = triggerStyle; expandSensor.appendChild(trigger); var shrinkSensor = expandSensor.cloneNode(true); shrinkSensor.firstChild.style = triggerStyle + " width: 200%; height: 200%"; resizeSensor.appendChild(shrinkSensor); } El.onSizeChange = function(domNode, fn) { if (!domNode) return; if (domNode.resizeListeners) { domNode.resizeListeners.push(fn); return; } domNode.resizeListeners = []; domNode.resizeListeners.push(fn); if(El.resizeSensorNode == undefined) El.initResizeNode(); domNode.resizeSensor = El.resizeSensorNode.cloneNode(true); domNode.appendChild(domNode.resizeSensor); var expand = domNode.resizeSensor.firstChild; var expandTrigger = expand.firstChild; var shrink = domNode.resizeSensor.childNodes[1]; var reset = function() { expandTrigger.style.width = ''100000px''; expandTrigger.style.height = ''100000px''; expand.scrollLeft = 100000; expand.scrollTop = 100000; shrink.scrollLeft = 100000; shrink.scrollTop = 100000; }; reset(); var hasChanged, frameRequest, newWidth, newHeight; var lastWidth = domNode.offsetWidth; var lastHeight = domNode.offsetHeight; var onResized = function() { frameRequest = undefined; if (!hasChanged) return; lastWidth = newWidth; lastHeight = newHeight; var listeners = domNode.resizeListeners; for(var i = 0; listeners && i < listeners.length; i++) listeners[i](); }; var onScroll = function() { newWidth = domNode.offsetWidth; newHeight = domNode.offsetHeight; hasChanged = newWidth != lastWidth || newHeight != lastHeight; if (hasChanged && !frameRequest) { frameRequest = requestAnimationFrame(onResized); } reset(); }; expand.addEventListener("scroll", onScroll); shrink.addEventListener("scroll", onScroll); }


Existe un método muy eficiente para determinar si se ha cambiado el tamaño de un elemento.

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

Esta biblioteca tiene una clase ResizeSensor que se puede usar para la detección de cambio de tamaño.
Utiliza un enfoque basado en eventos, por lo que es muy rápido y no pierde tiempo de CPU.

Ejemplo:

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

Por favor, no use el complemento jQuery onresize ya que usa el bucle setTimeout() para verificar los cambios.
Esto es increíblemente lento y no es preciso .

Divulgación: Estoy directamente asociado con esta biblioteca.


La mejor solución sería utilizar las llamadas consultas de elementos . Sin embargo, no son estándar, no existe ninguna especificación, y la única opción es usar uno de los polyfills / bibliotecas disponibles, si quiere ir de esta manera.

La idea detrás de las consultas de elementos es permitir que un determinado contenedor en la página responda al espacio que se le proporciona. Esto permitirá escribir un componente una vez y luego soltarlo en cualquier lugar de la página, mientras que ajustará su contenido a su tamaño actual. No importa cuál sea el tamaño de la ventana. Esta es la primera diferencia que vemos entre consultas de elementos y consultas de medios. Todos esperan que en algún momento se cree una especificación que estandarice las consultas de elementos (o algo que logre el mismo objetivo) y las haga nativas, limpias, simples y sólidas. La mayoría de las personas están de acuerdo en que las consultas de medios son bastante limitadas y no ayudan para el diseño modular y la verdadera capacidad de respuesta.

Hay algunos polyfills / bibliotecas que resuelven el problema de diferentes maneras (podrían llamarse soluciones en lugar de soluciones):

He visto otras soluciones a problemas similares propuestos. Por lo general, utilizan temporizadores o el tamaño de ventana / ventana gráfica debajo del capó, lo que no es una solución real. Además, creo que idealmente esto debería resolverse principalmente en CSS, y no en javascript o html.



Puede probar el código en el siguiente fragmento de código, que cubre sus necesidades usando javascript sin formato. ( ejecute el fragmento de código y haga clic en el enlace de página completa para activar la alerta de que el div está redimensionado si desea probarlo ).

Basado en el hecho de que este es un setInterval de 100 milisegundos, me atrevería a decir que mi PC no lo encontró con demasiada CPU. (El 0,1% de la CPU se usó como total para todas las pestañas abiertas en Chrome en el momento del análisis). Pero, de nuevo, esto es solo para un div, si desea hacer esto para una gran cantidad de elementos, entonces sí, podría estar muy saturado de CPU.

Siempre se puede usar un evento de clic para detener el rastreo del cambio de tamaño de todos modos.

var width = 0; var interval = setInterval(function(){ if(width <= 0){ width = document.getElementById("test_div").clientWidth; } if(document.getElementById("test_div").clientWidth!==width) { alert(''resized div''); width = document.getElementById("test_div").clientWidth; } }, 100);

<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>

También puedes consultar el fiddle

ACTUALIZAR

var width = 0; function myInterval() { var interval = setInterval(function(){ if(width <= 0){ width = document.getElementById("test_div").clientWidth; } if(document.getElementById("test_div").clientWidth!==width) { alert(''resized''); width = document.getElementById("test_div").clientWidth; } }, 100); return interval; } var interval = myInterval(); document.getElementById("clickMe").addEventListener( "click" , function() { if(typeof interval!=="undefined") { clearInterval(interval); alert("stopped div-resize sniffing"); } }); document.getElementById("clickMeToo").addEventListener( "click" , function() { myInterval(); alert("started div-resize sniffing"); });

<div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;"> <input type="button" value="button 1" id="clickMe" /> <input type="button" value="button 2" id="clickMeToo" /> <input type="button" value="button 3" /> </div>

Fiddle actualizado


Puede usar iframe u object usando contentWindow o contentDocument en el contentDocument de tamaño. Sin setInterval o setTimeout

Los pasos:

  1. Establezca la posición de su elemento en relative
  2. Añadir dentro de un IFRAME oculto absoluto transparente
  3. Escuche IFRAME.contentWindow - evento onresize

Un ejemplo de HTML:

<div style="height:50px;background-color:red;position:relative;border:1px solid red"> <iframe style=width:100%;height:100%;position:absolute;border:none;background-color:transparent allowtransparency=true> </iframe> This is my div </div>

El Javascript:

$(''div'').width(100).height(100); $(''div'').animate({width:200},2000); $(''object'').attr({ type : ''text/html'' }) $(''object'').on(''resize,onresize,load,onload'',function(){ console.log(''ooooooooonload'') }) $($(''iframe'')[0].contentWindow).on(''resize'',function(){ console.log(''div changed'') })

Ejemplo de ejecución

JsFiddle: https://jsfiddle.net/qq8p470d/

Ver más:


ResizeSensor.js es una enorme biblioteca, pero la reduzco a ESTO .

Soplo:

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

Cómo usarlo:

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


Sólo el objeto de la ventana genera un evento de "cambio de tamaño". La única forma que conozco de hacer lo que quiere hacer es ejecutar un temporizador de intervalos que verifique periódicamente el tamaño.


Solo Window.onResize existe en la especificación, pero siempre puede utilizar IFrame para generar un nuevo objeto de Window dentro de su DIV.

Por favor, compruebe esta answer . Hay un nuevo pequeño plugin de jquery , que es portátil y fácil de usar. Siempre puedes consultar el código fuente para ver cómo se hace.

<!-- (1) include plugin script in a page --> <script src="/src/jquery-element-onresize.js"></script> // (2) use the detectResizing plugin to monitor changes to the element''s size: $monitoredElement.detectResizing({ onResize: monitoredElement_onResize }); // (3) write a function to react on changes: function monitoredElement_onResize() { // logic here... }


Un nuevo estándar para esto es la api Resize Observer, disponible en Chrome 64.

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>

Cambiar el tamaño de observador

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

Polyfills: https://github.com/WICG/ResizeObserver/issues/3

Problema de Firefox: https://bugzil.la/1272409

Número de Safari: http://wkb.ug/157743

Soporte actual: http://caniuse.com/#feat=resizeobserver


Usando Clay.js ( https://github.com/zzarcon/clay ) es bastante simple detectar cambios en el tamaño del elemento:

var el = new Clay(''.element''); el.on(''resize'', function(size) { console.log(size.height, size.width); });


usando la respuesta de Bharat Patil simplemente devuelva falso dentro de su devolución de llamada de enlace para evitar el máximo error de pila, vea el ejemplo a continuación:

$(''#test_div'').bind(''resize'', function(){ console.log(''resized''); return false; });


var div = document.getElementById(''div''); div.addEventListener(''resize'', (event) => console.log(event.detail)); function checkResize (mutations) { var el = mutations[0].target; var w = el.clientWidth; var h = el.clientHeight; var isChange = mutations .map((m) => m.oldValue + '''') .some((prev) => prev.indexOf(''width: '' + w + ''px'') == -1 || prev.indexOf(''height: '' + h + ''px'') == -1); if (!isChange) return; var event = new CustomEvent(''resize'', {detail: {width: w, height: h}}); el.dispatchEvent(event); } var observer = new MutationObserver(checkResize); observer.observe(div, {attributes: true, attributeOldValue: true, attributeFilter: [''style'']});

#div {width: 100px; border: 1px solid #bbb; resize: both; overflow: hidden;}

<div id = "div">DIV</div>


Pensé que no se podía hacer, pero luego pensé en eso, puedes redimensionar manualmente un div mediante style = "resize: both;" para hacer eso, debe hacer clic en él, así que agregó una función onclick para verificar la altura y el ancho del elemento y funcionó. Con solo 5 líneas de javascript puro (seguro que podría ser incluso más corto) http://codepen.io/anon/pen/eNyyVN

<div id="box" style=" height:200px; width:640px; background-color:#FF0066; resize: both; overflow: auto;" onclick="myFunction()"> <p id="sizeTXT" style=" font-size: 50px;"> WxH </p> </div> <p>This my example demonstrates how to run a resize check on click for resizable div.</p> <p>Try to resize the box.</p> <script> function myFunction() { var boxheight = document.getElementById(''box'').offsetHeight; var boxhwidth = document.getElementById(''box'').offsetWidth; var txt = boxhwidth +"x"+boxheight; document.getElementById("sizeTXT").innerHTML = txt; } </script>


jQuery(document).ready( function($) { function resizeMapDIVs() { // check the parent value... var size = $(''#map'').parent().width(); if( $size < 640 ) { // ...and decrease... } else { // ..or increase as necessary } } resizeMapDIVs(); $(window).resize(resizeMapDIVs); });