js 尺寸和位置 笔记

/**
* 文档坐标
* 视口坐标
* 鼠标坐标
*
* 元素位置和尺寸
*/


function xx() {
    // 最大可滚动的大小 = 可滚动的大小 - 可视区域的大小
    var scrollMax = d1.scrollHeight - d1.clientHeight;

    // 如果最大可滚动的大小 - 已滚动的大小 >= 阀值
    if (scrollMax - d1.scrollTop >= threshold ) {
        // 开始请求ajax
    }

    // 偏移大小 包含边框大小 内边距大小 + 实际内容可视区域高度(如果有滚动条,包含滚动条大小)
    // d1.offsetHeight
}


// 获取窗口的滚动条偏移量
function getScrollOffsets(w) {
    w = w || window;

    // 对所有现代浏览器有效,除了ie<=8的浏览器
    if (w.pageXOffset != null) {
        return {
            x: w.pageXOffset,
            y: w.pageYOffset
        }
    }

    // 对所有在标准模式下的浏览器
    var d = w.document;
    if (d.compatMode === 'CSS1Compat') {
        return {
            x: d.documentElement.scrollLeft,
            y: d.documentElement.scrollTop
        }
    }

    // 如果处于怪异模式
    return {
        x: d.body.scrollLeft,
        y: d.body.scrollTop
    }
}


// 获取视口尺寸
function getViewportSize(w) {
    w = w || window;

    if (w.innerWidth != null) {
        return {
            w: w.innerWidth,
            h: w.innerHeight
        }
    }

    var d = w.document;
    if (d.compatMode === 'CSS1Compat') {
        return {
            w: d.documentElement.clientWidth,
            h: d.documentElement.clientHeight
        }
    }

    return {
        w: d.body.clientWidth,
        h: d.body.clientHeight
    }
   
}


// 返回一个元素在**视口(viewport)坐标系**中的坐标以及该元素的尺寸(ie没有包含元素的尺寸)
// dom.getBoundingClientRect()   // {left: , top, width, height}
// 包含padding和border,但不包含margin
function getBCR(dom) {
    var bcr = dom.getBoundingClientRect();
    bcr.width = bcr.width || (bcr.right - bcr.left);
    bcr.height = bcr.height || (bcr.bottom - bcr.top);
    return bcr;
}

// offsetWidth offsetHeight
// 只读的
// 单位是px
// 包括border和padding,但包括margin


// offsetLeft offsetRight
// 对已定位元素的子孙或者table cell,返回的坐标相对于祖先,如果offsetParent为null,则相对于document
// 计算一个元素在**文档坐标系**中的坐标
function getElementPosition(e) {
    var x = 0, y = 0;
    while (e != null) {
        x += e.offsetLeft;
        y += e.offsetTop;
        e = e.offsetParent;
    }
    return {
        left: x,
        top: y
    }
}

// offsetWidth包含border、content area、padding
// clientWidth跟offsetWidth的区别是前者不包含border,只有content area和 padding
// 如果有滚动条,clientWidth不包含滚动条的宽度,类似的clientHeight不包含滚动条的高度
// 在内联元素中clientWidth和clientHeight总是为0
// 标准模式下document.documentElement或者怪异模式下document.body,当没有垂直滚动条的时候调用 clientWidth跟 window.innerWidth返回的值是一致的,clientHeight和 window.innerHeight亦如此
// window.innerWidth,在有滚动条出现的情况下,默认已经包含了滚动条的宽度而document.documentElement.clientWidth是不包含滚动条宽度的
// 若果滚动条在左边或者上面的位置,那么clientLeft或clientTop包含滚动条的宽度或者高度
// scrollWidth和scrollHeight包含元素的content以及padding还有溢出(overflowing)的content
// scrollLeft和scrollTop是可读以及可写的
// 因为HTML elements没有scrollTo,素以你可以设置scrollLeft或scrollTop来达到同样的目的


// 当文档包含可滚动的元素的时候(when a document contains scrollable elements with overflowing content),上面的getElementPosition有缺陷
// 原因是之前定义的getElementPosition函数没有考虑到scrollbar position(it does not take scrollbar position into account)
// 修改如下,修改后的版本返回的值跟 getBoundingClientRect()一致(实践证明还是有些许的偏差)
// 经过修复后,getElementPosition2返回的是视口坐标系中的坐标,如果要转换成为文档坐标系中的坐标则需要加上getViewportSize()返回的left和top
function getElementPosition2(elt) {
    var x = 0, y = 0;

    // 循环累加 offsets
    for (var e = elt; e != null; e = e.offsetParent) {
        x += e.offsetLeft;
        y += e.offsetTop;
    }

    // 所有祖先元素
    for (var e = elt.parentNode; e != null && e.nodeType == 1; e = e.parentNode) {
        x -= e.scrollLeft;
        y -= e.scrollTop;
    }
    return {
        left: x,
        top: y
    }
}

/**
* jQuery offset() 返回的是文档坐标系中的坐标 如果要转换为 视口坐标系中的坐标可以加上$(window|document).scrollTop() 和 $(window|document).scrollLeft()
*
*/

// 翻译不好的书籍诟病:修饰(比如定于从句)信息丢失,术语解释别扭,翻译错误


// 纠正位于(0, 0)处元素的位置,ie会返回(2, 2),其他浏览器会返回(0, 0)
function getBoundingClientRect(element) {
    if (element.getBoundingClientRect) {
        // 先判断函数上是否有offset,这个属性作为临时缓存数据的地方来使用
        if (typeof arguments.callee.offset != 'number') {
            var scrollTop = document.documentElement.scrollTop;
            var scrollLeft = document.documentElement.scrollLeft;

            // 创建临时的html元素
            var temp = document.createElement('div');
            temp.style.cssText = 'position: absolute; left: 0; top: 0'; //定位元素的位置到视口坐标系中的(0, 0)处
            document.body.appendChild(temp);

            var offset = -temp.getBoundingClientRect().top - scrollTop;

            // 保存临时变量于函数上
            arguments.callee.offset = offset;

            // 销毁临时的html元素
            document.body.removeChild(temp);
            temp = null;
        }

        var rect = element.getBoundingClientRect();
        var offset = arguments.callee.offset;

        return {
            left: rect.left + offset,
            right: rect.right + offset,
            top: rect.top + offset,
            bottom: rect.bottom + offset
        }
    } else {
        var offset = getElementPosition2(element); // 获取视口坐标系中的元素坐标
        var left = offset.left;
        var top = offset.top;

        return {
            left: left - scrollLeft,
            top: top - scrollTop,
            right: left - scrollLeft + element.offsetWidth,
            bottom: top - scrollLeft + element.offsetHeight
        }
    }
}

posted @ 2013-04-28 14:05  leamiko  阅读(252)  评论(0编辑  收藏  举报
document.getElementById('MySignature') && document.getElementById('MySignature').style.display = "none"; document.getElementById('MySignature') && document.getElementById('blog_post_info').style.display = "none";