はてなブログのカテゴリーをタグクラウドにしてトップページに表示する cms-style(番外)

はてなブログのカテゴリーをタグクラウドにしてトップページに表示する cms-style(番外)

当サイトは、はてなブログに WordPress風の自作テーマをあてていますが、トップページをどうしようかと悩んだ末、タグクラウドを表示することにしました。

すでに完成していますのでトップページを見ていただければどういうものかわかると思いますが、Javascript でカテゴリーをタグクラウド風に再構成したものです。

はてなブログのカテゴリーはサイドバーに表示するようになっていますので、そのままの位置でよければ CSS だけでそれらしく出来ますが、表示位置を変えようとしますとどうしても DOM操作が必要になります。

完成イメージ

まずは完成イメージ、こんな感じです。目立つように派手に色付けして背景を黒にして言いますが、すべて CSS で指定変更できます。

これは画像です

この画像の見た目を参考にしています。

やっていることは、

  • カスタマイズ > サイドバー にカテゴリーモジュールを表示する
  • モジュールから a要素を取り出し、記事数によりクラス名を付与する
  • 記事数はツールチップで表示用に title属性に移す
  • 記事数により、少 → 多 → 少 と並べ替える
  • クラス名により文字色、文字サイズを指定する

という手順です。

カテゴリーをタグクラウドにする Javascript

サンプルでのタグクラウド表示先は、カスタマイズ > ヘッダ に以下を入れ、タイトルと記事の間に入れています。

<div id="tagcloud"></div>

表示先は、サイドバーでも、記事中でも、上の html を入れておけば表示されるはずです。

<script>
(function(){


    // 記事数によるクラス名のための変数(各数値以上に tagXXXL,tagXXL,tagXL,tagL,tagM,tagS,tagXS,tagXXS,tagXXXS)
    var xxxl = 120, xxl = 80, xl = 50, l =30, m = 20, s = 10, xs = 7, xxs = 3;
    
    // カテゴリーモジュールを取り出す
    var moduleCategories = document.getElementsByClassName('hatena-module-category')[0];
    
    // カテゴリーモジュールを非表示にしておく(css で .hatena-module-category{display:none;}とすればいらない)
    moduleCategories.style.display = 'none';
    
    // タグクラウドの表示先
    var target = document.getElementById('tagcloud');


    var tags = new Array();
    var fragment = document.createDocumentFragment();
    
    // カテゴリーの a要素を取り出し、記事数によりクラス名付与
    var categories = moduleCategories.getElementsByTagName('a');
    for( i=0; i<categories.length; i++ ){
    
        // 記事数を取り出しつつ、カテゴリー名から記事数削除(他にいい方法なかな?)
        var array = categories[i].textContent.match(/\s\(([0-9]{1,})\)/);
        categories[i].textContent = categories[i].textContent.replace(/\s\(([0-9]{1,})\)/, '');
        
        // serAttribute より classList.add の方が若干早そう
        switch(true){
            case array[1] >= xxxl:
                categories[i].setAttribute('class', 'tagXXXL');
                break;
            case array[1] >= xxl:
                categories[i].setAttribute('class', 'tagXXL');
                break;
            case array[1] >= xl:
                categories[i].setAttribute('class', 'tagXL');
                break;
            case array[1] >= l:
                categories[i].setAttribute('class', 'tagL');
                break;
            case array[1] >= m:
                categories[i].setAttribute('class', 'tagM');
                break;
            case array[1] >= s:
                categories[i].setAttribute('class', 'tagS');
                break;
            case array[1] >= xs:
                categories[i].setAttribute('class', 'tagXS');
                break;
            case array[1] >= xxs:
                categories[i].setAttribute('class', 'tagXXS');
                break;
            default:
                categories[i].setAttribute('class', 'tagXXXS');
        }
        
        // 記事数をツールチップで表示よう title属性に指定
        categories[i].setAttribute('title', array[1] + ' 本の記事');
        
        // 各タグホバーエフェクトのために親要素にクラス名を付与/削除する
        categories[i].addEventListener('mouseover', function(){ target.classList.add('hover'); });
        categories[i].addEventListener('mouseout', function(){ target.classList.remove('hover'); });


        // 記事数と a要素を連想配列に入れる
        tags[i] = {num:array[1], link:categories[i]};
    }


    // 連想配列を記事数で昇順ソートする
    tags = tags.sort(function(a, b){
        return a.num - b.num;
    });


    // 記事数の多い記事が中央になるように山形に並べ直す(他にいい方法ないかな?)
    var tmp = new Array();
    var j = 0;
    for ( i=0; i<tags.length; i++){
        if(i % 2 == 0) {
            fragment.appendChild(tags[i].link);
        } else {
            tmp[j] = tags[i].link;
            j++;
        }
    }
    for ( i=tmp.length-1; i>=0; i--){
        fragment.appendChild(tmp[i]);
    }
    
    // 完成したタグ一覧を表示先に入れる
    target.appendChild(fragment);


})();


</script>

(注)カテゴリーモジュールに「記事が多い順」というオプションがあることを知らずひと手間かけすぎています。

サンプル CSS

表示サンプルには、次の CSS が指定してあります。

html {  font-size: 62.5%; }


#tagcloud {
  text-align: center; }


  #tagcloud a {
    display: inline-block;
    vertical-align: middle;
    margin: 0 .4em;
    line-height: 1.2em;
    text-decoration: none;
    transition: all .3s linear; }


  #tagcloud.hover a:hover {
    text-shadow: 0 0 3px #fff; }


  #tagcloud.hover a:not(:hover) {
    opacity: .7;
    color: rgba(255, 255, 255, 0.5); }


  #tagcloud .tagXXXXL {
    color: #E4BB37;
    font-size: 3rem; }
  #tagcloud .tagXXXL {
    color: #E68D3A;
    font-size: 2.8rem; }
  #tagcloud .tagXXL {
    color: #CA5C00;
    font-size: 2.6rem; }
  #tagcloud .tagXL {
    color: #63b542;
    font-size: 2.4rem; }
  #tagcloud .tagL {
    color: #cbd636;
    font-size: 2.2rem; }
  #tagcloud .tagM {
    color: #a5a5a5;
    font-size: 2rem; }
  #tagcloud .tagS {
    color: #E4BB37;
    font-size: 1.8rem; }
  #tagcloud .tagXS {
    color: #5fcae6;
    font-size: 1.6rem; }
  #tagcloud .tagXXS {
    color: #CA5C00;
    font-size: 1.4rem; }
  #tagcloud .tagXXXS {
    color: #adadad;
    font-size: 1rem; }