随笔-34  评论-1965  文章-0  trackbacks-0
MMIS Prototype

众所周知,比较古老的圆角的做法是通过表格和图像构成。但随着AJAX的流行、CSS + DIV的页面布局技术的风靡,古老的做法显得苍白无力,所以人们不断寻求改进的方法。本文的实现就是一种现在比较流行的做法。

实现原理

其实这种方法的原理很简单——在要圆角的元素的上下堆放一些边缘(MARGIN)不同的<DIV>元素(也有的使用其它元素的,如<B>等,不过原理是一样的),如下图所示:

原理图
清单1 原理图

接下来的问题就是计算margin的长度。这也不难只要运用一下初中所学的勾股定理便可以求出来,如下图所示:

MARGIN求解图
清单2 MARGIN求解图

具体编码

下面该工具类的源码:

var Corner = {
   
// 标志圆角位置的旗标
   TOP_LEFT:     0x1 ,
   TOP_RIGHT:    
0x2 ,
   BOTTOM_LEFT:  
0x4 ,
   BOTTOM_RIGHT:
0x8 ,
   ALL:          
0xf ,
   
   
/* *******************************************************
   * target: 要圆角的目标元素
   * radius: 圆角的半径,默认值为5
   * flags: 圆角位置的旗标或其组合,默认值为全部
   * backgroundColor: 圆角的背景色,默认值为目标元素的背景色
   *******************************************************
*/

   round:
function (target, radius, flags, backgroundColor) {
       
var t = $(target);
       
var r = radius || 5 ;
       
var f = flags || Corner.ALL;
       
var c = Element.getStyle(t, 'backgroundColor');
       
var b = backgroundColor || c;
       
       
// 修正在IE里元素样式为FLOAT时,圆角DIV宽度为0的BUG
        var ft = Element.getStyle(t, ' float ');
       
if (navigator.appVersion.match( / \bMSIE\b / ) && ft != 'none' && ! t.style.width) {            
           Element.setStyle(t,
{ width: Element.getWidth(t) + 'px' } );
       }

       
       
// 创建DIV,并把目标元素的内容剪切到其中
        var d = document.createElement('div');          
       d.innerHTML
= t.innerHTML;
       t.innerHTML
= '';        
       
       
// 设置新DIV的背景色为目标元素的背景色,并目标元素为透明背景
       Element.setStyle( d, { backgroundColor: c } );      
       Element.setStyle( t,
{ backgroundColor: 'transparent' } );      
       
       
// 设置新DIV的高度为目标元素的高度
        var h = t.style.height;
       
var nh = 0 ;
       
if (h) {
           Element.setStyle( d,
{ height: h } );
           nh
= parseInt(h);
       }
                   
       
       
// 设置新DIV的缩进
        var p = Element.getStyle(t, 'padding');
       
if (p) {
           Element.setStyle( d,
{ padding: p } );            
           Element.setStyle( t,
{ padding: '0px 0px 0px 0px' } );
       }
         
       
       
// 创建用于新DIV和圆角DIV的文档片段,这样避免每次设置元素样式或添加新元素时重绘页面,提高效率
        var ds = document.createDocumentFragment();                
       
var ls = null ;
       
// 创建顶部圆角DIV
        if (f & (Corner.TOP_LEFT | Corner.TOP_RIGHT)) {
           ls
= Corner._createRoundFragment(r, f, b , false );            
           ds.appendChild(ls);             
           nh
+= r;
       }
       
       
       ds.appendChild(d);
       
       
// 创建底部圆角DIV
        if (f & (Corner.BOTTOM_LEFT | Corner.BOTTOM_RIGHT)) {
           ls
= Corner._createRoundFragment(r, f, b, true );            
           ds.appendChild(ls); 
           nh
+= r;
       }
 
       
       
if (h) {
           Element.setStyle( t,
{ height: nh + 'px' } );      
       }
       
       
       t.appendChild(ds);   
   }
,
   
   _createRoundFragment:
function (r, f, c, b) {
       
var ls = document.createDocumentFragment();
       
var l = null ;
       
var m = ml = mr = null ;
       
var j = 0 ;
       
for (i = 1 ; i <= r; i ++ ) {
           l
= document.createElement('div');
           
           
// 计算margin
           j = b ? i : r - i + 1 ;
           m
= Math.sqrt(r * r - j * j);            
           m
= Math.round(r - m) + 'px';
           
           
if (b) {
               ml
= f & Corner.BOTTOM_LEFT ? m : '0px';
               mr
= f & Corner.BOTTOM_RIGHT ? m : '0px';            
           }
else {
               ml
= f & Corner.TOP_LEFT ? m : '0px';
               mr
= f & Corner.TOP_RIGHT ? m : '0px';            
           }

           Element.setStyle( l,
{ backgroundColor: c,
                                  fontSize: '1px',
                                  height: '1px',                                   
                                  marginLeft: ml,
                                  marginRight: mr,
                                  overflowX: 'hidden',
                                  overflowY: 'hidden' }
);
           ls.appendChild(l);
       }

       
return ls;
   }

}
清单3 实现代码

