效果: http://lucyhao.com/tags/

hexo自带的tag cloud的标签展现不太美观,想能够展现出“云”效果的标签。在网上找到了d3-cloud这个项目,github地址:https://github.com/jasondavies/d3-cloud demo地址:https://www.jasondavies.com/wordcloud/

hexo生成的是静态博客,所以最后在网上看到的都是静态的内容,也就是说,我们的看到的标签云也是静态的已经生成好的内容,并不会随着刷新页面而重新计算生成另外样式的标签云。

当然d3-cloud这个项目,提供了浏览器端和node端运行的版本,见它的例子,我们可以在客户端运行,也可以在服务端作为 node运行。

如何在hexo搭建的博客系统中使用呢?

(1)hexo中提供的tag cloud.js的方法,在你的blog项目中,node_modules -> hexo ->plugins -> helper -> tagcloud.js

(2)本博客使用的是icarus主题,在主题下的layout->tags.ejs 文件中加载目录tags下面的内容

//这里加载了标签云,tagcloud也就是(1)中tagcloud.js提供的功能
<div class="layout-wrap-inner tag-cloud">
<% if(site.tags.length) { %>
<%- tagcloud() %>
<% } %>
</div>

  

由上所知 ,要修改hexo中的tagcloud, 只要修改tag cloud.js函数就可以啦~

现在我们来看看d3-cloud这个项目,如何把它与tagcloud结合起来。 首先,d3-cloud提供了在浏览器和在服务端运行的方式,见他的例子node.js和browserify.js。两个不同版本的原因,是因为在计算字符串的宽度的时候,利用了canvas的mesureText接口。在d3-cloud的 index.js源码中可以看到,有一行代码是

function cloudCanvas() {
return document.createElement("canvas");//生成虚拟的canvas
}

  

因为在计算标签云的时候,要保证标签之间不重叠,需要知道标签的宽度,高度;而js语言是不具备这个能力可以计算出来的,要不就是借助浏览器,生成一个dom,比如span标签,把字符串的内容放到span中,设置span的属性为字符串需要显示的属性,然后获取span的宽度。在d3-cloud中,则是直接利用canvas的接口来实现的。所以在客户端的版本中,浏览器提供的canvas功能;而在node版本中则需要 node-canvas模块。

由于我们是在hexo的“后台”来运行标签云的算法,得到静态的构造好的标签输出到页面上,所以我们应该选择用node版本。当然也可以用browserify.js版本,毕竟他就是一个运行在浏览器中的js, 放到博客的js中也是可以的,后续会介绍。

利用node-canvas遇到的问题

node-canvas模块的mesureText对于中文的支持有bug,在chrome中,同样的中文字符串"你好"的宽度是33.*;而用node-canvas的到的“你好”的宽度只有8.*

怎么办?我投机取巧的用两个英文字符“ab”代替一个中文字符,然后计算字符串的长度,这样的到的长度只是近似长度。

正式开始修改hexo的到d3-cloud的标签云

(1)安装需要的模块:

$ npm install canvas --save
$ npm install d3-cloud --save
$ npm install d3 --save(可选)

  

(2)找到文件: 你的 blog项目 -> node_modules -> hexo ->plugins -> helper -> index.js

  var tagcloud = require('./tagcloud');
helper.register('tagcloud', tagcloud);
helper.register('tag_cloud', tagcloud);
​
//修改为下面的代码:目的是不直接修改tagcloud.js,保留代码
var tagcloud = require('./tagcloud');
var tagcloudd3 = require('./tagcloudd3');
helper.register('tagcloud', tagcloudd3);
helper.register('tag_cloud', tagcloudd3);

  

(3)新建文件tagcloudd3.js :位置在blog项目 -> node_modules -> hexo ->plugins -> helper -> tagcloudd3.js

(4)tagcloudd3.js的 内容如下:

  • 代码中引用了d3 来给标签fill颜色,可以去掉,也可以像tagcloud一样根据是否需要颜色来设置

