Canvasに解像度を設定する
- 2011 年 4月 20 日
先日リリースしたオリジナルアプリ作文メーカーでは、ユーザー操作で描く文字の描画にCanvasを使っています。
titanium mobileでは描画APIが標準で用意されていない為、WebViewをつかってCanvasで代用した形です。僕はCanvasを使うのはこれが初めてでしたので、実装をCanvasでなく正攻法でいって描画系のモジュールを使うなどでも同じように1からだったのですが、Canvasでもそれなりにパフォーマンスが出るようだし、やはり僕のようなWeb系のデベロッパー/デザイナーにはWebの技術を使ったほうが間違いや不安も少ないと思ったので。今回のは単純な使い方だったしね。
このCanvasを使うにあたって疑問がありました。Ratina Display(640×960)の機種と通常ディスプレイ(320×480)の機種で使いわける必要があるのか?具体的にはキャンバスのサイズはどちらに設定すればいいのか?という点。開発時点ではRatina Displayの確認環境がなかったので、かなり疑問でした。
もう一つ、今回はアプリで使うデータになるので、Canvasで描いたものをtitaniumに渡さなくてはいけない。これできるの?という点。
結果的にどちらも疑問は解消したのですが、初めてってこともあって右往左往と調べたりしたので2回に分けてメモしておきます。参考になる方もいるかもです。
とりあえず今回は前者の疑問、サイズの問題。これをCanvasに解像度を設定すると題して説明します。
Ratina Display、通常ディスプレイ両方に対応させるとして、ソースにCanvasの見た目のサイズとして指定する値ですが、これは320×480のディスプレイに表示するものとして設定します。titaniumでは画像を表示する時、imageViewを使いますが、このimageViewもRatina Displayに対応していて、そのサイズは320×480の画面にあわせてwidthとheightを指定します。表示する画像ファイルを高解像度、低解像度2つ作り、高解像度の方のファイル名には@2xという文字を拡張子の前に加えます。Canvasの場合も考え方は同じ。見た目のサイズは通常で指定して、内部で処理する解像度を高くすればよいようです。
まず見た目のサイズとしてCSSでCanvasの幅と高さを指定します。
<style type="text/css"> canvas#stage{ position:absolute; top:0px; left:0px; border:0px; margin:0px; padding:0px; width:300px; height:300px; background-color:#FFFFFF; } </style> </head> <body> <canvas id="stage"></canvas> </body> </html> |
次にJavaScriptからCanvasを操作する為、Canvasを参照しコンテキストを取得。
ここまでは普通にキャンバスを操作するなら必ず通る道。
解像度を設定するには、この後、Canvasの属性値のwidthとheightを必要な解像度のサイズで設定しコンテキストもscaleで必要な解像度になる倍率を設定します。
今回は以下のようなsetQualityという関数で処理をまとめました。
function setQuality(value){ cvs.setAttribute("width", 300 * value); cvs.setAttribute("height",300 * value); ctx.scale( value, value ); } window.onload = function(){ cvs = document.getElementById("stage"); ctx = cvs.getContext( "2d" ); cvs.addEventListener( "mousedown", onTouchStart ); setQuality( 1 ); } |
上の場合だと、1倍だから特に解像度はかわらずそのまま。Ratina Displayなら setQuality( 2 )とすれば通常の倍の解像度でCanvasを扱える。
今回はブラウザで表示しているので、解像度の設定がわかるよう0.5を設定したサンプルを以下に載せておきます。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Canvasに解像度を設定</title> <style type="text/css"> body{ border:0px; margin:0px; padding:0px; background-color:#CCCCCC; } canvas#stage{ position:absolute; top:0px; left:0px; border:0px; margin:0px; padding:0px; width:300px; height:300px; background-color:#FFFFFF; } </style> <script type="text/javascript"> var cvs; var ctx; function onTouchStart( e ){ ctx.beginPath(); ctx.lineWidth = 3; ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.moveTo( e.pageX, e.pageY ); ctx.lineTo( e.pageX, e.pageY ); ctx.stroke() cvs.addEventListener( "mousemove", onTouchMove ); cvs.addEventListener( "mouseup", onTouchEnd ); e.preventDefault(); } function onTouchMove( e ){ ctx.lineTo( e.pageX, e.pageY ); ctx.stroke() e.preventDefault(); } function onTouchEnd( e ){ cvs.removeEventListener( "mousemove", onTouchMove ); cvs.removeEventListener( "mouseup", onTouchEnd ); ctx.lineTo( e.pageX, e.pageY ); ctx.stroke() e.preventDefault(); } function setQuality(value){ cvs.setAttribute("width", 300 * value); cvs.setAttribute("height",300 * value); ctx.scale( value, value ); } window.onload = function(){ cvs = document.getElementById("stage"); ctx = cvs.getContext( "2d" ); cvs.addEventListener( "mousedown", onTouchStart ); setQuality( 0.5 ); } </script>> </head> <body> <canvas id="stage"></canvas> </body> </html> |
0.5倍
通常(1倍)