眾所周知,比較古老的圓角的做法是通過表格和圖像構成。但隨著AJAX的流行、CSS + DIV的頁面布局技術的風靡,古老的做法顯得蒼白無力,所以人們不斷尋求改進的方法。本文的實現就是一種現在比較流行的做法。
實現原理
其實這種方法的原理很簡單——在要圓角的元素的上下堆放一些邊緣(MARGIN)不同的<DIV>元素(也有的使用其它元素的,如<B>等,不過原理是一樣的),如下圖所示:
清單1 原理圖
接下來的問題就是計算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 運行截圖
總結
以上代碼只作拋磚引玉之用,所以還有很多功能沒有實現。