определить, изменяется ли элемент в IE [дубликат]

Вы можете обойти это, заменив объект (и, следовательно, связать область):

def foo(a=[]):
    a = list(a)
    a.append(5)
    return a

Ужасно, но он работает.

256
задан William Choi 27 June 2011 в 13:13
поделиться

21 ответ

Существует очень эффективный метод определения того, был ли изменен размер элемента.

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

Эта библиотека имеет класс ResizeSensor, который может использоваться для определения размера.

Пример:

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

Пожалуйста, не используйте плагин jQuery onresize, , поскольку для проверки изменений используется цикл setTimeout(). ЭТО НЕВЕРОЯТНО МЕДЛЕННО И НЕ ТОЧНО.

Раскрытие: Я непосредственно связан с этой библиотекой.

200
ответ дан Hakam Fostok 21 August 2018 в 22:34
поделиться
  • 1
    @jake, поддержка IE11 теперь реализована. – Marc J. Schmidt 8 September 2014 в 13:25
  • 2
    @Aletheios вам следует поближе посмотреть. requestAnimationFrame не предназначен для обнаружения медленных измерений, а наоборот: он сглаживает все экстремальные числа событий, которые запускаются датчиком изменения размера реального события, чтобы сохранить время процессора. См. Обновленные документы в github.com/marcj/css-element-queries/blob/master/src/… – Marc J. Schmidt 17 March 2016 в 18:41
  • 3
    @Aletheios Я думаю, вы пропустите точку: setTimeout не только неточен, но и медленен, как черт. RequestAnimationFrame, который проверяет наличие простого логического порядка на порядок быстрее, чем setTimeout, все время проверяя свойства DOM. Кроме того, setTimeout также вызывается каждые несколько миллисекунд. – Marc J. Schmidt 17 March 2016 в 20:38
  • 4
    @ Оверлофил, вы, очевидно, ничего не поняли. Остановите downvoting ответы, где вы не знаете, как это работает внутри страны. Опять же: css-element-query: использует событие реального изменения размера, которое запускается каждый раз при изменении измерения. Так как вы получили слишком много событий (например, для drag'n'drop), он добавил проверку requestAnimationFrame для простой логической переменной, чтобы сгладить эти инициированные события до 1 / кадра. Плагин jquery: использует setTimeout, проверяя все время реквизита макета DOM (clientHeight и т. д.), где каждая проверка выполняется очень медленно, но часто нужно проверять, чтобы иметь такую ​​же функциональность. – Marc J. Schmidt 27 September 2016 в 14:01
  • 5
    @Aletheios, @Orwellophile и все, кто мог их ввести в заблуждение: requestAnimationFrame vs setTimeout не имеет значения, эта библиотека не зацикливается . requestAnimationFrame используется только для дебюта / дроссельной частоты вызова ваших обратных вызовов, не выполняет опрос . В отличие от этого, MutationObserver теоретически может использоваться для подобного эффекта, но не в старых браузерах. Это выдающийся ум. – Han Seoul-Oh 26 April 2017 в 02:29

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>

5
ответ дан Aikon Mogwai 21 August 2018 в 22:34
поделиться

Вы должны привязать событие resize к объекту window, а не к общему элементу html.

Затем вы можете использовать это:

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

и в функции обратного вызова вы можете проверить новую ширину вашего div вызова

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

Итак, ответ на ваш вопрос - нет, вы не можете связать событие resize с div.

38
ответ дан Alessandro Vendruscolo 21 August 2018 в 22:34
поделиться
  • 1
    @anu Нет, есть много способов изменить размер div ... – Roman Starkov 5 October 2013 в 13:31
  • 2
    этот ответ не достаточно хорош. изменения размера могут происходить без изменения размера окна. вообще. – vsync 16 March 2014 в 02:02
  • 3
    например, когда у вас есть элемент сплиттера или просто добавьте какой-либо текст или другой контент в элемент. – Günter Zöchbauer 3 May 2014 в 18:02
  • 4
    @anu неправда, вы можете иметь, например, модификацию DOM через javascript, заставляя CSS применять к новой структуре, что приводит к разному размеру макета каждого контейнера. – Antoniossss 17 January 2018 в 14:30

Вы можете использовать iframe или object, используя contentWindow или contentDocument при изменении размера. Без setInterval или setTimeout

Этапы:

  1. Установите позицию вашего элемента на relative
  2. Добавьте внутри прозрачного абсолютного скрытого IFRAME
  3. Слушайте 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/


Подробнее:

