slideDown,slideUp是页面中很常见的交互效果,一个元素会先以display:none的方式隐藏起来,等到触发的时候,再以以某种缓动动画展开到一定高度,那么如何获取到隐藏元素的高度?
考虑两种情况,第一,元素本身设置了隐藏可以用display === 'none'
判断,情况二,元素的父级设置了隐藏,但本身还是diplay:block,可以用getComputedStyle
获取元素的宽高来判断。
var rect = ele.getBoundingClientRect();
return rect.width === 0 && rect.height === 0;
思路
对于情况一,将元素display:block,visibility:hidden同时为了不影响其他的元素,还要设置绝对定位,计算完成以后,将元素的样式还原。
情况二,比较麻烦,向上查找父元素,然后设置父元素可见,再计算元素高度,未免显得繁琐,考虑使用cloneNode
将元素插入到body中,然后计算高度
实现
首先获取元素的关键样式
function getStyle (ele) {
var styles = window.getComputedStyle(ele);
return {
display: styles.display,
position: styles.position,
visibility: styles.visibility,
height: styles.height
}
}
获取正常显示情况下的样式
ele.style.display = 'block';
ele.style.position = 'absolute';
ele.style. visibility = 'hidden';
var actualHeight = ele.offsetHeight;
如果父级隐藏,则克隆节点
var cloned = ele. p.cloneNode(true);
document.body.appendChild(cloned);
代码
function getActualHeight (ele) {
function getStyle (e) {
var styles = window.getComputedStyle(e);
return {
display: styles.display,
position: styles.position,
visibility: styles.visibility,
height: styles.height
}
}
function isIntangible (e) {
var rect = e.getBoundingClientRect();
return rect.width === 0 && rect.height === 0;
}
function cloneEle(e) {
var cloned = e.cloneNode(true);
document.body.appendChild(cloned);
return cloned;
}
function getNormaledHeight (e) {
e.style.display = 'block';
e.style.position = 'absolute';
e.style. visibility = 'hidden';
return e.offsetHeight;
}
function resetStyle (e, origin) {
for (key in origin) {
e.style[key] = origin[key];
}
}
var originalStyle = getStyle(ele),
dataH,
actualHeight;
if ( datah = ele.getAttribute('data-height')) {
return datah;
}
if (originalStyle.display !== 'none' && (!isIntangible(ele))) {
actualHeight = getNormaledHeight(ele);
resetStyle(ele, originalStyle);
ele.setAttribute('data-height', actualHeight);
return originalStyle.height;
}
else if (originalStyle.display === 'none') {
var e = cloneEle(ele);
actualHeight = getNormaledHeight(e);
document.body.removeChild(e);
ele.setAttribute('data-height', actualHeight);
return actualHeight
}
}
写完再看,可以完全用克隆节点来解决,但是有一个弊端,如果设置节点样式的时候,选择器中包含着父级节点,那么这个节点克隆出来以后必然会,丢失一些样式,所以这个方法适用于独立化的css组件。
function getActualHeight (ele) {
function cloneEle(e) {
var cloned = e.cloneNode(true);
document.body.appendChild(cloned);
return cloned;
}
function getNormaledHeight (e) {
e.style.display = 'block';
e.style.position = 'absolute';
e.style. visibility = 'hidden';
return e.offsetHeight;
}
var n = cloneEle(ele);
var h = getNormaledHeight(n);
document.body.removeChild(n);
return h;
}