关于获取控件的offset

简介: 问题 通过点击一控件,在控件的下面显示一个浮动层,通常的做法是:获取此控件的offset值,再计算出浮动层的top,left等css属性的值,赋值即可。 那么下面就看一下如何获取控件的offset值。

问题

通过点击一控件,在控件的下面显示一个浮动层,通常的做法是:获取此控件的offset值,再计算出浮动层的top,left等css属性的值,赋值即可。

那么下面就看一下如何获取控件的offset值。

纯JS的实现

首先想到的是这样的一段js。

document.getElementById( " divFloat " ).style.top = document.getElementById( " Button " ).offsetLeft + 25 ;

发现需要添加值单位,那么就修改成下面这样子。

document.getElementById( " divFloat " ).style.top =( document.getElementById( " Button " ).offsetLeft + 25)+"px" ;

IETester和FireFox再测试下,IE6+下都可以,如以前一样,写出的纯js的方法无情地被FireFox鄙视了,获取的值不正确。

网上再查了下,发现应该这样写,通过循环,层层向上计算,最后得到准确的offset值。

function  getOffsetLeft(o)
{
    
var  left = 0 ;
    
var  offsetParent  =  o;
    
while  (offsetParent != null   &&  offsetParent != document.body) 
    {
        left
+= offsetParent.offsetLeft;
        offsetParent
= offsetParent.offsetParent;
    }
    
return  left;
}

jQuery的实现

再细一步去查相关问题时发现jQuery中已经包含了实现此功能的函数:offset(),很好地兼容了各浏览器。

$( " #Button " ).offset().left

 还有一个函数是:position(),两者详细的对比分析在这里:深入剖析Jquery中的offset()和position()

下载源码后发现jQuery是这样实现的

jQuery.fn.extend({
    position: 
function () {
        
if  (  ! this [ 0 ] ) {
            
return   null ;
        }

        
var  elem  =   this [ 0 ],

        
//  Get *real* offsetParent
        offsetParent  =   this .offsetParent(),

        
//  Get correct offsets
        offset        =   this .offset(),
        parentOffset 
=   / ^body|html$ / i.test(offsetParent[ 0 ].nodeName)  ?  { top:  0 , left:  0  } : offsetParent.offset();

        
//  Subtract element margins
         //  note: when an element has margin: auto the offsetLeft and marginLeft
         //  are the same in Safari causing offset.left to incorrectly be 0
        offset.top   -=  parseFloat( jQuery.curCSS(elem,  " marginTop " ,   true ) )  ||   0 ;
        offset.left 
-=  parseFloat( jQuery.curCSS(elem,  " marginLeft " true ) )  ||   0 ;

        
//  Add offsetParent borders
        parentOffset.top   +=  parseFloat( jQuery.curCSS(offsetParent[ 0 ],  " borderTopWidth " ,   true ) )  ||   0 ;
        parentOffset.left 
+=  parseFloat( jQuery.curCSS(offsetParent[ 0 ],  " borderLeftWidth " true ) )  ||   0 ;

        
//  Subtract the two offsets
         return  {
            top:  offset.top  
-  parentOffset.top,
            left: offset.left 
-  parentOffset.left
        };
    },

    offsetParent: 
function () {
        
return   this .map( function () {
            
var  offsetParent  =   this .offsetParent  ||  document.body;
            
while  ( offsetParent  &&  ( ! / ^body|html$ / i.test(offsetParent.nodeName)  &&  jQuery.css(offsetParent,  " position " ===   " static " ) ) {
                offsetParent 
=  offsetParent.offsetParent;
            }
            
return  offsetParent;
        });
    }
});

没有太理解,先贴在这里了!


作者:Parry
出处:http://www.cnblogs.com/parry/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

相关文章
|
2天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
13天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1281 5
|
12天前
|
机器学习/深度学习 人工智能 前端开发
通义DeepResearch全面开源!同步分享可落地的高阶Agent构建方法论
通义研究团队开源发布通义 DeepResearch —— 首个在性能上可与 OpenAI DeepResearch 相媲美、并在多项权威基准测试中取得领先表现的全开源 Web Agent。
1308 87
|
1天前
|
弹性计算 安全 数据安全/隐私保护
2025年阿里云域名备案流程(新手图文详细流程)
本文图文详解阿里云账号注册、服务器租赁、域名购买及备案全流程,涵盖企业实名认证、信息模板创建、域名备案提交与管局审核等关键步骤,助您快速完成网站上线前的准备工作。
171 82
2025年阿里云域名备案流程(新手图文详细流程)
|
1天前
|
自然语言处理 前端开发
基于Electron38+Vite7.1+Vue3+Pinia3+ElementPlus电脑端admin后台管理模板
基于最新版跨平台框架Electron38整合Vite7+Vue3+ElementPlus搭建轻量级客户端中后台管理系统解决方案。
151 86