Perl/CGI研究室 'PERL-LABO'

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

画像カウンターの研究

研究内容

gifcat.pl を利用して、カウンタをテキストでなく画像で表示するように変更しましょう。

詳細

完成したかと思われたカウンターですが、 IFRAMEでページ内で読み込み、テキストでカウンタを表示するというやりかたには 問題がありました。一番の問題はブラウザによって必要なIFRAMEのサイズが異なるため、 表示が乱れることがあるという点です。画像を使用することによって、 この問題を解決し、見た目をキレイにしましょう。

結果

gifcat.pl を利用すれば難しくありません

画像でカウンタを表示するのは、偉大なる画像連結ライブラリ gifcat.pl を利用すれば 難しくはありません。 0 〜 9 までの数字の画像を用意して、それを gifcat.pl で連結して1つの gif 画像として 画面に表示します。そのやり方は研究済み。やってみましょう。

どの数字を表示するか

アクセスカウンターは、今日、昨日、トータルの3つの数字を管理しているんでした。 画像でのカウンタ表示は、この中の1つしか表示できません。 3つとも表示させるためには、どの数字を表示するのかという情報をCGIプログラムに 渡してやることと、3回CGIプログラムを呼び出してやる必要があります。

表示するカウンターの指定方法ですが、次のようにしようと思います。

〜.cgi トータルカウントを表示
〜.cgi?v=yest 昨日のカウントを表示
〜.cgi?v=today 今日のカウントを表示
〜.cgi?v=text テキストで表示(今までの表示方法)

例えば、トップページに、今日、昨日、トータルの3つのカウンターを表示したい場合は 3回この cgi を呼び出すことになりますが、IPアドレスとクッキーで重複カウントのチェックを していますので、何回もカウントされることはありません。ですので、 いずれの呼び出しの場合でも、カウントは行うことにします。 そうすれば、今日のカウントのみ表示とか、トータルのみ表示といったことを しても、正しくカウントは行われます。

あ、あと、それぞれのカウンターの、表示する桁数の指定もできるようにしましょう。

作成したCGIプログラム

counter.cgi
#!/usr/bin/perl

require 'counter.pl';
require 'getformdata.pl';
require 'execgifcat.pl';

$fname    = "count.cgi";	# カウントデータファイル名
$dayfname = "count_day.cgi";	# カウント履歴ファイル名
$vmethod  = "";			# 表示方法デフォルト指定
$keta_tdy = 3;			# 今日カウント表示桁数
$keta_yst = 3;			# 昨日カウント表示桁数
$keta_tot = 5;			# トータルカウント表示桁数
@gif      =  (			# 数字画像gifファイル名
	"img/0.gif",
	"img/1.gif",
	"img/2.gif",
	"img/3.gif",
	"img/4.gif",
	"img/5.gif",
	"img/6.gif",
	"img/7.gif",
	"img/8.gif",
	"img/9.gif",
);

%form = plab::getformdata();

if ($form{'mode'} ne "acgraph") {
	@ret = plab::incl_counter($fname, $dayfname, 1, 1);
	plab::writecookie(-1);


	if (exists $form{'v'}) { $vmethod = $form{'v'}; }

	if (@ret[0] == 0) {
		print "Content-type: text/html\n\n";
		print "ERROR";	
	}
	elsif ($vmethod eq "text") {
		print "Content-type: text/html\n\n";
		print "<body style=\"margin:0;font-size:15px;\"><tt>";
		$txt = sprintf(
			"今日 %03d 昨日 %03d 計 %04d",
			$ret[1], $ret[2], $ret[3]);
		print $txt;
	}
	elsif ($vmethod eq "today") {
		print "Content-type: image/gif\n\n";
		plab::printint_execgifcat($ret[1], $keta_tdy, \@gif);
	}
	elsif ($vmethod eq "yest") {
		print "Content-type: image/gif\n\n";
		plab::printint_execgifcat($ret[2], $keta_yst, \@gif);
	}
	else {
		print "Content-type: image/gif\n\n";
		plab::printint_execgifcat($ret[3], $keta_tot, \@gif);
	}
}
else {
	print "Content-type: text/html\n";
	print "\n";
	plab::viewhistory_counter($fname, $dayfname, 400);
}

execgifcat.pl
# v 1.00

package plab;

require 'gifcat.pl';

# 画像で数字を表示します
# 引数(数値, 表示する桁数, 画像のファイル名配列の参照)
sub printint_execgifcat
{
	local $val    = $_[0];
	local $keta   = $_[1];
	local $gifref = $_[2];	# 配列の参照

	local $s = sprintf("%*d", $keta, $val);

	local @gifs;
	local $n = length($s);
	for (0 .. $n - 1) {
		local $number = int(substr($s, $_, 1));
		local $gifname = $$gifref[$number];
		push(@gifs, $gifname);
	}

	binmode(STDOUT);
	print gifcat::gifcat(@gifs);
}

