Javascript 如何检测DIV的维度改变?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6492683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:01:34  来源:igfitidea点击:

How to detect DIV's dimension changed?

javascriptjqueryhtml

提问by William Choi

I've the following sample html, there is a DIV which has 100% width. It contains some elements. While performing windows re-sizing, the inner elements may be re-positioned, and the dimension of the div may change. I'm asking if it is possible to hook the div's dimension change event? and How to do that? I currently bind the callback function to the jQuery resize event on the target DIV, however, no console log is outputted, see below:

我有以下示例 html,有一个宽度为 100% 的 DIV。它包含一些元素。在执行窗口大小调整时,内部元素可能会重新定位,div 的尺寸可能会发生变化。我在问是否可以挂钩 div 的尺寸更改事件?以及如何做到这一点?我目前将回调函数绑定到目标 DIV 上的 jQuery resize 事件,但是,没有输出控制台日志,见下文:

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

采纳答案by Marc J. Schmidt

There is a very efficient method to determine if a element's size has been changed.

有一种非常有效的方法可以确定元素的大小是否已更改。

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

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

This library has a class ResizeSensorwhich can be used for resize detection.
It uses an event-based approach, so it's damn fast and doesn't waste CPU time.

该库有一个ResizeSensor可用于调整大小检测的类。
它使用基于事件的方法,因此速度非常快并且不会浪费 CPU 时间。

Example:

例子:

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

Please do not use the jQuery onresize pluginas it uses setTimeout()in combination with reading the DOM clientHeight/clientWidthproperties in a loop to check for changes.
This is incredible slow and inaccuratesince it causes layout thrashing.

请不要使用jQuery onresize 插件,因为它setTimeout()与循环读取 DOM clientHeight/clientWidth属性结合使用以检查更改。
这是令人难以置信的缓慢和不准确,因为它会导致布局颠簸

Disclosure: I am directly associated with this library.

披露:我与这个图书馆直接相关。

回答by Daniel Herr

A new standard for this is the Resize Observer api, available in Chrome 64.

一个新的标准是 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: //wig.github.io/ResizeObserver

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

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

Firefox Issue: https://bugzil.la/1272409

Firefox 问题:https: //bugzil.la/1272409

Safari Issue: http://wkb.ug/157743

Safari 问题:http: //wkb.ug/157743

Current Support: http://caniuse.com/#feat=resizeobserver

当前支持:http: //caniuse.com/#feat=resizeobserver

回答by Alessandro Vendruscolo

You have to bind the resizeevent on the windowobject, not on a generic html element.

您必须resizewindow对象上绑定事件,而不是在通用 html 元素上。

You could then use this:

然后你可以使用这个:

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

and within the callback function you can check the new width of your divcalling

在回调函数中,您可以检查div呼叫的新宽度

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

So, the answer to your question is no, you can't bind the resizeevent to a div.

因此,您的问题的答案是否定的,您不能将resize事件绑定到 div。

回答by nkron

Long term, you will be able to use the ResizeObserver.

从长远来看,您将能够使用ResizeObserver

new ResizeObserver(callback).observe(element);

Unfortunately it is not currently supported by default in many browsers.

不幸的是,目前许多浏览器默认不支持它。

In the mean time, you can use function like the following. Since, the majority of element size changes will come from the window resizing or from changing something in the DOM. You can listen to window resizing with the window's resizeevent and you can listen to DOM changes using MutationObserver.

同时,您可以使用如下功能。因为,大多数元素大小的变化将来自调整窗口大小或更改 DOM 中的某些内容。您可以使用窗口的resize事件监听窗口大小调整,也可以使用MutationObserver监听 DOM 更改。

Here's an example of a function that will call you back when the size of the provided element changes as a result of either of those events:

这是一个函数示例,当提供的元素的大小因这些事件中的任何一个而发生变化时,该函数将回调您:

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

回答by Martin Wantke

ResizeSensor.jsis part of a huge library, but I reduced its functionality to THIS:

ResizeSensor.js是一个巨大的图书馆的一部分,但我减少了它的功能,以

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

How to use it:

如何使用它:

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

回答by JerryGoyal

I DO NOT recommend setTimeout()hack as it slows down the performance! Instead, you can use DOM mutation observersfor listening to Div size change.

我不推荐setTimeout()hack,因为它会降低性能!相反,您可以使用 DOM 突变观察器来监听 Div 大小的变化。

JS:

JS:

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

HTML:

HTML:

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

