隨筆-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 閱讀(6549) 評論(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 | 小孩
          好  回復  更多評論
            
          主站蜘蛛池模板: 茶陵县| 东台市| 东丽区| 铜山县| 贵州省| 吐鲁番市| 泸州市| 游戏| 宾川县| 揭东县| 丹阳市| 泸州市| 石河子市| 阿巴嘎旗| 塘沽区| 保德县| 建湖县| 苏尼特右旗| 安岳县| 马尔康县| 贞丰县| 惠水县| 金堂县| 同仁县| 遂宁市| 天峨县| 九江市| 通辽市| 北京市| 巴塘县| 政和县| 昭苏县| 仙游县| 阿拉善左旗| 砀山县| 都匀市| 二手房| 于都县| 朝阳区| 望都县| 西乌珠穆沁旗|