'use strict';
​
var Canvas = require("canvas");
var cloud = require("d3-cloud");
var d3 = require("d3");
​
var layout = cloud()//利用d3-cloud计算每个标签的位置
.size([600, 400])
.canvas(function() { return new Canvas(1, 1); })
.padding(7)
.rotate(function() { return ~~(Math.random() * 2) * 90; })
.font("Impact")
.fontSize(function(d) { return d.size; });
var fill = d3.scale.category20();//利用d3的接口给每个标签颜色
​
function tagcloudHelper(tags){
/****与tagcloud.js一样,获得tags 开始***/
if ((!tags || !tags.hasOwnProperty('length'))){
tags = this.site.tags;
}
​
if (!tags || !tags.length) return ''; var result = [];
​
tags = tags.sort('name', 1);
​
// Ignore tags with zero posts
tags = tags.filter(function(tag){
return tag.length;
});
/****与tagcloud.js一样,获得tags 结束***/ //计算标签出现次数最大值,比如,博客中一共有两个标签,一个是hello,一个是world,hello出现2次,world 出现1次,那么maxsize就是2
var maxsize = 1;
​
tags.sort('length').forEach(function(tag){
var length = tag.length;
if(length > maxsize)
maxsize = length;
});
​
//构建传入layout的words
var arr = [],words;
tags.forEach(function(tag){
arr.push({"name": tag.name,"num" : tag.length});
});
words = arr.map(function(d) {
var text = d.name.replace(/[^\x00-\xff]/g,"ab");//对中文的投机处理,用ab代替中文字符
return {name:d.name, text: text, size : Math.log(d.num)/(Math.log(maxsize)-Math.log(1)) * 15 + 30};//size的计算取对数,是为了让标签之间的大小相对平均一些。因为博客侧重前端内容,所以某一些标签会比较多,标签最大最小次数的差距会比较大。 });
layout.words(words);
layout.start();
​
result.push('<svg width="600" height="400"><g transform="translate(300,200)">');
words.forEach(function(word,i){
​
result.push(
'<text text-anchor="middle" fill="'+fill(i)+'" transform="translate('+word.x+','+word.y+')rotate('+
word.rotate+')" style="font-size:'+word.size+'px;font-family:Impact">'+
word.name+
'</text>'
);
});
result.push('</g></svg>'); return result.join(''); }
module.exports = tagcloudHelper;

  

(5)运行hexo

$ hexo s

  

如图所示得到自己的标签云:

(6)上传自己的博客, 没问题以后,就生成静态博客,并上传

$ hexo g
$ hexo d

简单说下在客户端引用d3-cloud

(1) browserify编译d3-cloud提供的browserify.js例子,得到tagtest.js 文件,里面把d3,d3-cloud,d3-dispatch打包到了一起

$ browserify broswerify.js > tagtest.js

(2)把index.js放到目录: 你的主题->source -> js -> tagtest.js

(3)把index引用入到你的主题中 <%- js('js/tagtest') %>

(4)修改tagtest.js中的代码,把words的部分修改成接受传参的形式,在tags.ejs中用site.tags把tags的参数传进去

这样会在博客中增加很多js,个人觉得有点违背了静态博客小而轻的感觉。。。

在hexo静态博客中利用d3-cloud来展现标签云的更多相关文章

  1. 开发小白也毫无压力的hexo静态博客建站全攻略 - 躺坑后亲诉心路历程

    目录 基本原理 方法1 - 本机Windows下建站 (力荐) 下载安装node.js 用管理员权限打开命令行,安装hexo-cli和hexo 下载安装git 初始化hexo 使用hexo gener ...

  2. [5]Hexo静态博客绑定域名及域名解析

    示例: http://zsy.xyz/ 前提预设:[4]Hexo静态博客背景及界面显示优化配置 [3]hexo+github搭建个人博客的主题配置 [2]hexo+github搭建个人博客的简单使用 ...

  3. 在windows下创建基于github的hexo静态博客

    最近边上的人都突然买起了域名搭起了个人网站,渣渣的我介于期末没事干也跟风搭了个静态博客.虽说博客基本不更新T T,嘛嘛回归正题. 首先准备工作: 1)安装nodejs 2)安装msysgit(虽然现在 ...

  4. 搭建hexo静态博客

    使用hexo搭建博客,并将博客部署到github 需要的工具 Node.js Git 一个Github账号 正式开始 在任意目录下新建一个文件夹,如blog,在该文件夹下右键打开git bash he ...

  5. Hexo 静态博客指南:建站教程(中)

    本文最初发布于我的个人博客Bambrow's Blog,采用 BY-NC-SA 许可协议,转载请注明出处.若有后续更新,将更新于原博客.欢迎去我的博客阅读更多文章! 本文详细记录一下站点建立过程,以便 ...

  6. Hexo静态博客搭建教程

    Hexo是一个快速.简洁且高效的博客框架.Hexo 使用 Markdown(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页.生成静态网页可以托管在github.下面简单介绍一下he ...

  7. [4]Hexo静态博客背景及界面显示优化配置

    示例预览:我的主页 前提预设: [3]hexo+github搭建个人博客的主题配置 [2]hexo+github搭建个人博客的简单使用 [1]hexo+github搭建个人博客的过程记录 背景图片添加 ...

  8. Hexo 静态博客指南:建站教程(上)

    本文最初发布于我的个人博客Bambrow's Blog,采用 BY-NC-SA 许可协议,转载请注明出处.若有后续更新,将更新于原博客.欢迎去我的博客阅读更多文章! 本文详细记录一下站点建立过程,以便 ...

  9. 复活hexo静态博客的方法

    我的个人博客http://webhmy.com/是通过hexo搭建的,它支持图片显示,支持md,无需主机空间,可以满足我的大部分需求.但是在2年的使用的过程中遇到一些问题,这里记录下来.便于下次快速复 ...

随机推荐

  1. Objective-C 利用OC的消息机制,使用Method Swizzling进行方法修改

    功能:修改父类不可修改函数方法,函数方法交换 应用场景:假如我们使用的他人提供一个的framework,.m已被打包成二进制.a无法修改源码,只留下.h头文件,那假如代码中某个函数出现了问题可以通过这 ...

  2. [iOS dispatch_once创建单例]

    自苹果引入了Grand Central Dispatch (GCD)(Mac OS 10.6和iOS4.0)后,创建单例又有了新的方法,那就是使用dispatch_once函数,当然,随着演进的进行, ...

  3. 判断请求是不是ajax

    public static bool IsAjaxRequest(HttpRequest request) { if (request == null) { throw new ArgumentNul ...

  4. 用批处理批量编译多个解决方案(.sln)

    批处理编译解决方案(.sln) @echo off path %SYSTEMROOT%\Microsoft.NET\Framework64\v4.0.30319\ echo 正在生成HelloWorl ...

  5. Oracle 子查询

    1.子查询在SELECT.UPDATE.DELETE语句内部可以出现SELECT语句.内部的SELECT语句结果可以作为外部语句中条件子句的一部分,也可以作为外部查询的临时表.子查询的类型有: ① 单 ...

  6. 第三次个人作业——关于K米(Andorid)的案例分析

    第三次个人作业--关于K米(Andorid)的案例分析 1.K米简介 官方网址:http://www.ktvme.com/ 2.评测 2.1.上手体验 带着找bug的心态,兴致勃勃地开始体验 K米.打 ...

  7. Python基本数据类型之int

    一.int的范围 2.7: 32位:-2^31~2^31-1 64位:-2^63~2^63-1 3.5: 在3.5中init长度理论上是无限的 二.python内存机制 在一般情况下当变量被赋值后,内 ...

  8. bootstrap学习总结-05 常用标签3

    1 单选框,多选框 1)单选框 单选框(radio)用于从多个选项中只选择一个.设置了 disabled 属性的单选或多选框都能被赋予合适的样式.对于和多选或单选框联合使用的 <label> ...

  9. dotnetbar入门

    1.下载dotnetbar组件 2.工具箱引用 3.项目引用 4.开始工作 //此处Form完整的名称是System.Windows.Forms.Form,表示FrmMain窗体类是继承于System ...

  10. MyEclipse快捷键大全(绝对全)

    存盘 Ctrl+s(肯定知道) 注释代码 Ctrl+/ 取消注释 Ctrl+\(Eclipse3已经都合并到Ctrl+/了) 代码辅助 Alt+/ 快速修复 Ctrl+1 代码格式化 Ctrl+Shi ...