Как определить изменение размера DIV?
У меня есть следующий пример html, есть DIV, который имеет 100% ширину. Он содержит некоторые элементы. При выполнении изменения размеров окон внутренние элементы могут быть перемещены, и размер div может измениться. Я спрашиваю, Можно ли подключить событие изменения размера div? и как это сделать? В настоящее время я привязываю функцию обратного вызова к событию изменения размера jQuery на целевом DIV, однако журнал консоли не выводится, см. ниже:


<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>
21 ответов:
существует очень эффективный метод, чтобы определить, если размер элемента был изменен.
http://marcj.github.io/css-element-queries/
эта библиотека имеет класс
ResizeSensorкоторый может быть использован для определения размера.
он использует событийный подход, так что это чертовски быстро и не тратит время процессора.пример:
new ResizeSensor(jQuery('#divId'), function(){ console.log('content dimension changed'); });пожалуйста, не используйте плагин jQuery onresize как он использует
setTimeout()цикл для проверки изменений.
ЭТО НЕВЕРОЯТНО МЕДЛЕННО И НЕ ТОЧНО.раскрытие: я непосредственно связан с этой библиотекой.
новым стандартом для этого является api Resize Observer, доступный в 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>Изменить Размер Обозреватель
Spec:https://wicg.github.io/ResizeObserver
полифилл:https://github.com/WICG/ResizeObserver/issues/3
проблема Firefox:https://bugzil.la/1272409
Проблема Safari: http://wkb.ug/157743
Поддержка: http://caniuse.com/#feat=resizeobserver
вы должны связать
resizeсобытиеwindowобъект, а не на общий элемент html.затем вы можете использовать это:
$(window).resize(function() { ... });и в функции обратного вызова вы можете проверить новые ширина
divвызов$('.a-selector').width();Итак, ответ на твой вопрос нет, вы не можете связать
resizeсобытие для div.
в долгосрочной перспективе, вы сможете использовать ResizeObserver.
new ResizeObserver(callback).observe(element);к сожалению, в настоящее время он не поддерживается по умолчанию во многих браузерах.
в то же время, вы можете использовать функцию, как показано ниже. Поскольку большинство изменений размера элемента будет происходить от изменения размера окна или от изменения чего-то в DOM. Вы можете слушать изменение размера окна с помощью окна изменение размера событие и вы можете прослушивать изменения DOM с помощью MutationObserver.
вот пример функции, которая будет вызывать вас обратно, когда размер предоставленного элемента изменяется в результате любого из этих событий:
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 }); };
взгляните на это http://benalman.com/code/projects/jquery-resize/examples/resize/
Он имеет различные примеры. Попробуйте изменить размер окна и посмотреть, как корректируются элементы внутри элементов контейнера.
пример с JS fiddle, чтобы объяснить, как заставить его работать.
Взгляните на эту скрипку http://jsfiddle.net/sgsqJ/4/в этом resize() событие привязано к элементам, имеющим класс "test" , а также для объекта window и в resize callback объекта window $('.тест").размер() называется.
например
$('#test_div').bind('resize', function(){ console.log('resized'); }); $(window).resize(function(){ $('#test_div').resize(); });
лучшим решением было бы использовать так называемые Элемент Запросов. Однако, они не стандартные, нет спецификация существует и единственный вариант-это использовать один из полифиллы/библиотеки, если вы хотите идти по этому пути.
идея запросов элементов заключается в том, чтобы позволить определенному контейнеру на странице отвечать на предоставленное ему пространство. Это позволит написать компонент один раз, а затем отбросить его в любом месте страницы, в то время как он будет настраивать его содержание к своему настоящему размеру. независимо от размера окна. Это первое различие, которое мы видим между поисковым элементом и медиа-запросы. Все надеются, что в какой-то момент будет создана спецификация, которая будет стандартизировать запросы элементов (или что-то, что достигает той же цели) и сделает их родными, чистыми, простыми и надежными. Большинство людей согласны с тем, что медиа-запросы довольно ограничены и не помогают для модульного проектирования и истинной отзывчивости.
там есть несколько полифилов / библиотек, которые решают проблему по-разному (можно было бы назвать обходные пути вместо решений, хотя):
- запросы элементов CSS -https://github.com/marcj/css-element-queries
- BoomQueries -https://github.com/BoomTownROI/boomqueries
- eq.js -https://github.com/Snugug/eq.js
- ElementQuery - https://github.com/tysonmatanich/elementQuery
- и еще несколько, которые я не собираюсь перечислять здесь, но вы можете свободно искать. Я бы не смог сказать, какой из доступных на данный момент вариантов является лучшим. Вам придется попробовать несколько и решить.
Я видел другие решения подобных проблем, предложенных. Обычно они используют таймеры или размер окна/видового экрана под капотом, что не является реальным решением. Кроме того, я думаю, что в идеале это должен решаться в основном в CSS, а не в javascript или html.
Я нашел эту библиотеку для работы, когда решение Марча не было:
https://github.com/sdecima/javascript-detect-element-resize
Он очень легкий и обнаруживает даже естественные размеры с помощью CSS или просто HTML-загрузки/рендеринга.
пример кода (взят из ссылки):
<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>
ResizeSensor.js-это огромная библиотека, но я уменьшаю ее до этой.
Puff:
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); };Как использовать:
let container = document.querySelector(".container"); new ResizeSensor(container, function() { console.log("dimension changed:", container.clientWidth, container.clientHeight); });
Я не рекомендую setTimeout() hack, как это замедляет производительность! Вместо этого, вы можете использовать наблюдатели мутации DOM для прослушивания изменения размера 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>вот скрипка https://jsfiddle.net/JerryGoyal/uep7nse1/
Попробуйте изменить размер div.
вы можете дополнительно обернуть свой метод в debounce метод для повышения эффективности.
debounceвызовет ваш метод за x миллисекунд вместо того, чтобы запускать каждый миллисекундный DIV изменяется.
можно использовать
iframeилиobjectиспользуяcontentWindowилиcontentDocumentна Изменить. БезsetIntervalилиsetTimeoutдействия:
- установите положение элемента в
relative- добавить внутри прозрачного абсолютного скрытого IFRAME
- слушать
IFRAME.contentWindow-onresizeсобытиепример 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>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') })запуск Пример
JsFiddle: https://jsfiddle.net/qq8p470d/
Посмотреть подробнее:
- глина на основе
element-resize-event- element-resize-event
только объект window генерирует событие "resize". Единственный способ, который я знаю, чтобы сделать то, что вы хотите сделать, это запустить интервальный таймер, который периодически проверяет размер.
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>
С Помощью Глины.js (https://github.com/zzarcon/clay) это довольно просто обнаружить изменения на размер элемента:
var el = new Clay('.element'); el.on('resize', function(size) { console.log(size.height, size.width); });
это сообщение в блоге помогло мне эффективно обнаруживать изменения размера элементов DOM.
http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/
Как использовать этот код...
AppConfig.addResizeListener(document.getElementById('id'), function () { //Your code to execute on resize. });упакованный код, используемый в Примере...
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__); } } } })();Примечание: AppConfig-это пространство имен / объект, который я использую для организации многоразовых функций. Не стесняйтесь искать и заменять имя на что угодно как.
мой плагин jQuery включает событие "resize" для всех элементов, а не только для
window.https://github.com/dustinpoissant/ResizeTriggering
$("#myElement") .resizeTriggering().on("resize", function(e){ // Code to handle resize });
вы можете попробовать код в следующем фрагменте, он охватывает ваши потребности с помощью простого javascript. (запустите фрагмент кода и нажмите на ссылку полная страница, чтобы вызвать предупреждение о том, что div изменяется, если вы хотите его проверить.).
исходя из того, что это
setIntervalиз 100 миллисекунд я бы осмелился сказать, что мой компьютер не нашел его слишком голодным. (0,1% CPU было использовано в качестве общего количества для всех открытых вкладок в Chrome на момент тестирования.). Но опять же это это только для одного div, если вы хотите сделать это для большого количества элементов, то да, это может быть очень голодный процессор.вы всегда можете использовать событие щелчка, чтобы остановить div-resize шмыг в любом случае.
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>вы можете проверить скрипка и
обновление
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>обновление Скрипка
это в значительной степени точная копия верхнего ответа, но вместо ссылки, это просто часть кода, которая имеет значение, переведенная, чтобы быть более читаемой и понятной ИМО. Несколько других небольших изменений включают использование cloneNode (), а не помещать html в строку js. Мелочи, но вы можете скопировать и вставить это как есть, и это будет работать.
способ его работы заключается в том, что два невидимых дива заполняют элемент, который вы смотрите, а затем помещают триггер в каждый, и установка положения прокрутки, которое приведет к запуску изменения прокрутки при изменении размера.
все реальные кредиты идут к Марку J, но если вы просто ищете соответствующий код, вот он:
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); }
Я думал, что это невозможно сделать, но потом я подумал об этом, вы можете вручную изменить размер div через style="resize: both;" для того, чтобы сделать это, вы должны нажать на него, поэтому добавили функцию onclick для проверки высоты и ширины элемента, и это сработало. Только с 5 строками чистого javascript (конечно, это может быть еще короче) 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); });
С помощью Бхарат Патил ответ просто возвращает false внутри вашего обратного вызова привязки, чтобы предотвратить максимальную ошибку стека см. пример ниже:
$('#test_div').bind('resize', function(){ console.log('resized'); return false; });
только
Window.onResizeсуществует в спецификации, но вы всегда можете использоватьIFrameсоздать новыйWindowобъект внутри вашего DIV.пожалуйста, проверьте это ответ. Есть новый маленький плагин jquery, это портативный и простой в использовании. Вы всегда можете проверить исходный код, чтобы увидеть, как это делается.
<!-- (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... }
Comments