[69-9] canvasでグラフィックスの変形をしよう (拡大・回転・移動・反転など)

これまでは、canvas に基礎的なグラフィックスを描いてみました。
四角形、三角形(直線)、円弧ライン(曲線)画像テキストをやってみましたね。

今回は、canvas に描画したそれらのグラフィックスを変形させてみます。
canvas にはグラフィックスの座標を自動的に変換するメソッドも用意されていて、
拡大・回転・移動・反転などはそれを利用します。

これまでいろいろ描画してみて、1度指定した「状態」は、指定を変えない限り、ずっと影響し続けることがわかりました。

(「状態」とは具体的には、線や塗りの指定透明度の指定線のスタイルの指定クリッピング領域の指定シャドウの指定重なり合った描画領域の指定フォントの指定です。)

変形の指定もこれらと同じです。例えば、1度「拡大」して次に「回転」だけを指定しても、「拡大して回転」されるのがわかります。サンプルを見ながら確認してみましょう。

本日のINDEX
  1. 変形は「座標軸」に対してやっている(何それ?!)
  2. 拡大・回転・移動をしてみよう
    1. 拡大してみる
    2. 回転してみる
    3. 移動してみる
  3. ひとつずつ「初期化」しながら拡大・回転・移動をしてみよう
  4. transformを使って変形してみる
  5. setTransformによる変形(transformとの違いを比較してみた)

今回のサンプルはこちらです。

変形は「座標軸」に対してやっている(何それ?!)

canvasに図形や線、画像、テキストを描画するとき、必ず座標を使ってますね。
左上の x=0, y=0 が基準点になって、x は右方向、y は下方向へピクセル単位で増えていきます。

canvas上のグラフィックスは、この座標軸を基準に描かれているので、canvas ではこの座標軸を変形することでグラフィックスを変形するんだそうです。
canvasに描いてあるブツを変形するんじゃなく、座標軸を変形する...なんのこっちゃ?!

こういう雰囲気みたい。

これはですね、
サンプルを作りながらあれこれ考えているうちに「あぁ、そういうことか」と理解するようになりました。(= コトバで説明できない。笑)
ですのでここは一旦 座標軸のことは忘れていただいて、とにかくサンプルを見ましょう。

拡大・回転・移動をしてみよう

サンプルでは「テキスト」を変形してみました。

サンプル1は、まずテキストのスタイル(太さやサイズ、書体、塗りの色)を指定し、
1番最初は、ノーマル状態で描き出し、続いて「拡大」「回転」「移動」を指定しています。
ノーマル状態(画面の左上の「テキスト=ノーマル」)のテキストサイズは15px、位置はx30px, y30pxです。(canvas の背景に描いたグリッドはいつものとおり20pxです。)
クリックでサンプルが開きます↓

/*テキストのスタイルを指定*/
    ctx1.font= 'bold 15px sans-serif';
	ctx1.fillStyle = '#6DD900';
/*テキストをノーマル状態で描画*/
	ctx1.fillText('テキスト=ノーマル',30,30); 

拡大してみる

scale() で拡大します。
()内は、x方向の拡大率、y方向の拡大率を入れます。ここでは両方とも2倍にしています。 小数で、たとえば「0.5」とか指定すれば、半分サイズに縮小になります。
fillTextで描画位置をノーマルの時と同じ「30,30」にしていますが、実際には「60,60」の位置に描画されました。座標が拡大縮小されることがこれでわかりますね。

ですので、拡大の起点はカンバスの 0,0 地点(左上)です。これが変形のデフォ。座標だから。

/*拡大*/
	ctx1.scale(2,2);
	ctx1.fillText('テキスト=拡大',30,30);

回転してみる

rotate() で回転します。
()内は角度をラジアン値で入れます。
下のソースでは、変数 angle を使っていますが、変数を使わずに、ctx1.rotate(20*Math.PI/180); と直接書いちゃって 1行目を省略しても同じ。ここでは回転の角度は20度にしています。

/*回転*/
	var angle = 20*Math.PI/180;
	ctx1.rotate(angle);
	ctx1.fillText('テキスト=回転',30,30);

回転の中心点もカンバスの 0,0 地点(左上ね)ですね。やっぱ座標軸だからね。

回転の方向は時計回りなんですかね。
円弧を描く時は、時計回りが false だったのにねぇ。(規則性の無さが気になる...)

