<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)航:
     
    主站蜘蛛池模板: 亚洲精品美女久久久久久久| 亚洲国产精品无码专区| 亚洲女人初试黑人巨高清| 国产一区二区三区免费| 国产亚洲av片在线观看播放| 日韩在线免费视频| 97se亚洲综合在线| 99蜜桃在线观看免费视频网站| 国产精品亚洲а∨无码播放| 东方aⅴ免费观看久久av| 国产亚洲精品a在线观看app| 免费污视频在线观看| 久久亚洲伊人中字综合精品| 久久综合给合久久国产免费| 久久99亚洲网美利坚合众国 | 黄色免费在线网址| 亚洲&#228;v永久无码精品天堂久久 | 免费高清小黄站在线观看| 亚洲成av人在线观看网站| 国产精品公开免费视频| 人成电影网在线观看免费| 亚洲中文字幕无码久久综合网| 野花香高清视频在线观看免费| 精品无码一区二区三区亚洲桃色| 黄页网站免费观看| 亚洲AV网一区二区三区| 亚洲精品亚洲人成人网| a拍拍男女免费看全片| 亚洲精华国产精华精华液好用| heyzo亚洲精品日韩| 久久这里只精品99re免费| 国产成人亚洲精品| 亚洲国产aⅴ综合网| 日韩av无码久久精品免费| 亚洲欧美日韩中文无线码| 亚洲午夜精品一级在线播放放| 在线观看亚洲电影| 亚洲成色www久久网站夜月| 97热久久免费频精品99| 一级毛片正片免费视频手机看| 亚洲爱情岛论坛永久|