7
ответ дан Aminadav Glickshtein 21 August 2018 в 22:34
поделиться
  • 1
    Примечание для тех, кто не использует jquery, IFRAME.contentWindow недоступен до тех пор, пока событие if onload не загорится. Кроме того, вы можете добавить стиль visibility:hidden;, так как iframe может блокировать ввод мыши в элементы, расположенные за ним (по-видимому, «IE» по крайней мере). – James Wilkins 16 June 2016 в 05:00
  • 2
    Хотя это и работает, это тяжелое решение с накладными расходами на создание целого нового контекста просмотра, чтобы наблюдать за изменением размера. Кроме того, в некоторых случаях нецелесообразно или невозможно изменить свойство display элемента. – trusktr 6 August 2016 в 07:05
  • 3
    согласился, это ужасное решение, как указано выше – 29er 15 November 2016 в 20:20
  • 4
    Как написано так страшное решение? – Aminadav Glickshtein 15 November 2016 в 20:47

Взгляните на это http://benalman.com/code/projects/jquery-resize/examples/resize/

Он имеет различные примеры. Попробуйте изменить размер окна и посмотреть, как отрегулированы элементы внутри элементов контейнера.

Пример с js скриптом, чтобы объяснить, как заставить его работать. Взгляните на эту скрипту http://jsfiddle.net/sgsqJ/4/

В том, что событие resize () связано с элементами, имеющими класс «test», а также к объекту window и изменению размера объекта окна $ ('. test'). Вызывается resize ().

, например

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

$(window).resize(function(){
   $('#test_div').resize();
});
14
ответ дан Bharat Patil 21 August 2018 в 22:34
поделиться
  • 1
    Интересно. Этот jsfiddle постоянно сбой хром с открытым инспектором, и я нажимаю кнопку «Добавить текст». ссылка. Firefox бросает «слишком много рекурсии». ошибки. – Dwayne 22 September 2013 в 18:58
  • 2
    Не используйте плагин resize jQuery. Это очень медленно и неточно. См. Мой ответ, чтобы получить лучшее решение. – Marc J. Schmidt 17 October 2013 в 05:03
  • 3
    Это НЕ напрямую определяет изменения размеров. это просто побочный продукт прослушивателя событий изменения размера. изменения измерения могут произойти многими другими способами. – vsync 16 March 2014 в 02:04
  • 4
    Что делать, если размер div зависит от изменения стиля или dom, а не от изменения размера окна? – awe 10 April 2015 в 11:46

В спецификации существует только 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...
}
-1
ответ дан Community 21 August 2018 в 22:34
поделиться
  • 1
    Это очень неэффективное решение, если у вас есть изменяемые div. – suricactus 12 November 2015 в 16:04

Новый стандарт для этого - Resize Observer api, доступный в 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>

Resize Observer

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

90
ответ дан Daniel Herr 21 August 2018 в 22:34
поделиться
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);

});
0
ответ дан Fábio Zangirolami 21 August 2018 в 22:34
поделиться

Я НЕ рекомендую взломать setTimeout (), поскольку это замедляет производительность! Вместо этого вы можете использовать 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.

7
ответ дан JerryGoyal 21 August 2018 в 22:34
поделиться
  • 1
    Единственная проблема с этим заключается в том, что он не сообщает об изменении, если на элемент не происходит мутация. Если элемент изменяет размер из-за добавления других элементов, это не сработает. – Tony K. 13 April 2018 в 20:40

Я нашел, что эта библиотека работает, когда решение MarcJ не выполнило:

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>
13
ответ дан joshcomley 21 August 2018 в 22:34
поделиться
  • 1
    Это оно. 147 строк, использует события прокрутки. Прочтите этот код, если вы хотите получить полный и верный ответ о том, как лучше всего определять изменения размера div. Подсказка: это не «просто использовать эту библиотеку». – Seph Reed 30 October 2016 в 21:22
  • 2
    Люди должны взглянуть на эту проблему , прежде чем попробовать эту библиотеку. – Louis 17 November 2016 в 20:34

Мой плагин jQuery позволяет событию «изменить размер» на всех элементах не только window.

https://github.com/dustinpoissant/ResizeTriggering

