如鵬網 大學生計算機學習社區

          CowNew開源團隊

          http://www.cownew.com 郵件請聯系 about521 at 163.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            363 隨筆 :: 2 文章 :: 808 評論 :: 0 Trackbacks

          php中可以使用strlen或者mb_strlen計算字符串的長度,但是這些長度計算的都是在計算機中表示的長度,并不是實際在屏幕上顯示的寬度。如下圖(使用的是arial字體):


          最理想的實現方式是使用imagettftext計算字符串使用特定字體顯示的寬度:
          function tf_strlen($str)
          {
           return ceil(tf_strwidth($str)/tf_strwidth('測'));
          }
          function tf_strwidth($str)
          {
           $im=imagecreatetruecolor(10,10);
           $r=imagettftext($im, 12, 0, 5, rand(14, 16),0, 'arial.ttf', $str);
           return $r[2]-$r[0];
          }

          需要在本地計算機的字體文件夾中找到'arial.ttf',然后上傳到php頁面同級的目錄下。這樣調用tf_strlen得到的就是字符串在屏幕上的顯示寬度了。但是因為imagettftext是GD級別的操作,因此效率非常低,編寫下面的程序驗證

          $begin=microtime(true);
          $im=imagecreatetruecolor(1000,1000);
          for($i=0;$i<10000;$i++)
          {
          imagettftext($im, 12, 0, 5, rand(14, 16),0, 'arial.ttf', "rupeng.com 如鵬網 在校不迷茫,畢業即輝煌");
          }
          $t1=microtime(true)-$begin;
          echo 'imagettftext:'.$t1.'<br/>';
          $begin=microtime(true);
          for($i=0;$i<10000;$i++)
          {
          strlen("rupeng.com 如鵬網 在校不迷茫,畢業即輝煌");
          }
          $t2=microtime(true)-$begin;
          echo 'strlen:'.$t2.'<br/>';

          echo $t1/$t2.'<br/>';

          運行后發現imagettftext的運行時間是strlen的4000多倍,太慢了,而且CPU占用率非常高,因此被否定。

          經過觀察發現arial字體下,漢字的寬度是一致的,而1、i、l等字符的寬度大約是漢字的0.4倍,而阿拉伯數字(除了1)的寬度則是漢字的約0.7倍,小寫字母(除了i、l等)的寬度是漢字的約0.7倍,大寫字母則是漢字的0.8倍,其他字符也可以得出相應的倍率。因此我編寫了下面程序用來計算字符串占的寬度(單位是1/2的中文寬度)。

          function arial_strlen($str)
          {
           $lencounter=0;
           for($i=0;$i<strlen($str);$i++)
           {
            $ch=$str[$i];
            if(ord($ch)>128)
            {
             $i++;
             $lencounter++;
            }
            else if($ch=='f'||$ch=='i'||$ch=='j'||$ch=='l'||$ch=='r'||$ch=='I'
            ||$ch=='t'||$ch=='1'
            ||$ch=='.'||$ch==':'||$ch==';'||$ch=='('||$ch==')'
            ||$ch=='*'||$ch=='!'||$ch=='\'')
            {
             $lencounter+=0.4;
            }
            else if($ch>='0'&&$ch<='9')
            {
             $lencounter+=0.7;
            }
            else if($ch>='a'&&$ch<='z')
            {
             $lencounter+=0.7;
            }
            else if($ch>='A'&&$ch<='Z')
            {
             $lencounter+=0.8;
            }  
            else
            {
             $lencounter++;
            }
           }
           return ceil($lencounter*2);
          }

          經過大量的測試,發現和imagettftext的運行結果非常接近,而速度則比imagettftext高很多,CPU占用率也低很多。
          解決思路對于其他語言,比如C#、Java等都適用。

          posted on 2009-11-15 14:06 CowNew開源團隊 閱讀(3928) 評論(5)  編輯  收藏

          評論

          # re: 計算文字在HTML中的顯示寬度 2009-11-15 17:54 杜國
          挺有意思的技術。

          不過這么復雜的技巧在實際應用中會很難以維護,特別對于不同瀏覽器/版本,不同字體,不同操作系統。 最好還是依賴瀏覽器自身的寬度控制width/overflow等來實現比較保險。  回復  更多評論
            

          # re: 計算文字在HTML中的顯示寬度 2009-11-15 19:59 CowNew開源團隊
          @杜國
          謝謝指教。不過像“文章列表中的標題長度不足部分用省略號,但是要盡可能用能用的空間顯示盡可能長的標題”這樣的需求怎么能滿足呢?  回復  更多評論
            

          # re: 計算文字在HTML中的顯示寬度 2009-11-16 10:07 Lancelot
          用CSS控制  回復  更多評論
            

          # re: 計算文字在HTML中的顯示寬度 2009-11-16 11:22 主任
          @Lancelot
          怎么樣用css控制字符串的長短?請指教。  回復  更多評論
            

          # re: 計算文字在HTML中的顯示寬度 2009-11-17 11:30 Ranker
          太厲害了,不過我絕對不用  回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 平安县| 建宁县| 万载县| 宜阳县| 织金县| 淮南市| 阳高县| 陕西省| 霞浦县| 澄迈县| 阜阳市| 衡山县| 会理县| 仁怀市| 巩留县| 南阳市| 筠连县| 永登县| 乌鲁木齐县| 彩票| 平乡县| 乌海市| 当涂县| 宁强县| 绥阳县| 梅河口市| 油尖旺区| 江北区| 广平县| 茶陵县| 临潭县| 连云港市| 东乡族自治县| 平江县| 镇安县| 峨山| 怀安县| 阿拉善盟| 化州市| 色达县| 临夏县|