この疑問は、このあと「移動」をしてみて解けました
実際は「座標軸が半時計回り(true の方向)に回る」が正解。詳細はすぐあと。

とにかく、この回転でわかるのは、直前に指定した「拡大」がまだ効いているということ。回転しか指定していないのに、実際は2倍に拡大したテキストを20度回転させていますね。

移動してみる

translate() で移動します。
()内は、x方向の移動の差分、y方向の移動の差分です。
サンプルでは、x方向は140px右に、y方向は移動しないで0にしています。
マイナスの値を使えばxなら左方向、yなら上方向に移動できます。

/*移動*/
	ctx1.translate(140,0);
	ctx1.fillText('テキスト=移動',30,30);

ここでも、前に指定している拡大・回転が効いているのがわかりますね。
それにしても、回転時の描画位置もなんだか納得いかなかったけど、まあこんなもんかな〜とごまかしていましたが、この移動、右へ140pxだけ移動するつもりなのに、なんでy軸もズレてるの? 下がってるじゃん!

これって、こういうことだと思うんです↓

やはり回転の時、座標軸が回転していたんですね。この場合、反時計まわりですので、円弧を描く時の true と同じです。(あースッキリした。笑!)

座標軸を回転させといて、その後、x方向だけ移動している。「拡大 scale(2,2)」が効いているので、140pxの倍の280pxの移動となっているわけです。
やっぱり座標軸が変形してるんだな。と、このあたりで理解した次第です。

ひとつずつ「初期化」しながら拡大・回転・移動をしてみた

ここまでで、1度指定した変形がずっと影響していくのがわかりました。
それを言ったら、最初に指定したテキストのスタイル(太さやサイズや色など)もず〜っと同じように効いてますね。

<canvas>用のメソッドは、このように指定が継承されるようになっているので、初期状態の描画を変形したいなら、その都度、元の状態に戻してから次の変形の指定をする必要があります。

サンプル2は、サンプル1と同じ変形をしながら、1度変形したら、すぐ初期状態に戻すしています。
例えば scale(2,2) で拡大して描画したら、すぐに scale(1/2,1/2) で元の大きさに戻しています。

このような面倒くさいことをしなくても、
状態を「保存・復元」するメソッドも canvasに用意されています。
これが、save と restore 。save と restoreは、次回使ってみましょう!

transformを使って変形してみる

transform()setTransform() は「座標変換マトリクス」を変更して変形させるそうです。
この「座標変換マトリクス」は「アフィン行列」というものを用いるそうなのですが、詳細は割愛。(高度過ぎて解説は無理!)
まずはサンプル3で、transform() を使ってテキストが鏡像で映り込んでいるようなモノを作ってみました。

transform(m11, m12, m21, m22, dx, dy) で指定します。とにかくこの順番で。
6個の引数はそれぞれ下記を指定します。

  • m11 水平スケール(幅)
  • m12 垂直方向の傾斜
  • m21 水平方向の傾斜
  • m22 垂直スケール(高さ)
  • dx x方向の移動
  • dy y方向の移動

ノーマル状態(変形しない)の各引数は、transform(1, 0, 0, 1, 0, 0) となるわけです。

サンプルでは、最初にノーマル状態のテキストを描画してから、下記のようにtransformを使っています。(4行目)

/*テキストを半透明に*/
	ctx3.globalAlpha =0.3;
/*テキストを反転させて描画*/
	ctx3.transform(1,0,0,-1,0,160);
	ctx3.fillText('TRANSFORM',300,80);

ノーマル状態(transform(1, 0, 0, 1, 0, 0) )から変えているのは、4番目の引数(垂直スケール)と最後の引数(y方向の移動)だけです。
4番目の引数(垂直スケール)を「-1」にすることで、同じ拡大率で鏡像にヒックリ返しています。
最後の引数(y方向の移動)は、ちょっと面倒くさいんですが、垂直スケールを-1にしたことがy座標にも影響してて、y位置を80pxに指定(5行目)すると、位置が-80(圏外。笑)になっちゃうんですよ。
なので160にして元々描きたい場所にもどしてやっています。

ですので下記の書き方でも同じ。
垂直スケールは0のままで、y方向の移動を見込んで描画位置をいじってます。
( -(-80) で+80になるって見込みで。こっちのほうが面倒くさい?)

	ctx3.transform(1,0,0,-1,0,0);
	ctx3.fillText('TRANSFORM',300,-80);

