У меня есть HTML код, в нём есть div, который имеет ширину в 100%. Он содержит несколько элементов. При изменении размера окна внутренние элементы могут быть перегруппированы, и размер div может измениться.
Можно ли подключить событие изменения размера div? И как это сделать?
В настоящее время я привязываю функцию обратного вызова к событию resize jQuery на нужный div, однако результат не выводится, см. Ниже:
Ответ
Существует очень эффективный метод определения того, был ли изменен размер элемента.
http://marcj.github.io/css-element-queries/
Код библиотеки:
/**
* Copyright Marc J. Schmidt. See the LICENSE file at the top-level
* directory of this distribution and at
* https://github.com/marcj/css-element-queries/blob/master/LICENSE.
*/
;
(function(root, factory) {
if (typeof define === "function" && define.amd) {
define(factory);
} else if (typeof exports === "object") {
module.exports = factory();
} else {
root.ResizeSensor = factory();
}
}(this, function() {
// Make sure it does not throw in a SSR (Server Side Rendering) situation
if (typeof window === "undefined") {
return null;
}
// Only used for the dirty checking, so the event callback count is limited to max 1 call per fps per sensor.
// In combination with the event based resize sensor this saves cpu time, because the sensor is too fast and
// would generate too many unnecessary events.
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
function(fn) {
return window.setTimeout(fn, 20);
};
/**
* Iterate over each of the provided element(s).
*
* @param {HTMLElement|HTMLElement[]} elements
* @param {Function} callback
*/
function forEachElement(elements, callback) {
var elementsType = Object.prototype.toString.call(elements);
var isCollectionTyped = ('[object Array]' === elementsType ||
('[object NodeList]' === elementsType) ||
('[object HTMLCollection]' === elementsType) ||
('[object Object]' === elementsType) ||
('undefined' !== typeof jQuery && elements instanceof jQuery) //jquery
||
('undefined' !== typeof Elements && elements instanceof Elements) //mootools
);
var i = 0,
j = elements.length;
if (isCollectionTyped) {
for (; i < j; i++) {
callback(elements[i]);
}
} else {
callback(elements);
}
}
/**
* Class for dimension change detection.
*
* @param {Element|Element[]|Elements|jQuery} element
* @param {Function} callback
*
* @constructor
*/
var ResizeSensor = function(element, callback) {
/**
*
* @constructor
*/
function EventQueue() {
var q = [];
this.add = function(ev) {
q.push(ev);
};
var i, j;
this.call = function() {
for (i = 0, j = q.length; i < j; i++) {
q[i].call();
}
};
this.remove = function(ev) {
var newQueue = [];
for (i = 0, j = q.length; i < j; i++) {
if (q[i] !== ev) newQueue.push(q[i]);
}
q = newQueue;
}
this.length = function() {
return q.length;
}
}
/**
*
* @param {HTMLElement} element
* @param {Function} resized
*/
function attachResizeEvent(element, resized) {
if (!element) return;
if (element.resizedAttached) {
element.resizedAttached.add(resized);
return;
}
element.resizedAttached = new EventQueue();
element.resizedAttached.add(resized);
element.resizeSensor = document.createElement('div');
element.resizeSensor.className = 'resize-sensor';
var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;';
var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;';
element.resizeSensor.style.cssText = style;
element.resizeSensor.innerHTML =
'
if (element.resizeSensor.offsetParent !== element) { element.style.position = 'relative'; }
var expand = element.resizeSensor.childNodes[0]; var expandChild = expand.childNodes[0]; var shrink = element.resizeSensor.childNodes[1]; var dirty, rafId, newWidth, newHeight; var lastWidth = element.offsetWidth; var lastHeight = element.offsetHeight;
var reset = function() { expandChild.style.width = '100000px'; expandChild.style.height = '100000px';
expand.scrollLeft = 100000; expand.scrollTop = 100000;
shrink.scrollLeft = 100000; shrink.scrollTop = 100000; };
reset();
var onResized = function() { rafId = 0;
if (!dirty) return;
lastWidth = newWidth; lastHeight = newHeight;
if (element.resizedAttached) { element.resizedAttached.call(); } };
var onScroll = function() { newWidth = element.offsetWidth; newHeight = element.offsetHeight; dirty = newWidth != lastWidth || newHeight != lastHeight;
if (dirty && !rafId) { rafId = requestAnimationFrame(onResized); }
reset(); };
var addEvent = function(el, name, cb) { if (el.attachEvent) { el.attachEvent('on' + name, cb); } else { el.addEventListener(name, cb); } };
addEvent(expand, 'scroll', onScroll); addEvent(shrink, 'scroll', onScroll); }
forEachElement(element, function(elem) { attachResizeEvent(elem, callback); });
this.detach = function(ev) { ResizeSensor.detach(element, ev); }; };
ResizeSensor.detach = function(element, ev) { forEachElement(element, function(elem) { if (!elem) return if (elem.resizedAttached && typeof ev == "function") { elem.resizedAttached.remove(ev); if (elem.resizedAttached.length()) return; } if (elem.resizeSensor) { if (elem.contains(elem.resizeSensor)) { elem.removeChild(elem.resizeSensor); } delete elem.resizeSensor; delete elem.resizedAttached; } }); };
return ResizeSensor;
}));
Эта библиотека имеет класс ResizeSensor, который можно использовать для определения размера.
Он основан на событиях, поэтому он чертовски быстро определяет и не нагружает процессор.
Пример:
new ResizeSensor(jQuery('#divId'), function(){ console.log('content dimension changed'); });
Пожалуйста, не используйте плагин resize для jQuery, поскольку он использует цикл setTimeout() для проверки изменений.
Комментариев нет:
Отправить комментарий