Here'sthe fiddle
Try to change the div size.

这是小提琴
尝试更改 div 大小。



You can further wrap your method in the debouncemethod to improve efficiency. debouncewill trigger your method every x milliseconds instead of triggering every millisecond the DIV is being resized.

您可以进一步将您的方法包装在方法中debounce以提高效率。debounce将每 x 毫秒触发一次您的方法,而不是每毫秒触发一次 DIV 调整大小。

回答by joshcomley

I found this library to work when MarcJ's solution didn't:

当 MarcJ 的解决方案没有时,我发现这个库可以工作:

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

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

It's very lightweight and detects even natural resizes via CSS or simply the HTML loading/rendering.

它非常轻量级,甚至可以通过 CSS 或简单的 HTML 加载/渲染来检测自然调整大小。

Code sample (taken from the link):

代码示例(取自链接):

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

回答by Stan

The best solution would be to use the so-called Element Queries. However, they are not standard, no specification exists - and the only option is to use one of the polyfills/libraries available, if you want to go this way.

最好的解决方案是使用所谓的Element Queries。但是,它们不是标准的,不存在规范 - 如果您想这样做,唯一的选择是使用可用的 polyfills/库之一。

The idea behind element queries is to allow a certain container on the page to respond to the space that's provided to it. This will allow to write a component once and then drop it anywhere on the page, while it will adjust its contents to its current size. No matter what the Window size is.This is the first difference that we see between element queries and media queries. Everyone hopes that at some point a specification will be created that will standardize element queries (or something that achieves the same goal) and make them native, clean, simple and robust. Most people agree that Media queries are quite limited and don't help for modular design and true responsiveness.

元素查询背后的想法是允许页面上的某个容器响应提供给它的空间。这将允许编写一次组件,然后将其放在页面上的任何位置,同时将其内容调整为当前大小。无论窗口大小如何。这是我们在元素查询和媒体查询之间看到的第一个区别。每个人都希望在某个时候创建​​一个规范来标准化元素查询(或实现相同目标的东西)并使它们原生、干净、简单和健壮。大多数人都同意媒体查询非常有限,并且无助于模块化设计和真正的响应能力。

There are a few polyfills/libraries that solve the problem in different ways (could be called workarounds instead of solutions though):

有一些 polyfills/libraries 以不同的方式解决问题(虽然可以称为解决方法而不是解决方案):

I have seen other solutions to similar problems proposed. Usually they use timers or the Window/viewport size under the hood, which is not a real solution. Furthermore, I think ideally this should be solved mainly in CSS, and not in javascript or html.

我已经看到了针对类似问题提出的其他解决方案。通常他们在引擎盖下使用计时器或窗口/视口大小,这不是真正的解决方案。此外,我认为理想情况下这应该主要在 CSS 中解决,而不是在 javascript 或 html 中。

回答by Bharat Patil

Take a look at this http://benalman.com/code/projects/jquery-resize/examples/resize/

看看这个http://benalman.com/code/projects/jquery-resize/examples/resize/

It has various examples. Try resizing your window and see how elements inside container elements adjusted.

它有各种例子。尝试调整窗口大小并查看容器元素中的元素如何调整。

Example with js fiddle to explain how to get it work.
Take a look at this fiddle http://jsfiddle.net/sgsqJ/4/

使用 js fiddle 的示例来解释如何让它工作。
看看这个小提琴http://jsfiddle.net/sgsqJ/4/

In that resize() event is bound to an elements having class "test" and also to the window object and in resize callback of window object $('.test').resize() is called.

在该 resize() 事件绑定到具有类“test”的元素以及窗口对象,并在窗口对象 $('.test').resize() 的调整大小回调中被调用。

e.g.

例如

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

$(window).resize(function(){
   $('#test_div').resize();
});

回答by Aminadav Glickshtein

You can use iframeor objectusing contentWindowor contentDocumenton resize. Without setIntervalor setTimeout

您可以使用iframeobject使用contentWindowcontentDocument调整大小。没有setIntervalsetTimeout

The steps:

步骤:

  1. Set your element position to relative
  2. Add inside an transparent absolute hidden IFRAME
  3. Listen to IFRAME.contentWindow- onresizeevent
  1. 将元素位置设置为 relative
  2. 在透明的绝对隐藏 IFRAME 内添加
  3. 聆听IFRAME.contentWindow- onresize事件

An example of HTML:

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

The Javascript:

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

Running Example

运行示例

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

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



See more:

查看更多: