如鹏网 大学生计算机学习社区

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开源团队 阅读(3855) 评论(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
太厉害了,不过我绝对不用  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: