JavaScript图片显示

来源:岁月联盟 编辑:zhuzhu 时间:2008-10-21

 时常看到一种js效果,点击网页上一个图片,背景变灰,前景出现一个图片框,框里显示被点击图片的大图。著名的实现有lightbox和thickbox。

  以前看到这种效果觉得很酷,现在自己也来简单实现一个(就叫DDbox哈哈)。

  第一步:设计页面标记

  首先要考虑的是在页面文档中要怎么标记这样一个位置:当你点击该位置的时候会出现上文所述效果。

  考虑到当JavaScript被禁用时,仍能确保一定的用户体验,我们使用带有href属性的a标签。当JavaScript被允许的时候,点击该标签可以展示我们的动画,并且阻止跳转。当JavaScript被禁用的时候,我们通过<a>标签的链接地址转到图片所在位置。

  这里我们会考虑到图片可能需要一些注释。注释的获取考虑借用属性rel(之前考虑过用自定义的属性字段,但是发现除了IE之外其他浏览器都读不出这些自定义的属性字段),我们把注释相关语句的字符串在页面中写入到rel属性中去。

  是了,不要忘了,我们还要标记怎样的一个<a>标签才是我们要实现效果的一个位置,加上class属性 class="DDbox"。

  图片效果

  接下来设计一下这样的<a>标签被点击时,想要达到的效果。

  设计大致流程如下:点击class为DDbox的<a>标签

  - > 出现灰色覆盖层

  - > 图片框在页面中间位置以适宜的大小纵向展开,接着图片渐现(这里暂不考虑图片载入时未能显示的问题)

  - > 图片框最终展开,图片框上部是图片,下部是图片注释

  - > 鼠标点击覆盖层

  - > 图片框与覆盖层同时渐隐消失

  页面元素

  根据上面的需求设计页面元素如下,这个比较简单,就不多说了。

  Code

<divid="DDoverlay"></div>
<divid="DDimgBox">
  <divclass="imgFrame"><imgsrc=""alt=""/></div>
  <divclass="imgNote"></div>
</div>

  CSS

  样式表简单设计如下:

  Code

#DDoverlay{
  display:none;
  position:fixed;top:0px;left:0px;
  height:100%;width:100%;
  background-color:#000;z-index:1000;
  filter:alpha(opacity=60);opacity:0.6;
}
#DDimgBox{
  display:none;
  position:absolute;
  border:3pxsolid#000;
  background-color:#EEE;
  padding:8px;z-index:1100;
  overflow:hidden;
  /*以下样式实际应用时应省略,这里为演示用*/
  width:602px;
}
#DDimgBox.imgFrame{
  display:block;
  border:1pxsolid#333;
  background-color:#DDD;
  /*以下样式实际应用时应省略,这里为演示用*/
  width:600px;
}
#DDimgBox.imgNote{
  display:block;padding:8px;
  text-align:center;color:#333;
  font-size:12px;height:auto;
}

  

  使用IE6.0的朋友请注意,这里演示效果的js代码没有考虑IE6.0的兼容性,IE6.0中覆盖层将滑到页面最底部,关闭图片框请到页面底部点击灰色覆盖层。

  有时间我再改好,不好意思……

  第二步:准备工具

  根据第一步设计的页面标记与图片效果,我们需要准备一些工具,实现以下功能:

  1. 在文档中获取class属性为"DDbox"标签为<a>的元素,我们可以调用之前介绍过的一个函数hasClass;

  2. 阻止默认事件(本例中为页面跳转)的函数,这一个在之前也介绍过stopDefault函数;

  3. 元素渐现函数和渐隐函数,我们将其取名为fade,待会会尝试去实现;

  4. 考虑到浏览器兼容问题,我们需要封装一个setOpacity函数来设置元素的透明度,用于实现渐隐渐现;

  5. 元素展开函数,这个用之前发布过的natrualSlide可以实现,不过这里我们还是重新写一个比较简单的slide函数;

  6. 当然不要忘了很重要的一点,如何去实现图片框的适宜大小以及居中定位,这里可能会比较复杂。我们要设计一个函数,通过传入元素长和宽来定位居中位置。

  暂时想到这些,接下来一个一个实现

  hasClass函数

  Code

//找出所有具有相同类名的元素
functionhasClass(name,type){
  varr=[];
  varre=newRegExp("(^|s)"+name+"(s|$)");
  vare=document.getElementsByTagName(type||"*");
  for(varj=0;j<e.length;j++)
    if(re.test(e[j].className))
      r.push(e[j]);
  returnr;
};

  这里考虑到一个class属性中可能写入多个class style,所以用正则表达式进行检测而不是直接判断相等。

  stopDefault函数

  Code

//阻止默认事件
functionstopDefault(e){
  if(e&&e.preventDefault)
    e.preventDefault();
  else
    window.event.returnValue=false;
  returnfalse;
}

 由于ie和其他浏览器的兼容问题,这里必须使用两种方式来阻止默认事件。

  setOpacity函数

  Code

//设置元素透明度
functionsetOpacity(elem,level){
  if(elem.filters)
    elem.style.filter='alpha(opacity='+level+')';
  else
    elem.style.opacity=level/100;
}

  第一个分支是处理ie的元素透明度设置,第二个分支是处理其他浏览器的元素透明度设置。

  这里顺便提醒一下,在ie中要使alpha滤镜起作用,必须搭配position:absolute样式设置,否则透明设置可能不起作用。

  fade函数

  Code

