2008年3月31日月曜日

prototype.js を使ったスターレイティング(JavaScript 星評価)

YouTube や Amazon、livedoor Reader でコンテンツの評価に使われているスターレイティングを prototype.js を使って割と汎用的に実装してみました。

http://www.masugadesign.com/the-lab/scripts/unobtrusive-ajax-star-rating-bar/
などには高機能なライブラリがあるようですが、とっつきにくいので自作しました。順を追って説明していきます。

準備と前提条件:
  1. prototype.js(今回は ver1.6)を使用します。 http://prototypejs.org/ からソースをダウンロードしておきましょう。
  2. 5段階の星を表現するために、未選択のものを含めて 6つの画像が必要です。私は http://iconlet.com/ から素材を入手してペイントで加工しました。(サンプル:、使った素材のライセンスはコチラ http://creativecommons.org/licenses/by-sa/3.0/)


上記 2つの準備が終わったら、starrating.js を作成します。計算部分は livedoor Reader を参考にさせていただきました。
StarRating = Class.create({
initialize: function(id, images, options) {
var img = $(id);
Event.observe(img, "mousemove", function(e) {
if (!img.getAttribute("orgSrc")) {
img.setAttribute("orgSrc", img.src);
}
var width = img.offsetWidth;
var cell = width / images.length;
var offsetX = !isNaN(e.offsetX) ? e.offsetX: e.layerX - img.offsetLeft;
// Position.cumulativeOffset(img)[0]
if (offsetX == 0) offsetX++;
if (offsetX > width) offsetX = width;
var rate = Math.ceil(offsetX / cell);
if (rate < 1) {
rate = 1;
}
if (options.basePath) {
img.src = options.basePath + images[rate - 1];
} else {
img.src = images[rate - 1];
}
img.setAttribute("rate", rate);
});
Event.observe(img, "mouseout", function(e) {
var src = img.getAttribute("orgSrc");
if (src) {
img.src = src;
}
});
if (options.onClick) {
Event.observe(img, "click", function(e) {
img.removeAttribute("orgSrc");
options.onClick.call(this, img, img.getAttribute("rate"));
});
}
}
});

prototype.js, starrating.js、星画像を次のようにウェブサーバに配置します。
  • /js/prototype.js
  • /js/starrating.js
  • /img/rate0.png
  • /img/rate1.png
  • /img/rate2.png
  • /img/rate3.png
  • /img/rate4.png
  • /img/rate5.png

そして最後にスターレイティングを呼び出すコードを書きます。
<script src="/js/prototype.js" type="text/javascript"></script>
<script src="/js/starrating.js" type="text/javascript"></script>
<img src="/img/rate0.png" width="80" height="16" id="starRating" />
<script language="javascript" type="text/javascript">
new StarRating(
"starRating",
["rate1.png", "rate2.png", "rate3.png", "rate4.png", "rate5.png"], {
basePath: "/img/",
onClick: function (img, rating) {
alert(rating);
}
}
);
</script>

まず、img 要素で rateX.png を定義します。このとき、id には任意の名前を指定してください。サンプルでは "starRating" を使っています。次に、script タグの中で StarRating を 生成します。第一引数は img 要素の id、第二引数は、マウスオーバーで切り替える画像の配列を指定します。第三引数のオプションでは basePath と onClick コールバック関数を指定することが可能です。onClick コールバック関数の引数は img 要素と算出されたレイティングです。

サンプルは alert しているだけですが、実際には Ajax.Request 等を用いてサーバ側にユーザがどの星をクリックしたかを送信することになると思います。

ロゴ決まりました

知り合いの "jiju" さんにロゴ作っていただきました。ありがとうございますm(_ _)m
try-catch がプログラムの用語であること、「やさしげでクール」、そんな印象でデザインしてくださったそうです。

ロゴに負けないいい会社にしたいですねー。

2008年3月18日火曜日

レンタルオフィス

