A-A+

javascript实现定位并且可拖动的弹出框

2016年01月28日 前端设计 评论 2 条 阅读 8 views 次

实现弹出一个框,这个框是出现在超链接或按钮附近的,即可以给框定位,也可以随意拖拽,代码如下 第一种情况就是ie下获取scrollTop/scrollLeft值,最典型的就是文档类型,DOCTYPE ,不同取值方式不同,兼容各浏览器实现
如下:

  1. function getScrollXY() {   
  2.       var scrOfX = 0, scrOfY = 0;   
  3.       iftypeof( window.pageYOffset ) == 'number' ) {   
  4.         //Netscape compliant   
  5.         scrOfY = window.pageYOffset;   
  6.         scrOfX = window.pageXOffset;   
  7.       } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {   
  8.         //DOM compliant   
  9.         scrOfY = document.body.scrollTop;   
  10.         scrOfX = document.body.scrollLeft;   
  11.       } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {   
  12.         //IE6 standards compliant mode   
  13.         scrOfY = document.documentElement.scrollTop;   
  14.         scrOfX = document.documentElement.scrollLeft;   
  15.       }   
  16.       return [ scrOfX, scrOfY ];   
  17. }  

主要是关注document.documentElement.scrollTop和document.body.scrollTop应用场景。

第二种情况就是获取页面某个元素的位置,指标top/left值,普遍的方案如下:

  1. var getPosition = function(obj){   
  2.     var pos = [0,0];   
  3.     if(obj.offsetParent){   
  4.         while(obj.offsetParent){   
  5.             pos[0] += obj.offsetTop;   
  6.             pos[1] += obj.offsetLeft;   
  7.             obj = obj.offsetParent;   
  8.         }   
  9.     }   
  10.     return pos;   
  11. }  

传入一个页面元素对象,获取当前对象在页面中的位置top和left。通过循环offsetParent获取offsetTop和 offsetLeft值。

其实在实际应用中还有很多问题,如弹出框浮动,漂浮等,先了解一下这两种情况,继续完善,第三种获取元素位置与定位方法,性能更高,浏览器兼容性更强,高度推荐。

  1. var getPosition = function(el){   
  2. var ua = navigator.userAgent.toLowerCase();   
  3. var isOpera = (ua.indexOf('opera') != -1);   
  4. var isIE = (ua.indexOf('msie') != -1 && !isOpera); // not opera spoof   
  5.   
  6. if(el.parentNode === null || el.style.display == 'none')     
  7. {   
  8.     return false;   
  9. }   
  10.   
  11. var parent = null;   
  12. var pos = [];   
  13. var box;   
  14.   
  15. if(el.getBoundingClientRect)    //IE   
  16. {   
  17.     box = el.getBoundingClientRect();   
  18.     var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);   
  19.     var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);   
  20.   
  21.     return {x:box.left + scrollLeft, y:box.top + scrollTop};   
  22. }   
  23. else if(document.getBoxObjectFor)    // gecko   
  24. {   
  25.     box = document.getBoxObjectFor(el);   
  26.            
  27.     var borderLeft = (el.style.borderLeftWidth)?parseInt(el.style.borderLeftWidth):0;   
  28.     var borderTop = (el.style.borderTopWidth)?parseInt(el.style.borderTopWidth):0;   
  29.   
  30.     pos = [box.x - borderLeft, box.y - borderTop];   
  31. }   
  32. else    // safari & opera   
  33. {   
  34.     pos = [el.offsetLeft, el.offsetTop];   
  35.     parent = el.offsetParent;   
  36.     if (parent != el) {   
  37.         while (parent) {   
  38.             pos[0] += parent.offsetLeft;   
  39.             pos[1] += parent.offsetTop;   
  40.             parent = parent.offsetParent;   
  41.         }   
  42.     }   
  43.     if (ua.indexOf('opera') != -1     
  44.         || ( ua.indexOf('safari') != -1 && el.style.position == 'absolute' ))     
  45.     {   
  46.             pos[0] -= document.body.offsetLeft;   
  47.             pos[1] -= document.body.offsetTop;   
  48.     }     
  49. }   
  50.         
  51. if (el.parentNode) { parent = el.parentNode; }   
  52. else { parent = null; }   
  53.   
  54. while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML')     
  55. // account for any scrolled ancestors   
  56.     pos[0] -= parent.scrollLeft;   
  57.     pos[1] -= parent.scrollTop;   
  58.   
  59.     if (parent.parentNode) { parent = parent.parentNode; }     
  60.     else { parent = null; }   
  61. }   
  62. return {x:pos[0], y:pos[1]};   

