弹出控件的位置该如何计算?

近段时间在写组件,页面有一个输入框,点击输入框,弹出一个国家控件或者是城市控件。但是这个控件的位置该如何放一直是一个头疼的问题。可能是开始没有沉下心来想,总觉得这是个技术难题,还在网上和群里 向很多高手请教,他们给出的答案也并不是我想要的。最后不得不自己想想该如何解决这个问题了,现在把自己的一些思考写出来,一来防止忘记,二来也算个分享。

思路:

前提条件:只能拿到一个输入框对象。

1、position的取值:absolute、relative和fixed三种。relative是相对定位,很明显不适合,因为在实际操作中,根本不确定input是否有父节点,以及父节点的定位是什么,那么相对定位,相对的对象是不可知的,所以可以排除relative。其次是固定定位fixed,这个也是不可行的。举个简单的例子,如果把控件定位到(100,100)的位置,那么如果有滚动条,该控件不会跟着页面滚动,要是还是不明白,想想博客园页面上回到顶部的功能就应该明白了。

2、经过以上思考,至少可以确定,控件的position一定是absolute了,那么它的left值和top值该怎么计算呢?肯定要先从input输入框入手。

3、由于在开发中用的jquery库,那么首先想到的就是$.offset()方法,查看API得知,offset是用于设置或返回当前匹配元素相对于当前文档的偏移,也就是相对于当前文档的坐标,说白了就是获取当前元素的绝对位置。且该位置是相对于当前文档(页面)的。既然是这样,控件的left就应该是当前元素的left值,控件的top就应该是当前元素的top值加上当前元素的自身高度了。为了验证,立马写了一个例子:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    <script type="text/javascript" src="demo/jquery-1.9.1.js" ></script>
    <style type="text/css">
        .layer{width:400px; height:300px; background:red;position: absolute;}
    </style>
    </head>
    <body style="height:2000px;">
        <input type="text" id="input1" placeholder="请选择 "  style="margin-top:100px;" onclick="addLayer();"/>
    </body>
</html>
<script type="text/javascript">
    function addLayer(){
        var pointer = $("#input1").offset();
        var $div = $("<div class=‘layer‘></div>");
        $div.css({left:pointer.left, top:pointer.top+$("#input1").height()});
        $("body").append($div);
    }
</script>

运行正常,也不会随着滚动条的变动而变动位置,很不错。

4、然而由于我的整个项目是用的angular的路由来控制的,左边是导航,右边是内容区,发现异常了,控件和input输入框分离了,找了半天原因,也没找到,开始怀疑自己写的控件有问题,亦或计算位置的思路不正确?纠结了半天,没找到问题的原因,最后不得不用那万能的排除法了。

5、怎么排除呢?首先在网上找了一个日历控件(My97 datepicker),引用进来,发现还是存在这个问题。非常开心,看来不是控件写的有问题,那到底是啥原因呢?继续找。。。。。

6、然后各种实验,最后终于找到原因了:滚动条的问题,如果不是body的滚动条或者是iframe的滚动条,就会遇到这个问题。其实沉下心来想想,很容易就想通,因为offset是根据document计算的相对偏移量,虽然input框所在的区域包含滚动条,但是这个滚动条不是属于document的,所以在滚动的时候,input会随着走,而控件始终留在相对于document的位置。另外,input会跟着动,是因为input并不是根据document来定位的。也就是说,我控件的位置是根据input相对于document的偏移量来获取的,但是并不代表input的位置就是按照这个偏移量来设置的。

 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="UTF-8">
 5         <title></title>
 6     <script type="text/javascript" src="demo/jquery-1.9.1.js" ></script>
 7     <style type="text/css">
 8         .layer{width:400px; height:300px; background:red;position: absolute;}
 9         .wrap{height:500px;overflow: auto;}
10         .inner{height:1000px;}
11     </style>
12     </head>
13     <body style="height:2000px;">
14         <div class="wrap">
15             <div class="inner">
16                     <input type="text" id="input1" placeholder="请选择 "  style="margin-top:100px;" onclick="addLayer();"/>
17             </div>
18         </div>
19     </body>
20 </html>
21 <script type="text/javascript">
22     function addLayer(){
23         var pointer = $("#input1").offset();
24         var $div = $("<div class=‘layer‘></div>");
25         $div.css({left:pointer.left, top:pointer.top+$("#input1").height()});
26         $("body").append($div);
27     }
28 </script>

7、看来这个问题真是没办法解决了,真的没有办法呢?不死心,接着想。。。。。

8、一不小心,又发现了jquery的position()方法,那就用这个方法试试,思路是先用position()方法获取input相对父元素的偏移量,然后给控件设置位置。另外用递归查找input的所有父元素中第一个position为relative的的父元素,把控件append上去。实验表明,如果input的父节点直接是relative的,没有问题,但是要是input的所有父节点都没有,最后还是找到body上去了。结果和上面一样的。