$("#myElement") .resizeTriggering().on("resize", function(e){
  // Code to handle resize
}); 
3
ответ дан Louis 21 August 2018 в 22:34
поделиться
  • 1
    Ваша ссылка указывала на место, которое больше не существует. Я искал имя плагина и нашел страницу, соответствующую вашему описанию. Поскольку вы являетесь автором плагина, я также отредактировал язык вашего ответа, чтобы сделать его явным, что это ваша работа. Правила этого сайта таковы, что когда вы пишете ответы, рекомендуем использовать что-то, что вы разработали, must сделать явные отношения. – Louis 17 November 2016 в 20:29
  • 2
    Это неплохое решение, потому что вы снова и снова запускаете некоторые функции в setTimer, что означает, что браузер постоянно сжигает CPU, даже если ничего не происходит. Владельцы ноутбуков и сотовых телефонов выигрывают от решения, которое использует события браузера только тогда, когда есть какие-то действия, например, с использованием события onScroll. – Roman Zenka 23 January 2018 в 17:26

Я думал, что это невозможно сделать, но потом я подумал об этом, вы можете вручную изменить размер div с помощью стиля = «изменить размер: оба;» чтобы сделать это, вы должны щелкнуть по нему, чтобы добавить функцию 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>
0
ответ дан Marc Stober 21 August 2018 в 22:34
поделиться
  • 1
    Это вычисляется только при запуске события щелчка, который не является частью требования вопроса. – Rob Evans 14 July 2015 в 14:39

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);
});
8
ответ дан Martin Wantke 21 August 2018 в 22:34
поделиться
  • 1
    Это то, что делают диаграммы js. – Antoniossss 17 January 2018 в 14:12
  • 2
    Спасибо, что сжали это. Я собираюсь попробовать это :) – Tony K. 13 April 2018 в 20:40
  • 3
    В этом выражении что-то отсутствует parseInt( getComputedStyle(element) ) – GetFree 7 May 2018 в 18:41

В долгосрочной перспективе вы сможете использовать ResizeObserver .

new ResizeObserver(callback).observe(element);

К сожалению, он не поддерживается по умолчанию во многих браузерах.

В то же время вы можете использовать функцию, как показано ниже. Так как большинство изменений размера элемента происходит из изменения размера окна или из-за изменения чего-либо в DOM. Вы можете прослушивать изменение размера окна с помощью события resize окна, и вы можете прослушивать изменения 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
  });
};
17
ответ дан nkron 21 August 2018 в 22:34
поделиться
  • 1
    К сожалению, MutationObserver не может обнаружить изменения в Shadow DOM. – Ajedi32 27 October 2015 в 15:51
  • 2
    @nkron, к сожалению, если вы используете CSS3 resize , изменение размера может произойти, когда пользователь изменяет размер вручную. Это событие невозможно поймать. – Pacerier 19 February 2016 в 02:38
  • 3
    @ Ajedi32 Да, но вы можете использовать MutationObserver внутри ShadowDOM. Я имею в виду, вместо просмотра body, как в этом примере, вы можете смотреть элемент напрямую. Это на самом деле более эффективный и эффективный, чем просмотр всего тела. – trusktr 6 August 2016 в 06:58
  • 4
    @ Ajedi32 Ну, единственная проблема в том, что если дерево Shadow DOM закрыто, то вы не сможете получить доступ к внутренним элементам, но я не думаю, что это обычно то, что вам нужно делать, и если вам нужно наблюдать такое закрытое дерево, что может быть проблемой в дизайне. В идеале вам нужно только понаблюдать за своими собственными элементами, к которым у вас есть доступ. Компонент Shadow-DOM, который требует, чтобы вы наблюдали его внутренний размер, может быть неправильно спроектирован. У вас есть конкретный пример? Если да, возможно, я могу помочь предложить решение (потому что я тоже заинтересован в этом, но пока нет примера). – trusktr 6 August 2016 в 07:02
  • 5
    @trusktr У меня нет MCVE на данный момент, но в принципе любой элемент Shadow DOM, который может изменить свой размер в результате некоторого ввода пользователя, будет достаточным для того, чтобы вызвать эту проблему. Например, поле, которое расширяется с дополнительной информацией при нажатии. Обратите внимание, что я просматриваю страницу, а не отдельный элемент, потому что я хочу автоматически прокручивать вниз, когда размер страницы увеличивается, независимо от причины. Расширение Shadow DOM является лишь одной из многих возможных причин, по которым страница может стать более длинной. – Ajedi32 8 August 2016 в 13:40

Вы можете попробовать код в следующем фрагменте, он покрывает ваши потребности, используя простой javascript. ( запустите фрагмент кода и нажмите ссылку полной страницы, чтобы вызвать предупреждение о том, что размер div изменяется, если вы хотите его протестировать. ).