完整实例,代码如下:

  1. popup(showid,contents,isbox,divleft);  
  2. /** 
  3.  * 显示弹出框 
  4.  * @param  string id 
  5.  * @param  string contents:弹出框的内容 
  6. * @param  int isbox 
  7.  * @param  int divleft 
  8.  */  
  9. function popup(showid, contents, isbox, divleft)  
  10. {  
  11.         var jsmenu = new Array();  
  12.         jsmenu['active'] = new Array();  
  13.  if(isUndefined(isbox)) isbox = 0;  
  14.  if(isUndefined(divleft)) divleft = 0;  
  15.  var offset = 0;  
  16.  var div = $(showid + "_menu");  
  17.  if(div)  
  18.        {  
  19.         div.parentNode.removeChild(div);  
  20.  }  
  21.  div = document.createElement('div');  
  22.  div.id = showid + "_menu";  
  23.  div.style.position = 'absolute';  
  24.  if(isbox)  
  25.        {  
  26.   divclass = 'popupmenu_centerbox';  
  27.   offset = -1;  
  28.  }  
  29.         else  
  30.        {  
  31.   divclass = 'popupmenu_popup';  
  32.  }  
  33.  if(iserrortipbox)  
  34.        {  
  35.   divclass = 'popupmenu_inner';  
  36.  }  
  37.  div.className = divclass;  
  38.  div.style.display = '';  
  39.  $('append_parent').appendChild(div);  
  40.  div.innerHTML = "<div style='width: 200px;'>" + contents + "</div>";  
  41.  jsmenu['active'][0] = div;  
  42.  $('append_parent').appendChild(div);  
  43.  //定位弹出框  
  44.  setPopupPosition(showid, offset, divleft);  
  45. }  
  46.    
  47. /** 
  48.  * 定位弹出框 
  49.  * @param  string showid:显示弹出框的id 
  50.  * @param  int offset: 这个参数有四种情况,默认值为:0 
  51.  * offset= -1 :弹出框会出现在屏幕中央位置 
  52.  * offset=1 :弹出框的右上角在鼠标点击位置附近,但垂直位置始终保持在鼠标的下方 
  53.  * offset=2 :弹出框的右上角在鼠标点击位置附近,但垂直位置始终保持在鼠标的上方 
  54.  * offset=其它值:弹出框的右上角在鼠标点击位置附近,但垂直位置会根据滚动条位置判断, 
  55.  * @param  int divleft 
  56.  */  
  57. function setPopupPosition(showid, offset, divleft)  
  58. {  
  59.  var showobj = $(showid);  
  60.  var menuobj = $(showid + '_menu');  
  61.  if(isUndefined(offset)) offset = 0;  
  62.  if(showobj)  
  63.        {  
  64.   showobj.pos = fetchOffset(showobj);  
  65.   showobj.X = showobj.pos['left'];  
  66.   showobj.Y = showobj.pos['top'];  
  67.   showobj.w = showobj.offsetWidth;  
  68.   showobj.h = showobj.offsetHeight;  
  69.   menuobj.w = menuobj.offsetWidth;  
  70.   menuobj.h = menuobj.offsetHeight;  
  71.   var sTop = document.documentElement && document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;  
  72.   if(offset != -1)  
  73.                {  
  74.   menuobj.style.left = (showobj.X + menuobj.w > document.body.clientWidth) && (showobj.X + showobj.w - menuobj.w  
  75.                 >= 0) ? showobj.X + showobj.w - menuobj.w + 'px' : (showobj.X - divleft) + 'px';  
  76.                 menuobj.style.top = offset == 1 ? showobj.Y + 'px' : (offset == 2 || ((showobj.Y + showobj.h + menuobj.h > sTop + document.documentElement.clientHeight) && (showobj.Y - menuobj.h >= 0)) ? (showobj.Y - menuobj.h) + 'px' : showobj.Y + showobj.h + 'px');  
  77.   }  
  78.                else if(offset == -1)  
  79.                {  
  80.    menuobj.style.left = (document.body.clientWidth-menuobj.w)/2 + 'px';  
  81.    if (document.documentElement.clientHeight > menuobj.h + 300)  
  82.    {  
  83.     var divtop = sTop + (document.documentElement.clientHeight-menuobj.h)/2;  
  84.     if(divtop > 100) divtop = divtop - 100;  
  85.    }  
  86.                        else  
  87.                        {  
  88.     divtop = 100;  
  89.    }  
  90.                        menuobj.style.top = divtop + 'px';  
  91.         }  
  92.        if(menuobj.style.clip && !is_opera)  
  93.                {  
  94.    menuobj.style.clip = 'rect(auto, auto, auto, auto)';  
  95.   }  
  96.  }  
  97.  menuobj.onmousedown = function(event) {try{popupdrag(menuobj, event, 1);}catch(e){}};  
  98.  document.body.onmousemove = function(event) {try{popupdrag(menuobj, event, 2);}catch(e){}};  
  99.  menuobj.onmouseup = function(event) {try{popupdrag(menuobj, event, 3);}catch(e){}};  
  100. }  
  101.    
  102. /** 
  103.  * 拖动弹出框 
  104.  * @param  obj 可拖动的对象 
  105.  * @param  e event 
  106.  * @param  int op 1:表示onmousedown 2:表示onmousemove 3:表示onmouseup 
  107.  */  
  108. var menudragstart = new Array();  
  109. function popupdrag(menuobj, e, op)  
  110. {  
  111.  if(op == 1)  
  112.        {  
  113.   if(in_array(is_ie ? event.srcElement.tagName : e.target.tagName, ['TEXTAREA', 'INPUT', 'BUTTON', 'SELECT']))  
  114.                {  
  115.    return;  
  116.   }  
  117.   menudragstart = is_ie ? [event.clientX, event.clientY] : [e.clientX, e.clientY];  
  118.   menudragstart[2] = parseInt(menuobj.style.left);  
  119.   menudragstart[3] = parseInt(menuobj.style.top);  
  120.   doane(e);  
  121.  }  
  122.         else if(op == 2 && menudragstart[0])  
  123.         {  
  124.   var menudragnow = is_ie ? [event.clientX, event.clientY] : [e.clientX, e.clientY];  
  125.   menuobj.style.left = (menudragstart[2] + menudragnow[0] - menudragstart[0]) + 'px';  
  126.   menuobj.style.top = (menudragstart[3] + menudragnow[1] - menudragstart[1]) + 'px';  
  127.   doane(e);  
  128.  }  
  129.         else if(op == 3)  
  130.        {  
  131.   menudragstart = [];  
  132.   doane(e);  
  133.  }  
  134. }  
  135.    
  136. /** 
  137.  * @param  event 
  138.  */  
  139. function doane(event)  
  140. {  
  141.  e = event ? event : window.event;  
  142.  if(is_ie)  
  143.         {  
  144.   //e.returnValue设置为false的时候可以组织浏览器执行默认的事件动作,同e.preventDefault();  
  145.   e.returnValue = false;  
  146.   //e.cancelBubble把它设置为true的时候,将停止事件进一步起泡到包容层次的元素,同e.stopPropagation();  
  147.   e.cancelBubble = true;  
  148.  }  
  149.        else if(e)  
  150.        {  
  151.   e.stopPropagation();  
  152.   e.preventDefault();  
  153.  }  
  154. }  
  155.    
  156. /** 
  157.  * 获取定位 
  158.  * @param  obj 
  159.  */  
  160. function fetchOffset(obj)  
  161. {  
  162.  var left_offset = obj.offsetLeft;  
  163.  var top_offset = obj.offsetTop;  
  164.  while((obj = obj.offsetParent) != null)  
  165.        {  
  166.   left_offset += obj.offsetLeft;  
  167.   top_offset += obj.offsetTop;  
  168.  }  
  169.  return { 'left' : left_offset, 'top' : top_offset };  
  170. }  
标签:

2 条留言  访客:2 条  博主:0 条

  1. 洞潭村农业

    太专业的东西,菜鸟看得懂,慢慢学习了,经常来

  2. LZY

    建议把运行效果截个图附上,访客能够一眼看到这个效果是不是自己所需要的

给我留言