最近在弄个 blogbus 的模板,折腾了几天,难产 again…暂时性转移到另一个 idea 上来,给 blogbus 的 tags 输出做成 tag clouds( 标签云 ) 效果。什么是 Tag 呢? 自己去看 blogbus 的 help 吧。什么是 Tag Clouds 呢? 请看下面这个效果图,tag 文字大小依据使用频率多少区分开来,使用 Tag Clouds 可以更清楚的传达 what’s your blog all about,更多的信息看 SmashingMagazine 的这篇文章 Tag Clouds Gallery: Examples And Good Practices 吧。

Blogbus 的 tag 输出方式是固定的,排列顺序由使用最多的到使用最少的,你可以设定显示 tag 的数目,为了更好的 Tag Clouds 效果,建议设置显示数目大点 ( 太大了,也不是件好事,至于为什么,我待会再说 )。正是因为 Blogbus 的封装处理,要 hack 这种 Tag Clouds 效果只能从 javascript+CSS 入手了 (:此 hack 不适用于旧版 blogbus 模板系统 )

JAVASCRIPT 部分

<script type="text/javascript">
function tagClouds(id, maxsize, minsize) {
  if (!document.getElementById || !document.getElementsByTagName) return;
  if (!document.getElementById(id)) return;

  var taglist = document.getElementById(id);
  var tag = taglist.getElementsByTagName('li');
  var maxcount = parseInt(tag[0].getElementsByTagName('span')[0].firstChild.nodeValue.substring(1,3));
  var mincount = parseInt(tag[tag.length-1].getElementsByTagName('span')[0].firstChild.nodeValue.substring(1,3));
  var offset = (maxsize-minsize)/(maxcount-mincount);

  for (var i=0;i<tag.length;i++) {
    var count = parseInt(tag[i].getElementsByTagName('span')[0].firstChild.nodeValue.substring(1,3));
    var weight = (count-mincount)*offset+minsize;
    tag[i].getElementsByTagName('a')[0].style.fontSize = weight+'em';
  };
}

window.onload = function() {
  tagClouds('tags', 2.2, 1); 
  //2.2 和 1 分别为 TagClouds 的最大字号与最小字号值,2.2 表示是普通字号的 2.2 倍
}
</script>

上面这段代码加哪的话你还是看我第一篇 hack 吧。补充一点,如果你也用了我那个”保存评论框信息”的脚本的话,你可以把这两段代码都放到一个 <script type="text/javascript"> ... </script> 中间,两段 window.onload 可以合并为如下格式,并放到代码的最后面。

window.onload = function() {
  tagClouds('tags', 2.2, 1);
  rememberFormInputs('commentForm','input_',120); //另一个脚本程序
}

CSS 部分

将以下代码加入到 blogbus 模板里的 CSS 处:

#tags ul li {display:inline;margin-left:6px;}

#tags ul li span{display:none;} /*如果你不希望显示诸如[36]的 tag 使用次数的话*/

HACK 说明

hack 思路解释

因为是 hack,不是 tutorial,我只说下前面那段 javascript 的思路就是了。求出最大使用频率 tag 与最小使用频率 tag 之间的使用数差值,然后通过你所设置的 maxsizeminsize 之差除以 tag 使用数差值求得位移量。利用 for 循环来算出每个 tag 比最小使用频率 tag 的位移量多多少,再赋予 CSS 中的 font-size 属性,实现字号的不同。

其中要注意的是,因为我用的是 parseInt(*.substring(1,3)),意思是从那个类似于 [36] 的使用频率中截取出数字来,再把 string 转化为 int 型。也就是说,如果你自定义了 [36] 的显示方式为其他的,就可能需要重新调整 substring(1,3) 中的两个 value 了,substring 的意思是截取第 i+1 个字符到第 j 个字符。例如你自定义的显示方式是 ||36|| 的话,那需要截取的是第 3,第 4 个字符,substring(1,3) 相应调整为 substring(2,4)

CSS 中定义的 #tags ul li {display:inline;} 是为了实现横排,因为 li 默认是 block 级别,每一个 li 占了一行,而 inline 值只会占据其内容宽度。

你可以自己更改 window.onload() ...tagClouds('tags', 2.2, 1) 后面的两个数值大小,它们一个是最大字号,一个是最小字号。我在 javascript 里设置的 font-size 用的是 em 单位,而不是 px,因为 empx 在字号控制上灵活的多。用 px 的话,我们只能设置整数值,而 em 的话,它其实是当前普通字号的倍数值,例如默认的 li 字号可能是 12px,那么一个较大使用频率的 tag,它的字号倍数是 1.9 的话,相应的大小就是 12px*1.9=22.8px 了,比起直接使用 px 灵活的多。我的 blog 上字号设置用的就都是 em !

The Downside of this Script

正如我刚才说的,Tag 的显示条目数并非越大越好,因为每增加一个 tag 显示条目数,就意味着程序要多运算一次。而 Javascript 的运算负担是完全由客户端来承担的,假如你用上千个 tag,你把它们都显示出来的话,那浏览者在看你的页面时,光是载入运算那个 javascript 就要花上不少时间,一般来说,数十个 tag 还是可以接受的,别忘了电脑的运算速度比人脑快哦!