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

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

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

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

          公告

          “如鵬教育”(http://www.RuPeng.com )是一個(gè)為計(jì)算機(jī)、信息等IT類(lèi)專(zhuān)業(yè)在校大學(xué)生服務(wù)的學(xué)習(xí)社區(qū)。 每周舉辦免費(fèi)講座,為大一新生答疑解惑,幫大二、大三學(xué)生解決學(xué)習(xí)問(wèn)題,幫同學(xué)提高實(shí)戰(zhàn)開(kāi)發(fā)能力,幫大四學(xué)生增強(qiáng)求職技巧,成功應(yīng)聘名企。

          常用鏈接

          留言簿(83)

          隨筆分類(lèi)

          隨筆檔案

          新聞檔案

          相冊(cè)

          友情鏈接

          團(tuán)隊(duì)成員

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

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


          最理想的實(shí)現(xiàn)方式是使用imagettftext計(jì)算字符串使用特定字體顯示的寬度:
          function tf_strlen($str)
          {
           return ceil(tf_strwidth($str)/tf_strwidth('測(cè)'));
          }
          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頁(yè)面同級(jí)的目錄下。這樣調(diào)用tf_strlen得到的就是字符串在屏幕上的顯示寬度了。但是因?yàn)閕magettftext是GD級(jí)別的操作,因此效率非常低,編寫(xiě)下面的程序驗(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)行時(shí)間是strlen的4000多倍,太慢了,而且CPU占用率非常高,因此被否定。

          經(jīng)過(guò)觀察發(fā)現(xiàn)arial字體下,漢字的寬度是一致的,而1、i、l等字符的寬度大約是漢字的0.4倍,而阿拉伯?dāng)?shù)字(除了1)的寬度則是漢字的約0.7倍,小寫(xiě)字母(除了i、l等)的寬度是漢字的約0.7倍,大寫(xiě)字母則是漢字的0.8倍,其他字符也可以得出相應(yīng)的倍率。因此我編寫(xiě)了下面程序用來(lái)計(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)過(guò)大量的測(cè)試,發(fā)現(xiàn)和imagettftext的運(yùn)行結(jié)果非常接近,而速度則比imagettftext高很多,CPU占用率也低很多。
          解決思路對(duì)于其他語(yǔ)言,比如C#、Java等都適用。

          posted on 2009-11-15 14:06 CowNew開(kāi)源團(tuán)隊(duì) 閱讀(3927) 評(píng)論(5)  編輯  收藏

          評(píng)論

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

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

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

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

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

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


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 大方县| 富锦市| 泽州县| 长岭县| 临清市| 河源市| 锡林郭勒盟| 望城县| 政和县| 五莲县| 平安县| 漳州市| 兰考县| 尼木县| 山阳县| 新昌县| 铁力市| 乌拉特前旗| 博白县| 望城县| 横峰县| 盖州市| 浑源县| 玉田县| 阳原县| 承德县| 安岳县| 梁山县| 门源| 惠水县| 若尔盖县| 余姚市| 耿马| 济阳县| 策勒县| 桦南县| 安陆市| 万盛区| 永靖县| 新乐市| 阜城县|