前端获取元素定位位置的法宝

简介:

box chrome

在前端开发中,我们经常需要定位一个元素。如tooltip、popover或者modal等,或许是我们需要将它们定位在依赖元素的周围或屏幕滚动屏幕中心位置。这对于前端开发的码农来说并不是难事。算出和依赖元素的offset,设置元素的left、right。对于稍复杂的场景我们可能需要考虑被positioned的祖先元素。

但往往不是所有的事情都是这么简单的。笔者最新在项目开发中就遇见这样一个问题:这里的HTML是嵌入的,其来自jpedal商业软件从PDF文件自动生成的;为了展示的样式,jpedal统一使用了 position:absolute和relative来定位PDF元素。然而由于业务的需求,我们需要操作这类HTML。其中一个需求就是需要在每段文字附近显示操作工具条。

对于这类未知的DOM定位,那么我们就需要遍历它的DOM树来计算它的相对位置了。行为下面的这段代码:

    function isStaticPositioned(element) {
      return (getStyle(element, 'position') || 'static' ) === 'static';
    }

    var parentOffsetEl = function(element) {
      var docDomEl = $document[0];
      var offsetParent = element.offsetParent || docDomEl;
      while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {
        offsetParent = offsetParent.offsetParent;
      }
      return offsetParent || docDomEl;
    };

在这里,我们会根据元素递归查询它所在的的DOM树中被positioned的最接近的祖先元素,然后才计算它们的相对位置。

这是一段来自Angular-UI bootstrap的$position服务的源码。这也是本文将要提到的获取定位元素位置的法宝。其源码位置在https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js

在$position服务中为我们提供了3个有用的位置服务:position、offset和positionElements。position是计算具体元素的定位位置,返回一个带有width、height、top、left的对象;positionElements则是返回某元素相对于其依赖容器元素的定位位置,一个带有top、left的对象。

笔者为了测试这写API,在jsbin中写了一个特定的指令:

JavaScript:

angular.module("com.ngbook.demo", ['ui.bootstrap.position'])
.directive('position', ['$position', function($position){
    return {
        restrict: 'EA',
        templateUrl: '/position.html',
        scope:{
            title:"@"
        },
        link:function(scope, elm, iAttrs){
        scope.data =  $position.position(elm);
       }
    };
}]);

HTML:

<script type="text/ng-template" id="/position.html">
   <table class="table">
       <thead>
           <th colspan="2">{{title}}</th>
       </thead>
    <tbody>
       <tr ng-repeat="field in ['width', 'height', 'left', 'top']">
       <td>{{field}}</td>
       <td>{{data[field]}}</td>
     </tr>
    </tbody>
   </table>
 </script>

所以我们可以如下测试这类API:

<position title ="no positioned parent"></position>

<div style="position: relative;padding:50px;">
    <position title ="relative parent"></position>

     <div style="position: absolute;top:250px; padding:50px;">
         <position title="relative->absolute parent"></position>
     </div>
 </div>

 <div style="position: absolute;top:0px;left:250px; padding:50px;">
         <position title="absolute parent"></position>
 </div>

其效果可以在jsbin demo:

$position demo

同样你也可以在官方的文档中看见对它的测试: https://github.com/angular-ui/bootstrap/blob/master/src/position/test/test.html

简单的说:如果我们需要获取某个元素的定位信息,则我们可以用 $position.position(element);获取相对于固定元素的定位,则可以使用$position.positionElements(hostEl, targetEl, positionStr, appendToBody)。其中positionStr是一个横向和纵向的字符串,如:”top-left”、”bottom-left”。其默认值为center。如笔者项目所期望的在某文字段落的左上角显示工具条:

$position.after($toolbar);
var elPosition = $position.positionElements($paragraph, $toolbar, “top-left”);
$toolbar.css({left: elPosition.left + 'px', top: elPosition.top + 'px'});

