1 var Position = {};
2 (function () {
3 Position.getAbsolute = function (reference, target) {
4 var result = {
5 left: -target.clientLeft,
6 top: -target.clientTop
7 }
8 var node = target;
9 while(node != reference && node != document){
10 result.left = result.left + node.offsetLeft + node.clientLeft;
11 result.top = result.top + node.offsetTop + node.clientTop;
12 node = node.parentNode;
13 }
14 if(isNaN(reference.scrollLeft)){
15 result.right = document.documentElement.scrollWidth - result.left;
16 result.bottom = document.documentElement.scrollHeight - result.top;
17 }else {
18 result.right = reference.scrollWidth - result.left;
19 result.bottom = reference.scrollHeight - result.top;
20 }
21 return result;
22 }
23 Position.getViewport = function (target) {
24 var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
25 var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
26 var windowHeight = window.innerHeight || document.documentElement.offsetHeight;
27 var windowWidth = window.innerWidth || document.documentElement.offsetWidth;
28 var absolutePosi = this.getAbsolute(document, target);
29 var Viewport = {
30 left: absolutePosi.left - scrollLeft,
31 top: absolutePosi.top - scrollTop,
32 right: windowWidth - (absolutePosi.left - scrollLeft),
33 bottom: windowHeight - (absolutePosi.top - scrollTop)
34 }
35 return Viewport;
36 }
37 })();
现在我们使用 Position.getViewport(targetNode) 方法可以获取元素左上角相对于窗口4个方向的定位:
1 Position.getViewport(targetNode); //{left: left, top: top, right: right, bottom: bottom}
有了这个方法,现在就可以真正的判断元素是否在可视区域内了:
1 var Position = {};
2 (function () {
3 Position.getAbsolute = function (reference, target) {
4 //因为我们会将目标元素的边框纳入递归公式中,这里先减去对应的值
5 var result = {
6 left: -target.clientLeft,
7 top: -target.clientTop
8 }
9 var node = target;
10 while(node != reference && node != document){
11 result.left = result.left + node.offsetLeft + node.clientLeft;
12 result.top = result.top + node.offsetTop + node.clientTop;
13 node = node.parentNode;
14 }
15 if(isNaN(reference.scrollLeft)){
16 result.right = document.documentElement.scrollWidth - result.left;
17 result.bottom = document.documentElement.scrollHeight - result.top;
18 }else {
19 result.right = reference.scrollWidth - result.left;
20 result.bottom = reference.scrollHeight - result.top;
21 }
22 return result;
23 }
24 Position.getViewport = function (target) {
25 var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
26 var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
27 var windowHeight = window.innerHeight || document.documentElement.offsetHeight;
28 var windowWidth = window.innerWidth || document.documentElement.offsetWidth;
29 var absolutePosi = this.getAbsolute(document, target);
30 var Viewport = {
31 left: absolutePosi.left - scrollLeft,
32 top: absolutePosi.top - scrollTop,
33 right: windowWidth - (absolutePosi.left - scrollLeft),
34 bottom: windowHeight - (absolutePosi.top - scrollTop)
35 }
36 return Viewport;
37 }
38 Position.isViewport = function (target) {
39 var position = this.getViewport(target);
40 //这里需要加上元素自身的宽高,因为定位点是元素的左上角
41 if(position.left + target.offsetWidth < 0 || position.top + target.offsetHeight < 0){
42 return false;
43 }
44 if(position.bottom < 0 || position.right < 0){
45 return false;
46 }
47 return true;
48 }
49 })();
判断理由很简单,如果有一边的定位是负值,那么元素就不在视窗内。