Исходя из того факта, что это setInterval в 100 миллисекунд, я бы осмелился сказать, что мой компьютер не обнаружил, что он слишком сильно голоден. (0,1% ЦП было использовано как общее для всех открытых вкладок в Chrome в тесте времени.). Но опять же, это только для одного div, если вы хотите сделать это для большого количества элементов, тогда да, это может быть очень жарко.

Вы всегда можете использовать событие click для остановки div -resize sniffing в любом случае.

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

Обновлено Fiddle

2
ответ дан Peter Darmis 21 August 2018 в 22:34
поделиться

Только объект window генерирует событие «изменить размер». Единственный способ, которым я знаю делать то, что вы хотите сделать, - запустить таймер интервала, который периодически проверяет размер.

6
ответ дан Pointy 21 August 2018 в 22:34
поделиться

Это довольно точная копия верхнего ответа, но вместо ссылки это просто часть кода, которая важна, переводится как IMO, более читабельная и понятная. Несколько других небольших изменений включают использование cloneNode (), а не помещение html в строку js. Маленький материал, но вы можете копировать и вставлять это как есть, и он будет работать.

Способ, которым он работает, заключается в том, что два невидимых divs заполняют элемент, который вы просматриваете, а затем добавляете триггер в каждом, и установить положение прокрутки, которое приведет к запуску изменения прокрутки, если размер изменится.

Все реальные кредиты идут на Marc 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);
    }
0
ответ дан Seph Reed 21 August 2018 в 22:34
поделиться

Лучшим решением было бы использовать так называемые запросы элементов. Тем не менее, они не являются стандартными, спецификации не существует, и единственный вариант - использовать одну из доступных полипол / библиотек, если вы хотите пойти этим путем.

Идея, лежащая в основе запросов элементов, заключается в том, чтобы разрешить определенный контейнер на странице для ответа на пространство, которое ему предоставляется. Это позволит написать компонент один раз, а затем отбросить его в любом месте страницы, в то время как он будет корректировать его содержимое до его текущего размера. Независимо от размера окна. Это первое отличие, которое мы видим между запросами элементов и медиа-запросами. Все надеются, что в какой-то момент будет создана спецификация, которая будет стандартизировать запросы элементов (или то, что достигает той же цели) и сделать их родными, чистыми, простыми и надежными. Большинство людей согласны с тем, что запросы СМИ довольно ограничены и не помогают модульным дизайном и реальной отзывчивостью.

Существует несколько полипол / библиотек, которые решают проблему по-разному (можно назвать обходные решения вместо решений хотя):

Я видел другие решения аналогичных проблем. Обычно они используют таймеры или размер окна / видового экрана под капотом, что не является реальным решением. Более того, я думаю, что в идеале это должно решаться главным образом в CSS, а не в javascript или html.

14
ответ дан Stan 21 August 2018 в 22:34
поделиться
  • 1
    +1 для запросов элементов, но я не надеюсь увидеть их в ближайшее время. На данный момент нет даже спецоперации AFAIK ... может быть, одна из нас заинтересованные стороны должны поставить ее вместе и представить? – Rob Evans 14 July 2015 в 14:42
  • 2
    Это, конечно, хорошая идея. Для достижения окончательной версии потребуется много времени, нужно обратить много внимания. Построение этого в хорошем смысле не кажется мне тривиальным. Кросс-браузерная совместимость, круговые зависимости, отладка, читаемость и обслуживание и т. Д. Итак, давайте начнем как можно раньше :) – Stan 17 July 2015 в 10:00
  • 3
    @Stan, я думаю, что этот ответ может быть лучше, добавив более подробную информацию о том, что такое элементный запрос. – Pacerier 19 February 2016 в 02:40

, используя ответ Bharat Patil, просто верните ложь внутри обратного вызова связывания, чтобы предотвратить максимальную ошибку стека, см. пример ниже:

$('#test_div').bind('resize', function(){
   console.log('resized');
   return false;
});
0
ответ дан White Rabbit 21 August 2018 в 22:34
поделиться

Использование Clay.js ( https://github.com/zzarcon/clay ) довольно просто обнаружить изменения размера элемента:

var el = new Clay('.element');

el.on('resize', function(size) {
    console.log(size.height, size.width);
});
3
ответ дан Zzarcon 21 August 2018 в 22:34
поделиться
  • 1
    Пожалуйста, предоставьте соответствующее раскрытие, учитывая, что это ваша библиотека. – jhpratt 19 May 2018 в 22:28
  • 2
    – Máxima Alekz 2 October 2018 в 14:50
Другие вопросы по тегам:

Похожие вопросы: