详解原生js实现offset方法
在为jTool提供offset(获取当前节点位置)方法时,先后使用了两种方式进行实现,现整理出来以作记录。
前后共使用了两种方式实现了该方法,这里将这两种方法分别列出。
通过递归实现
functionoffset(element){
varoffest={
top:0,
left:0
};
var_position;
getOffset(element,true);
returnoffest;
//递归获取offset,可以考虑使用getBoundingClientRect
functiongetOffset(node,init){
//非Element终止递归
if(node.nodeType!==1){
return;
}
_position=window.getComputedStyle(node)['position'];
//position=static:继续递归父节点
if(typeof(init)==='undefined'&&_position==='static'){
getOffset(node.parentNode);
return;
}
offest.top=node.offsetTop+offest.top-node.scrollTop;
offest.left=node.offsetLeft+offest.left-node.scrollLeft;
//position=fixed:获取值后退出递归
if(_position==='fixed'){
return;
}
getOffset(node.parentNode);
}
}
//执行offset
vars_kw_wrap=document.querySelector('#s_kw_wrap');
offset(s_kw_wrap);//=>Object{top:181,left:400}
通过ClientRect实现
functionoffset2(node){
varoffest={
top:0,
left:0
};
//当前为IE11以下,直接返回{top:0,left:0}
if(!node.getClientRects().length){
returnoffest;
}
//当前DOM节点的display==='node'时,直接返回{top:0,left:0}
if(window.getComputedStyle(node)['display']==='none'){
returnoffest;
}
//Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。
//返回值包含了一组用于描述边框的只读属性——left、top、right和bottom,单位为像素。除了width和height外的属性都是相对于视口的左上角位置而言的。
//返回如{top:8,right:1432,bottom:548,left:8,width:1424…}
offest=node.getBoundingClientRect();
vardocElement=node.ownerDocument.documentElement;
return{
top:offest.top+window.pageYOffset-docElement.clientTop,
left:offest.left+window.pageXOffset-docElement.clientLeft
};
}
//执行offset
vars_kw_wrap=document.querySelector('#s_kw_wrap');
offset2(s_kw_wrap);//=>Object{top:181.296875,left:399.5}
offset2()函数中使用到了.getClientRects()与.getBoundingClientRect()方法,IE11以下浏览器并不支持;所以该种实现,只适于现代浏览器。
.getClientRects()
返回值是ClientRect对象集合(与该元素相关的CSS边框),每个ClientRect对象包含一组描述该边框的只读属性——left、top、right和bottom,单位为像素,这些属性值是相对于视口的top-left的。
并包含length属性,IE11以下可以通过是否包含length来验证当前是否为IE11以上版现。
.getBoundingClientRect()
返回值包含了一组用于描述边框的只读属性——left、top、right和bottom,单位为像素。除了width和height外的属性都是相对于视口的左上角位置而言的。
.getBoundingClientRect()与.getClientRects()的关系
- 这两个方法的区别与当前的display相关,当display=inline时,.getClientRects()返回当前节点内每一行文本的ClientRect对象数组,此时数组长度等于文本行数。
- 当display!=inline时,.getClientRects()返回当前节点的ClientRect对象数组,此时数组长度为1.
- .getBoundingClientRect()总是返回当前节点的ClientRect对象,注意这里是ClientRect对象而不是对象数组。
提示
以上测试,可以通过在百度首页执行进行测试,document.querySelect('#s_kw_wrap')所获取到的节点为百度首页输入框
希望对大家的学习有所帮助,也希望大家多多支持毛票票。