最后结论:最初的方法应该就是正确的方法。所以有时候真的没有必要把问题想的太复杂了,否则进入死巷子出不来。

时间: 2024-08-08 13:59:11

弹出控件的位置该如何计算?的相关文章

JS各种iframe弹出控件没有滚动条或者失灵的解决办法

举例: easyui panel layer 多数的配置是 iframe : true 或者 iframeScrolling:true ,但是设置后滚动条仍然失灵 解决办法,在iframe页面 中加入框架DIV style设置为 width=100%;height=100%;overflow:auto; 原文链接 作程的博客 http://www.zuocheng.net/it/?p=208

[深入浅出WP8.1(Runtime)]浮出控件(Flyout)

4.15 浮出控件(Flyout) 浮出控件(Flyout)是一个轻型的辅助型的弹出控件,通常会作为提示或者要求用户进行相关的交互来使用.Flyout控件与Windows Phone里面的弹出框MessageDialog是有很大区别的,首先Flyout控件是一个辅助控件,需要与其他控件结合起来才能使用,还有就是取消的规则不一样,Flyout控件可以通过单击或在外部点击都可以轻松消除浮出控件.你可以使用Flyout控件收集用户输入.显示与某个项目相关的更多信息或者要求用户确认某个操作.只有当为了响

silverlight——获取控件相对位置

事出有因:页面中存在滚动条,然后点击页面按钮时会进行正确性检查,如果出错在控件的位置会出现提示信息,但由于滚动条的出现,有可能在非可视区域内的控件出了问题,但目前是看不见的,因此,考虑获得出问题控件的相对位置,将滚动条自动滚动到出问题控件的位置上. 1 //获得控件间的相对位置,其中原理还不是很了解,这个先放着稍后再加以理解. 2 GeneralTransform gt = tb4.TransformToVisual(LayoutRoot); 3 Point point = gt.Transfo

基于jquery扩展的弹层控件

漂亮且超好用的弹出层事件类JS代码,支持各种对话框.弹出层等,弹出层可拖拽移动且拖拽流畅,浏览器兼容良好.可自定义内容.标题.宽高.按钮.和绑定相对应的事件简单方便的实现弹层,实现添加数据或显示详细信息等功能. 下面跟着我的步伐走 (1)准备好要显示的内容,这不仅仅是内容,也可以是html代码 (2)准备好内容之后,要记得给它取个响亮的标题,明确下主题,当然也可以不需要 (3)是不是觉得有些时候确定和取消这两个家伙没必要出现,如果不用它们可以将舍弃,不填他们就好了 是不是很简单,还在等什么,快来

获取鼠标点相对于各屏幕、窗体和当前控件的位置

//获取鼠标相对于当前控件的位置 Point mousePos = dgvAddCommand.PointToClient(MousePosition); //获取鼠标相对于当前窗体的位置 mousePos = PointToClient(MousePosition); //获取鼠标相对于屏幕左上点的位置 mousePos = PointToScreen(MousePosition); //偏移位置 mousePos.Offset(3, 20);

IOS Ui控件 修改位置和尺寸,代码添加控件

所有的UI控件最终都继承自UIView,UI控件的公共属性都定义在UIView中, UIView的常见属性 UIView *superview; 获得自己的父控件对象 NSArray *subviews; 获得自己的所有子控件对象 NSInteger tag; 控件的ID(标识),父控件可以通过tag来找到对应的子控件 CGAffineTransform transform; 控件的形变属性(可以设置旋转角度.比例缩放.平移等属性) CGRect frame; 控件所在矩形框在父控件中的位置和尺

【万里征程——Windows App开发】用浮出控件做预览效果

在前面学习控件的时候,我们已经见过了MessageDialog了,关于Button还有一个浮出控件Flyout哦.具体是怎样用呢?接下来就一起看看咯. 我们还是延续前面的那个示例好了,那么,代码来了. <Button x:Name="btnWhat" Content="这是什么?"> <Button.Flyout> <Flyout> <StackPanel> <TextBlock Width="430&

c# asp.net 鼠标改变控件坐标位置,更改控件坐标,注册表保存读取,打印,查找局域网内打印机等等收集

界面虽然被我弄的很难看,但功能还可以 里边注册表的路径自己设置一下,或者加一个创建注册表的语句,不然会报错 前台: Html代码   <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="FPSZ.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML

C#winform调整控件的位置

现在有三个控件并排放置 第二个控件有隐藏功能 隐藏后第一个控件和第三个控件的距离要缩小,于是就要改变第三个控件的位置 尝试用Location.X属性去设置,但是被告知此非变量 于是只能另外想办法 搜到如下解决方案: http://blog.csdn.net/daowzq/article/details/7488332 第一种方法: //控制一个控件的显示位置            button1.Top = 100;            button1.Left = 100; 第二种方法: /