当然也不要忘记为toolbar元素设置position: absolute;


本文转自破狼博客园博客,原文链接:http://www.cnblogs.com/whitewolf/p/4792360.html,如需转载请自行联系原作者

目录
相关文章
|
缓存 运维 Java
nacos常见问题之点击下线提示报错如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
550 2
|
11月前
|
数据采集 机器学习/深度学习 人工智能
基于AI的网络流量分析:构建智能化运维体系
基于AI的网络流量分析:构建智能化运维体系
1787 13
|
Java Maven Android开发
eclipse搭建springboot项目
本文介绍了如何使用Spring Initializr官网生成Spring Boot项目并用Eclipse打开和运行该项目,包括配置项目信息、添加依赖、下载依赖以及启动项目的步骤。
805 1
|
视频直播 Windows
FFmpeg开发笔记(四十一)结合OBS与MediaMTX实现SRT直播推流
《FFmpeg开发实战》书中介绍了直播中的RTSP、RTMP和SRT协议,SRT提供更低延迟和稳定性。FFmpeg从4.0版起支持SRT,OBS Studio和MediaMTX等工具也已支持。在Windows环境下,通过集成libsrt的FFmpeg,可以建立SRT直播系统。MediaMTX日志显示SRT服务监听8890端口,OBS Studio设置SRT推流至"publish:live"。ffplay和VLC通过"read:live"拉流成功,验证了SRT推拉流功能。更多详情见《FFmpeg开发实战:从零基础到短视频上线》。
731 2
FFmpeg开发笔记(四十一)结合OBS与MediaMTX实现SRT直播推流
|
存储 C语言 C++
|
存储 人工智能 安全
人工智能浪潮下的数据隐私保护技术
在大数据与人工智能(AI)的高速发展中,数据隐私保护成为亟待解决的关键议题。本文将探讨当前AI时代下数据隐私保护的技术手段及其面临的挑战,并分析未来发展趋势。文章首先介绍数据隐私的重要性和当前面临的风险,然后深入讨论加密技术和匿名化处理等保护措施,最后评估这些技术的有效性及潜在的改进方向。
713 0
|
C# 数据可视化 开发者
WPF开发者福音:深度解析OxyPlot与LiveCharts图表库,轻松实现数据可视化不再是难题!
【8月更文挑战第31天】在WPF应用中,数据可视化对提升用户体验至关重要。本文介绍并演示了两种流行图表库OxyPlot和LiveCharts的集成与使用方法。OxyPlot是一款适用于.NET应用的开源图表库,提供多种图表类型,易于集成。LiveCharts则以其丰富的图表类型和动画效果,特别适合实时数据展示。通过具体代码示例,本文展示了如何利用这两种图表库创建折线图和柱状图,并详细说明了安装和配置步骤。希望本文能帮助开发者在WPF应用中轻松实现高效、美观的数据可视化。
1337 0
[UE 虚幻引擎] DTLoadFbx 运行时加载FBX本地模型插件说明
该插件支持在运行时动态加载FBX模型,无需预先打包。通过新建Actor并添加DT Runtime Fbx Component,然后调用LoadFile函数加载模型路径(不支持动画)。加载时可选择是否创建碰撞体,该组件基于UProceduralMeshComponent,提供与PMC相似的设置。启用异步计算(Use Async Cooking)可加速碰撞体生成。
594 0
|
JavaScript Linux Python
【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)
我们使用chip tool结合生成的QR码进行调试,重新打开一个终端,使用默认的chip tool工具(记住不是之前构建应用程序生成的chip tool),通过QR码可以快捷迅速地将虚拟设备添加到网络中,我们使用chip tool对设备进行调试
913 0
|
JavaScript 前端开发 测试技术
npm run dev启动报错:TypeError: Cannot read property 'upgrade' of undefined
npm run dev启动报错:TypeError: Cannot read property 'upgrade' of undefined
563 0