[关闭]
@yellowhouse 2015-06-07T17:01:46.000000Z 字数 5110 阅读 2348

JavaScript获取页面的位置

JavaScript&获取位置


参考阮一峰的教程
顺带一提:
JavaScript中冒号的作用:
1.声明对象的成员
如:
var o = {a:1,b:2};
表示建立一个具有a b两个属性的对象,访问使用:o.a或o["a"]
2.switch语句分支
3.三元表达式

怪异模式和标准模式(主要是对盒子模型的渲染)
IE 盒模型中
box width = content width + padding (left+right) + border(left+right)
W3C 标准盒模型
box width = content width
由于历史的原因,各个浏览器在对页面的渲染上存在差异,甚至同一浏览器在不同版本中,对页面的渲染也不同。在W3C标准出台以前,浏览器在对页面的渲染上没有统一规范,产生了差异(Quirks mode或者称为Compatibility Mode);由于W3C标准的推出,浏览器渲染页面有了统一的标准(CSScompat或称为Strict mode也有叫做Standars mode),这就是二者最简单的区别。

W3C标准推出以后,浏览器都开始采纳新标准,但存在一个问题就是如何保证旧的网页还能继续浏览,在标准出来以前,很多页面都是根据旧的渲染方法编写的,如果用的标准来渲染,将导致页面显示异常。为保持浏览器渲染的兼容性,使以前的页面能够正常浏览,浏览器都保留了旧的渲染方法(如:微软的IE)。这样浏览器渲染上就产生了Quircks mode和Standars mode,两种渲染方法共存在一个浏览器上。

E 是最早提出 Quirks Mode 与 Standards Mode(与 Quirks 相对应的一种模式)的,后来 Firefox、Chrome、Safari、Opera 等浏览器也都支持了这两种渲染方式。但是只有在 IE 中用户才可以自由地在两种方式之间切换,其他浏览器都是自动匹配其中一种。(现在也是?自动选择符合的一项,但IE可以选择那个优先度差的一个模式)

