我有下面的样本html,有一个DIV有100%的宽度。它包含了一些元素。在执行窗口调整大小时,内部元素可能会被重新定位,div的尺寸可能会改变。我在问是否有可能挂钩div的维度变化事件?以及如何做到这一点?我目前绑定回调函数到目标DIV上的jQuery调整大小事件,但是,没有输出控制台日志,如下所示:
<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>
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);
};
如何使用:
let container = document.querySelector(".container");
new ResizeSensor(container, function()
{
console.log("dimension changed:", container.clientWidth, container.clientHeight);
});
有一种非常有效的方法来确定元素的大小是否已经改变。
http://marcj.github.io/css-element-queries/
这个库有一个resizessensor类,可以用于调整大小检测。它使用基于事件的方法,所以它非常快,而且不会浪费CPU时间。
例子:
new ResizeSensor(jQuery('#divId'), function(){
console.log('content dimension changed');
});
请不要使用jQuery onresize插件,因为它使用setTimeout()结合在循环中读取DOM clienttheight /clientWidth属性来检查更改。这是令人难以置信的缓慢和不准确,因为它会导致布局抖动。
披露:我与这个库直接相关。
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>