zoukankan      html  css  js  c++  java
  • 在hexo静态博客中利用d3-cloud来展现标签云

    效果: 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
    

      

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

    tags

    (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,个人觉得有点违背了静态博客小而轻的感觉。。。

  • 相关阅读:
    metal的gpu query
    体积雾 global fog unity 及改进
    hdr rt format对颜色的影响
    unity deferred lighting
    unity linear space时 photoshop blend的正确设置
    unity linear work flow
    一些数据 bandwidth之类
    deferred rendering with msaa
    unity 显示mipmaplevel
    【转】在C#中使用SendMessage
  • 原文地址:https://www.cnblogs.com/lilyimage/p/5207697.html
Copyright © 2011-2022 走看看