とにかく、transform() の()内で、値がお互いに影響し合うのがわかりましたね。

setTransformによる変形(transformとの違いを比較してみた)

transformは、他の変形メソッド(scale、rotate、translate)と同じく、1度指定すると、そのあと初期化してあげない限り指定が効き続けます。
setTransform() は、一旦そこまでの変形を初期化してから、自分の引数で変形するんだって。
「ひとり restore 」できる。こいつは超変わり種です。
自分の()内の指定が影響し合うのは transform と同じです。

サンプル4では setTransform() を使ってみました。
transformも同時に(2回=薄いピンクの文字)使って、最後にsetTransform(ブルーの文字)を使い、違いを比較しています。

/*テキストのスタイルを指定*/
    ctx4.font= 'bold 60px Century Gothic';
	ctx4.textAlign = 'center';
	ctx4.fillStyle = '#FF71D6';
/*テキストをノーマル状態で描画*/
	ctx4.fillText('TRANSFORM',300,100);
/*テキストを半透明に*/
	ctx4.globalAlpha =0.3;
/*テキストを「transform」で反転させて縦に拡大して描画*/
	ctx4.transform(1,0,0,-2,0,300);
	ctx4.fillText('TRANSFORM',300,100);
/*テキストを「transform」で反転させて等倍に*/
	ctx4.transform(1,0,0,-1,0,200);
	ctx4.fillText('TRANSFORM',300,100);
/*テキストの色を変えて*/
	ctx4.fillStyle = '#00BFFF';
/*テキストを「setTransform」で反転させて等倍に描画*/
	ctx4.setTransform(1,0,0,-1,0,200);
	ctx4.fillText('TRANSFORM',300,100);

濃いピンクの文字がノーマルテキストです。(ソースは1〜6行目)
うすいピンクの文字は2つとも transform で続けて指定しています。
最初は垂直スケール(4番目の引数)を「-2」にして、縦長の鏡像にしています。(10行目)
次に垂直スケールを「-1」にしています。(13行目)
-2の-1で「2」となり、高さが2倍の正の像になってますね。前の変形がずっと影響しています。

次に文字の色を変え(16行目)、setTransformで高さが-1の鏡像を指定してみます(18行目)
ソースの上の行でさんざん変形しているにもかかわらず、ちゃんと期待通りの効果で描けました。
すげ〜。setTransformって便利かもよ。

次回予告

今回、変形は一度指定すると初期化しない限りずっと指定が効き続けるということがわかりました。

簡単な描画ならいいけど、複雑な描画の時に、いちいち元に戻すソースを計算して書くのは面倒くさいかも。そんな時に、描画の状態を保存(save)・復元(restore)するメソッドが用意されています。次回はそれを使ってみます。

関連記事
この記事をはてなブックマークに追加

やる気を保つためにランキングに参加しています。
応援してくださると すっごいやる気を出します! (笑)

初心者にも使いやすい(と思う)レンタルサーバー

最近よく「レンタルサーバーはどこがいい?」とご質問が来ます。
自分でも使っていてオススメなのはミニバード。管理画面がわかりやすくていい感じす。
仕事で使ってるロリポップもわかりやすい管理画面で、初めてでもすんなり使えると思います。
両方とも、なんといっても料金が安いです。初めてだとなるべく安いほうがイイですからね。

それよりちょっと料金は高いけど、高スペックでコスパが良く、信頼性も高いサーバといえば、やはりさくらのレンタルサーバと、XSERVER(エックスサーバー)だと思う。この2つは老舗でユーザーも多いので、質問する場がたくさんあり、初心者の方でもイケるだろうと思います。

レンタルサーバーは、たくさんあり過ぎて迷いますよね。近いうちに、初心者にも良さげなサーバーについて記事にまとめます。*記事をアップしたらココにもリンクを貼ります。

スポンサーリンク

コメントの投稿

スポンサーリンク
最新記事
Category
オススメの本
Links
Calendar
05 | 2017/06 | 07
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
Archive
RSS Link
Profile

yuki★hata

Author : yuki★hata
せめて月1回の更新をめざします~。

メールフォームはこちら

スポンサーリンク
スポンサーリンク
Copyright © ほんっとにはじめてのHTML5とCSS3 All Rights Reserved.