因为Javascript是没有方法重写的,所以当你调用Corner.round('div1')和调用Coner.round('div1', 20)是一样的,它们最终调用的都是Corner.round(target, radius, flags, backgroundColor),只过没有赋值的参数会为undefined。这里有一个小技巧,就var r = radius || 5,这里的“||”符号表示如果radius为undefined、null或0等值时,r的取值为5。

接着让我们看看运行的页面代码:

<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
   
< title > RounderCorner Prototype </ title >   
   
< script type ="text/javascript" src ="scripts/prototype-1.5.0.js" ></ script >
   
< script type ="text/javascript" src ="scripts/Corner.js" ></ script >
   
< script type ="text/javascript" >
   
// <![CDATA[      
    Event.observe(window, 'load', init, false );
    
   
function init() {        
        Corner.round('div1');
        Corner.round('div2',
20 , Corner.TOP_LEFT | Corner.BOTTOM_RIGHT);
        Corner.round('div3',
20 , Corner.ALL, 'Red');
    }

   
// ]]>
    </ script >    
</ head >
< body >
   
< div id ="div1" style ="width: 318px; height: 103px; background-color: #ffcccc" >
        Corner.round('div1');
</ div >
   
< br />
   
< div id ="div2" style ="width: 317px; height: 100px; background-color: #cccccc" >
        Corner.round('div2', 20, Corner.TOP_LEFT | Corner.BOTTOM_RIGHT);
</ div >
   
< br />
   
< div id ="div3" style ="width: 315px; height: 100px; background-color: #ccffcc" >
        Corner.round('div3', 20, Corner.ALL, 'Red');
</ div >

</ body >
</ html >
清单4 测试代码

上述代码很简单明了,相信大家都明白。下面看一下运行截图吧。

运行截图
清单5 运行截图

总结

以上代码只作抛砖引玉之用,所以还有很多功能没有实现。

posted on 2007-03-23 01:37 Max 阅读(6524) 评论(12)  编辑  收藏 所属分类: 方法与技巧(Tips & tricks)

评论:
# re: 基于Prototype的圆角工具类[未登录] 2007-03-23 09:31 | ronghao
好文  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2007-03-23 10:33 | BeanSoft
真的很有创意哦!  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2007-03-23 12:45 | dennis
very good.刚好可以用上  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2007-03-23 23:44 | cresposhi
google是这样做的,不过没搞这么复杂。。。初中学的勾股定理都出来了,呵呵。。。支持楼主  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2007-03-24 22:37 | Max
@cresposhi
数学还很有用的:-)  回复  更多评论
  
# re: 基于Prototype的圆角工具类[未登录] 2007-06-28 15:54 | wind
作为一个对程序也比较感兴趣的美工,我要说 这真是吃饱了撑的,我们应该把有限的精力放在更有用的地方,这些圆角问题按标准化说是样式问题,用比较简单的css就可以实现比较灵活的效果,弄成这么复杂真是有点呐个了  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2007-06-29 00:24 | Max
@wind
我是一个对美工也比较感兴趣的程序员,对于程序进行圆角的方法在当今还是很流行的,它比传统的做法要更灵活,更AJAX。
你可以参考一下http://www.ruzee.com/blog/shadedborder这位高手的做法是用一个1x1大小的div画圆角,达到反锯齿的效果。  回复  更多评论
  
# re: 基于Prototype的圆角工具类[未登录] 2007-09-06 12:41 | tin
这种做法有局限:
1、它需要bind在window.onload上,所以在速度不是很快的时候会闪。不像传统的css是随下载逐渐解释显示的。
2、它还是高度污染了html结构,个人不是非常认同动态dom修改的方案。因为理想的说css是表现,js是行为,只有非常必要的情况下才可以考虑相互的侵入。  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2008-08-03 00:09 | Oscar Tang
我觉得这样做太笨了~~  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2008-08-21 14:37 | 胡文飞
博主非常感谢你的文章,我最近一直想学struts2.0,只是没有什么好的入门教程,看到你的文章感觉非常的好!谢谢!  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2010-09-26 12:05 | 风里面
姐 你真的很牛。。  回复  更多评论
  
# re: 基于Prototype的圆角工具类 2013-11-07 12:10 | 小孩
好  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: