自炊にちょうどいいブックリーダーアプリを開発する話 #03 imgタグをcanvasタグで表示する

2024年1月6日

Javascript アプリケーション

eyecatch 自炊の自炊による自炊の為のアプリを作る時に重要なのは、画像に扱い方です。 imgタグとcss3でなんとかなるだろうと考えていた自分の甘々納豆な考えを払拭するべく、 画像はcanvasで扱っておくに越したことはないという判断をしました。 事の顛末も含めて、今回のimgをcanvasに変換するドラマを御覧ください。

なんでcanvas?

今回の自炊アプリは、読み込んだ書籍をどんなブラウザ端末でも良さげな操作で閲覧できる事を目的にしているので、パソコンやタブレットのような大画面で見る場合は見開き。 スマートフォンなどの小さな端末で見る場合は、片開きページで見るようにします。 見開きを片開きにする時に、画像を右(または左)半分に裁断したかのうように画像を取り扱う必要が出てきました。 例えばこのような見開きをスマートフォンで見る場合、次のようにしたいんですね。
これを、cssだけでできると思っていたら、全く想定通りに行きませんでした。 まず、やった内容としては、親にdivタグを設置して、横幅を半分にして、それぞれ右寄せ、左寄せにするということを考えて、overflow:hiddenにすればいいや!と考えたんですが、 画像のサイズが固定化していないと、個別ページ毎にサイズを指定することになり、共通cssでの恩恵が受けられなくなります。 imgタグに object-fitを設置しているので、そもそも画像内でのscale調整は難しく、もしかしたらできるのかもしれないが、丸一日ぐらいやってみてできなかったので、画像+CSS方式は諦めました。

imgタグをcanvasタグへの変換方法

なんだ、画像をcanvasで操作すれば、片開きの単一ページのタグが単体で作れるではないか!とひらめき、imgタグをcanvasタグにコンバートすることにしました。 function set_canvas(img , page_sub_flg){ const canvas = document.createElement("canvas") const ctx = canvas.getContext("2d") const w = img.naturalWidth const h = img.naturalHeight canvas.width = w canvas.height = h let x = 0 if(w > h && page_sub_flg){ canvas.width = w / 2 x = -(w / 2) } ctx.drawImage(img, x, 0, w, h) return canvas }
@img : imgタグ @page_sub_flg : ページを分割した時の1ページ目と2ページ目を別々にcanvasタグにするため、後のページの場合はこのフラグをtrueにする
上記の関数に、imgタグを送ってあげると、整形されたcanvasタグが返ってきます。 今回の自炊アプリじゃなくても、画像をcanvasタグで表示したいときなど、サイズを自由自在に調整して使えるので、このコード結構便利ですよ。

注意点

imgタグは、画像が読み込まれた状態で送ってください。 img.onload = set_canvas.bind(this , this.target, page_sub_flg) とすると、いい感じになると思います。

あとがき

canvasの描画って、imgタグをそのまま表示するよりも非常に効率的なんですよね。 単純に表示するだけであれば、わかりにくいんですが、たくさんの画像や描画切り替えなどを行う時は、imgタグじゃなくてcanvas一択です。 レンダリングに特化したタグであることがわかるのは、WebGLなどもcanvasで実装されるので、ゲームなどで使われるのもよくわかります。 今回は手軽にimgタグをcanvasタグで表示するだけの仕様を書きましたが、そもそもcanvasタグ内で動作するアプリにしてもいいかも・・・ その仕様を決めるのはもう少し後になりそうですが・・・

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。