【原生JS】仿新浪微博名片弹框

   博客已经搬家地址:http://cm2009.sinaapp.com/

第一次用原生JS写小功能,有很多不足的地方,例如事件绑定没有使用事件委托功能,而是直接用零级DOM进行批量绑定,以及很多我自己不知道的不足。

  这个弹框效果跟新浪微博的名片弹框效果差不多,可以随着相应事件的头像位置的不同而改变出现的位置,当发生事件的位置位于屏幕上方,则弹框从下弹出,反之亦;当事件发生时鼠标位于屏幕25%的左方,则弹框从右边弹出,反之亦,但是事件发生在左右的优先级高于发生在上下的优先级(即先判断左右,后判断上下)。

  名片框的灰色边框使用的是一个半透明DIV层来模拟的,这个DIV与放置内容的DIV是在同一层的,所以他的半透明CSS效果不会对其他div造成影响,小箭头则是一张PNG-24图片,明显,PNG-24在IE6下肯定会很难看。

  另外,如果一个页面里面需要用到不用种类的框,可以多创建几个实例。在每一次进行实例化的时候,会为对象设置一个这样的id:'Info-preview-' + (new Date()).getTime(),理论上,这样会造成id重复,当计算机速度足够快的时候,在1毫秒内能创建多个实例的话,bug就出现了,应该再添加一个序号。因为在实践中没有出现1毫秒能创建多个实例的情况,就没作修改。 在写代码的时候,我发现当弹框出现在头像上方的时候不太好处理css,因为框的定位属性是left跟top,也就是必须计算框本身的高度才能准确定位,而在框display='block'之前是无法计算offsetHeight的,也就无法确定top了,无法确定top,不确定top那显示出来必然会错位,好像很矛盾。后来采用了一种取巧的方法,使用两次setCss()方法,第一次setCss()可以得到框的offsetHeight,而top值没有定义,再执行一次setCss(),把刚才的offsetHeight取到重新计算一下top,这下定位就准了。而这个过程十分迅速,第一次的setCss()根本就察觉不到。到现在,定位问题解决了,如果是用Ajax来获取内容填充到框里,务必要在ajax过程结束之后来一次setCss()修正一下定位,否则会造成框内容突然出现,高度增加,把头像给遮挡住。 

 效果:

