今回は ImageHandlerPlugin クラスの processImage メソッドで使ってる画像処理のメソッドを作っていくことにするね。 | |
transformImage メソッドと scaleImage メソッドと rotateImage メソッドと boxBlur メソッドの4つだったよね。 | |
そうそう。 それじゃまずは boxBlur メソッドから作ってこっか。 |
|
あ、transformImage メソッドからじゃないんだ? | |
簡単なメソッドから作っていこうかなーと思ってね。 その方が説明もしやすいし。 |
|
そーなんだ。 | |
ってワケで、これが boxBlur メソッドだよ。 |
ホントにカンタンだね… ってゆーか doBoxBlur メソッドを呼び出してるだけ? |
|
※doBoxBlur メソッドについては §9.6 参照。 | |
ん、別に他にすることないから。 引数は大丈夫だよね? |
|
えっと、第1引数と第2引数がそれぞれ eximage マクロに指定されてる xblur 属性と yblur 属性を数値にした値になるんだよね? | |
そ。これは特に問題ないよね。 | |
うん。 | |
じゃ次は scaleImage メソッドね。 まずこれがスクリプト。 |
今度はだいぶ長くなったね… | |
まぁ一時レイヤとか作ったりしてるしね。 ただ、基本的にやってることは §9.2 で画像を拡大した時とほとんど同じだよ。 |
|
そーなの? | |
最初の一時レイヤを作ってるとこは前にやったのとほぼ同じでしょ? | |
前は layer0 だったのが layer になってるけど、確かにほとんどおんなじだね。 | |
前は 0 番の前景レイヤの画像を拡大するって始めから決めてたけど、 今回はどの前景レイヤの画像でも拡大できるように、 レイヤへの参照(layer のことね)を引数にしてるの。 | |
あ、なるほど。 えっと、次の xscale と yscale っていう変数は前はなかったよね。 しかもなんか代入の式が複雑だし… |
|
この式は三項演算子を2回使ってるんだけど、どうなってるかわかる? | |
※三項演算子については §1.20 参照。 | |
ん〜っと…どーなってるんだろ? | |
じゃあ『var xscale = elm.xscale !== void ? A : B;』っていう式だとどうなる? | |
その式だったら、elm.xscale が void じゃなかったら xscale に A っていう値が代入されて、 elm.xscale が void だったら xscale には B っていう値が代入されるんだよね? | |
ん、そうだね。 んじゃ『var xscale = elm.scale !== void ? B1 : B2;』っていう式は? |
|
elm.scale が void じゃなかったら xscale に B1 っていう値が代入されて、 elm.scale が void だったら xscale に B2 っていう値が代入されるよね。 | |
だね。 で、1つ目の式の B の所に2つ目の式を入れてみると、 elm.xscale が void じゃない時は xscale に A が代入されて、 elm.xscale が void だったら、今度は elm.scale の値をチェックして… |
|
elm.scale が void じゃなかったら xscale に B1 を代入して、 elm.scale が void だったら B2 を代入するってコト? | |
そういうこと。つまりこの式はこう処理されるわけね。 |
う〜ん、なんかややこしーね… ねぇ、これって… |
これじゃダメなの? | |
もちろんそれでも OK だよ。 | |
こっちのがわかりやすいと思うんだけどなぁ… | |
scaleImage メソッドはスクリプトが結構長いから、
三項演算子を2回使って代入文を書いてみたんだ。こうすると1行で書けるからね。 ただ、どっちでも結果は同じだから、どんなふうに書くかは自由だよ。 |
|
確かにこっちだとわかりやすいけどスクリプトは7行になっちゃってるね。 | |
まぁこんなふうに同じ処理をするスクリプトでも色んな書き方ができるわけだけど、 他の人が見たり自分が後から見た時でも何が書いてあるかすぐにわかるようなスクリプトを書くようにするといいんじゃないかな。 | |
そだね。 | |
じゃ scaleImage メソッドの話に戻って… xscale と yscale はそれぞれ横方向と縦方向の拡大率(何%に拡大/縮小するかってことね)を表す変数なんだ。 |
|
えっと、xscale の方は eximage マクロに xscale 属性が指定されてたら xscale 属性の値を数値にして代入してて、 xscale 属性は指定されてないけど scale 属性が指定されてたら scale 属性の値を数値にして代入してて、 どっちの属性も指定されてなかったら 100 を代入してるんだよね? | |
ん、ちょっとややこしいけどそういうことだね。 yscale の方は xscale が yscale に置き換わってるだけで代入の仕方は同じね。 |
|
scale 属性って確か縦方向と横方向の拡大率が同じになる時に指定するんだったよね? | |
そ。xscale 属性と yscale 属性を指定せずに scale 属性だけ指定すると xscale と yscale 両方の変数に +elm.scale が代入されるようになってるでしょ。 | |
確かにそれだと縦方向と横方向でおんなじ拡大率になるね。 | |
あと、どの属性も指定されてなかった時に代入する 100
ってのは画像のサイズを 100% にするってことだから、つまり拡大も縮小もしないってことね。 次は newWidth と newHeight に拡大/縮小後の画像の幅と高さを代入してるんだけど、 この計算は前にもやったから OK だよね? |
|
layer.imageWidth に xscale(横方向の拡大率だよね)を掛けてるのはわかるんだけど、 何でその後 100 で割ってるの? | |
拡大率は%(パーセント)単位で指定するから、 画像の幅は (xscale÷100) 倍になるの。 | |
あー、なるほどね。 だから高さも layer.imageHeight に yscale / 100 を掛けてるんだね。 |
|
そういうこと。 | |
ここまではわかったけど、その次にあるこの2つの式って何やってるの? | |
画像のサイズが小さくなり過ぎないようにしてるの。 | |
それってどーゆーこと? | |
例えば、幅が 40 ピクセルの画像を拡大率 1% で縮小したら、縮小後の幅は何ピクセルになる? | |
1%?…って 0.01 倍ってことだよね… えっと、40×0.01 だから 0.4 ピクセル? |
|
画像の幅は整数だから、int 演算子を使って小数点以下を切り捨てると… | |
0 ピクセル? | |
…にはできないから、
newWidth が
1 より小さくなってたら
newWidth に 1 を代入することで、
画像の幅が最低でも 1 ピクセルになるようにしてるってワケ。 あと高さも同じようにして 1 ピクセル以上になるようにしてるの。 |
|
※画像の幅(第1引数)や高さ(第2引数)を 0 以下にして setImageSize メソッドを呼び出すと例外が発生します。 | |
なるほどねぇ…でもそんなに小さくしたりすることってあるのかなぁ…? | |
ま、普通はしないだろうけど、念のためってことで。 でその後は一時レイヤのサイズを拡大後の画像のサイズに合わせて、 stretchCopy メソッドで画像を拡大コピーしてるんだけど、 これは前にやったのとおんなじやり方だよ。 |
|
その後一時レイヤを無効化するのも前とおんなじみたいだね。 | |
ん、そうだね。 | |
最後に setPosition っていうメソッドを呼び出してるけど、 これって前はなかったよね? | |
setPosition メソッドはね、 pos 属性が指定されてる時にレイヤの位置を調整するために作ってるんだ。 | |
pos 属性って、image タグの pos 属性のこと? | |
そうだよ。 | |
pos 属性って eximage マクロの中で image タグを実行する時にチェックしてるんじゃないの? | |
確かに image タグを実行する時に pos 属性が指定されてたら、レイヤの位置を自動的に調整してくれるんだけど… | |
でしょ? | |
でも、image タグを実行する時にはまだ画像が拡大/縮小されてないから、 pos 属性の値をチェックしてレイヤの位置を調整した後で画像が拡大/縮小されるわけね。 | |
うん…でもそれって何か問題あるの? | |
レイヤの位置を調整した後で画像のサイズを変えると、例えばこんな感じになっちゃうの。 |
<pos 属性を "c" にして画像の読み込みと拡大を行った場合>
この図は pos 属性を
"c" にして画像を読み込んで、その後画像を2倍に拡大した時の例なんだ。 左側が画像を拡大する前、つまり image タグを実行した直後の状態で、 右側が画像を拡大した後、つまり stretchCopy メソッドを呼び出した直後の状態だよ。 |
|
なんか拡大した後の画像の下の方が切れちゃってるね。 | |
stretchCopy メソッドで画像を拡大しても、
画像の左上の点の位置は変わらないからこうなっちゃうの。 ホントはこうなって欲しいよね。 |
<pos 属性を "c" にした場合の拡大後の画像の正しい位置>
そーだね。これだとちゃんと pos 属性を "c" にした時の位置になってるね。 | |
こんなふうに画像を拡大した後にレイヤを正しい位置に表示するために、 pos 属性が指定されてたらここで setPosition メソッドを呼び出してレイヤの位置を設定し直してるってワケ。 | |
なるほどねぇ…単に画像を拡大すればおっけーってわけじゃないんだね。 | |
left 属性とか top 属性でレイヤの位置を設定してるんなら画像を拡大するだけでいいんだけど、
pos 属性を使ってるとそうはいかないんだよね。 じゃ setPosition メソッドのスクリプトを見ていくね。 |
setPosition メソッドには引数が2つあって、 第1引数の layer を第2引数の pos で指定した位置に表示するんだ。 | |
えっと、最初の行で center っていう変数に代入してる kag.scPositionX[pos] ってなんなの? | |
scPositionX は Config.tjs の中に出てくるんだけど、見覚えない? | |
え、そーなの? う〜ん…なんだったっけ? |
|
pos 属性でレイヤの中心位置をどこに合わせるかを設定する部分だよ。 初期状態の Config.tjs だとこうなってるよね。 |
<scPositionX の設定(Config.tjs より抜粋)>
あー、これなら見たことあるよ〜。 | |
でしょ。 例えば、pos 属性に "c" を指定した時は scPositionX.c の値になるから… |
|
scPositionX.c = scPositionX.center; って書いてあるから、
scPositionX.c は scPositionX.center とおんなじ値なんだね。 scPositionX.center = 320; だから、結局 scPositionX.c は 320 ってコトかな? |
|
ん、そう。 ウィンドウのサイズを 640×480 ピクセルにしてるっていう想定で設定してあるから、 pos を "c" にした時にレイヤの真ん中が 320 の位置、 つまりウィンドウのちょうど真ん中になるわけね。 |
|
なるほどね。 | |
んじゃ setPosition メソッドの話に戻るね。 1行目で center に kag.scPosition[pos] の値を代入してるわけだけど、こうすると例えば pos が "c" だった時に、Config.tjs で設定してる scPositionX.c の値が center に代入されるの。 |
|
えっと、引数の pos が "c" だったら
center = kag.scPositionX["c"]; になるよね。 あ、そーいえば scPositionX って辞書配列なの? |
|
そうだよ。だから kag.scPositionX["c"] と kag.scPositionX.c はおんなじ意味になるよね。 | |
※辞書配列については §1.15 参照。 | |
だね。 あ、でも Config.tjs の方は kag.scPositionX じゃなくて scPositionX になってるんだけど? |
|
この KAGWindow_config っていうメソッドは kag オブジェクトのコンテキスト上で実行されるから、単に scPositionX って書いてあっても、実際は kag.scPositionX っていう意味になるんだ。 | |
※KAGWindow_config メソッドは KAGWindow クラス(kag オブジェクトのクラス)のコンストラクタの中で (KAGWindow_config incontextof this)(); という形で実行されています。 | |
えっと、それってどーゆーコト? | |
§2.11 でコンテキストについて一応説明してるんだけど、もう忘れちゃったかな? | |
うーん、そー言われればコンテキストって前に出てきた気がするけど、 第2章って難しい話が多かったからねぇ… | |
簡単に言うと、kag オブジェクトのコンテキスト上で
KAGWindow_config メソッドを実行するってことは、
このメソッドを kag オブジェクトのメソッドとして実行するって感じだね。 kag オブジェクトのメソッドの中だと kag. を付けなくても scPositionX って書くだけで kag オブジェクトの scPositionX って意味になるでしょ。 |
|
なるほど、確かにそーなるね。 じゃあ、例えば scPositionX.left = 160; は kag.scPositionX.left = 160; とおんなじ意味ってコトでいーんだよね? |
|
まぁそういうコトだね。 じゃ setPosition メソッドのスクリプトに戻って… あとは center が void じゃなかったら setOptions メソッドを呼び出してレイヤの位置を設定すれば OK。 |
|
center って void になることあるの? | |
pos 属性が正しく指定されてれば void にはならないんだけど、一応チェックしてるの。 | |
ふぅん、そうなんだ。 | |
setOptions メソッドは前に使ったことあるけど覚えてる? | |
え〜っとね…確か layopt タグを実行した時に呼び出されるって言ってなかったっけ? | |
そうそう。だから引数の辞書配列には layopt タグと同じ属性が指定できるわけね。 | |
※setOptions メソッドについては §6.2 参照。 | |
引数の辞書配列には left と top が指定されてるから、 left 属性と top 属性を指定して layopt タグを実行するのとおんなじなわけだね。 | |
そ。じゃ left と top の計算の仕方はわかる? | |
top の方にある scHeight ってのがよくわかんないんだけど…? | |
これも Config.tjs に出てくる値だよ。 | |
え、そーなの? | |
これなんだけど、見たことない? |
<scHeight の設定(Config.tjs より抜粋)>
あ〜、画面の高さを指定する値だね。 | |
だからこの kag.scHeight は画面の高さになってるってワケ。 | |
kag が付いてるのは scPositionX の時とおんなじ理由なの? | |
そだよ。 どっちも Config.tjs の KAGWindow_config メソッドの中にあるからね。 |
|
そーなんだ。じゃあ… |
こんな感じで left と top の値を計算してるのかな? | |
ん、そうそう。 さて、それじゃこれで setPosition メソッドと scaleImage メソッドがチェックできたから、今回はこの辺にしとこっか。 |
|
そーだね。まだメソッドが残ってるけど、結構長くなっちゃったもんね。 | |
残りの transformImage メソッドと rotateImage メソッドは次回見ていくことにするね。 | |
りょ〜かい! | |
それじゃ、また次回ね! |