###要件
html2canvas
で得た画像データを90度回転させる。
###詳細
html2canvasはページ一部の領域をhtml,css解読してスクリーンショット取ってくれる神ライブラリ。
今回は作品を紹介するような紹介カードを作れるという機能を実装したが、PC版で最初にやってしまったためスマホで同じサイズ比のカードテンプレートを作ろうと思うと90度回転しなければならなくなった。
html2canvas
の場合、対象領域のHTMLelement
を渡すとコールバックでcanvas
を渡してくれるが、この時点で幅・高さ・向きは決定してしまっているため、なかなか編集に手こずった。
コンテキストを回転させる方法はctx.rotate
という。これは分かっていたのだが、そのまま適応させてもcanvas
自体は回転していないのでこうなる ↓
また、canvasのサイズを後から変更すると描画内容も一緒に失われるのでこれも出来ない。
挙句の果てに迷走し、JSで画像データを(canvasでなく)そのままいじれないか!?とか考えてexif周りの事を調べたりもした。当然できなかった。
JSで画像データをいじる際は必ずcanvasを通して行います。
------------ https://ja.javascript.info/blob#ref-122
ちくしょうスマホのトリミング機能使いてぇ......
###結果
新しくcanvasを作り、描画内容は元canvasからコピーしてくる。
function canvasRotate270(img){
const canvas = document.createElement('canvas');
canvas.width = img.clientHeight;
canvas.height = img.clientWidth;
//縦横比反転canvas
const ctx = canvas.getContext('2d');
ctx.save();
ctx.translate(0,canvas.height);
ctx.rotate( 270 * Math.PI / 180 );
ctx.drawImage(img, 0, 0,canvas.height,canvas.width,0,0,canvas.height,canvas.width);
ctx.restore();
return canvas;
}
canvas・contextの使い方をよく理解していなかった。
###解説
ctx.drawImageは元画像のある指定領域を切り抜き、貼り付け先画像にも貼り付ける領域を指定できる(元画像データはimgからでなくてもcanvasからでも可。)
⇒ よってctx(コンテキスト)の向きが回転していても、ctx.translate
で中心点ずれててもきちんと座標を指定できれば問題ない。
今回私の場合は270度の回転が必要だったが、中心点(グラフの座標原点みたいなイメージ)をしらべるとcanvasの縦横比に関わらず、左上に原点が設定されることが分かった。
よって、ctxの回転前にtranslateで描画原点を回転後のcanvasの左上に設定すればいい。
ctx.translate(0,canvas.height);
あとはctx.drawImageで元画像(赤矩形)の(0,0)~(x,y)を指定し切り抜き、回転後の青の矩形で(0,0)~(x,y)へ貼り付ける。
ctx.drawImage(img, 0, 0,canvas.height,canvas.width,0,0,canvas.height,canvas.width);
ctx.rotete
のせいでx,yが反転してることに注意。
今考えたら90度でよくね??
###まとめ
主に、drawImageの性質の理解が足りていなかった。本質は画像のコピーと貼り付けを同時に行えるクリップ機能だった。
これとtranslateとrotateがあれば何でもできる為、ネット記事では解説することもなかったのだろう。
なんだか書いてるうちにtranslateのあたりの座標説明がずれてるな....と感じたがそろそろ次の作業に入りたいのでやめておく。
コンテキストによる描画の回転ctx.rotate()
について挙動がよく分からない方は正常なcanvasをctx.rotate(10 * Math.PI / 180)
で10度だけ回してみたり、ちょっとだけctx.translate
してみたりするのが一番早いと思います。私も結局そうでした。
以上です。いろいろ落ち着いたらcanvas使ってゲーム作りたいな。