这里是演示地址: namecardbox.html
PS:框上的小箭头位置可以通过传入的参数进行修正,好像示例的箭头符号有点大,没事,可以通过传入的参数进行修正。
示例页面中的使用方法:
var box = new NameCardBox(document.getElementsByTagName('span'),document.getElementsByTagName('li'),300);

 以下是这个名片框的js代码,可以拷贝到任何页面使用:

  1 /*******************************  2  *  3  *    通用的NameCardBox小模块  4  *  5  *******************************/  6   7 function NameCardBox() {  8     this.initialize.apply(this, arguments);  9 } 10  11 NameCardBox.prototype = { 12     /* 13      *    targetObj:欲使用此名片功能的node节点的集合 14      *    innerNode:在box中装入的节点集合 15      *    width : 一个数字,描述提示框的宽度 16      *    offsetFix : 小箭头的偏移量修正值 17      *    注意:targetObj与innerNode要按顺序一一对应 18    */ 19     initialize : function(targetObj, innerNode, width, offsetXFix, offsetYFix) { 20         var _this = this; 21         this.id = 'Info-preview-' + (new Date()).getTime(); 22         this.creatElement(); 23         this.wrapper = document.getElementById(this.id); 24         this.wrapper2 = this.wrapper.getElementsByTagName('div')[0]; 25         this.bg = this.wrapper.getElementsByTagName('div')[1]; 26         this.content = this.wrapper.getElementsByTagName('div')[2]; 27         this.arrow = this.wrapper.getElementsByTagName('div')[3]; 28         this.width = width + 'px'; 29         this.borderWidth = 4; 30         this.target = targetObj; 31         this.inner = innerNode; 32         this.directionFlag 33         this.direction = []; 34         this.timer = null; 35         this.option = { 36             'top' : '-1px', 37             'bottom' : '-23px', 38             'left' : '-45px', 39             'right' : '-70px' 40         }; 41         this.offsetXFix = offsetXFix || 0; 42         this.offsetYFix = offsetYFix || 0; 43         this.initCss(); 44         this.addEvent(this.directionFlag); 45         this.wrapper.onmouseover = function() { 46             _this.doKeep(); 47         } 48         this.wrapper.onmouseout = function() { 49             _this.doHide(); 50         } 51     }, 52     //创建box的HTML代码 53     creatElement : function(inner) { 54         var d = document; 55         var wrapper = d.createElement('div'); 56         var wrapper2 = d.createElement('div'); 57         var bg = d.createElement('div'); 58         var content = d.createElement('div'); 59         var arrow = d.createElement('div'); 60         content.innerHTML = "</ br></ br></ br></ br></ br></ br>"; 61         wrapper.setAttribute('id', this.id); 62         wrapper2.appendChild(bg); 63         wrapper2.appendChild(content); 64         wrapper2.appendChild(arrow); 65         wrapper.appendChild(wrapper2); 66         document.body.appendChild(wrapper); 67     }, 68     //计算箭头应该出现的方向以及box放置的方位 69     getDirection : function(event) { 70         var event = window.event || event; 71         var X = event.clientX; 72         var Y = event.clientY; 73         var screenH = screen.availHeight; 74         var screenW = screen.availWidth; 75         if(X / screenW < 0.25 || X / screenW >= 0.75) { 76             this.directionFlag = false; 77         } else { 78             this.directionFlag = true; 79         } 80         if(this.directionFlag === true) { 81             this.direction[0] = 'top'; 82             this.direction[1] = Y / screenH; 83         } else { 84             this.direction[0] = 'left'; 85             this.direction[1] = X / screenW; 86         } 87     }, 88     //为对象绑定box事件 89     addEvent : function() { 90         var _this = this; 91         var obj = this.target; 92         if( typeof obj === 'object' && typeof obj.length === 'number') { 93             for(var i = 0; i < obj.length; i++) { 94                 obj[i].setAttribute('NameCard', i); 95                 obj[i].onmouseover = function() { 96                     _this.getDirection(event); 97                     //第一次获取定位 98                     _this.getPosition(this, _this);100                     _this.content.innerHTML = _this.inner[this.getAttribute('NameCard')].innerHTML;101                     //尝试显示102                     _this.doShow(this);103                     //获取修正后的定位104                     _this.getPosition(this, _this);105                     //再次显示106                     _this.doShow(this);107                     _this.doKeep();108                 }109                 obj[i].onmouseout = function() {110                     _this.doHide();111                 }112             }113         } else if( typeof obj == 'object' && !( obj instanceof Array)) {114             obj.onmouseover = function() {115                 _this.getDirection(event);116                 //第一次获取定位117                 _this.getPosition(this, _this);118                 _this.content.innerHTML = this.getAttribute('data');119                 //尝试显示120                 _this.doShow(this);121                 //获取修正后的定位122                 _this.getPosition(this, _this);123                 //再次显示124                 _this.doShow(this);125                 _this.doKeep();126             }127             obj.onmouseout = function() {128                 _this.doHide()129             };130         } else131             throw Error('type error!');132     },133     doShow : function(obj) {134         //第一次设置CSS,本次无法预知框的高度135         this.setCss(obj);136         this.wrapper.style.display = 'block';137         //根据实际情况修正一次CSS(根据高度修正)138         this.setCss(obj);139     },140     doHide : function() {141         var _this = this;142         this.timer = setTimeout(function() {143             _this.wrapper.style.display = 'none';144         }, 300);145     },146     doKeep : function() {147         if(this.timer != null) {148             clearTimeout(this.timer);149         }150     },151     //给整个框赋予基本的CSS152     initCss : function() {153         var w = this.wrapper;154         var w2 = this.wrapper2;155         var bg = this.bg;156         var c = this.content;157         var a = this.arrow;158         w.style.cssText = 'position:absolute;display:none';159         w2.style.cssText = 'position:relative';160         c.style.cssText = 'position:absolute;padding:10px;background:#FFF;opacity:1;z-index:2;border: 1px solid #bbb;';161         bg.style.cssText = 'left:-4px;top:-4px;background-color: #000;opacity:0.1;position:absolute;z-index:1;filter:alpha(opacity=10)';162         a.style.cssText = 'height:25px;width:25px;position:absolute;left:30px;top:-17px;z-index:2;background-image: url(/images/InfoPreviewBox_arrow.png);background-repeat: no-repeat;background-position-x: -1px; background-position-y: -1px;';163         c.style.width = this.width || '281px';164     },165     //用来给箭头位置、半透明边框定位166     setCss : function(obj) {167         var w = this.wrapper;168         var bg = this.bg;169         var arrow = this.arrow;170         var aFixX = 30 + this.offsetXFix + 'px';171         var aFixY = 30 + this.offsetYFix + 'px';172         var contentW = this.content.offsetWidth;173         var contentH = this.content.offsetHeight;174         bg.style.width = this.content.offsetWidth + this.borderWidth * 2 + 'px';175         bg.style.height = this.content.offsetHeight + this.borderWidth * 2 + 'px';176         bg.style.left = 0 - this.borderWidth;177         bg.style.top = 0 - this.borderWidth;178         w.style.left = obj.getAttribute('css-left') + 'px';179         w.style.top = obj.getAttribute('css-top') + 'px';180 181         if(this.direction[0] === 'left') {182             if(this.direction[1] < 0.5) {183                 arrow.style.backgroundPositionY = this.option.left;184                 arrow.style.left = '-20px';185                 arrow.style.top = aFixY;186             } else {187                 arrow.style.backgroundPositionY = this.option.right;188                 arrow.style.left = this.content.offsetWidth - 11 + 'px';189                 arrow.style.top = aFixY;190             }191         } else {192             if(this.direction[1] > 0.5) {193                 arrow.style.backgroundPositionY = this.option.bottom;194                 arrow.style.left = aFixX;195                 arrow.style.top = this.content.offsetHeight - 4 + 'px';196             } else {197                 arrow.style.backgroundPositionY = this.option.top;198                 arrow.style.left = aFixX;199                 arrow.style.top = '-17px';200             }201         }202     },203     //设置box的定位信息204     getPosition : function(obj, _this) {205         var offsetLeft = obj.getBoundingClientRect().left;206         var clientOffsetTop = document.documentElement.scrollTop || document.body.scrollTop;207         var offsetTop = obj.getBoundingClientRect().top + clientOffsetTop;208         var leftR = offsetLeft - parseInt(this.width) - 35;209         var leftL = offsetLeft + obj.offsetWidth + 15;210         var leftB = offsetTop;211         var topL = offsetLeft;212         var topB = offsetTop + obj.offsetHeight + 15;213         var topT = offsetTop - _this.content.offsetHeight - 15;214         if(this.direction[0] === 'left') {215             if(this.direction[1] < 0.5) {216                 obj.setAttribute('css-left', leftL);217                 obj.setAttribute('css-top', leftB);218             } else {219                 obj.setAttribute('css-left', leftR);220                 obj.setAttribute('css-top', leftB);221             }222         } else {223             if(this.direction[1] > 0.5) {224                 obj.setAttribute('css-left', topL);225                 obj.setAttribute('css-top', topT);226             } else {227                 obj.setAttribute('css-left', topL);228                 obj.setAttribute('css-top', topB);229             }230         }231     }232 }

posted on 2011-12-14 18:13 月之轮回2009 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/circle-of-the-moon/archive/2011/12/14/2287924.html

【原生JS】仿新浪微博名片弹框相关推荐

  1. js仿苹果风格弹出框alert插件

    下载地址 js仿苹果风格弹出框alert插件,多种调用方式. dd:

  2. html 监听input输入框的值,利用原生JS实时监听input框输入值

    利用原生JS实时监听input框输入值 原生JS中可以使用oninput,onpropertychange,onchange oninput,onpropertychange,onchange的用法 ...

  3. 原生js打印阅览复选框不显示问题

    原生js打印阅览复选框不显示问题 原生js打印预览,主要是阅览时候回出现一些问题,比如复选框传值,√不显示,那么怎么来解决这个问题呢?首先我们看一下效果图:我的页面是vue环境 这是预览状态,√和元页 ...

  4. 【每日一练】原生js仿淘宝主图放大镜功能,附学习源码

    在我们的项目中,经常会遇到各种功能效果的实现,对于每一项功能的实现方式,都有很多种,这些实现方式没有好坏之分,只有适合与否,但是我个人建议,如果项目急就选择自己擅长的方式实现,比较完成工作更加重要嘛. ...

  5. html 对勾单选框,利用原生js和jQuery实现单选框的勾选和取消操作的方法

    根据以下的Demo,大概就可以看的明白 Demo: window.onload = function(){ var dom_a = document.getElementById('a1'); var ...

  6. JS:原生JS实现message消息提示框

    简介 学习了一下如何使用原生JS(加上class类)实现message消息提示框的封装(繁琐版). 使用到的主要技术点:class类,JS. 功能点 1.四种提示状态(message success ...

  7. 安卓仿Toasty消息弹框

    Toast是安卓非常常用的消息弹框之一,但是原生的弹框过于朴素,无法适应不同场景的样式需求,因此设计一个类似于Toasty的弹框构建工具. 不废话直接上代码 import android.conten ...

  8. js仿新浪微博消息发布功能

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. 原生js实现select下拉框选择

    最近在做一个项目需要兼容到ie不同版本,在使用select时遇到了各种问题.后来索性就自己使用原生js实现了这样一个下拉框,话不多说,直接上代码吧. <html lang="en&qu ...

最新文章

  1. python怎么读取文件-python怎么读写文件操作
  2. 27对象的向上向下转型
  3. WeihanLi.Npoi 导出支持自定义列内容啦
  4. 每日一题(27)—— define定义一个宏表明1年中有多少秒
  5. LeetCode 1130. 叶值的最小代价生成树(区间DP/单调栈贪心)
  6. log4net 小记
  7. mysql generator备注_MyBatis Generator 自定义生成注释
  8. python爬虫中文乱码_Python爬虫处理抓取数据中文乱码问题
  9. Java实现Redis的消息订阅和发布
  10. 2003退休去世领了2年退休金没回本就死了能退吗?
  11. ubuntu18.04+nvidia显卡安装+cuda9.0+cudnn7+pycharm2018.2专业版激活+anaconda3+tensorflow-gpu1.6.0+keras+opencv3
  12. 【对比Java学Kotlin】类型别名
  13. molten php 上传,molten:PHP 应用透明链路追踪工具
  14. 在手机上图片分辨率怎么调?怎样用手机改300dpi图片?
  15. Git创建分支和查看分支命令
  16. 【集创赛】arm杯一等奖作品:智能BLDC驱动系统
  17. 不用计算机怎么算三角函数,1.不用计算机怎么求根式和三角函数值?
  18. 情商为什么比智商更重要1
  19. 7-12 两个数的简单计算器
  20. Navicat Mysql 破解教程(亲测可用)

热门文章

  1. 有什么好用的测量仪器尺子?手机也能其妙满足
  2. 一个比较全的vim命令
  3. 最全的网站推广方案(SEO)
  4. 用python的turtle画分形树
  5. word里贴代码神器(不需要下载)
  6. Nature Communications:使用连接组的嵌入向量表征映射大脑结构与功能之间的高阶关系
  7. 文件上传之500错误
  8. MySQL 索引介绍!
  9. 用canvas代码写或者three.js代码写一张截图,这张截图里面包含4张图片 ,其中3张图片有倾斜立体效果,剩下的一张是背景图...
  10. 《深入理解计算机系统》实验二Bomb Lab下载和官方文档机翻