六本木にレンタルオフィス 1席を借りました。とても気に入りました。

独立して 3年立ちますが、すべて業務委託で常駐だったのでこの自由さには驚愕です。
今は昼前に起きてゆっくりご飯を食べてから出勤してます。

2008年3月14日金曜日

Java でタグクラウドの実装

Java でタグクラウドの実装をする必要があったので、ググってみましたがなかなかピンとくる情報に出会えなかったため、ネタにしてみます。

幸いにも計算部分は Perl の実装を参考にさせていただくことができたので、Java 風のアレンジを加えてみました。

まずタグのインタフェースを定義します。Comparable を継承しているのはソートに使用するためです。
public interface Tag extends Comparable {
/** タグそのものを返します */
String getValue();
/** タグの使用回数など指標になる数値を返します */
int getScore();
/** タグクラウドの文字の大きさを返します */
int getCloudLevel();
/** タグクラウドの文字の大きさを設定します */
void setCloudLevel(int cloudLevel);
}

次にインタフェース Tag の実装クラスです。
import java.io.Serializable;
public class ExampleTag implements Tag, Serializable {
private String value;
private int score;
private int cloudLevel;
public ExampleTag(String value, int score) {
this.value = value;
this.score = score;
}
public String getValue() {
return value;
}
public int getScore() {
return score;
}
public int getCloudLevel() {
return cloudLevel;
}
public void setCloudLevel(int cloudLevel) {
this.cloudLevel = cloudLevel;
}
public int compareTo(Object o) {
Tag tag = (Tag) o;
return (getScore() - tag.getScore());
}
public String toString() {
return "ExampleTag[value=" + value + ",score=" + score
+ ",cloudLevel=" + cloudLevel + "]";
}
}

最後にタグクラウドの実装です。main にテスト用のコードを書いておきます。TagCloud クラスを作成して Tag オブジェクトを addTag していって最後に getTags で取り出して使います。順序を維持するために java.util.LinkedHashSet を使っています。
import java.util.Iterator;
import java.util.Set;
public class TagCloud {
/** フォントの大きさの段階を指定 */
private final int maxLevel;
/** タグを順序どおりに格納する Set */
private final Set<Tag> tags;
/** 計算済みフラグ */
private boolean clouded;
/** 最小 */
private int minScore = Integer.MAX_VALUE;
/** 最大 */
private int maxScore = Integer.MIN_VALUE;
/** コンストラクタ */
public TagCloud(int maxLevel) {
this(maxLevel, 16);
}
/** コンストラクタ */
public TagCloud(int maxLevel, int capacity) {
if (maxLevel < 1) {
throw new IllegalArgumentException("invalid maxLevel " + maxLevel);
}
this.maxLevel = maxLevel;
this.tags = new java.util.LinkedHashSet<Tag>(capacity);
}
/** タグを追加します */
public void addTag(Tag tag) {
if (tag != null) {
tags.add(tag);
int score = tag.getScore();
this.minScore = Math.min(minScore, score);
this.maxScore = Math.max(maxScore, score);
this.clouded = false;
}
}
/** タグの Set を返します */
public Set getTags() {
cloud();
return tags;
}
/** タグクラウドのための計算をします */
private void cloud() {
final int size = tags.size();
if (clouded || size == 0) {
return;
}
if (size == 1) {
Tag tag = tags.iterator().next();
tag.setCloudLevel(1);
} else {
double min = (minScore == 0) ? 0.0: Math.log(minScore);
double max = (maxScore == 0) ? 0.0: Math.log(maxScore);
double f;
if (min == max) {
min -= maxLevel;
f = 1.0;
} else {
f = maxLevel / (max - min);
}
if (size < maxLevel) {
f *= ((double) size / maxLevel);
}
for (Tag tag: tags) {
int score = tag.getScore();
if (score != 0) {
tag.setCloudLevel((int) ((Math.log(score) - min) * f));
}
}
}
this.clouded = true;
}
// NOTE: for test
public static void main(String[] args) {
TagCloud tagCloud = new TagCloud(4);
tagCloud.addTag(new ExampleTag("abcd", 3));
tagCloud.addTag(new ExampleTag("efg", 1));
tagCloud.addTag(new ExampleTag("hijk", 2));
tagCloud.addTag(new ExampleTag("lmn", 10));
tagCloud.addTag(new ExampleTag("opqrstu", 7));
tagCloud.addTag(new ExampleTag("vwxyz", 5));
System.out.println(tagCloud.getTags());
}
}

