<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    如鵬網(wǎng) 大學(xué)生計(jì)算機(jī)學(xué)習(xí)社區(qū)

    CowNew開源團(tuán)隊(duì)

    http://www.cownew.com 郵件請聯(lián)系 about521 at 163.com

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

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


    最理想的實(shí)現(xiàn)方式是使用imagettftext計(jì)算字符串使用特定字體顯示的寬度:
    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];
    }

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

    $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 如鵬網(wǎng) 在校不迷茫,畢業(yè)即輝煌");
    }
    $t1=microtime(true)-$begin;
    echo 'imagettftext:'.$t1.'<br/>';
    $begin=microtime(true);
    for($i=0;$i<10000;$i++)
    {
    strlen("rupeng.com 如鵬網(wǎng) 在校不迷茫,畢業(yè)即輝煌");
    }
    $t2=microtime(true)-$begin;
    echo 'strlen:'.$t2.'<br/>';

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

    運(yùn)行后發(fā)現(xiàn)imagettftext的運(yùn)行時間是strlen的4000多倍,太慢了,而且CPU占用率非常高,因此被否定。

    經(jīng)過觀察發(fā)現(xiàn)arial字體下,漢字的寬度是一致的,而1、i、l等字符的寬度大約是漢字的0.4倍,而阿拉伯?dāng)?shù)字(除了1)的寬度則是漢字的約0.7倍,小寫字母(除了i、l等)的寬度是漢字的約0.7倍,大寫字母則是漢字的0.8倍,其他字符也可以得出相應(yīng)的倍率。因此我編寫了下面程序用來計(jì)算字符串占的寬度(單位是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);
    }

    經(jīng)過大量的測試,發(fā)現(xiàn)和imagettftext的運(yùn)行結(jié)果非常接近,而速度則比imagettftext高很多,CPU占用率也低很多。
    解決思路對于其他語言,比如C#、Java等都適用。

    posted on 2009-11-15 14:06 CowNew開源團(tuán)隊(duì) 閱讀(3917) 評論(5)  編輯  收藏

    評論

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

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

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

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

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

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


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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 久久久久免费看黄a级试看| 免费国产高清毛不卡片基地| 中国毛片免费观看| 亚洲美日韩Av中文字幕无码久久久妻妇| 亚洲精品无码少妇30P| 亚洲AV无码成人专区| 麻豆国产精品免费视频| www.91亚洲| 一级成人a做片免费| 国产亚洲?V无码?V男人的天堂| 亚洲一区中文字幕在线电影网| 最近高清中文字幕免费| 亚洲一级免费毛片| 成人免费无码大片A毛片抽搐| 亚洲经典千人经典日产| 亚洲国产精品不卡毛片a在线| www成人免费视频| 国产偷v国产偷v亚洲高清| 久久99热精品免费观看牛牛| 亚洲沟沟美女亚洲沟沟| 国外成人免费高清激情视频| 美女被免费网站在线视频免费 | 久久乐国产精品亚洲综合| 中出五十路免费视频| 亚洲成在人天堂在线| 免费AA片少妇人AA片直播| 亚洲人成人伊人成综合网无码| 免费观看日本污污ww网站一区| 大妹子影视剧在线观看全集免费| 亚洲av午夜福利精品一区| 国产四虎免费精品视频| 亚洲a∨无码精品色午夜| 亚洲女初尝黑人巨高清| 国内精自视频品线六区免费| 亚洲欧洲精品成人久久曰| 国产成人亚洲精品狼色在线| 日韩免费精品视频| 国产福利电影一区二区三区,免费久久久久久久精 | 久久国产亚洲电影天堂| 久久不见久久见中文字幕免费| AV激情亚洲男人的天堂国语|