Movable Type 備忘録

 Sparklines with jQuery

  • Jan032009
  • Vote:
    http://bizcaz.com/archives/2009/01/03-044707.php
  • Categories: jQuery
  • Tags:
  • Social Bookmark

こんばんわ^^

何だか寝れなくなっちゃったので、Sparklines プラグインを使ってページごとのアクセスカウンタを作ってみました。
短時間で作って割にはちゃんと動いてるようなので自分でもビックリです (; ̄∇ ̄A

Sparklines プラグインは、インラインでミニチュアなグラフ表示がカンタンに作れるプラグインです。

サンプルを表示できませんでした。

上記は棒グラフと折れ線グラフをハイブリッドして表示してます。
棒グラフで 1 日単位のアクセス数を、折れ線グラフでは時間単位のアクセス数を表示させてます。
こんなかんじのをわたしのサイトの各ページ右上に表示してます。
まだ設置したばっかりだからデータがなくってグラフ表示しょぼいですけどね。

使い方

使い方はカンタンで、インライン( たとえば、記事中にグラフを埋め込みたいなど )で表示する場合には以下のようなマークアップになります。

インラインでグラフ表示

  1. <span class="sparklines">127,280,640,406,596,480,322</span>

上記のようにグラフ表示のための値を埋め込むだけです。
上記データを以下のコードを使うことでグラフ表示されます。

インラインで表示するためのコード

  1. $('.sparklines').sparkline('html', {
  2.     type: 'bar',
  3.     barColor: '#4d5aaf'
  4. });

ポイントは青字の部分で、記事中に埋め込まれたデータをグラフ表示する場合には必ず 'html' にする必要があります。
また、直接データを渡すこともできます。

直接データを渡す場合のマークアップ

  1. <span class="sparklines"></span>

そして、以下のようなコードをでグラフ表示します。

動的にグラフ表示するコード

  1. $('.sparklines').sparkline([4,1,5,7,9,9,8,7,6,6,4,7], {
  2.     spotColor: '#f8b862',
  3.     minSpotColor: '#f6bfbc',
  4.     maxSpotColor : '#fffffc',
  5.     fillColor: false,
  6.     lineColor: '#d7003a'
  7. });

青字のように直接データを配列として渡すだけです。
グラフ表示も棒グラフ、折れ線グラフ以外にもパイ・チャート表示もできたりします。

各グラフ表示で共通なオプションを以下に記します。

  • type

    グラフのタイプを以下から選択します。

    • line: 折れ線グラフ表示( デフォルト )
    • bar: 棒グラフ表示
    • tristate: トライステート( 特定の基準点から上下( プラス/マイナス )に棒グラフ表示
    • discrete: 離散グラフ表示
    • bullet or pie: パイチャート
  • width

    グラフ幅を指定します。指定なしの場合にはちょうど良い幅に調整されます。

  • height

    グラフ高さを指定します。指定なしの場合には自動調整されます。

  • lineColor

    'type' オプションで 'line' or 'discrete' 選択時の線の色をを指定します。

  • fillColor

    'type' オプションで 'line' or 'discrete' 選択時の線下を塗りつぶすことができます。その場合には任意の色を指定します。不要の場合には 'false' を指定します。

  • chartRangeMin

    グラフ表示時の最小値を指定できます。デフォルトはデータ中の最も小さな値が最小値になります。

  • chartRangeMax

    グラフ表示時の最大値を指定できます。デフォルトは、データ中の最も大きな値が最大値になります。

  • composite

    グラフを重ねて表示するか否かを選択できます。複数のグラフを重ねて表示する場合には 'true' を、単独なら 'false' を指定します。デフォルトは 'false' になります。

上記以外にも、各グラフ個別のオプションもあります。
それについては配布元の説明を参照してください。

ちなみに上記サンプルでは以下のようなコードでグラフを重ねて表示してます。

サンプルで使用してるオプション

  1. $('.sparklines')
  2.     .sparkline('html', {
  3.         type: 'bar',
  4.         barColor: '#4d5aaf',
  5.         barWidth: 6,
  6.         height: 50
  7.     })
  8.     .sparkline([4,1,5,7,9,9,8,7,6,6,4,7], {
  9.         composite: true,
  10.         spotColor: '#f8b862',
  11.         minSpotColor: '#f6bfbc',
  12.         maxSpotColor : '#fffffc',
  13.         fillColor: false,
  14.         lineColor: '#d7003a'
  15.     });

まだテスト中ですが即席で作ったページカウンタのコードは以下の通りです。

ページカウンタコード

  1. (function ($) {
  2. /*
  3.  ****************************************************************************
  4.  * File : jquery.counter.js 1.00
  5.  *
  6.  * Copyright (C) 2005-2009 http://bizcaz.com/ All rights reserved.
  7.  ****************************************************************************
  8.  */
  9. $.fn.counter = function(opt) {
  10.     opt = $.extend({
  11.         base : 'http://bizcaz.com/example/jquery/Sparklines',
  12.         blogid: 0,
  13.         type : '',
  14.         id : 0
  15.     }, opt || {});
  16.  
  17.     var $me = $(this);
  18.  
  19.     $me
  20.         .css('display', 'none')
  21.         .append('<div id="sparklines"></div>');
  22.  
  23.     var params = ['blogid=', opt.blogid, '&type=', opt.type, '&id=', opt.id].join('');
  24.  
  25.     $.post(opt.base+'/cnt.php', params, function(message, status) {
  26.         if ('success' == status) {
  27.             var json = eval(message);
  28.  
  29.             $me.css('display', 'block');
  30.             $('#sparklines')
  31.                 .append('<span class="cnt_bar"></span>')
  32.                 .append('<span class="cnt_total cntblock"></span>')
  33.                 .append('<span class="cnt_today cntblock"></span>')
  34.                 .append('<span class="cnt_yesterday cntblock"></span>');
  35.  
  36.             $('#sparklines span.cnt_bar')
  37.                 .css({'display':'block', 'float':'left', 'margin-right':'5px'})
  38.                 .sparkline(json.daily, {
  39.                     type: 'bar',
  40.                     barColor: '#4d5aaf',
  41.                     barWidth: 6,
  42.                     height: 50
  43.                 })
  44.                 .sparkline(json.timely, {
  45.                     composite: true,
  46.                     spotColor: '#f8b862',
  47.                     minSpotColor: '#f6bfbc',
  48.                     maxSpotColor : '#fffffc',
  49.                     fillColor: false,
  50.                     lineColor: '#d7003a'
  51.                 });
  52.             $('#sparklines span.cntblock')
  53.                 .css({'display':'block', 'font-size':'10px', 'font-family':'font-family:Trebuchet MS, Helvetica, Arial'});
  54.             $('#sparklines span.cnt_total').html(['TOTAL:', json.total].join(''));
  55.             $('#sparklines span.cnt_today').html(['TODAY:', json.today].join(''));
  56.             $('#sparklines span.cnt_yesterday').html(['YESTERDAY:', json.yesterday].join(''));
  57.         }
  58.     }, 'json');
  59. };
  60. }) (jQuery);

で、ログ収集プログラムは以下の通りです。

ログ収集プログラム

  1. <?php
  2.     require_once('cnt_config.php');
  3.  
  4.     if (!isset($_REQUEST['blogid']) || !isset($_REQUEST['type']) || !isset($_REQUEST['id'])) return;
  5.  
  6.     $GLOBALS['BLOGID'] = $_REQUEST['blogid'];
  7.     $GLOBALS['TYPE'] = $_REQUEST['type'];
  8.     $GLOBALS['ENTRYID'] = $_REQUEST['id'];
  9.     $GLOBALS['IP'] = $_SERVER['REMOTE_ADDR'];
  10.     $GLOBALS['LAST_DAY'] = date("YmdH", mktime(date("H"), 0, 0, date("m"), date("d") + 1, date("Y")));
  11.     $GLOBALS['LAST_HOUR'] = date("YmdH", mktime(date("H") + 1, 0, 0, date("m"), date("d"), date("Y")));
  12.     $GLOBALS['NOW'] = date("YmdH");
  13.     $GLOBALS['LOG'] = sprintf("b%d%s%d%s", $GLOBALS['BLOGID'], $GLOBALS['TYPE'], $GLOBALS['ENTRYID'], $GLOBALS['COUNT_DATA']);
  14.  
  15.     $GLOBALS['TOTAL'] = 0;
  16.     $GLOBALS['DAILY'] = array(0, 0, 0, 0, 0, 0, 0);// 1週間分
  17.     $GLOBALS['TIMELY'] = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);// 12 時間分
  18.  
  19.     if (not_selfaddr() && not_dupaddr()) {
  20.         write_counter();
  21.     }
  22.     else {
  23.         read_counter();
  24.     }
  25.  
  26.     require_once('JSON.php');
  27.  
  28.     $num = count($GLOBALS['DAILY']);
  29.     $data = array(
  30.         "total" => $GLOBALS['TOTAL'],
  31.         "today" => $GLOBALS['DAILY'][$num - 1],
  32.         "yesterday" => $GLOBALS['DAILY'][$num - 2],
  33.         "daily" => $GLOBALS['DAILY'],
  34.         "timely" => $GLOBALS['TIMELY'],
  35.     );
  36.     $json = new Services_JSON;
  37.     $encode = $json->encode($data);
  38.  
  39.     header("Content-Type: text/javascript; charset=utf-8");
  40.     echo $encode;
  41.  
  42. function read_counter()
  43. {
  44.     if (file_exists($GLOBALS['LOG'])) {
  45.         error_reporting(0);
  46.         $fp = @fopen($GLOBALS['LOG'], 'r');
  47.         while (FALSE == flock($fp, LOCK_EX)) usleep(500000);
  48.         list($GLOBALS['TOTAL'], $d, $t) = explode("<>", fgets($fp));
  49.         $GLOBALS['DAILY'] = explode(",", $d);
  50.         $GLOBALS['TIMELY'] = explode(",", $t);
  51.         fclose($fp);
  52.     }
  53. }
  54.  
  55. function write_counter()
  56. {
  57.     if (file_exists($GLOBALS['LOG'])) {
  58.         error_reporting(0);
  59.         $fp = @fopen($GLOBALS['LOG'], 'r+');
  60.         while (FALSE == flock($fp, LOCK_EX)) usleep(500000);
  61.  
  62.         list($GLOBALS['TOTAL'], $d, $t) = explode("<>", fgets($fp));
  63.  
  64.         $GLOBALS['TOTAL']++;// トータルカウンタをインクリメント
  65.         $dd = explode(",", $d);// 日別カウンタ
  66.         $tt = explode(",", $t);// 時別カウンタ
  67.  
  68.         $i = 0;
  69.         $all = count($GLOBALS['DAILY']);
  70.  
  71.         if ($GLOBALS['NOW'] > $GLOBALS['LAST_DAY']) {
  72.             $i = ($all <= $GLOBALS['NOW'] - $GLOBALS['LAST_DAY']) ? $all : $GLOBALS['NOW'] - $GLOBALS['LAST_DAY'] / 100;
  73.         }
  74.  
  75.         for ($n = 0;$all > $i;$i++, $n++) $GLOBALS['DAILY'][$n] = $dd[$i];
  76.         $GLOBALS['DAILY'][$all - 1]++;
  77.  
  78.         $i = 0;
  79.         $all = count($GLOBALS['TIMELY']);
  80.  
  81.         if ($GLOBALS['NOW'] > $GLOBALS['LAST_HOUR']) {
  82.             $i = ($all <= $GLOBALS['NOW'] - $GLOBALS['LAST_HOUR']) ? $all : $GLOBALS['NOW'] - $GLOBALS['LAST_HOUR'];
  83.         }
  84.  
  85.         for ($n = 0;$all > $i;$i++, $n++) $GLOBALS['TIMELY'][$n] = $tt[$i];
  86.         $GLOBALS['TIMELY'][$all - 1]++;
  87.  
  88.         $dat = implode("<>", array($GLOBALS['TOTAL'], implode(",", $GLOBALS['DAILY']), implode(",", $GLOBALS['TIMELY'])));
  89.         fseek($fp, 0, SEEK_SET);
  90.         fputs($fp, $dat);
  91.         fclose($fp);
  92.     }
  93.     else {
  94.         error_reporting(0);
  95.         $fp = @fopen($GLOBALS['LOG'], 'w');
  96.         while (FALSE == flock($fp, LOCK_EX)) usleep(500000);
  97.  
  98.         $GLOBALS['TOTAL']++;
  99.         $GLOBALS['DAILY'][count($GLOBALS['DAILY']) - 1]++;
  100.         $GLOBALS['TIMELY'][count($GLOBALS['TIMELY']) - 1]++;
  101.  
  102.         $dat = implode("<>", array($GLOBALS['TOTAL'], implode(",", $GLOBALS['DAILY']), implode(",", $GLOBALS['TIMELY'])));
  103.         fputs($fp, $dat);
  104.         fclose($fp);
  105.     }
  106. }
  107.  
  108. function not_selfaddr()
  109. {
  110.     foreach ($GLOBALS['SELF_ADDR'] as $value) {
  111.         if ($value == $GLOBALS['IP']) return 0;
  112.     }
  113.  
  114.     return 1;
  115. }
  116.  
  117. function not_dupaddr()
  118. {
  119.     $file = sprintf("b%d%s%dlock.txt", $GLOBALS['BLOGID'], $GLOBALS['TYPE'], $GLOBALS['ENTRYID']);
  120.  
  121.     if (file_exists($file)) {
  122.         error_reporting(0);
  123.         $fp = @fopen($file, "r+");
  124.         while (FALSE == flock($fp, LOCK_EX)) usleep(500000);
  125.  
  126.         list($GLOBALS['LAST_DAY'], $GLOBALS['LAST_HOUR'], $ip) = explode("<>", fgets($fp));
  127.         $ips = explode(",", $ip);
  128.         $day = $GLOBALS['LAST_DAY'];
  129.         $hour = $GLOBALS['LAST_HOUR'];
  130.  
  131.         if ($GLOBALS['NOW'] > $day) {
  132.             $day = date("YmdH", mktime(date("H"), 0, 0, date("m"), date("d") + 1, date("Y")));
  133.             unset($ips); $ip = '';
  134.         }
  135.  
  136.         if ($GLOBALS['NOW'] > $hour) {
  137.             $hour = date("YmdH", mktime(date("H") + 1, 0, 0, date("m"), date("d"), date("Y")));
  138.         }
  139.  
  140.         foreach ($ips as $value) {
  141.             if ($value == $GLOBALS['IP']) return 0;
  142.         }
  143.  
  144.         $dat = implode("<>", array($day, $hour, implode(",", array($ip, $GLOBALS['IP']))));
  145.         fseek($fp, 0, SEEK_SET);
  146.         fputs($fp, $dat);
  147.         fclose($fp);
  148.     }
  149.     else {
  150.         error_reporting(0);
  151.         $fp = @fopen($file, "w");
  152.         while (FALSE == flock($fp, LOCK_EX)) usleep(500000);
  153.         $dat = implode("<>", array($GLOBALS['LAST_DAY'], $GLOBALS['LAST_HOUR'], $GLOBALS['IP']));
  154.  
  155.         fputs($fp, $dat);
  156.         fclose($fp);
  157.     }
  158.  
  159.     return 1;
  160. }
  161. ?>

しばらく様子をみて問題なさそうなら後日ご紹介しますね (>∀< )

 Trackback Pings(0)

No trackbacks found.

 Comments(0)

No comments found.

 Post a Comment

 

コメント用フィード