检测元素是否已通过javascript调整大小?

Jim*_*ers 19 html javascript css

是否可以简单地将事件侦听器添加到某些元素以检测其高度或宽度是否已被修改?我喜欢这样做而不使用密集的东西:

$(window).resize(function() { ... });
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想绑定到特定元素:

$("#primaryContent p").resize(function() { ... });
Run Code Online (Sandbox Code Playgroud)

似乎在窗口上使用调整大小处理程序是唯一的解决方案,但这感觉有点矫枉过正.它也没有考虑以编程方式修改元素尺寸的情况.

csu*_*cat 5

我刚刚想出了一种纯粹基于事件的方法来检测可以包含子元素的任何元素的元素大小调整,我已经粘贴了下面解决方案中的代码。

另请参阅原始博客文章,其中包含一些历史细节。此答案的先前版本基于博文的先前版本。


以下是启用调整大小事件侦听所需的 JavaScript。

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

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

  window.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__);
      }
    }
  }
})();
Run Code Online (Sandbox Code Playgroud)

用法

这是此解决方案的伪代码用法:

var myElement = document.getElementById('my_element'),
    myResizeFn = function(){
        /* do something on resize */
    };
addResizeListener(myElement, myResizeFn);
removeResizeListener(myElement, myResizeFn);
Run Code Online (Sandbox Code Playgroud)

演示

http://www.backalleycoder.com/resize-demo.html

  • 在发布对多个问题的复制和粘贴样板/逐字回答时要小心,这些问题往往被社区标记为“垃圾邮件”。如果您这样做,则通常意味着问题是重复的,因此请改为将它们标记为重复。 (2认同)
  • @Kev - 我看到你在这里欺骗了答案:http://stackoverflow.com/questions/8082729/how-to-detect-css3-resize-events。现在,您如何判断“如何检测 CSS3 调整大小事件”与“检测元素是否已通过 javascript 调整大小”相同?- 他们是不一样的。他们共享一个共同的解决方案,但提问者的需求来自网络堆栈的完全不同的领域,一个来自 CSS,另一个来自 JS。 (2认同)

kev*_*nji 4

这是一个 jQuery 插件,watch其中包含unwatch可以监视元素的特定属性的方法。它作为 jQuery 对象的方法被调用。它使用浏览器中的内置功能,在 DOM 更改时返回事件,并用于setTimeout()不支持这些事件的浏览器。

watch函数的一般语法如下:

$("selector here").watch(props, func, interval, id);
Run Code Online (Sandbox Code Playgroud)
  • props是您想要查看的属性的逗号分隔字符串(例如"width,height")。
  • func是一个回调函数,传递参数watchData, index,其中watchData指的是表单 的对象{ id: itId, props: [], func: func, vals: [] }index是更改后的属性的索引。this指的是改变的元素。
  • intervalsetInterval()是不支持 DOM 属性监视的浏览器中的时间间隔(以毫秒为单位) 。
  • id是一个可选的 id,用于标识此观察程序,用于从 jQuery 对象中删除特定的观察程序。

unwatch函数的一般语法如下:

$("selector here").unwatch(id);
Run Code Online (Sandbox Code Playgroud)
  • id是一个可选的 id,用于标识要删除的观察者。如果id未指定,则对象中的所有观察者都将被删除。

对于那些好奇的人,该插件的代码复制如下:

$.fn.watch = function(props, func, interval, id) {
    /// <summary>
    /// Allows you to monitor changes in a specific
    /// CSS property of an element by polling the value.
    /// when the value changes a function is called.
    /// The function called is called in the context
    /// of the selected element (ie. this)
    /// </summary>    
    /// <param name="prop" type="String">CSS Property to watch. If not specified (null) code is called on interval</param>    
    /// <param name="func" type="Function">
    /// Function called when the value has changed.
    /// </param>    
    /// <param name="func" type="Function">
    /// optional id that identifies this watch instance. Use if
    /// if you have multiple properties you're watching.
    /// </param>
    /// <param name="id" type="String">A unique ID that identifies this watch instance on this element</param>  
    /// <returns type="jQuery" /> 
    if (!interval)
        interval = 200;
    if (!id)
        id = "_watcher";

    return this.each(function() {
        var _t = this;
        var el = $(this);
        var fnc = function() { __watcher.call(_t, id) };
        var itId = null;

        if (typeof (this.onpropertychange) == "object")
            el.bind("propertychange." + id, fnc);
        else if ($.browser.mozilla)
            el.bind("DOMAttrModified." + id, fnc);
        else
            itId = setInterval(fnc, interval);

        var data = { id: itId,
            props: props.split(","),
            func: func,
            vals: []
        };
        $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); });
        el.data(id, data);
    });

    function __watcher(id) {
        var el = $(this);
        var w = el.data(id);

        var changed = false;
        var i = 0;
        for (i; i < w.props.length; i++) {
            var newVal = el.css(w.props[i]);
            if (w.vals[i] != newVal) {
                w.vals[i] = newVal;
                changed = true;
                break;
            }
        }
        if (changed && w.func) {
            var _t = this;
            w.func.call(_t, w, i)
        }
    }
}
$.fn.unwatch = function(id) {
    this.each(function() {
        var w = $(this).data(id);
        var el = $(this);
        el.removeData();

        if (typeof (this.onpropertychange) == "object")
            el.unbind("propertychange." + id, fnc);
        else if ($.browser.mozilla)
            el.unbind("DOMAttrModified." + id, fnc);
        else
            clearInterval(w.id);
    });
    return this;
}
Run Code Online (Sandbox Code Playgroud)