comic balloons ver 1.0 / HTML5 <canvas> and JavaScript
downlowd balloons.js here! (enc=EUC-JP)
what / なにこれ
HTML5 の canvas 要素に漫画の吹き出しのようなものを描画する "tkuri.cv.drawBalloonPath()" を提供します.
パラメータによって,吹き出しがトゲトゲになったり,モコモコになったりします.簡単ながら,吹き出しで喋っている人物の位置や方向を表す「ヒゲ」も付ける事ができます.(ヒゲ? 正式名称を知らないので,ここでは "ヒゲ" と呼んでいます)
moveTo(),lineTo() やベジェ曲線などを使い淡々とコンテキストにパスを追加していくだけなので,その後,コンテキストに対して色設定をしたり fill() もしくは stroke() (あるいは両方) する必要があります.また,文字列も別途描画する必要があります.その分,色や文字に関しちゃ自由度高いよ,という事で.
licence / ライセンス
BSD License かなと.balloons.js の中身のクレジットをむやみやたらと改変しなければ,いろいろ自由です.売ってもいいですよ.
example / コードの例
// 'ex1' は canvas 要素につけた ID
var ctx = document.getElementById('ex1').getContext('2d');
var spikes = 7;
var spikeDepth = -0.2;
ctx.beginPath();
tkuri.cv.drawBalloonPath(ctx, 30, 30, 100, 40, spikes, spikeDepth);
ctx.stroke();
ctx.font = '20pt Arial';
ctx.fillText('really!?', 40, 60);
result / 実行結果
detail / 詳しく
design / 仕様
tkuri.cv.drawBalloonPath() は,ユーザの次の要求を満たします.
- 矩形 (x, y)-(width, height) に文字列を描画するから,その周囲に吹き出しを描画して欲しい.決して矩形 (x, y)-(width, height) の中に吹き出しの線が架かってしまわないよう気をつけて欲しい.
- 吹き出しに,感情を表現するトゲトゲやモコモコをつけたい.その高さを指定したい.※ 高さは一律です.トゲの一山ごとに高さを指定する事はできません
- 人物の位置を示す「ヒゲ」を付けたい.吹き出しのどこに「ヒゲ」をつけるかを指定したい.高さも.
tkuri.cv.drawBalloonPath() は,次のように処理をしています.
- 指定の矩形に外接するような楕円のデータを計算します.
- hige が指定されている場合,ちょっとヒゲを付け足す処理をします.
- 楕円データの通りにパスを描画します.spikes が指定されている場合,元々の楕円データをすこしいじり,ジグザグになるように曲線を描画します.
API 解説
function tkuri.cv.drawBalloonPath(ctx, x, y, w, h, spikes, spikeDepth, rotate, hige)
ctx .. 描画対象のコンテキストオブジェクト.canvas.getContext('2d')
x .. テキストを描画したいと思っている矩形の左上座標
y .. 〃
w .. 矩形の横幅
h .. 矩形の高さ
-- 以下は省略可能なパラメータ --
spikes .. トケトゲ/モコモコの数.5〜20 あたりが相場.
spikeDepth .. トゲトゲ/モコモコの深さ.
0 より大きい場合はモコモコに,0より小さい場合はトゲトゲになる.
-1 〜 1 あたりが相場.
rotate .. spike の山谷や,ヒゲの発生場所をずらす.
0〜359 の角度を指定するが,あまり正確ではないはず.
hige .. ヒゲの長さ.大体 0.2〜0.5 あたりが相場.
0 未満の値を入力すると,吹き出しの内側にヒゲが入り込む.
x, y, w, h
矩形 (x, y)-(w, h) に邪魔にならないように吹き出しを描画します.
例の図では,(x, y)-(w, h) で strokeRect() をしています.この矩形の中に吹き出しの線が侵入したりしていない事が分かります.これならば,あなたは安心して (x, y)-(w, h) 内に文字列を描画できますよね.……ただ,吹き出しが不自然に大きく感じられる事もあるかも知れませんが.(spikeDepth がマイナスの場合,吹き出しが大きめになる傾向があります)
spikes, spikeDepth
トゲトゲ/モコモコの数と深さを指定できます.spikes と spikeDepth は同時に指定してください.spikeDepth がどのような意味の値なのかを説明するのは困難ですが,大体 -1 〜 1 あたりを入力しておけばよく,マイナスの場合はトゲトゲ,プラスの場合はモコモコになる事を知っておけばよいでしょう.
rotate
0〜359 の度数で指定します.主にこれは「ヒゲ」の位置を指定する目的のパラメータですが,トゲトゲ/モコモコの位置を少し変えたりする事にもなります.吹き出し自体を斜めにしたりするわけではありません.そういうのは context.rotate() メソッドに任せればいいと思います.
rotate を適当に指定して描画した吹き出しを重ねると,面白い効果をつける事ができるかもしれません.
hige
発言者の方向を表す「ヒゲ」の種類もしくは高さを表します.
文字列を入力した場合は (例の左下の吹き出し) その文字列の長さだけ「○」を描画します.吹き出し本体に最も近い「○」は,引数 h の 1/10 の大きさです.「○」の大きさは,吹き出し本体から離れるにつれ 1/2 になります.
数値を入力した場合は,これも spikeDepth と同じく,どのような意味の値かを解説するのは困難です.大体 0.5 あたりを入力しておけばよいです.0 より小さい場合は,「ヒゲ」は吹き出しの内側に入り込みます.
この例で,rotate の指定により「ヒゲ」の位置が変わっている事に注意してください.
注意:例えば rotate に 60 度を指定したとしても,完全に正しく斜め 60 度の方向に「ヒゲ」が出るわけではありません.楕円というものを近似的に扱っている関係上,ほんの少しだけズレている事が多いです.
application, or problem / 応用とか,出来ない事とか
いろいろと応用してみるとよいです.また,この API では表現できない吹き出しもありますが,なんとか応用してしまえないかと.
吹き出しを連結
複数の吹き出しを重ねた状態で stroke() すると,当然ですが,お互いの線がお互いの吹き出しに重なってしまいます (例の図の左).
stroke() はせず,shadowOffsetX = shadowOffsetY = 0, shadowBlur = 3 くらいで fill() するといい感じ.
吹き出しを半透明にしたい場合は,context.clip() メソッドや context.globalCompositeOperation プロパティも使って擬似的にでもマスクを作り……なんとかすべし.例の図の右では単に半透明にしただけですが,shadow の色も混ざり,狙った透明度にはなっていません.
トゲの少ない,「ビシィ!」みたいな叫び
トゲが多いと,なんか驚いた叫び声?みたいな?感じですが,トゲを減らすと「おだまりなさい!」みたいな,一発言い切り!みたいな,……なんかすいませんでした.
この例では,4 つのトゲを持つ吹き出しを 2 つ重ねています.片方の吹き出しは rotate を指定し,トゲがある位置を傾けています.当然 stroke() すると線が重なってしまうので,shadow をつけて fill() のみ.
直線的なトゲトゲ [未解決]
トゲは必ず曲線的です.直線のトゲは出来ません.
もうちょっとランダムなトゲトゲ/モコモコ [未解決]
規則的なトゲトゲモコモコじゃなくて,もうちょっと自由なのが欲しいですよね.
履歴
2010-6-10 またまた微修正
2010-6-9 微修正
2010-6-7 公開
2010-6-6 書いた