Canvasに解像度を設定する

  • 2011 年 4月 20 日
  • kosuke

先日リリースしたオリジナルアプリ作文メーカーでは、ユーザー操作で描く文字の描画に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倍)

“Canvasに解像度を設定する” に コメントはありません

コメントをどうぞ