1;

実行結果

当サイトのアクセスカウンターです。 このページのアクセス数ではなく、当サイト全体のアクセス数になります。 数字が小さくのはご愛嬌 (^^; (トップページに置いてあるカウンターは、トータルカウントのみを表示するようにしています。)

今日   昨日   計

ホント、アクセスの少ないサイトなので良かったらリンクしてくださいネ (^^

解説

プログラムの解説 - counter.cgi

ファイルの最初のところで、いくつかの設定を行うようにしました。 ファイル名の他、今回加える機能に必要な、 数字の桁数や表示する画像ファイルのパスなどを指定しておきます。 画像ファイルは、URLではなくて、パソコンの中のCGIプログラムとの相対パスで指定してやります。 それに、0 〜 9 っていう順番で配列に入れます。 これを間違えると違う値が表示されてしまいます。 あと、表示方法のデフォルトっていう項目がありますが、これは余計だったかな? オマケみたいなものです。

実際の処理は、$vmethod という変数に表示方法が入っていますので、それに従って 表示処理をしています。画像の表示は、別ファイル execgifcat.pl 内の関数 printint_execgifcat で行います。

プログラムの解説 - execgifcat.pl

私、ライブラリを作るのが好きなんですよねぇ。 新しいライブラリを作りました。 関数は現在のところ printint_execgifcat のみです。

printint_execgifcat 関数は、数値を画像で表示するっていう処理を行います。 引数は、表示する数値、表示する桁数、表示するのに使う画像ファイル名の配列への参照です。 配列の参照は初めて出てきましたが、次のようにして使います。

\@array;			# 配列の参照を表します
$arrayref = \@array;	# 配列の参照を変数に代入します
@$arrayref;		# これで配列を表します
$$arrayref[$index];	# これで配列の要素にアクセスします

\ によって参照を取得して、$ を1つ余分に付けてアクセスするんでしたね。

で、実際の処理ですが、まず最初に数値を文字列に変換します。 sprintf ですね。ここで少し特殊な(?)処理をしています。 "%*d" というところです。普通、数値を文字列に変えるときは %桁数d という指定をします。今まででてきたのは、%04d とか %02d とかでした。 04、02 というように 0 が付いているのは、その桁数に足りなかった場合は 0 で埋めてくださいっていう 意味です。で、今回は、表示する桁数が分からないというか、桁数も動的に変えたいんですよね。 こういうとき、桁数のところを * として、桁数もその後ろのとこで指定しますよ、というふうにします。 こういう便利な機能が sprintf 関数にはあるんですよね。 あるいは、同じことをするのに、次のようにしてもいいですね。 桁数が 4 なら %4d ですが、それを先に作ってあげるっていうやり方です。 . は文字列を連結する演算子です。

local $fmt = "%" . $keta . "d";
local $s = sprintf($fmt, $val);

で、作った文字列の文字数を length 関数で $n に入れて、 0 から $n - 1 までループして、1文字ずつ処理します。 $n でなくて $n - 1 になっているのは、 Perl では1文字目を 0番目の文字 と考えるので、 最後の文字は $n 番目の文字 でなくて $n-1 番目の文字 となるからです。 この辺、ちょっとややこしいですね。 あとは、substr 関数で1文字ずつ取り出して、int 関数でそれを数値に戻して その数値に対応する gif ファイル名を配列 @gifs の末尾に入れていきます。 つまり、1桁ずつ順に表示すべき画像ファイル名を調べているんです。 で、gifcat 関数でこれを連結表示して、終わりです。

動きました

これでプログラムは完成。CGIプログラムの呼び出しをIFRAMEタグからIMGタグに変更して… ちゃんと画像でカウントが表示されました! ここで使った画像ファイルは、横が 11、縦が 13 っていう大きさなので、 表示する桁数に合わせてあらかじめサイズを指定しておきます。 サイズは指定しなくても表示はされますが、画像はサイズを指定しないと 画像が読み込まれてサイズが確定するまでページ全体の配置が確定されないっていうのが ありますので、あらかじめ指定しておいた方がいいですよね。 私は、時々忘れちゃいますけど (^^;

これで完成?

今度こそ完成?って、歴史は繰り返すかも知れません (^^; そもそも、プログラムというものは完成なんて永久に来ないのかも、なんてことも思ってみたりして。

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

Copyright (c) 'PERL-LABO' All Rights Reserved.  リンクフリーです。