//实现渐隐或者渐显动画的函数
//参数:动画元素,开始透明度,结束透明度,动画持续时间
//返回:动画句柄数组
functionfade(elem,startVal,finishVal,time){
  diff=finishVal-startVal;
  vart=time||1000;
  varhandles=[];
  for(vari=0;i<100;i++){
    (function(n){
      handles.push(setTimeout(function(){
        setOpacity(elem,(startVal+diff*n/100));
      },t*n/100));
    })(i);
  }
  returnhandles;
}

  slide函数

  Code

//实现滑动动画的函数,可以实现横/纵向滑动展开/收拢,或者横/纵向滑动位移
//参数:动画元素,动画属性,开始值,结束值,动画持续时间
//动画属性可选值:'top','left','height','left','padding','margin'
//返回:动画句柄数组
functionslide(elem,styleName,startVal,finishVal,time){
  diff=finishVal-startVal;
  vart=time||1000;
  varhandles=[];
  for(vari=0;i<200;i++){
    (function(n){
      handles.push(setTimeout(function(){
        elem.style[styleName]=(startVal+(diff*n/200))+'px';
      },t*n/200));
    })(i);
  }
  returnhandles;
}

 一系列获取当前页面或窗口相关长宽和位置的并具有兼容性的函数

  Code

//获取页面宽度
functionpageWidth(){
  returndocument.body.scrollWidth;
}
//获取页面高度
functionpageHeight(){
  returndocument.body.scrollHeight;
}
//获取浏览器视口高度
functionwindowHeight(){
  varde=document.documentElement;
  returnself.innerHeight||(de&&de.clientHeight)||document.body.clientHeight;
}
//获取浏览器视口宽度
functionwindowWidth(){
  varde=document.documentElement;
  returnself.innerWidth||(de&&de.clientWidth)||document.body.clientWidth;
}
//获取当前向右卷动的长度
functionscrollX(){
  varde=document.documentElement;
  returnself.pageXOffset||(de&&de.scrollLeft)||document.body.scrollLeft;
}
//获取当前像下卷动的长度
functionscrollY(){
  varde=document.documentElement;
  returnself.pageYOffset||(de&&de.scrollTop)||document.body.scrollTop;
}

  getCenterPos函数:通过传入长宽值获取中心位置的left和top值

  Code

functiongetCenterPos(w,h){
  returnnewArray((scrollX()+(windowWidth()-w)/2),(scrollY()+(windowHeight()-h)/2));
}

  第三步:代码实现

  工具都准备得差不多了,开始进入主体编码阶段,首先要创建我们需要的html结构(前文提到的页面元素),并将其添加到body元素的末尾。
 createBox函数

  Code

functioncreateBox(){
  //创建覆盖层DDoverlay
  ol=document.createElement('div');
  ol.id='DDoverlay';
  //创建图片框DDimgBox
  pb=document.createElement('div');
  pb.id='DDimgBox';
  pb.innerHTML='<divclass="imgFrame"><imgsrc=""alt=""/></div><divclass="imgNote"></div>';
  //在body元素内部末尾绑定覆盖层和图片框
  document.body.appendChild(ol);
  document.body.appendChild(pb);
}

  接着获取所有的class为DDbox的<a>标签绑定onclick响应函数。

  Code

  varol=document.getElementById('DDoverlay');
  varbox=document.getElementById('DDimgBox');
  varim=pb.getElementsByTagName('img')[0];
  varnote=pb.getElementsByTagName('div')[1];
  varmg=50;
  varelems=hasClass('DDbox','a');
  for(vari=0;i<elems.length;i++){
    elems[i].onclick=showDDbox;
  }

  其中指定标签click事件的响应函数showDDbox如下:

  Code

  functionshowDDbox(e){
    which=this; //习惯性做法,这样可以避免this在函数闭包里面的误用
    //初始化box里面的一系列元素
    box.style.width='auto';
    box.style.height='auto';
    note.innerHTML=which.rel;
    im.style.height='auto';
    im.style.height='auto';
    im.src=which.href;
    im.alt=which.rel;
    setOpacity(im,0);
    im.onerror=function(){
      alert('图片载入失败!');
    }
    im.onload=function(){
      ol.style.display='block';
      box.style.visibility='hidden';
      box.style.display='block';
      //自适应调整图片长宽
      varboxX=box.clientWidth+mg*2;
      if(boxX>windowWidth()){
        im.style.width=(windowWidth()-20-mg*2)+'px';
        im.style.height='auto';
      }
      varboxY=box.clientHeight+mg*2;
      if(boxY>windowHeight()){
        im.style.height=(windowHeight()-60-mg*2)+'px';
        im.style.width='auto';
      }
      //获取并设置居中位置
      varpos=getCenterPos(box.clientWidth,box.clientHeight);
      box.style.left=pos[0]+'px';
      box.style.top=pos[1]+'px';
      //图片框展开
      varboxHeight=box.clientHeight-15;
      box.style.height='0px';
      box.style.visibility='visible';
      slide(box,'height',0,boxHeight,1000);
      //图片框展开后图片渐现
      setTimeout(function(){
        fade(im,0,1000,1000);
      },1001);
    };
    //阻止默认事件响应函数,即页面跳转
    returnfalse;
  }


  可能有些冗长呵呵,没有仔细推敲。

  另外还要为覆盖层的单击事件绑定一个关闭图片框的函数,这里就简单隐藏掉图片框和覆盖层,不加什么动画效果了。

  Code

  ol.onclick=function(){
    box.style.display='none';
    ol.style.display='none';
  }

  第四步:整理打包