上記 3つのソースを同じディレクトリにおいて javac *.java でコンパイル、java TagCloud でテスト実行すると以下のような結果が出力されます。
[ExampleTag[value=abcd,score=3,cloudLevel=1],
ExampleTag[value=efg,score=1,cloudLevel=0],
ExampleTag[value=hijk,score=2,cloudLevel=1],
ExampleTag[value=lmn,score=10,cloudLevel=3],
ExampleTag[value=opqrstu,score=7,cloudLevel=3],
ExampleTag[value=vwxyz,score=5,cloudLevel=2]]

このクラスを利用して JSP などで HTML 出力すれば
<style type="text/css">
.tagcloud {width:180px;}
.tagcloud span {padding:5px; font-weight:bold; color:steelblue;}
.tagcloud .tag0 {font-size:10px;}
.tagcloud .tag1 {font-size:16px;}
.tagcloud .tag2 {font-size:22px;}
.tagcloud .tag3 {font-size:28px;}
</style>
<div class="tagcloud">
<span class="tag1">abcd</span>
<span class="tag0">efg</span>
<span class="tag1">hijk</span>
<span class="tag3">lmn</span>
<span class="tag3">opqrstu</span>
<span class="tag2">vwxyz</span>
</div>


こんな感じのタグクラウドになります。

2008年3月5日水曜日

登記

さて、会社名を決めたところで次は登記をせねばなりません。

今年は確定申告を専門の会社にお願いしたので、同じところに登記お任せすることにしました。まず決める必要があると教えていただいたのが次の 5つでした。
  • 会社名
  • 事業目的
  • 資本金
  • 取締役の数
  • 本店の住所
すごく分かりやすく親切な方に出会いまして、順序を追って主要なことから説明を頂いているようです。

会社名は決めたので、次に事業目的を改めて考えてみました。口語ではなんとなく説明できるのですが、それらしい言葉が浮かんでこないのでウェブで調べて最終的に次の 4つに決めました。

事業目的:
1) インターネットウェブサイトのコンサルティング、企画、 設計、開発、運営及び販売
2) インターネット等のオンラインを利用した市場調査、宣伝 及び広告等の受託
3) コンピュータシステムのコンサルティング、企画、設計、 開発、運営及び販売
4) 株式の保有、売買並びにその他の投資事業

どこかで「定款を変更するのは大変だからなるべくたくさん書いたほうが良い」と聞いていたのですが、まずは現実的な範囲で思いつく事業目的にすれば良いようです。

資本金は 100万円としました。取締役は私一人です。本店の住所はレンタルオフィスを借りることにしました。月 5万円程度の予算で考えています。

2008年3月1日土曜日

会社名決定

「株式会社トライキャッチ」です。プログラムで使われる try-catch ブロックが由来です。
trycatch.jp ドメインも取得しました。

いろいろ悩んだ候補はコチラ。
  • ハードワーカー(13画がいいらしいといと聞いていたのと、自分らしいということで。求人が厳しいとのアドバイス受けて却下w)
  • シンプルイズベスト(Simple is the best と the が抜けているとの指摘受け却下w)
  • プレイウェブ(ウェブを楽しもうと。最終的にピンとこないので却下)
ぼちぼち定款とか資本金を決めて手続きはじめます。3月末を設立の目標とします。