那么浏览器究竟该采用哪种模式渲染呢?这就引出的DTD,既是网页的头部声明,浏览器会通过识别DTD而采用相对应的渲染模式,可以概括为:
怪异模式:无doctype声明,有了也不能被浏览器识别的,使用HTML4以下(不包括HTML4)的DTD声明。
标准模式:被浏览器识别的DOC标声明(参考http://hsivonen.iki.fi/doctype/),HTML4以上的DTD声明,
现在基本有DTD声明的都是用标准模式

compatmode(一般用于浏览器兼容)
document.compatMode用来判断当前浏览器采用的渲染方式(兼容模式)。渲染即解释html,css,js之类的代码,从而给网页添加样式
兼容模式:只影响宽度和高度,但会影响浏览器和网页的大小,如clientwidth,scrollwidth,不涉及就不用考虑。
BackCompat:标准兼容模式关闭。BackCompat Standards-compliant mode is not switched on. (Quirks Mode即表示怪异模式)
CSS1Compat:标准兼容模式开启。CSS1Compat Standards-compliant mode is switched on. (Standards Mode即表示标准模式)

Standards Mode和Quirks Mode是有很大差别的,在Standards Mode下对于盒模型的解释和其他的标准浏览器是一样,但在Quirks Mode模式下则有很大差别,而在不声明Doctype的情况下,IE默认又是Quirks Mode。所以为兼容性考虑,我们可能需要获取当前的文档渲染方式。 故可以视为IE为Quirks Mode,其他浏览器为standard mode

当document.compatMode等于BackCompat时,浏览器客户区宽度是document.body.clientWidth;
当document.compatMode等于CSS1Compat时,浏览器客户区宽度是document.documentElement.clientWidth。

offsetparent
offsetParent属性返回一个对象的引用(看作对象好了……),这个对象是距离调用offsetParent的元素最近的(在包含层次中最靠近的),并且是已进行过CSS定位(absolute或者relative)的容器元素。 如果父级元素无CSS定位且父父级元素有CSS定位,则以父父级元素作为参考,直至到达body。(无论怪异模式还是标准模式都是body)
当容器元素的style.display 被设置为 "none"时(译注:IE和Opera除外),offsetParent属性 返回 null。当再无上级元素时,也是null。

一、网页的大小和浏览器窗口的大小
首先,要明确这两个基本概念。
网页:一张网页的全部面积,就是它的大小。通常情况下,网页的大小由内容和CSS样式表决定
浏览器窗口:浏览器窗口的大小,则是指在浏览器窗口中看到的那部分网页面积,又叫做viewport(视口)。(不包含空白部分)
如果网页的内容能够在浏览器窗口中全部显示(也就是不出现滚动条),那么网页的大小和浏览器窗口的大小是相等的。如果不能全部显示,则滚动浏览器窗口,可以显示出网页的各个部分。
浏览器窗口是部分的网页面积,即浏览器窗口是网页的子集。

二、获取网页的大小
网页上的每个元素,都有clientHeight和clientWidth属性。这两个属性指元素的内容部分再加上padding的所占据的视觉面积,不包括border和滚动条占用的空间。即clientHeight=height+padding上和下
因此,document元素的clientHeight和clientWidth属性,就代表了网页的大小。

function getViewport(){
        width: document.body.clientWidth,
        height: document.body.clientHeigh
        }

其中width和height是document的属性
考虑到浏览器兼容,则有

function getViewport(){
    if (document.compatMode == "BackCompat"){
      return {
        width: document.body.clientWidth,
        height: document.body.clientHeight
      }
    } else {
      return {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
      }
    }
  }

当document.compatMode等于BackCompat时,浏览器客户区宽度是document.body.clientWidth;
当document.compatMode等于CSS1Compat时,浏览器客户区宽度是document.documentElement.clientWidth。
注意事项:
(1)这个函数必须在页面加载完成后才能运行,否则document对象还没生成,浏览器会报错。(与document对象有关的都要注意这点)
(2)大多数情况下,都是document.documentElement.clientWidth返回正确值。但是,在IE6的quirks模式中,document.body.clientWidth返回正确的值,因此函数中加入了对文档模式的判断。(IE6是body属性)
(3)clientWidth和clientHeight都是只读属性,不能对它们赋值。(加以中介才能:获取-赋予中介-调用-赋值)

同理:网页上的每个元素还有scrollHeight和scrollWidth属性,指包含滚动条在内的该元素的视觉面积。
那么,document对象的scrollHeight和scrollWidth属性就是网页的大小,意思就是滚动条滚过的所有长度和宽度。
将以上函数的clientwidth改成scrollwidth之类的修改即可。

四、获取网页元素的绝对位置
网页元素的绝对位置,指该元素的左上角相对于整张网页(网页的大小)左上角的坐标。这个绝对位置要通过计算才能得到。
首先,每个元素都有offsetTop和offsetLeft属性,表示该元素的左上角与父容器(offsetParent对象)左上角的距离。所以,只需要将这两个值(此处指的应该是offsetLeft和offsetTop)进行累加,就可以得到该元素的绝对坐标。
获取绝对位置的横坐标(纵坐标与此类似)

function getElementLeft(element){
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;
    while (current !== null){
      actualLeft += current.offsetLeft;
      current = current.offsetParent;/*用于循环
    }
    return actualLeft;
  }

/*element代表调用这个函数的对象,作为参数调用
由于在表格和iframe中,offsetParent对象未必等于父容器,所以上面的函数对于表格和iframe中的元素不适用。
应该是多次迭代才能够使得parent.offsetleft等于页面与父父父……元素的距离吧?直至curent=null,这是一个循环

五、获取网页元素的相对位置
网页元素的相对位置,指该元素左上角相对于浏览器窗口(浏览器大小)左上角的坐标。
将绝对坐标减去页面的滚动条滚动的距离就可以得到相对位置。滚动条已经滚动的垂直距离,是document对象的scrollTop属性;滚动条已经滚动的水平距离是document对象的scrollLeft属性。(滚动方向为从上到下,从左到右,滚动条只是一个缩小的指示块,滚动的距离包括浏览器的border)
对上一节中的两个函数进行相应的改写:
 

 *function getElementViewLeft(element){
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;
    while (current !== null){
      actualLeft += current.offsetLeft;
      current = current.offsetParent;
    }*以上与前面的代码完全相同
    if (document.compatMode == "BackCompat"){
      var elementScrollLeft=document.body.scrollLeft;
    } else {
      var elementScrollLeft=document.documentElement.scrollLeft; 
    }/*声明滚动条的已滚动距离
    return actualLeft-elementScrollLeft;
  }/*将绝对坐标减去页面的滚动条滚动的距离就可以得到相对位置

scrollTop和scrollLeft属性是可以赋值的,并且会立即自动滚动网页到相应位置,因此可以利用它们改变网页元素的相对位置。另外,element.scrollIntoView()方法也有类似作用,可以使网页元素出现在浏览器窗口的左上角。(相比于client是只读,还要声明一个中介值)

六、获取元素位置的快速方法
使用getBoundingClientRect()方法。它返回一个对象,其中包含了left、right、top、bottom四个属性,分别对应了该元素的左上角和右下角相对于浏览器窗口(viewport)左上角和右下角的距离。(获得的是相对位置,故要想获得绝对位置,只需加上滚动条的距离)
所以,网页元素的相对位置就是
  var X= this.getBoundingClientRect().left;
  var Y =this.getBoundingClientRect().top;
再加上滚动距离,就可以得到绝对位置
  var X= this.getBoundingClientRect().left+document.documentElement.scrollLeft;
  var Y =this.getBoundingClientRect().top+document.documentElement.scrollTop;

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注