<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>KRAY Inc</title>
	<atom:link href="http://kray.jp/feed/" rel="self" type="application/rss+xml" />
	<link>http://kray.jp</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Fri, 03 Feb 2012 01:32:43 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>JavaScript 3DレンダリングエンジンのThree.jsを試す</title>
		<link>http://kray.jp/blog/three-js/</link>
		<comments>http://kray.jp/blog/three-js/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 01:28:21 +0000</pubDate>
		<dc:creator>takuru</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Three.js]]></category>
		<category><![CDATA[webgl]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=5462</guid>
		<description><![CDATA[こんにちは。 KRAYアルバイトの浅海です。 今回は、最近ちまたで噂のThree.jsで遊んでみようとおもいます。 http://github.com/mrdoob/three.js webgl対応のブラウザで見ている方 [...]]]></description>
			<content:encoded><![CDATA[<p><iframe src="http://canvas.d-adv.net/ex_logo/" width="640" height="480" frameborder="0" scrolling="no" style="position:absolute;top:50px;left: 400px;"></iframe></p>
<p>こんにちは。<br />
KRAYアルバイトの浅海です。</p>
<p>今回は、最近ちまたで噂のThree.jsで遊んでみようとおもいます。<br />
<a href="http://github.com/mrdoob/three.js" target="_blank">http://github.com/mrdoob/three.js</a></p>
<p>webgl対応のブラウザで見ている方は、右上に3Dのボックスが表示されていると思います。<br />
Three.jsを使えば、このようなことを簡単にJavascriptで実現できるのです。</p>
<p>半信半疑で使ってみたところ、たしかにThree.jsでは、3D特有の行列計算や数学的思考をせずとも、3Dを表示、操作することができました。</p>
<p>「ちょっとのプログラムで3Dができる。」<br />
この面白さを皆さんに届けたいです。</p>
<h2>目次</h2>
<ul>
<li><a href="#ex1">立方体を表示する</a></li>
<li><a href="#ex2">光をあてる</a></li>
<li><a href="#ex3">テスクチャを貼り付ける</a></li>
<li><a href="#ex4">マウスで回転させる</a></li>
<li><a href="#ex5">マウスで移動させる</a></li>
<li><a href="#ex6">クリック判定する</a></li>
</ul>
<h2>Three.js</h2>
<p>web上には、HTML5のcanvasを利用した様々なサンプルページやアプリケーションが色々できてきました。<br />
その中でも、ひと際目を引くのが<a href="http://mrdoob.github.com/three.js/" target="_blank">Three.jsを使用したサンプル</a>です。<br />
ブラウザの進歩もここまできたか・・・、というようなものばかりです。<br />
ついこの間まで人類は、marqueeタグやマウスポインタを変な画像が追っかけるjavascriptで遊んでいたはずですが・・・</p>
<p>このThree.jsのサンプル、どれを見ても、とても難しそうなことをしています。<br />
人の顔が3Dで精巧に作られていたり、なんか凄い綺麗な空間がはじけていたり・・、ですが、ソースを見てみると、JavaScript部分は非常に短い事がわかります。<br />
Three.jsがほとんどの計算をやってくれるからです。</p>
<h2><a name="ex1">立方体を表示する</a></h2>
<p>Hello world!!<br />
さて、単純な立方体を表示してみます。</p>
<p><a href="http://kray.jp/blog/three-js/attachment/ex1/" rel="attachment wp-att-5678"><img src="http://kray.jp/wp-content/uploads/2012/02/ex1.png" alt="" title="ex1-preview" width="328" height="248" class="alignnone size-full wp-image-5678" /></a><br />
<a href="http://canvas.d-adv.net/ex1/" target="_blank">実際の動作</a></p>
<h3>HTML</h3>
<p>canvasが無いことに気づくと思います。<br />
canvasはThree.jsが内部的に生成するので必要ありません。</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #00bbdd;">&lt;!DOCTYPE html&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/meta.html"><span style="color: #000000; font-weight: bold;">meta</span></a> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span>example 1<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/link.html"><span style="color: #000000; font-weight: bold;">link</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;./style.css&quot;</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;./Three.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;./main.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;canvas-wrapper&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span></div></div>
<h3>JavaScript</h3>
<p>Three.jsには大きさを指定するだけで立方体を作ってくれる機能があり、四角形を表示するだけならJavaScriptは約15行書くだけです。お手軽！</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> width <span style="color: #339933;">=</span> <span style="color: #CC0000;">640</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> height <span style="color: #339933;">=</span> <span style="color: #CC0000;">480</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> geometry <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">CubeGeometry</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">100</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">100</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">100</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 立方体作成</span><br />
<span style="color: #003366; font-weight: bold;">var</span> material <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">MeshBasicMaterial</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>color<span style="color: #339933;">:</span> 0x0000aa<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 材質作成</span><br />
<span style="color: #003366; font-weight: bold;">var</span> mesh &nbsp; &nbsp; <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">Mesh</span><span style="color: #009900;">&#40;</span>geometry<span style="color: #339933;">,</span> material<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 立方体と材質を結びつけてメッシュ作成</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> camera &nbsp; <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">PerspectiveCamera</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">40</span><span style="color: #339933;">,</span> width <span style="color: #339933;">/</span> height<span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// カメラ作成。画角40、距離1〜1000の部分を表示できる。</span><br />
camera.<span style="color: #660066;">position</span>.<span style="color: #660066;">z</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">400</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// カメラの位置はz軸の-400</span><br />
camera.<span style="color: #660066;">lookAt</span><span style="color: #009900;">&#40;</span>mesh.<span style="color: #660066;">position</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// メッシュの位置にカメラを向ける。</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> scene &nbsp; &nbsp;<span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">Scene</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// シーン作成</span><br />
scene.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span>mesh<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// シーンにメッシュ追加</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> renderer <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">WebGLRenderer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// レンダラ作成</span><br />
renderer.<span style="color: #660066;">setSize</span><span style="color: #009900;">&#40;</span>width<span style="color: #339933;">,</span> height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
window.<span style="color: #000066;">onload</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'canvas-wrapper'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>renderer.<span style="color: #660066;">domElement</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; renderer.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span>scene<span style="color: #339933;">,</span> camera<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// sceneをcameraで映す（表示）</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>四角形が表示されました。</p>
<h3>レンダラー</h3>
<p>Three.jsには、canvasのレンダラとwebGLのレンダラを切り替えることができる機能があります。<br />
canvasのレンダラを使えばiPad等、webGLに対応していない環境でも見ることができるのですが、WebGLレンダラでないと実現できないことも多くあるようです。</p>
<p>といっても今回のサンプルはCanvasレンダラでも十分やっていけますので、<br />
WebGL対応してない方のために、この<a href="#cr">記事の最後</a>にCanvasレンダラ対応のものを用意してあります。</p>
<p>canvasのレンダラを使用したい場合は、上記javascript１５行目<br />
THREE.WebGLRenderer()<br />
の部分を<br />
THREE.CanvasRenderer()<br />
とすることにより、canvasのレンダラを使用できます。</p>
<h2><a name="ex2">光をあてる</a></h2>
<p>とりあえず表示されましたが、ベタ塗りされているので立方体なのかどうかはまだわかりません。<br />
非常にダサい感じがあります。<br />
なので光をあてて輪郭をはっきりさせてみます。</p>
<p><a href="http://kray.jp/blog/three-js/attachment/ex2/" rel="attachment wp-att-5679"><img src="http://kray.jp/wp-content/uploads/2012/02/ex2.png" alt="" title="ex2-preview" width="329" height="248" class="alignnone size-full wp-image-5679" /></a><br />
<a href="http://canvas.d-adv.net/ex2/" target="_blank">実際の動作</a></p>
<h3>JavaScript</h3>
<p>光源を作成してsceneに追加します。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// scene作成後に追加</span><br />
<span style="color: #003366; font-weight: bold;">var</span> light &nbsp; &nbsp;<span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">DirectionalLight</span><span style="color: #009900;">&#40;</span>0xffffff<span style="color: #339933;">,</span> <span style="color: #CC0000;">1.5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 光源の色, 強さ</span><br />
light.<span style="color: #660066;">position</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>x<span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> y<span style="color: #339933;">:</span> <span style="color: #CC0000;">0.2</span><span style="color: #339933;">,</span> z<span style="color: #339933;">:</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#125;</span> <span style="color: #006600; font-style: italic;">// 光源の位置</span><br />
scene.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span>light<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>また、現在の立方体に設定されているマテリアル（材質）だと光を反射しないので、光を反射してくれるマテリアルに変更します。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// material作成の行を以下と入れ替え</span><br />
<span style="color: #006600; font-style: italic;">// ランバート反射を行うマテリアル</span><br />
<span style="color: #003366; font-weight: bold;">var</span> material <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">MeshLambertMaterial</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>color<span style="color: #339933;">:</span> 0x0000aa<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>これで立方体の輪郭がはっきりして、3Dプログラムをしている気分になりました!</p>
<h2><a name="ex3">テクスチャを貼り付ける</a></h2>
<p>テクスチャとしてこの画像を使います。<br />
<img src="http://kray.jp/wp-content/themes/kray/images/company/member/img_anko150.jpg"></p>
<p>テクスチャがなんなのかは、サンプルをどうぞ。</p>
<p><a href="http://kray.jp/blog/three-js/attachment/ex3/" rel="attachment wp-att-5680"><img src="http://kray.jp/wp-content/uploads/2012/02/ex3.png" alt="" title="ex3-preview" width="328" height="249" class="alignnone size-full wp-image-5680" /></a><br />
<a href="http://canvas.d-adv.net/ex3/" target="_blank">実際の動作</a></p>
<h3>JavaScript</h3>
<p>Materialの作成した部分を以下のように書き換えます。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> texture &nbsp;<span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">ImageUtils</span>.<span style="color: #660066;">loadTexture</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/images/anko.jpg'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> material <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">MeshLambertMaterial</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>map<span style="color: #339933;">:</span> texture<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// テクスチャ反映</span></div></div>
<p>これだけで、方向なども自動にテクスチャが貼られます。<br />
お手軽ですね。</p>
<h2><a name="ex4">マウスで回転させる</a></h2>
<p>マウスドラッグで立方体を回転できるようにします。<br />
単純化のため、マウスのx移動、y移動をそのままx方向、y方向の回転に対応させます。<br />
なので、立方体を逆さにするとx回転が逆になりますが、そこは目をつぶって下さいませ・・・。</p>
<p><a href="http://canvas.d-adv.net/ex4/" target="_blank">実際の動作</a></p>
<h3>JavaScript</h3>
<p>角度の変更は、meshのrotationを変えるだけでできるようになっています。<br />
簡単です。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> mousedown <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
renderer.<span style="color: #660066;">domElement</span>.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mousedown'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; mousedown <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; prevPosition <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>x<span style="color: #339933;">:</span> e.<span style="color: #660066;">pageX</span><span style="color: #339933;">,</span> y<span style="color: #339933;">:</span> e.<span style="color: #660066;">pageY</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
renderer.<span style="color: #660066;">domElement</span>.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mousemove'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>mousedown<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; moveDistance <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>x<span style="color: #339933;">:</span> prevPosition.<span style="color: #660066;">x</span> <span style="color: #339933;">-</span> e.<span style="color: #660066;">pageX</span><span style="color: #339933;">,</span> y<span style="color: #339933;">:</span> prevPosition.<span style="color: #660066;">y</span> <span style="color: #339933;">-</span> e.<span style="color: #660066;">pageY</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; mesh.<span style="color: #660066;">rotation</span>.<span style="color: #660066;">x</span> <span style="color: #339933;">+=</span> moveDistance.<span style="color: #660066;">y</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">0.01</span><span style="color: #339933;">;</span><br />
&nbsp; mesh.<span style="color: #660066;">rotation</span>.<span style="color: #660066;">y</span> <span style="color: #339933;">-=</span> moveDistance.<span style="color: #660066;">x</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">0.01</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; prevPosition <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>x<span style="color: #339933;">:</span> e.<span style="color: #660066;">pageX</span><span style="color: #339933;">,</span> y<span style="color: #339933;">:</span> e.<span style="color: #660066;">pageY</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; render<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
renderer.<span style="color: #660066;">domElement</span>.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mouseup'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; mousedown <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>描画をrender関数にまとめました。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; renderer.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span>scene<span style="color: #339933;">,</span> camera<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h2><a name="ex5">マウスで移動させる</a></h2>
<p>シフトを押しながらマウスドラッグで立方体を移動できるようにします。</p>
<p><a href="http://canvas.d-adv.net/ex5/" target="_blank">実際の動作</a></p>
<h3>JavaScript</h3>
<p>mousemoveのイベントリスナを以下のように書き換えます。<br />
positionを変更することにより移動できます。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">shiftKey</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; mesh.<span style="color: #660066;">position</span>.<span style="color: #660066;">x</span> <span style="color: #339933;">+=</span> moveDistance.<span style="color: #660066;">x</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">0.5</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; mesh.<span style="color: #660066;">position</span>.<span style="color: #660066;">y</span> <span style="color: #339933;">+=</span> moveDistance.<span style="color: #660066;">y</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">0.5</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">else</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; mesh.<span style="color: #660066;">rotation</span>.<span style="color: #660066;">x</span> <span style="color: #339933;">+=</span> moveDistance.<span style="color: #660066;">y</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">0.01</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; mesh.<span style="color: #660066;">rotation</span>.<span style="color: #660066;">y</span> <span style="color: #339933;">-=</span> moveDistance.<span style="color: #660066;">x</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">0.01</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>これで移動できるようになりました。<br />
移動や回転、基本的なことはやったので、次はもう少し高度なことを試してみます。</p>
<h2><a name="ex6">クリック判定する</a></h2>
<p>マウスが立方体をクリックしたかどうかを簡単に検出することができます。<br />
そう、Three.jsならね。</p>
<p>3Dのプログラムでよく使われる、レイによる衝突判定を行います。<br />
イメージとして、クリックした位置から、３Dの世界に向かってレイ（光線）が発射されます。<br />
その光線が、メッシュと衝突したかどうかを計算して判定しているのです。<br />
といっても、全ての計算はThree.jsがやってくれますが・・。</p>
<p><a href="http://canvas.d-adv.net/ex6/" target="_blank">実際の動作</a></p>
<h3>JavaScript</h3>
<p>以下を追加します。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> projector <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">Projector</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
renderer.<span style="color: #660066;">domElement</span>.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mousedown'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> mouse_x <span style="color: #339933;">=</span> &nbsp; <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">pageX</span><span style="color: #339933;">-</span>e.<span style="color: #660066;">target</span>.<span style="color: #660066;">offsetParent</span>.<span style="color: #660066;">offsetLeft</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> renderer.<span style="color: #660066;">domElement</span>.<span style="color: #660066;">width</span><span style="color: #009900;">&#41;</span> &nbsp;<span style="color: #339933;">*</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> mouse_y <span style="color: #339933;">=</span> <span style="color: #339933;">-</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">pageY</span><span style="color: #339933;">-</span>e.<span style="color: #660066;">target</span>.<span style="color: #660066;">offsetParent</span>.<span style="color: #660066;">offsetTop</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> renderer.<span style="color: #660066;">domElement</span>.<span style="color: #660066;">height</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> vector <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">Vector3</span><span style="color: #009900;">&#40;</span>mouse_x<span style="color: #339933;">,</span> mouse_y<span style="color: #339933;">,</span> <span style="color: #CC0000;">0.5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; projector.<span style="color: #660066;">unprojectVector</span><span style="color: #009900;">&#40;</span>vector<span style="color: #339933;">,</span> camera<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> ray <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> THREE.<span style="color: #660066;">Ray</span><span style="color: #009900;">&#40;</span>camera.<span style="color: #660066;">position</span><span style="color: #339933;">,</span> vector.<span style="color: #660066;">subSelf</span><span style="color: #009900;">&#40;</span>camera.<span style="color: #660066;">position</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">normalize</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// レイの作成</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> ray.<span style="color: #660066;">intersectObjects</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>mesh<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// レイがメッシュに衝突するかどうか</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// 戻り値は、衝突したメッシュが配列で入っている。</span><br />
<br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>obj.<span style="color: #660066;">length</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> text <span style="color: #339933;">=</span> document.<span style="color: #660066;">createTextNode</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;立方体をクリックしました。 x = &quot;</span><span style="color: #339933;">+</span>obj<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">point</span>.<span style="color: #660066;">x</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;y = &quot;</span><span style="color: #339933;">+</span>obj<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">point</span>.<span style="color: #660066;">y</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;z = &quot;</span><span style="color: #339933;">+</span>obj<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">point</span>.<span style="color: #660066;">z</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> p <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'p'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; p.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>text<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; document.<span style="color: #660066;">body</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<h3>ray.intersectObjects(array)</h3>
<p>このメソッドには、meshを配列で渡します。<br />
今回の例はmeshが一つですが、複数のメッシュを配列で持っておけば、全てのメッシュとレイの衝突判定を行なってくれます。</p>
<p>戻り値は衝突したメッシュ毎に配列で返ってきます。<br />
その内容は以下のとおりで、これだけの情報が簡単に取得できるThree.jsは凄いですね。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; distance<span style="color: #339933;">:</span> <span style="color: #006600; font-style: italic;">// 距離</span><br />
&nbsp; point<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>x<span style="color: #339933;">:</span> y<span style="color: #339933;">:</span> z<span style="color: #339933;">:</span><span style="color: #009900;">&#125;</span> <span style="color: #006600; font-style: italic;">// クリック座標</span><br />
&nbsp; object<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span> <span style="color: #006600; font-style: italic;">// クリックされたオブジェクトの情報</span><br />
&nbsp; face<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span> <span style="color: #006600; font-style: italic;">// クリックされた面の情報</span></div></div>
<h2>最後に</h2>
<p>Three.jsで3Dした気分になりました。<br />
簡単な3Dゲームですら実現できそうです。<br />
はたしてこの先、ブラウザ上の3Dはどう活用されていくのでしょうか・・・。</p>
<p>個人的に、最後の例のように、文章など普通のwebコンテンツの上に3Dがドカーンと置いてあるのは、中々面白いと思います。</p>
<h2><a name="cr">おまけその１　Canvasレンダラ使用Ver</a></h2>
<p>上記と同じものを、Canvasレンダラを使用して作ったバージョンです。<br />
WebGLに対応していないiPadなどでも見えるかと思います。<br />
タッチイベントに対応するために、プログラムは少し変えています。</p>
<p><a href="http://canvas.d-adv.net/ex_canvas/" target="_blank">Canvasレンダラバージョン</a></p>
<p>webGLレンダラ版と違い、動きがもっさりして、ポリゴンの継ぎ目が見えてしまいます。<br />
さらに、初代のiPadでは、テクスチャが壊れてしまいました。</p>
<h3>操作方法</h3>
<p>  １本指:回転<br />
  ２本指:移動</p>
<h2>おまけその２　lookAt</h2>
<p>camera.lookAt(position)<br />
でカメラをpositionの位置に向けられます。</p>
<p>クリックした物体の方向にカメラを向けるサンプル。<br />
<a href="http://canvas.d-adv.net/ex_lookat/" target="_blank">lookAtのサンプル</a></p>
<h2>おまけその３　githubリポジトリ</h2>
<p>全てのサンプルページではソースを見れますが、githubにも公開しました。<br />
ご自由にお使い下さい！<br />
<a href="https://github.com/asaumi/webgl_sample" target="_blank">https://github.com/asaumi/webgl_sample</a><br />
リポジトリ git://github.com/asaumi/webgl_sample.git</p>
<p>以上です。</p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/three-js/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[Amazon EC2] AMI をゼロから作る CentOS 6.2 / S3-Backed 版</title>
		<link>http://kray.jp/blog/centos62-s3backed-ami-from-scratch/</link>
		<comments>http://kray.jp/blog/centos62-s3backed-ami-from-scratch/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 04:00:17 +0000</pubDate>
		<dc:creator>morimori</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[ec2]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=5011</guid>
		<description><![CDATA[CentOS 6.2 の最小インストールの AMI を作る方法を解説します。]]></description>
			<content:encoded><![CDATA[<h2>まえがき</h2>
<p>もりやまです。<br />
今回は、一昨年の 7 月に弊社サイトをリニューアルして、サイトのアクセス数が大分増えるよりも前に書いた <a href="http://kray.jp/blog/ami-%E3%82%92%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8B/">EC2 の AMI を作る記事</a>を、CentOS 6.2 ベースでやってみようと思います。<br />
少し長いですが、お付き合いください。</p>
<h2>はじめに</h2>
<p>公式の手順は「<a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/creating-loopback-s3-linux.html">From a Loopback &#8211; Amazon Elastic Compute Cloud</a>」にあります。<br />
基本はこの通りなのですが、如何せん Fedora Core 4 を使った例なので、最新の OS で作るにはそのままでは使えませんのでご注意ください。</p>
<p>CentOS 6.2 のベースである RHEL6 は、rpm パッケージのペイロードが xz 形式で圧縮されるようになったため、<strong>RHEL5 以前の rpm では展開することができません</strong>。<br />
そのため AMI のビルド環境は、xz 形式のペイロードを展開できるバージョンの rpm が使われている OS を使う必要があります。<br />
今回はビルド用の環境に、<a href="http://www.momonga-linux.org/">Momonga Linux</a> (64bit) の trunk 環境を使用しましたが、作成する AMI と同じ OS・アーキテクチャで揃えておくのが安心です。<br />
それでは実際に作っていきたいと思います。</p>
<h2>0. 準備</h2>
<p>AMI の作成には、<a href="http://aws.amazon.com/developertools/368">EC2 AMI Tools</a> というパッケージを使うので、インストールしておいてください。<br />
ruby で書かれているので、ruby も入っている必要があります。</p>
<h2>1. loopback イメージを作成</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=CentOS-<span style="color: #000000;">6.2</span>-<span style="color: #000000;">1</span>.kray-i386.img <span style="color: #007800;">bs</span>=1G <span style="color: #007800;">count</span>=<span style="color: #000000;">8</span></div></div>
<p>このイメージがそのままインスタンスのルートデバイスになります。今回は 8GB で作成します。<br />
AMI にする際にイメージの空き領域はほとんど圧縮されてしまうので、必要な領域がそれほど多くなくても大きめに作っておいて問題ありません。<br />
ただし、S3-Backed なインスタンスで使えるルートデバイスの最大サイズは 10GB です。</p>
<h2>2. loopback イメージにファイルシステムを作成してマウント</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mkfs.ext4 <span style="color: #660033;">-F</span> <span style="color: #660033;">-L</span> _<span style="color: #000000; font-weight: bold;">/</span> CentOS-<span style="color: #000000;">6.2</span>-<span style="color: #000000;">1</span>.kray-i386.img<br />
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> ami-root<br />
<span style="color: #c20cb9; font-weight: bold;">mount</span> <span style="color: #660033;">-o</span> loop CentOS-<span style="color: #000000;">6.2</span>-<span style="color: #000000;">1</span>.kray-i386.img ami-root<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> ami-root</div></div>
<p>今回はルートデバイスを ext4 でフォーマットします。ルートデバイスで使えるファイルシステムは「<a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/UserProvidedkernels.html">Enabling Your Own Linux Kernels &#8211; Amazon Elastic Compute Cloud</a>」に記載されています。<br />
以前は AWS 側で用意されている kernel しか使えなかったのですが、2010 年 7 月に、PV-GRUB を使ってインスタンスにインストールされている kernel を起動できるようになりました。<br />
今回はそれを使う AMI を作るので、PV-GRUB が認識できるファイルシステムを使う必要があります。</p>
<h2>3. インストールに必要なファイルを作成</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> etc proc dev<br />
<br />
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;</span> etc<span style="color: #000000; font-weight: bold;">/</span>fstab <span style="color: #cc0000; font-style: italic;">&lt;&lt;EOS<br />
LABEL=_/ &nbsp; / &nbsp; &nbsp; &nbsp; &nbsp; ext4 &nbsp; &nbsp;defaults &nbsp; &nbsp; &nbsp; 1 1<br />
none &nbsp; &nbsp; &nbsp; /dev/pts &nbsp;devpts &nbsp;gid=5,mode=620 &nbsp;0 0<br />
none &nbsp; &nbsp; &nbsp; /dev/shm &nbsp;tmpfs &nbsp; defaults &nbsp; &nbsp; &nbsp; &nbsp;0 0<br />
none &nbsp; &nbsp; &nbsp; /proc &nbsp; &nbsp; proc &nbsp; &nbsp;defaults &nbsp; &nbsp; &nbsp; &nbsp;0 0<br />
none &nbsp; &nbsp; &nbsp; /sys &nbsp; &nbsp; &nbsp;sysfs &nbsp; defaults &nbsp; &nbsp; &nbsp; &nbsp;0 0<br />
EOS</span><br />
<br />
<span style="color: #c20cb9; font-weight: bold;">mount</span> <span style="color: #660033;">-t</span> proc none proc</div></div>
<p>こちらはほぼ公式のドキュメントの通りで、特筆すべきところはありません。</p>
<h2>4. インストール用の yum.conf を作成</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">-O</span> ..<span style="color: #000000; font-weight: bold;">/</span>RPM-GPG-KEY-CentOS-<span style="color: #000000;">6</span> http:<span style="color: #000000; font-weight: bold;">//</span>ftp.riken.jp<span style="color: #000000; font-weight: bold;">/</span>Linux<span style="color: #000000; font-weight: bold;">/</span>centos<span style="color: #000000; font-weight: bold;">/</span>RPM-GPG-KEY-CentOS-<span style="color: #000000;">6</span><br />
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;</span> ..<span style="color: #000000; font-weight: bold;">/</span>repos.conf <span style="color: #cc0000; font-style: italic;">&lt;&lt;EOS<br />
[ami-base]<br />
name=CentOS-6 - Base<br />
mirrorlist=http://mirrorlist.centos.org/?release=6&amp;arch=i386&amp;repo=os<br />
gpgcheck=1<br />
gpgkey=file://${PWD}/../RPM-GPG-KEY-CentOS-6<br />
<br />
#released updates <br />
[ami-updates]<br />
name=CentOS-6 - Updates<br />
mirrorlist=http://mirrorlist.centos.org/?release=6&amp;arch=i386&amp;repo=updates<br />
gpgcheck=1<br />
gpgkey=file://${PWD}/../RPM-GPG-KEY-CentOS-6<br />
EOS</span></div></div>
<p>こちらもほぼ公式のドキュメント通りですが、ビルドに使用するホストが Momonga Linux で CentOS の GPG 公開鍵を持っていないため、事前にダウンロードしています。</p>
<h2>5. 最小限の構成をインストール</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setarch i386 <span style="color: #c20cb9; font-weight: bold;">yum</span> <span style="color: #660033;">-y</span> <span style="color: #660033;">-c</span> ..<span style="color: #000000; font-weight: bold;">/</span>repos.conf <span style="color: #660033;">--installroot</span>=<span style="color: #007800;">$PWD</span> <span style="color: #660033;">--disablerepo</span>=<span style="color: #000000; font-weight: bold;">*</span> <span style="color: #660033;">--enablerepo</span>=ami-base,ami-updates groupinstall Core</div></div>
<p>公式のドキュメントでは「Base」グループでインストールしていますが、ここではさらに少ない「Core」グループでインストールします。<br />
「setarch i386」は、ビルドに使用するホストが 64bit 環境のため指定しています。<br />
「<span>-</span>-disablerepo=* <span>-</span>-enablerepo=ami-base,ami-updates」は、ビルドに使用するホストに設定してあるリポジトリまでロードされてしまうため、このように指定しています。<br />
以降 yum を実行する際は、すべてこれらを指定します。</p>
<h2>6. 不要なパッケージを削除</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">rpm <span style="color: #660033;">-e</span> <span style="color: #660033;">--root</span> <span style="color: #007800;">$PWD</span> selinux-policy-targeted selinux-policy policycoreutils libselinux-utils libsemanage checkpolicy iptables-ipv6<br />
setarch i386 <span style="color: #c20cb9; font-weight: bold;">yum</span> <span style="color: #660033;">-y</span> <span style="color: #660033;">--installroot</span>=<span style="color: #007800;">$PWD</span> remove <span style="color: #ff0000;">&quot;*-firmware&quot;</span></div></div>
<p>SELinux や IPv6 は使わないので、関連するパッケージを削除します。<br />
さらに、EC2 で動かすには必要ないファームウェアも削除してしまいます。</p>
<h2>7. kernel をインストール</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setarch i386 <span style="color: #c20cb9; font-weight: bold;">yum</span> <span style="color: #660033;">-y</span> <span style="color: #660033;">-c</span> ..<span style="color: #000000; font-weight: bold;">/</span>repos.conf <span style="color: #660033;">--installroot</span>=<span style="color: #007800;">$PWD</span> <span style="color: #660033;">--disablerepo</span>=<span style="color: #000000; font-weight: bold;">*</span> <span style="color: #660033;">--enablerepo</span>=ami-base,ami-updates <span style="color: #c20cb9; font-weight: bold;">install</span> kernel</div></div>
<p>PV-GRUB で User Provided Kernel による起動をするので、kernel をインストールします。<br />
ディストリビューションによっては Xen 用の kernel が別にあるものもありますが、CentOS6 では kernel パッケージで問題ないようです。</p>
<h2>8. ec2-ami-tools と ec2-metadata をインストール</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setarch i386 <span style="color: #c20cb9; font-weight: bold;">yum</span> <span style="color: #660033;">-y</span> <span style="color: #660033;">-c</span> ..<span style="color: #000000; font-weight: bold;">/</span>repos.conf <span style="color: #660033;">--installroot</span>=<span style="color: #007800;">$PWD</span> <span style="color: #660033;">--disablerepo</span>=<span style="color: #000000; font-weight: bold;">*</span> <span style="color: #660033;">--enablerepo</span>=ami-base,ami-updates <span style="color: #c20cb9; font-weight: bold;">install</span> ruby rsync<br />
rpm <span style="color: #660033;">-Uvh</span> <span style="color: #660033;">--root</span>=<span style="color: #007800;">$PWD</span> http:<span style="color: #000000; font-weight: bold;">//</span>s3.amazonaws.com<span style="color: #000000; font-weight: bold;">/</span>ec2-downloads<span style="color: #000000; font-weight: bold;">/</span>ec2-ami-tools.noarch.rpm<br />
<span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">-O</span> usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>ec2-metadata http:<span style="color: #000000; font-weight: bold;">//</span>s3.amazonaws.com<span style="color: #000000; font-weight: bold;">/</span>ec2metadata<span style="color: #000000; font-weight: bold;">/</span>ec2-metadata<br />
<span style="color: #c20cb9; font-weight: bold;">chmod</span> +x usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>ec2-metadata</div></div>
<p>ここは必須ではありませんが、あると便利なので入れておきます。</p>
<h2>9. fstab に /mnt と swap パーティションの設定を追加</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> etc<span style="color: #000000; font-weight: bold;">/</span>fstab <span style="color: #cc0000; font-style: italic;">&lt;&lt; EOS<br />
/dev/xvde2 /mnt &nbsp; &nbsp; &nbsp;ext4 &nbsp; &nbsp;defaults &nbsp; &nbsp; &nbsp; &nbsp;1 0<br />
/dev/xvde3 swap &nbsp; &nbsp; &nbsp;swap &nbsp; &nbsp;defaults &nbsp; &nbsp; &nbsp; &nbsp;0 0<br />
EOS</span></div></div>
<p>instance storage をマウントする設定を追加します。デバイス名が xvde2, xvde3 と決め打ちですが、これは t1.micro を除く 32bit のインスタンスで設定されます。<br />
64bit 環境ではまた変わってくるので、詳しくは「<a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/InstanceStorage.html">Amazon EC2 Instance Storage &#8211; Amazon Elastic Compute Cloud</a>」を参照してください。</p>
<p>ちなみに、Amazon Linux AMI を起動すると xvda になるのですが、今回の方法で作った AMI では xvde になってしまいました。<br />
AWS 公式の RHEL6 の AMI でも xvde になるので、Amazon Linux AMI が特別なのでしょうか。</p>
<h2>10. ネットワークの設定</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;</span> etc<span style="color: #000000; font-weight: bold;">/</span>sysconfig<span style="color: #000000; font-weight: bold;">/</span>network-scripts<span style="color: #000000; font-weight: bold;">/</span>ifcfg-eth0 <span style="color: #cc0000; font-style: italic;">&lt;&lt; EOS<br />
DEVICE=eth0<br />
BOOTPROTO=dhcp<br />
ONBOOT=yes<br />
TYPE=Ethernet<br />
USERCTL=yes<br />
PEERDNS=yes<br />
IPV6INIT=no<br />
EOS</span><br />
<br />
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;</span> etc<span style="color: #000000; font-weight: bold;">/</span>sysconfig<span style="color: #000000; font-weight: bold;">/</span>network <span style="color: #cc0000; font-style: italic;">&lt;&lt; EOS<br />
NETWORKING=yes<br />
EOS</span><br />
<br />
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;</span> etc<span style="color: #000000; font-weight: bold;">/</span>hosts <span style="color: #cc0000; font-style: italic;">&lt;&lt; EOS<br />
127.0.0.1 &nbsp; &nbsp; &nbsp; localhost.localdomain localhost<br />
EOS</span></div></div>
<p>こちらはほぼ公式のドキュメントの通りです。</p>
<h2>11. rc.local に ssh 公開鍵を取得する設定を追加</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;</span> etc<span style="color: #000000; font-weight: bold;">/</span>rc.local <span style="color: #cc0000; font-style: italic;">&lt;&lt; EOS<br />
# Update the Amazon EC2 AMI creation tools<br />
rpm -Uvh http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm<br />
&nbsp;<br />
# Update ec2-metadata<br />
wget -O /usr/bin/ec2-metadata http://s3.amazonaws.com/ec2metadata/ec2-metadata<br />
chmod 755 /usr/bin/ec2-metadata<br />
<br />
if [ -f &quot;/root/firstrun&quot; ] ; then<br />
&nbsp; dd if=/dev/urandom count=50|md5sum|passwd --stdin root<br />
&nbsp; rm -f /root/firstrun<br />
else<br />
&nbsp; echo &quot;* Firstrun *&quot; &amp;&amp; touch /root/firstrun<br />
fi<br />
&nbsp;<br />
if [ ! -d /root/.ssh ] ; then<br />
&nbsp; mkdir -p /root/.ssh<br />
&nbsp; chmod 0700 /root/.ssh<br />
fi<br />
<br />
ATTEMPTS=5<br />
FAILED=0<br />
# Fetch public key using HTTP<br />
while [ ! -f /root/.ssh/authorized_keys ]; do<br />
&nbsp; curl -f http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key &gt; /tmp/aws-key 2&gt;/dev/null<br />
&nbsp; if [ $? -eq 0 ]; then<br />
&nbsp; &nbsp; cat /tmp/aws-key &gt;&gt; /root/.ssh/authorized_keys<br />
&nbsp; &nbsp; chmod 0600 /root/.ssh/authorized_keys<br />
&nbsp; &nbsp; rm -f /tmp/aws-key<br />
&nbsp; &nbsp; echo &quot;Successfully retrieved AWS public key from instance metadata&quot;<br />
&nbsp; else<br />
&nbsp; &nbsp; FAILED=$(($FAILED + 1))<br />
&nbsp; &nbsp; if [ $FAILED -ge $ATTEMPTS ]; then<br />
&nbsp; &nbsp; &nbsp; echo &quot;Failed to retrieve AWS public key after $FAILED attempts, quitting&quot;<br />
&nbsp; &nbsp; &nbsp; break<br />
&nbsp; &nbsp; fi<br />
&nbsp; &nbsp; echo &quot;Could not retrieve AWS public key (attempt #$FAILED/$ATTEMPTS), retrying in 5 seconds...&quot;<br />
&nbsp; &nbsp; sleep 5<br />
&nbsp; fi<br />
done<br />
EOS</span></div></div>
<p>基本は「<a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/AESDG-chapter-sharingamis.html">Sharing AMIs Safely &#8211; Amazon Elastic Compute Cloud</a>」に記載されている通りです。<br />
合わせて ec2-ami-tools と ec2-metadata のアップデートをするようにしています。</p>
<h2>12. sshd の設定を変更</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">perl</span> <span style="color: #660033;">-p</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s,^#PermitRootLogin yes,PermitRootLogin without-password,'</span> etc<span style="color: #000000; font-weight: bold;">/</span>ssh<span style="color: #000000; font-weight: bold;">/</span>sshd_config<br />
<span style="color: #c20cb9; font-weight: bold;">perl</span> <span style="color: #660033;">-p</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s,^#UseDNS yes,UseDNS no,'</span> etc<span style="color: #000000; font-weight: bold;">/</span>ssh<span style="color: #000000; font-weight: bold;">/</span>sshd_config<br />
<span style="color: #c20cb9; font-weight: bold;">perl</span> <span style="color: #660033;">-p</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s,^PasswordAuthentication yes,PasswordAuthentication no,'</span> etc<span style="color: #000000; font-weight: bold;">/</span>ssh<span style="color: #000000; font-weight: bold;">/</span>sshd_config<br />
<span style="color: #c20cb9; font-weight: bold;">perl</span> <span style="color: #660033;">-p</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s,^UsePAM yes,UsePAM no,'</span> etc<span style="color: #000000; font-weight: bold;">/</span>ssh<span style="color: #000000; font-weight: bold;">/</span>sshd_config</div></div>
<p>こちらも上記のドキュメントに記載されているのですが、更にパスワード認証と PAM を無効にしています。</p>
<h2>13. grub の設定を追加</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;</span> boot<span style="color: #000000; font-weight: bold;">/</span>grub<span style="color: #000000; font-weight: bold;">/</span>menu.lst <span style="color: #cc0000; font-style: italic;">&lt;&lt;EOS<br />
default=0<br />
timeout=0<br />
hiddenmenu<br />
title CentOS6.2<br />
&nbsp; &nbsp; &nbsp; &nbsp; root (hd0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; kernel /boot/vmlinuz-$(rpm --root=$PWD -q --queryformat &quot;%{version}-%{release}.%{arch}\n&quot; kernel) ro root=LABEL=_/<br />
&nbsp; &nbsp; &nbsp; &nbsp; initrd /boot/initramfs-$(rpm --root=$PWD -q --queryformat &quot;%{version}-%{release}.%{arch}\n&quot; kernel).img<br />
EOS</span></div></div>
<p>PV-GRUB 用の設定です。通常の GRUB の設定と同じですね。</p>
<h2>14. 「4gb seg fixup」対策</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;hwcap 1 nosegneg&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> etc<span style="color: #000000; font-weight: bold;">/</span>ld.so.conf.d<span style="color: #000000; font-weight: bold;">/</span>libc6-xen.conf<br />
<span style="color: #c20cb9; font-weight: bold;">chroot</span> . ldconfig</div></div>
<p>EC2 に限らず、<a href="http://wiki.xensource.com/xenwiki/XenFaq#head-e05786f1e0d6a833bc146a6096cab2d96f2b30ae">Xen 環境で発生する問題</a>のようですが、「4gb seg fixup &#8230;」というようなメッセージが延々と /var/log/messages に出力されてしまうことがあります。<br />
上記はそれを防ぐための設定です。</p>
<h2>15. 不要なファイルを削除してイメージをアンマウント</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setarch <span style="color: #800000;">${ARCH}</span> <span style="color: #c20cb9; font-weight: bold;">yum</span> <span style="color: #660033;">-y</span> <span style="color: #660033;">-c</span> ..<span style="color: #000000; font-weight: bold;">/</span>repos.conf <span style="color: #660033;">--installroot</span>=<span style="color: #007800;">$PWD</span> <span style="color: #660033;">--disablerepo</span>=<span style="color: #000000; font-weight: bold;">*</span> <span style="color: #660033;">--enablerepo</span>=ami-base,ami-updates clean all<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> ..<br />
<span style="color: #c20cb9; font-weight: bold;">umount</span> ami-root<span style="color: #000000; font-weight: bold;">/</span>proc<br />
<span style="color: #c20cb9; font-weight: bold;">umount</span> <span style="color: #660033;">-d</span> ami-root</div></div>
<p>AMI を作成する前に、yum のキャッシュ等を削除します。<br />
スクラッチから作る場合には問題ないと思いますが、既存のインスタンスを AMI 化する際には、ssh の公開鍵や sshd のホストキー、.bash_history やログ等、削除すべきファイルが多々あるので注意しましょう。</p>
<h2>16. loopback イメージをバンドル</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> ami-bundle<br />
ec2-bundle-image <span style="color: #660033;">-i</span> CentOS-<span style="color: #000000;">6.2</span>-<span style="color: #000000;">1</span>.kray-i386.img <span style="color: #660033;">-k</span> <span style="color: #800000;">${EC2_PRIVATE_KEY}</span> <span style="color: #660033;">-c</span> <span style="color: #800000;">${EC2_CERT}</span> <span style="color: #660033;">-u</span> <span style="color: #800000;">${AWS_ACCOUNT_NUMBER}</span> <span style="color: #660033;">-d</span> .<span style="color: #000000; font-weight: bold;">/</span>ami-bundle <span style="color: #660033;">-r</span> i386 <span style="color: #660033;">--kernel</span> aki-ec5df7ed</div></div>
<p>インストールが済んだ loopback イメージを AMI としてバンドルします。<br />
ここで PV-GRUB の AKI を指定するのですが、同じ AKI でもリージョンごとに ID が違います。今回は東京リージョン（ap-northeast-1）のものを指定します。<br />
PV-GRUB 用の最新の AKI は、<a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/UserProvidedkernels.html">User Provided Kernel</a> のドキュメントに載っています。<br />
ファイル名の pv-grub- の後が、hd0 のものが S3-Backed 用、hd00 のものが EBS-Backed 用のようです。<br />
今回は「東京リージョン」「S3-Backed」「32bit」なので、「aki-ec5df7ed ec2-public-images-ap-northeast-1/pv-grub-hd0_1.02-i386.gz.manifest.xml」を指定します。</p>
<h2>17. バンドルした AMI を S3 にアップロード</h2>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ec2-upload-bundle <span style="color: #660033;">-b</span> <span style="color: #800000;">${S3_BUCKET}</span> <span style="color: #660033;">-a</span> <span style="color: #800000;">${AWS_ACCESS_KEY}</span> <span style="color: #660033;">-s</span> <span style="color: #800000;">${AWS_SECRET_ACCESS_KEY}</span> <span style="color: #660033;">-m</span> .<span style="color: #000000; font-weight: bold;">/</span>ami-bundle<span style="color: #000000; font-weight: bold;">/</span>CentOS-<span style="color: #000000;">6.2</span>-<span style="color: #000000;">1</span>.kray-i386.img.manifest.xml <span style="color: #660033;">--retry</span> <span style="color: #660033;">--location</span> ap-northeast-<span style="color: #000000;">1</span></div></div>
<p>東京リージョンのバケットにアップロードするので、「<span>-</span>-location ap-northeast-1」を指定しています。<br />
この際、アップロード先のバケット名にドットが含まれていると、証明書の検証に失敗してアップロードに失敗します。<br />
ec2-upload-bundle を使わずに別の方法でアップロードするか、ec2-upload-bundle が内部で curl を使うので、~/.curlrc に「insecure」と書いておくことで回避できます。<br />
後者が簡単ですが、アップロードが完了したら「insecure」を削除することをお忘れなく。</p>
<h2>18. AMI を登録</h2>
<p>さて、いよいよアップロードした AMI を登録するのですが、実は登録用のコマンドは EC2 AMI Tools には含まれていません。<br />
登録用のコマンドは <a href="http://aws.amazon.com/developertools/351">EC2 API Tools</a> というパッケージに含まれているのですが、今回はそれを使わずに <a href="https://console.aws.amazon.com/">AWS Management Console</a> から登録してみます。</p>
<ol>
<li>EC2 のタブを開く</li>
<li>Navigation の Region を「<strong>Asia Pacific(Tokyo)</strong>」に変更</li>
<li>Navigation から「<strong>AMI</strong>」を選択</li>
</ol>
<p><img alt="" src="https://s3-ap-northeast-1.amazonaws.com/kray.jp-ap-northeast-1/assets/images/blog/centos62-s3backed-ami-from-scratch/01.png" title="AWS Management Console の AMI のページ" class="alignnone" width="544" height="311" /></p>
<ol start="4">
<li>Amazon Machine Images の「<strong>Register New AMI</strong>」を選択</li>
<li>AMI Manifest Path に、アップロードした AMI の URL を入力して「<strong>Register</strong>」</li>
</ol>
<p><img alt="" src="https://s3-ap-northeast-1.amazonaws.com/kray.jp-ap-northeast-1/assets/images/blog/centos62-s3backed-ami-from-scratch/02.png" title="AMI のマニフェストファイルを登録" class="alignnone" width="480" height="194" /></p>
<ol start="6">
<li><strong>登録完了！</strong></li>
</ol>
<p><img alt="" src="https://s3-ap-northeast-1.amazonaws.com/kray.jp-ap-northeast-1/assets/images/blog/centos62-s3backed-ami-from-scratch/03.png" title="登録された AMI" class="alignnone" width="612" height="56" /></p>
<h2>まとめ</h2>
<p>あとは起動して動作確認して、問題なければ完成です。<br />
今回の手順をシェルスクリプトにして、コマンド一発で S3 へのアップロードまで済むようにしたものを <a href="https://gist.github.com/1624560/">Gist</a> に上げたので、参考にしてみてください。</p>
<p>今回 S3-Backed の AMI を作ったので、次回はそれを EBS-Backed の AMI にする方法を紹介したいと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/centos62-s3backed-ami-from-scratch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RailsのデプロイとUnicornのトラブルシューティング</title>
		<link>http://kray.jp/blog/troubleshooting-rails-unicorn/</link>
		<comments>http://kray.jp/blog/troubleshooting-rails-unicorn/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 02:50:54 +0000</pubDate>
		<dc:creator>irohiroki</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[unicorn]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=5502</guid>
		<description><![CDATA[Troubleshooting an issue caused with Unicorn and gtk2.]]></description>
			<content:encoded><![CDATA[<h2>デプロイしたけど何かおかしい？</h2>
<p>先日、<a href="http://unicorn.bogomips.org">Unicorn</a>を採用しているウェブアプリで問題が発生しました。デプロイした最新のコードが実行されているように見えますが、時々古いコードの挙動を見せるのです。</p>
<p>今回はそのトラブルシューティングの一部始終を紹介しながら、Unicornのホットデプロイ（ダウンタイムなしでアプリケーションを更新すること）の仕組みをおさらいします。担当は私、去年KRAYに入社しました<a href="http://twitter.com/irohiroki">@irohiroki</a>です。よろしくお願いします。</p>
<h2>問題</h2>
<p>まずはデプロイ先のサーバにSSHして、Unicornのプロセスを調べてみました。</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ps ax -H<br />
&nbsp; PID TTY &nbsp; &nbsp; &nbsp;STAT &nbsp; TIME COMMAND<br />
&nbsp;3159 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; unicorn master (old) -c unicorn.conf -D<br />
&nbsp;3162 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; &nbsp; unicorn worker[0] -c unicorn.conf -D<br />
&nbsp;3164 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; &nbsp; unicorn worker[1] -c unicorn.conf -D<br />
&nbsp;3169 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; &nbsp; unicorn master -c unicorn.conf -D<br />
&nbsp;3173 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; &nbsp; &nbsp; unicorn worker[0] -c unicorn.conf -D<br />
&nbsp;3175 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; &nbsp; &nbsp; unicorn worker[1] -c unicorn.conf -D</div></div>
<p>無関係な部分は省いてありますが、だいたい上のような状態でした。Unicornは複数のworkerプロセスを一つのmasterプロセスが管理する構成です。ところが問題発生時は上の通り、本物のmasterプロセスとは別に、(old)のついたmasterプロセスとそのworkerが存在していました。これはデプロイ前の古いコードを走らせているプロセスです。そのため、HTTPリクエストを新旧２系統のunicornが取り合って、新しいコードが実行されたり古いコードが実行されたりしていました。正常ならば下のようになるはずです。</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ps ax -H<br />
&nbsp; PID TTY &nbsp; &nbsp; &nbsp;STAT &nbsp; TIME COMMAND<br />
&nbsp;3169 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; unicorn master -c unicorn.conf -D<br />
&nbsp;3173 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; &nbsp; unicorn worker[0] -c unicorn.conf -D<br />
&nbsp;3175 ? &nbsp; &nbsp; &nbsp; &nbsp;Sl &nbsp; &nbsp; 0:00 &nbsp; &nbsp; unicorn worker[1] -c unicorn.conf -D</div></div>
<h2>ホットデプロイの流れ</h2>
<p>ここでUnicornの正常なホットデプロイの流れをおさらいしておきます。</p>
<ol>
<li>
    <strong>新しいmasterを生成</strong><br />
    <span>masterプロセスにUSR2シグナルを送ると、masterプロセスは新しいmasterプロセスを生成して、自分と同じコマンドを最初から実行させます。</span>
  </li>
<li>
    <strong>新しいworker誕生</strong><br />
    <span>新しいmasterプロセスの実行に問題がなければ、自動的に設定した数のworkerプロセスが新masterから生まれます。</span>
  </li>
<li>
    <strong>古いworker終了</strong><br />
    <span>新しいworkerが無事誕生したら、古いmasterにQUITシグナルを送ります。QUITシグナルを受け取ったmasterプロセスは、自分のworkerたちに同じくQUITシグナルを送ります。そうするとworkerプロセスたちは、自分が現在処理中のリクエストを処理し終わった時点で終了します。</span>
  </li>
<li>
    <strong>古いmaster停止</strong><br />
    <span>QUITを受け取ったmasterは、workerが終了したのを確認して自分自身も終了します。</span>
  </li>
</ol>
<p>よってホットデプロイを成功させるには、まずmasterにUSR2を送り、新しいmasterおよびworkerが正常に起動できたことを確認して、古いmasterにQUITを送る、となります。</p>
<p>しかしこれらの作業を手でやることはありません。まっとうなWeb developerなら必ず自動化します。ではその自動化ツールと、上記の具体的な実施箇所を見てみましょう。</p>
<h3>capistrano-unicorn</h3>
<p><a href="https://github.com/capistrano/capistrano/wiki">Capistrano</a>は伝統的なデプロイの自動化ツールです。Rubyの表現力を生かして、言わば“実行できる設定ファイル”を書くことができます。<a href="https://github.com/sosedoff/capistrano-unicorn">capistrano-unicorn</a>は、CapistranoでUnicornをサポートするための拡張です。</p>
<p>早速ホットデプロイに関係する部分を見てみましょう。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; desc <span style="color:#996600;">'Reload Unicorn'</span><br />
&nbsp; task <span style="color:#ff3333; font-weight:bold;">:reload</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span>, <span style="color:#ff3333; font-weight:bold;">:except</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:no_release <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> remote_file_exists?<span style="color:#006600; font-weight:bold;">&#40;</span>unicorn_pid<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; logger.<span style="color:#9900CC;">important</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Stopping...&quot;</span>, <span style="color:#996600;">&quot;Unicorn&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; run <span style="color:#996600;">&quot;#{try_sudo} kill -s USR2 `cat #{unicorn_pid}`&quot;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; &nbsp; &nbsp; logger.<span style="color:#9900CC;">important</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;No PIDs found. Starting Unicorn server...&quot;</span>, <span style="color:#996600;">&quot;Unicorn&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># （略）</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>（<a href="https://github.com/sosedoff/capistrano-unicorn/blob/master/lib/capistrano-unicorn/capistrano_integration.rb#L57">https://github.com/sosedoff/capistrano-unicorn/blob/master/lib/capistrano-unicorn/capistrano_integration.rb#L57</a>周辺）</p>
<p>中程でunicornプロセスにUSR2を送っているのがわかります。（よく見るとログのメッセージが間違ってますが、これは後で作者にパッチを送ります。）このtaskはunicornという名前空間にあるので、cap unicorn:reloadでUSR2を送れることになります。</p>
<p>続いてQUITを送る必要がありますが、これはcapistranoのtaskではなく、Unicornの設定ファイルの中に書きます。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">preload_app <span style="color:#0000FF; font-weight:bold;">true</span><br />
<br />
before_fork <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>server, worker<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; old_pid = <span style="color:#996600;">&quot;#{server.config[:pid]}.oldbin&quot;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>old_pid<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> server.<span style="color:#9900CC;">pid</span> != old_pid<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">begin</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">Process</span>.<span style="color:#9900CC;">kill</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;QUIT&quot;</span>, <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>old_pid<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">Errno</span>::ENOENT, <span style="color:#CC00FF; font-weight:bold;">Errno</span>::ESRCH<br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># someone else did our job for us</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>（<a href="https://github.com/sosedoff/capistrano-unicorn/blob/master/examples/rails3.rb#L36">https://github.com/sosedoff/capistrano-unicorn/blob/master/examples/rails3.rb#L36</a>周辺を改変）</p>
<p>before_forkというフックの中で古いmasterのプロセスIDを読み込んでQUITを送っています。before_forkは、masterがworkerを産む直前に実行する処理を登録するメソッドです。こうして古いworkerとmasterは削除されます。</p>
<p>しかし、上で述べたホットデプロイの手順には「新しいmasterおよびworkerが正常に起動できたことの確認」があります。before_forkの時点でその確認はできているのでしょうか？</p>
<p>実はそれを担保するのが、上のスニペットの先頭にあるpreload_app trueです。この設定により、masterがworkerを産む前に新しいコードがロードされ、初期化が実行されます。よってbefore_forkが実行される時には、HTTPリクエストを受け付ける準備ができていると考えられるのです。これでホットデプロイがcapistrano-unicornでどのように実現されているかがわかりました。</p>
<h3>仮説と検証</h3>
<p>以上の調査結果と理論を照らし合わせて、問題が発生する経緯について仮説を立ててみます。</p>
<p>Unicornのプロセスを見ると、新しいmasterとworkerが動作していますので、USR2を受け取って新しいコードをロードし、forkまでしていることがわかります。しかし、before_forkで送られたはずのQUITの効果が見られません。つまりQUITシグナルがどこかで失われたと考えられます。</p>
<p>そこで、新しいコードと使用しているgemを「QUIT」で検索してみたところ、gtk2 gemがQUITを無視していることがわかりました。</p>
<div class="codecolorer-container c twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigfunc<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> signal<span style="color: #009900;">&#40;</span>SIGHUP<span style="color: #339933;">,</span> SIG_IGN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigfunc<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> signal<span style="color: #009900;">&#40;</span>SIGINT<span style="color: #339933;">,</span> SIG_IGN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigfunc<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> signal<span style="color: #009900;">&#40;</span>SIGQUIT<span style="color: #339933;">,</span> SIG_IGN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigfunc<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> signal<span style="color: #009900;">&#40;</span>SIGBUS<span style="color: #339933;">,</span> SIG_IGN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigfunc<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> signal<span style="color: #009900;">&#40;</span>SIGSEGV<span style="color: #339933;">,</span> SIG_IGN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigfunc<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">5</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> signal<span style="color: #009900;">&#40;</span>SIGPIPE<span style="color: #339933;">,</span> SIG_IGN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>（<a href="http://ruby-gnome2.svn.sourceforge.net/viewvc/ruby-gnome2/ruby-gnome2/trunk/gtk2/ext/gtk2/rbgtkmain.c?revision=4697&#038;view=markup">http://ruby-gnome2.svn.sourceforge.net/viewvc/ruby-gnome2/ruby-gnome2/trunk/gtk2/ext/gtk2/rbgtkmain.c?revision=4697&amp;view=markup</a>）</p>
<h3>対策</h3>
<p>この問題を解決するには、gtk2 gemを改造するか、QUITを使わない方法を考えだすしかありません。他人のgemを安易に修正するのはトラブルの元なので、自分のコードで何とかすることにします。</p>
<p>実はUnicornはWINCHというシグナルにもハンドラが設定されており、masterがこれを受け取るとworkerを行儀よく終了させます。つまりQUITの仕事の一部を達成できます。ではWINCHを使うことにして、あとはどうやって古いmasterを停止するかです。</p>
<p>gtk2はINTやHUP、TERMといった一般的な停止シグナルを全て無視するので、KILLを送ることにします。しかし、WINCHを送った後もworkerはやりかけの処理を続けますから、KILLを送るのが早過ぎるとworkerを看取る人がいなくなってしまい、うまくありません。</p>
<p>一般的に、ウェブアプリケーションサーバにはタイムアウトがあります。HTTPリクエストに対する処理時間が長過ぎる場合に、エラーとして処理する作法です。本アプリケーションの場合、タイムアウトは30秒になっていました。つまりWINCHを送ってから30秒後には、どんなworkerも終了またはエラーとして処理されているわけです。よってWINCHを送ってから30秒後にKILLを送ることにします。</p>
<p>以上のことを踏まえてbefore_forkを書いてみます。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">before_fork <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>server, worker<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; old_pid = <span style="color:#996600;">&quot;#{server.config[:pid]}.oldbin&quot;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>old_pid<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> server.<span style="color:#9900CC;">pid</span> != old_pid<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">begin</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">Process</span>.<span style="color:#9900CC;">kill</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;WINCH&quot;</span>, <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>old_pid<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">sleep</span> <span style="color:#006666;">30</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">Process</span>.<span style="color:#9900CC;">kill</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;KILL&quot;</span>, <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>old_pid<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">Errno</span>::ENOENT, <span style="color:#CC00FF; font-weight:bold;">Errno</span>::ESRCH<br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># someone else did our job for us</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>WINCHを送り、30秒後にKILLを送るようにしました。しかしこれは不正解です。これではせっかくmasterが起動してもforkまでに30秒空費することになります。その点を考慮したのが下の設定です。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">before_fork <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>server, worker<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; old_pid = <span style="color:#996600;">&quot;#{server.config[:pid]}.oldbin&quot;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>old_pid<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> server.<span style="color:#9900CC;">pid</span> != old_pid<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">begin</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">Process</span>.<span style="color:#9900CC;">kill</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;WINCH&quot;</span>, <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>old_pid<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">sleep</span> <span style="color:#006666;">30</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">Process</span>.<span style="color:#9900CC;">kill</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;KILL&quot;</span>, <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>old_pid<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">Errno</span>::ENOENT, <span style="color:#CC00FF; font-weight:bold;">Errno</span>::ESRCH<br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># someone else did our job for us</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>30秒待つのは別のスレッドにしました。これでQUITを使わずにホットデプロイを達成できました。</p>
<p>gtk2はマルチプラットフォームのGUIウィジェットや音声・動画処理フレームワークなどを提供する優れたライブラリです。今回のプロジェクトではPDF文書をパース／生成するのに利用しました。このような強力なライブラリとUnicornを併用できないのは勿体ないことだと思います。gtk2との併用に限らず、本エントリがUnicornの理解に役立てば幸いです。</p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/troubleshooting-rails-unicorn/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>学んだことまとめ 2011/11/14〜11/25</title>
		<link>http://kray.jp/blog/daily-2011-1114-1125/</link>
		<comments>http://kray.jp/blog/daily-2011-1114-1125/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 07:06:01 +0000</pubDate>
		<dc:creator>amachin</dc:creator>
				<category><![CDATA[ブログ]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=5436</guid>
		<description><![CDATA[まえがき 一週間ずつだと遅れていくので、今日は二週間分です。 そろそろ、ちゃんとしたブログ書かないとなー。 Webアプリ開発 Bundler 1.1 http://patshaughnessy.net/2011/11/5 [...]]]></description>
			<content:encoded><![CDATA[<h2>まえがき</h2>
<p>一週間ずつだと遅れていくので、今日は二週間分です。<br />
そろそろ、ちゃんとしたブログ書かないとなー。</p>
<h2>Webアプリ開発</h2>
<h4>Bundler 1.1</h4>
<p><a href="http://patshaughnessy.net/2011/11/5/besides-being-faster-what-else-is-new-in-bundler-1-1">http://patshaughnessy.net/2011/11/5/besides-being-faster-what-else-is-new-in-bundler-1-1</a></p>
<blockquote><p>
（ Besides being faster, what else is new in Bundler 1.1? – Pat Shaughnessy より）<br />
<strong>・速い</strong><br />
<strong>・bundle outdated</strong><br />
　新しいバージョンがあるgemをリストアップする<br />
<strong>・bundle clean</strong><br />
　pathを使ってる場合、bundle installまたはupdateした時に自動的に使ってないgemを消してくれる。&#8211;pathではなくsystem gem repositoryを使ってる場合、bundle clean &#8211;forceで同じことができる（他のディレクトリのGemfileに書かれてるgemは無視することになるので注意）。<br />
<strong>・bundle install &#8211;standalone</strong><br />
　pathを使った場合、/bundler/setup.rbを作ってくれる。このスクリプトはbundlerがない環境でも &#8211;path のgemを$LOAD_PATHに加えてくれる、言うなれば“standaloneのbundler”である。
</p></blockquote>
<h4>joemiller/aws-cf-private-streaming-tools &#8211; GitHub</h4>
<p><a href="https://github.com/joemiller/aws-cf-private-streaming-tools">https://github.com/joemiller/aws-cf-private-streaming-tools</a><br />
CloudFront でコンテンツをプライベートに設定するためのコマンドラインツール。<br />
Origin Access Id の設定はできたけど、AWSSDKforPHP で発行した URL にアクセスしても何も返ってこない。</p>
<h4>スマートフォンアプリなんかに使うバックエンドシステム用クラウドサービス？</h4>
<p><a href="https://cloudmine.me/">https://cloudmine.me/</a><br />
スキーマレスDB、ユーザ管理などをRESTfulなAPI経由でサービスしている？</p>
<h4>Nodeで使えるECMA Script 5の新機能</h4>
<p><a href="http://d.hatena.ne.jp/Jxck/20110709/1310215628">http://d.hatena.ne.jp/Jxck/20110709/1310215628</a></p>
<h4>Deploying node.js on Amazon EC2</h4>
<p><a href="http://blog.carbonfive.com/2011/09/01/deploying-node-js-on-amazon-ec2/">http://blog.carbonfive.com/2011/09/01/deploying-node-js-on-amazon-ec2/</a></p>
<h4>node.jsのモジュールリスト</h4>
<p><a href="https://github.com/joyent/node/wiki/modules">https://github.com/joyent/node/wiki/modules</a></p>
<h4>BDD for node.js</h4>
<p><a href="http://node-bdd.heroku.com/#1">http://node-bdd.heroku.com/#1</a></p>
<h4>npm 1.0: Global vs Local installation « node blog</h4>
<p><a href="http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/">http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/</a><br />
基本的にnodeではmodulesをグローバルなディレクトリではなくプロジェクトの./node_modulesに入れる</p>
<h4>MongoDBはcompactする必要がある</h4>
<p><a href="http://oblog.objectclub.jp/mongodb-10">http://oblog.objectclub.jp/mongodb-10</a></p>
<h2>その他</h2>
<h4>プログラマを一生の仕事にできるビジネスモデルで目指す未来のビジョン</h4>
<p><a href="http://www.publickey1.jp/blog/11/si.html">http://www.publickey1.jp/blog/11/si.html</a><br />
<a href="http://www.publickey1.jp/blog/11/post_191.html">http://www.publickey1.jp/blog/11/post_191.html</a><br />
いろいろ参考になります。</p>
<h4>Google Maps APIの有料化、「上位0.35％のサイトのみが影響」と説明 -INTERNET Watch</h4>
<p><a href="http://internet.watch.impress.co.jp/docs/news/20111124_493211.html">http://internet.watch.impress.co.jp/docs/news/20111124_493211.html</a><br />
よっぽど継続的にアクセスを集めなければ大丈夫なんだろうか。</p>
<h4>ゲーム開発プロジェクトマネジメント講座</h4>
<p><a href="http://www.square-enix.com/jp/info/library/dldata/PM/PM.pdf">http://www.square-enix.com/jp/info/library/dldata/PM/PM.pdf</a></p>
<h4>旅行関連のディスカバリープラットフォームを運営するGogobot、モバイル分野にも進出を開始</h4>
<p><a href="http://jp.techcrunch.com/archives/20111018gogobot-takes-social-travel-discovery-platform-mobile-with-ios-app/">http://jp.techcrunch.com/archives/20111018gogobot-takes-social-travel-discovery-platform-mobile-with-ios-app/</a></p>
<h4>NoSQL は REST に影響を与えるか？</h4>
<p><a href="http://www.infoq.com/jp/news/2011/10/nosql-rest">http://www.infoq.com/jp/news/2011/10/nosql-rest</a></p>
<p><br style="clear: both;" /></p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/daily-2011-1114-1125/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>開発合宿、やってます。</title>
		<link>http://kray.jp/blog/camp/</link>
		<comments>http://kray.jp/blog/camp/#comments</comments>
		<pubDate>Thu, 15 Dec 2011 01:20:07 +0000</pubDate>
		<dc:creator>ishizima</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[kray]]></category>
		<category><![CDATA[開発合宿]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=5309</guid>
		<description><![CDATA[今回は社内のことを紹介してみたいと思います。
クレイでは開発合宿という形で、自分たちが提供するサービスの開発に集中する時間を設けています。]]></description>
			<content:encoded><![CDATA[<h2>はじめに</h2>
<p>今日は普段の技術系記事と違って、社内のことを紹介してみたいと思います。<br />
クレイでは3週間に1度、開発合宿を行なっています。普段の業務は受注案件の開発がメインですが、合宿という形で自分たちが提供するサービスの開発に集中する時間を設けるのが目的です。</p>
<h2>なぜ開発合宿？</h2>
<p>先ほども書いた通り、クレイの主な業務は受注案件、つまりお客様から依頼されたシステムを開発するのが中心です。一方で、自分たちで企画して自分たちで実装したWebサービスを提供していきたい、という思いも持っています。</p>
<p>とは言うものの、普段の業務時間から自社のための開発時間を作りだすというのは案外難しいものです。それはスケジュールを守るためであったり、電話やメールによる何かしらの対応のためであったり。</p>
<p>なので、強制的に普段の業務をリセットして自分たちの時間を確保するため、普段のオフィスを離れて、どうせなら泊まりで集中作業しよう……、となったわけです。<br />
普段はスタッフそれぞれ担当のプロジェクトを手がけていますが、開発合宿の時だけは同時に全員が同じプロジェクトに取り組みます。<strong>皆で同じ方向を向いて進む</strong>というのも重要なのかもしれません。</p>
<h2>合宿風景</h2>
<p>クレイでは、日付を決めて当日朝から翌昼までを開発合宿期間としています。<br />
この期間だけは極力他の業務を止めて、事前に全員で合意した目標を達成するための作業を行います。<br />
なので、事前の目標を決めたりだとかタスクの洗い出しだとか、ある程度の準備は必要です。合宿中にやると時間食われちゃいますからね。</p>
<h3>開発中</h3>
<p><img src="http://kray.jp/wp-content/uploads/2011/12/DSC_0142.jpg" alt="開発風景" title="開発風景" width="300" class="size-medium wp-image-5317" /><br />
合宿の大半は黙々とコーディングしてます。皆が向き合って作業していると、図らずもコミュニケーションが取りやすいメリットが。ただ、それぞれが自分の作業に熱中してしまうのか、それほどコミュニケーションが発生しないのが現在の課題です。<br />
もちろん、開発速度向上というメリットはじゅうぶん享受できているのではないでしょうか。</p>
<p>それから仮眠。開発合宿はホテルの会議室を借りています。仮眠に使う部屋が別の階にあることもあって、みんなあまり利用しようとしません。時間がもったいないという意識もあるのでしょう。効率を考えると寝た方がいいのですが。<br />
一部スタッフからは椅子で寝たほうがいいという意見もあります。</p>
<h3>食事中</h3>
<p><a href="/wp-content/uploads/2011/12/DSC_0139.jpg" target="_blank"><img src="http://kray.jp/wp-content/uploads/2011/12/DSC_0139.jpg" alt="食事風景" title="食事風景" width="300"  class="alignnone size-medium wp-image-5321" /></a><br />
食事風景。よく見ると、ダニーのお茶碗は山盛りですね。コードの品質と炭水化物の量は比例するのかもしれません。</p>
<h3>ふりかえり</h3>
<p><img src="http://kray.jp/wp-content/uploads/2011/12/KPT.jpg" alt="KPT" title="KPT" width="300"  class="alignnone size-full wp-image-5338" /><br />
そして、合宿の最後はふりかえりです。30分程度、この1日半の合宿内容を振り返る時間を設けています。<br />
やり方を具体的に書くと、<strong>Keep</strong>(良かったこと、続けたいこと)、<strong>Problem</strong>(問題だったこと)、<strong>Try</strong>(次回挑戦したいこと)の3項目について意見をポストイットのようなカードに書き出します。<br />
以下、実際に初回の開発合宿でふりかえったときの内容を書いてみます。</p>
<ul>
<li><strong>Keep</strong></li>
<ul>
<li><strong>足りない点をすぐ話して解決できる</strong></li>
<li><strong>集中して作業できた</strong></li>
<li><strong>協力できている</strong></li>
<li><strong>全員が一つのことをする</strong></li>
</ul>
<li><strong>Problem</strong></li>
<ul>
<li><strong>本がない</strong></li>
<li><strong>途中で失速した</strong></li>
<li><strong>二日目の眠気</strong></li>
<li><strong>自分の役割が明確になっていなかった</strong></li>
</ul>
<li><strong>Try</strong></li>
<ul>
<li><strong>目標を設定する</strong></li>
<li><strong>仮眠スペースを用意する</strong></li>
<li><strong>外付けキーボードを用意する</strong></li>
<li><strong>休憩を入れてメリハリをつける</strong></li>
</ul>
</ul>
<p>Keepはこんなことが良かった！ということを皆で共有することで、モチベーションアップやノウハウの共有につながります。そして、Problemに対して何をTryしていくか、次回以降実際にTryすることでProblemを解決するサイクルができあがれば、開発合宿（だけじゃないですけど）がより良いものになっていくでしょう。</p>
<h2>開発合宿で開発してるモノについて</h2>
<p>冒頭で自分たちのサービスを提供したいって書いたのですが、ではどんなサービスなのでしょうか。軽く紹介させてください。</p>
<h4>旅の思い出作りに</h4>
<p>みなさんは旅行で撮った写真をオンラインでアルバム化したいと思ったことはありませんか？<br />
FlickrやPicasa、500pxなど写真共有サービスって色々あると思うんですけど、旅に特化したものを探すと案外ありません。なので、今回旅の記録を写真で残せる、そして人に見せられるサービスを開発しようと思い立ちました。詳しいことはまた別の機会に！</p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/camp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>学んだことまとめ 2011/10/07〜11/11</title>
		<link>http://kray.jp/blog/daily-2011-1007-1111/</link>
		<comments>http://kray.jp/blog/daily-2011-1007-1111/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 06:27:03 +0000</pubDate>
		<dc:creator>ishizima</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[情報共有]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=5291</guid>
		<description><![CDATA[まえがき 皆さんこんにちは。 いきなりですが、この前クルマに轢かれました。皆さんも横断歩道を渡るときは青信号でも左右に注意しましょう……。とりあえずMacが無事でよかったです。 まとめ JavaScript, HTML, [...]]]></description>
			<content:encoded><![CDATA[<h2>まえがき</h2>
<p>皆さんこんにちは。<br />
いきなりですが、この前クルマに轢かれました。皆さんも横断歩道を渡るときは青信号でも左右に注意しましょう……。とりあえずMacが無事でよかったです。</p>
<h2>まとめ</h2>
<h3>JavaScript, HTML, CSS 関連</h3>
<h4>canvas上の描いたテキストの横のサイズを取得する方法。</h4>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ctx <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span>‘canvas’<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span>‘2d’<span style="color: #009900;">&#41;</span><br />
ctx.<span style="color: #660066;">font</span> <span style="color: #339933;">=</span> ‘20px Arial’<br />
m <span style="color: #339933;">=</span> ctx.<span style="color: #660066;">measureText</span><span style="color: #009900;">&#40;</span>‘amamdmdmdm’<span style="color: #009900;">&#41;</span><br />
m.<span style="color: #660066;">width</span></div></div>
<h4>HTML5 API チェッカー</h4>
<p><a href="http://html5.jp/tutorial/apicheck/" target="_blank">http://html5.jp/tutorial/apicheck/</a></p>
<h3>Ruby, Rails 関連</h3>
<h4>Gem を作って公開してみた</h4>
<p><a href="https://rubygems.org/gems/endeco" target="_blank">https://rubygems.org/gems/endeco</a><br /><a href="https://rubygems.org/gems/endeco" target="_blank">https://github.com/morimori/endeco</a><br />
環境依存の設定ファイルを管理する。</p>
<h3>Git 関連</h3>
<h4>コミットをしくじった時の対処法</h4>
<blockquote><p>
<a href="http://d.hatena.ne.jp/keisukefukuda/20111105/p1" target="_blank">http://d.hatena.ne.jp/keisukefukuda/20111105/p1</a><br />
gitのコミットをしくじった時の対処法について、一覧性の高いまとめがなかったので作りました。
</p></blockquote>
<p>複数人で使ってるよ → もうpushしちゃったよ → さらに誰かが（依存する）変更をpushしてるよ → 涙ふけよ</p>
<h3>その他</h3>
<h4>InfoQ: AmazonとEucalyptusのセキュリティ脆弱性</h4>
<p><a href="http://www.infoq.com/jp/news/2011/11/amazon-eucalyptus-security-holes" target="_blank">http://www.infoq.com/jp/news/2011/11/amazon-eucalyptus-security-holes</a><br />
シグネチャラッピング攻撃の件。この脆弱性の発表前に対策はされたようなので、とりあえずは安心。</p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/daily-2011-1007-1111/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>rails3 + html5 canvasでお絵かき投稿サイトを作ろう！</title>
		<link>http://kray.jp/blog/rails3-html5-canvas/</link>
		<comments>http://kray.jp/blog/rails3-html5-canvas/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 05:35:44 +0000</pubDate>
		<dc:creator>takuru</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[rails3]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=5112</guid>
		<description><![CDATA[はじめましてこんにちは。 KRAYアルバイトの浅海です。 html5のcanvasを使ってお絵かき投稿サイトを作ってみようと思います。 初めてブログ記事を書くということで気合が入りました。 ちょっと長めですがお付き合い下 [...]]]></description>
			<content:encoded><![CDATA[<p>はじめましてこんにちは。<br />
KRAYアルバイトの浅海です。</p>
<p>html5のcanvasを使ってお絵かき投稿サイトを作ってみようと思います。<br />
初めてブログ記事を書くということで気合が入りました。<br />
ちょっと長めですがお付き合い下さい。</p>
<h2>機能</h2>
<p>お絵かき投稿サイトの必要最低限な機能って？<br />
ざっと下のような機能を入れてみます。</p>
<ul>
<li><a href="#draw">絵を描ける</a></li>
<li><a href="#clear">絵を消せる</a></li>
<li><a href="#undo">描画を一回分戻れる</a></li>
<li><a href="#width">線の太さを変えられる</a></li>
<li><a href="#color">線の色を変える</a></li>
<li><a href="#post">絵を投稿できる</a></li>
<li><a href="#list">投稿された画像の一覧を表示できる</a></li>
</ul>
<p>→ <a href="http://canvas.d-adv.net/">完成見本はこちら</a></p>
<h2><a name="draw">絵を描ける</a></h2>
<p>HTML5のcanvasにマウスの軌道に線を引いていくわけです。<br />
canvasでのマウス軌道の描き方は、<br />
<b>・mousemoveイベント発生時に点をプロット</b><br />
という手段が真っ先に思い浮かぶと思いますが、これは、以下の様になります。<br />
<a href="http://kray.jp/blog/rails3-html5-canvas/attachment/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88%ef%bc%882011-11-11-1-00-42%ef%bc%89/" rel="attachment wp-att-5121"><img src="http://kray.jp/wp-content/uploads/2011/11/24505c8e58ef2a67c4e5b7fe6cc8e231.png" alt="" title="20111111_点々" width="280" height="138" class="alignnone size-full wp-image-5121" /></a></p>
<p>これではお話になりません。<br />
なので、点ではなく線を引くことにします。<br />
これは下のようになります。<br />
<a href="http://kray.jp/blog/rails3-html5-canvas/attachment/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88%ef%bc%882011-11-11-1-03-49%ef%bc%89/" rel="attachment wp-att-5126"><img src="http://kray.jp/wp-content/uploads/2011/11/c1fbf9acbd3a91a03c7b848d99e80395.png" alt="" title="20111111_線" width="269" height="210" class="alignnone size-full wp-image-5126" /></a><br />
この方法でもまだ、曲線の時に粗が目立ちます。</p>
<p>そこで、線と線の間に点をプロットする、今までの２つの方法を合わせて使います。<br />
すると下のように、綺麗な線が描けます。<br />
<a href="http://kray.jp/blog/rails3-html5-canvas/attachment/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88%ef%bc%882011-11-11-1-10-45%ef%bc%89/" rel="attachment wp-att-5131"><img src="http://kray.jp/wp-content/uploads/2011/11/da476e70c60e964191e204bc4cc2ed9a.png" alt="" title="20111111_線点" width="250" height="112" class="alignnone size-full wp-image-5131" /></a></p>
<p>※canvasのプロパティに、lineJoinというものがありまして、これに&#8217;round&#8217;を入れておくとパスとパスの間を滑らかに連結してくれるようです。<br />
しかし、<s>考えるのが面倒だったため</s>全ての線は個別に描画しました。</p>
<p>※11/21<br />
<a href="http://www.html5.jp/canvas/ref/property/lineCap.html">.lineCap</a>でいけそうです・・</p>
<h3>controller</h3>
<p>railsアプリを作成してからpictures controllerを作ります。</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ rails new canvas<br />
$ cd canvas<br />
$ rails generate controller</div></div>
<h3>ルーティング</h3>
<p>ルーティングを設定します。<br />
pictures controllerのnew actionで絵を書くことにします。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># config/routes.rb</span><br />
&nbsp; root <span style="color:#ff3333; font-weight:bold;">:to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'pictures#new'</span></div></div>
<h3>erb</h3>
<p>何の変哲もないcanvasタグを書きます。<br />
CSSだけでwidthとheightの設定をすると調子が悪いので、<br />
必ずcanvasタグ内でサイズ指定して下さい。</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># app/views/pictures/new.html.erb<br />
<span style="color: #009900;">&lt;canvas <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;draw-area&quot;</span> <span style="color: #000066;">width</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;300&quot;</span> <span style="color: #000066;">height</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;300&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span>canvas&gt;</span></div></div>
<h3>coffee script</h3>
<p>canvasのcontextを取得して、点を描画する機能と線を描画する機能を追加します。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; canvas <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#draw-area'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; ctx <span style="color: #339933;">=</span> canvas<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'2d'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; ctx.<span style="color: #660066;">lineWidth</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><br />
<br />
&nbsp; ctx.<span style="color: #660066;">putPoint</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>x<span style="color: #339933;">,</span> y<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span> # x<span style="color: #339933;">,</span>yに点を描画<br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">beginPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">arc</span><span style="color: #009900;">&#40;</span>x<span style="color: #339933;">,</span> y<span style="color: #339933;">,</span> <span style="color: #339933;">@</span>.<span style="color: #660066;">lineWidth</span> <span style="color: #339933;">/</span> <span style="color: #CC0000;">2.0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> Math.<span style="color: #660066;">PI</span><span style="color: #339933;">*</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">fill</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">closePath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; ctx.<span style="color: #660066;">drawLine</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>sx<span style="color: #339933;">,</span> sy<span style="color: #339933;">,</span> ex<span style="color: #339933;">,</span> ey<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span> # 始点<span style="color: #009900;">&#40;</span>sx<span style="color: #339933;">,</span> sy<span style="color: #009900;">&#41;</span> から 終点<span style="color: #009900;">&#40;</span>ex<span style="color: #339933;">,</span> ey<span style="color: #009900;">&#41;</span>に線を描画<br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">beginPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">moveTo</span><span style="color: #009900;">&#40;</span>sx<span style="color: #339933;">,</span> sy<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">lineTo</span><span style="color: #009900;">&#40;</span>ex<span style="color: #339933;">,</span> ey<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">stroke</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">closePath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></div></div>
<p>そして、canvasをクリックしたときに点を描画します。<br />
mousedownというフラグ変数を用意して、マウスを押している状態か判定しています。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; mousedown <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; canvas.<span style="color: #660066;">mousedown</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">prevPos</span> <span style="color: #339933;">=</span> getPointPosition<span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; mousedown <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">putPoint</span><span style="color: #009900;">&#40;</span>ctx.<span style="color: #660066;">prevPos</span>.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> ctx.<span style="color: #660066;">prevPos</span>.<span style="color: #660066;">y</span><span style="color: #009900;">&#41;</span></div></div>
<p>マウスが動いている間は点と点を線で繋ぎます。<br />
始点は一つ前のイベント発生時の座標、<br />
終点は現在のイベント発生時の座標です。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; canvas.<span style="color: #660066;">mousemove</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> unless mousedown<br />
&nbsp; &nbsp; nowPos <span style="color: #339933;">=</span> getPointPosition<span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">drawLine</span><span style="color: #009900;">&#40;</span>ctx.<span style="color: #660066;">prevPos</span>.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> ctx.<span style="color: #660066;">prevPos</span>.<span style="color: #660066;">y</span><span style="color: #339933;">,</span> nowPos.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> nowPos.<span style="color: #660066;">y</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">putPoint</span><span style="color: #009900;">&#40;</span>nowPos.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> nowPos.<span style="color: #660066;">y</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">prevPos</span> <span style="color: #339933;">=</span> nowPos</div></div>
<p>マウスの押下をやめた時と、canvasからポインタが出た時に描画を終了します。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; canvas.<span style="color: #660066;">mouseup</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; mousedown <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; canvas.<span style="color: #660066;">mouseout</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; mousedown <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span></div></div>
<h2><a name="clear">絵を消せる</a></h2>
<p>キャンバス上の絵を全消去できるようにします。</p>
<h3>erb</h3>
<p>消去のボタンを作成します。<br />
CSSのデザイン設定等は省略します。</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- &nbsp;app/views/pictures/new.html.erb --&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;clear-button&quot;</span>&gt;</span>消去<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;</span></div></div>
<h3>coffee script</h3>
<p>#clear-buttonが押された時、context.clearRectでcanvas全体を指定して消去します。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#clear-button&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">clearRect</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">width</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">height</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span></div></div>
<h2><a name="undo">描画を一回分戻れる</a></h2>
<p>人間は失敗するものです。<br />
描画を一回分戻れるようにしてあげます。</p>
<h3>erb</h3>
<p>戻すボタンを作成します。</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- app/views/pictures/new.html.erb --&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;return-button&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;controll-button&quot;</span>&gt;</span>戻す<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;</span></div></div>
<h3>coffee script</h3>
<p>contextに現在の状態を保存する機能を追加します。<br />
getImageDataを使えば指定領域の描画情報を取得することができます。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; ctx.<span style="color: #660066;">savePrevData</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">prevImageData</span> <span style="color: #339933;">=</span> <span style="color: #339933;">@</span>.<span style="color: #660066;">getImageData</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">width</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">height</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span></div></div>
<p>canvas.mousedownに描画前の状態を保存する以下の一行追加します。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; canvas.<span style="color: #660066;">mousedown</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">savePrevData</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> # この一行を追加<br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">prevPos</span> <span style="color: #339933;">=</span> getPointPosition<span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; mousedown <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">putPoint</span><span style="color: #009900;">&#40;</span>ctx.<span style="color: #660066;">prevPos</span>.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> ctx.<span style="color: #660066;">prevPos</span>.<span style="color: #660066;">y</span><span style="color: #009900;">&#41;</span></div></div>
<p>ボタンを押したとき、contextのputImageDataを使って、保存してあったprevImageDataをcanvasに上書きします。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#return-button&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">putImageData</span><span style="color: #009900;">&#40;</span>ctx.<span style="color: #660066;">prevImageData</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span></div></div>
<p>これで描画をやり直せます。<br />
思う存分間違って大丈夫です。</p>
<h2><a name="width">線の太さを変えられる</a></h2>
<p>線の太さは現在1pxの固定になっています。<br />
これではつまらない！<br />
これをHTML5のスライダーを使って変更できるようにします。</p>
<p><a href="http://kray.jp/blog/rails3-html5-canvas/attachment/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88%ef%bc%882011-11-13-0-23-05%ef%bc%89/" rel="attachment wp-att-5216"><img src="http://kray.jp/wp-content/uploads/2011/11/a0f150a9139af21bbc8392ec542745f6.png" alt="" title="線の太さ設定スライダー" width="189" height="42" class="alignnone size-full wp-image-5216" /></a></p>
<h3>erb</h3>
<p>HTML5のスライダーは、Railsのrange_field_tagヘルパーがあるので使います。<br />
初期値1、最小値1、最大値20で作成しました。<br />
その下には、現在の太さを表示するための領域を用意しました。</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- app/views/pictures/show.html.erb --&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> range_field_tag <span style="color: #ff0000;">'pen-width-slider'</span>, <span style="color: #cc66cc;">1</span>, :min <span style="color: #66cc66;">=</span>&gt;</span> 1, :max =&gt; 20 %&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;show-pen-width&quot;</span>&gt;</span>1<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;</span>px</div></div>
<h3>coffee script</h3>
<p>スライダーの操作はchangeイベントで捕捉できます。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#pen-width-slider&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">change</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">lineWidth</span> <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#show-pen-width&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>ctx.<span style="color: #660066;">lineWidth</span><span style="color: #009900;">&#41;</span></div></div>
<p>これで線の太さを変えられるようになりました。</p>
<h2><a name="color">色を変えられる</a></h2>
<p>「黒一色じゃつまらないです。いろんな色で書きたいです。」<br />
「やりましょう。」</p>
<p><a href="http://kray.jp/blog/rails3-html5-canvas/attachment/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88%ef%bc%882011-11-13-0-23-19%ef%bc%89/" rel="attachment wp-att-5217"><img src="http://kray.jp/wp-content/uploads/2011/11/64d5a0c57cff21d3d114d38399370ff2.png" alt="" title="線の色設定スライダー" width="185" height="142" class="alignnone size-full wp-image-5217" /></a></p>
<h3>erb</h3>
<p>R,G,Bそれぞれのスライダーで実装します。<br />
#preview-colorという、色をプレビューするボックスも用意しまいした。</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- app/views/pictures/show.html.erb&quot; --&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> range_field_tag <span style="color: #ff0000;">'pen-color-red-slider'</span>, <span style="color: #cc66cc;">0</span>, :min <span style="color: #66cc66;">=</span>&gt;</span> 0, :max =&gt; 255 %&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;red&quot;</span>&gt;</span>R<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;</span> <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;show-pen-red&quot;</span>&gt;</span>0<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;&lt;<a href="http://december.com/html/4/element/br.html"><span style="color: #000000; font-weight: bold;">br</span></a> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> range_field_tag <span style="color: #ff0000;">'pen-color-green-slider'</span>, <span style="color: #cc66cc;">0</span>, :min <span style="color: #66cc66;">=</span>&gt;</span> 0, :max =&gt; 255 %&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;green&quot;</span>&gt;</span>G<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;</span> <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;show-pen-green&quot;</span>&gt;</span>0<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;&lt;<a href="http://december.com/html/4/element/br.html"><span style="color: #000000; font-weight: bold;">br</span></a> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> range_field_tag <span style="color: #ff0000;">'pen-color-blue-slider'</span>, <span style="color: #cc66cc;">0</span>, :min <span style="color: #66cc66;">=</span>&gt;</span> 0, :max =&gt; 255 %&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;blue&quot;</span>&gt;</span>B<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;</span> <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;show-pen-blue&quot;</span>&gt;</span>0<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;&lt;<a href="http://december.com/html/4/element/br.html"><span style="color: #000000; font-weight: bold;">br</span></a> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;preview-color&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span></div></div>
<h3>scss</h3>
<p>現在の色をプレビューするボックスのスタイルです。<br />
ただの四角です。</p>
<div class="codecolorer-container css twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="css codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/* app/assets/stylesheets/pictures.css.scss */</span><br />
<span style="color: #cc00cc;">#preview-</span><span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">30px</span><span style="color: #00AA00;">;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">30px</span><span style="color: #00AA00;">;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">rgb</span><span style="color: #00AA00;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">solid</span> <span style="color: #933;">1px</span> <span style="color: #000000; font-weight: bold;">black</span><span style="color: #00AA00;">;</span><br />
<span style="color: #00AA00;">&#125;</span></div></div>
<h3>coffee script</h3>
<p>contextに色変更の機能を加えます。<br />
strokeStyleとfillStyleにスライダーの色を設定するだけです。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; ctx.<span style="color: #660066;">setColor</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; color <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;rgb(#{red_slider.val()},#{green_slider.val()},#{blue_slider.val()})&quot;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">strokeStyle</span> <span style="color: #339933;">=</span> color<br />
&nbsp; &nbsp; <span style="color: #339933;">@</span>.<span style="color: #660066;">fillStyle</span> <span style="color: #339933;">=</span> color<br />
&nbsp; &nbsp; preview_color.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'background-color'</span><span style="color: #339933;">,</span> color<span style="color: #009900;">&#41;</span></div></div>
<p>スライダーの操作を取得します。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; red_slider <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#pen-color-red-slider&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; green_slider <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#pen-color-green-slider&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; blue_slider <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#pen-color-blue-slider&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; preview_color <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#preview-color&quot;</span><span style="color: #009900;">&#41;</span><br />
<br />
&nbsp; red_slider.<span style="color: #660066;">change</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">setColor</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#show-pen-red&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; green_slider.<span style="color: #660066;">change</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">setColor</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#show-pen-green&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; blue_slider.<span style="color: #660066;">change</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; ctx.<span style="color: #660066;">setColor</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#show-pen-blue&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span></div></div>
<p>これで色を変えられるようになりました。</p>
<h2><a name="post">絵を投稿できる</a></h2>
<p>さて、ついに絵をサーバ側に保存します。<br />
仕様は適当に、<br />
・public/imagesディレクトリに保存<br />
・１００件まで。超えたら古いものから削除していく。<br />
です。</p>
<h3>erb</h3>
<p>保存するボタンを作ります。</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- app/views/pictures/show.html.erb --&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;save-button&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;controll-button&quot;</span>&gt;</span>保存<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">span</span></a>&gt;</span></div></div>
<h3>coffee script</h3>
<p>canvasでtoDataURLすると、base64エンコードされた画像文字列が取得できます。<br />
これをpictures controllerのcreate actionにポストします。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#save-button&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; url <span style="color: #339933;">=</span> canvas<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">toDataURL</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; $.<span style="color: #660066;">post</span> <span style="color: #3366CC;">'/pictures'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>data<span style="color: #339933;">:</span> url<span style="color: #009900;">&#125;</span></div></div>
<h3>ruby</h3>
<p>画像データ受信元のルーティングを追加します。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># config/routes.rb</span><br />
&nbsp; resources <span style="color:#ff3333; font-weight:bold;">:pictures</span>, only: <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:create</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#008000; font-style:italic;"># この一行を追加</span></div></div>
<p>ピクチャーモデルを作成します。<br />
実際はmysqlの設定などしていますが、省略です。<br />
今回、カラムはidしか使わないためマイグレーションはいじらずにさっさとdb:migrateしました。</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ rails generate model picture<br />
$ rake db:migrate</div></div>
<p>コントローラの動作です。<br />
ブラウザから送られてきた画像データから、<br />
最初の文字列を削除してbase64デコードすると画像として保存できます。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># app/controllers/pictures_controller.rb</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> create<br />
&nbsp; &nbsp; path = <span style="color:#996600;">'public/images/'</span><br />
&nbsp; &nbsp; picture = Picture.<span style="color:#9900CC;">create</span><br />
&nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{Rails.root}/#{path}/#{picture.id}.png&quot;</span>, <span style="color:#996600;">&quot;wb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; f.<span style="color:#9900CC;">write</span> <span style="color:#CC00FF; font-weight:bold;">Base64</span>.<span style="color:#9900CC;">decode64</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:data</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">sub!</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'data:image/png;base64,'</span>, <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> Picture.<span style="color:#9900CC;">count</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">100</span><br />
&nbsp; &nbsp; &nbsp; picture = Picture.<span style="color:#9900CC;">order</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">first</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">begin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">unlink</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{Rails.root}/#{path}/#{picture.id}.png&quot;</span>, <span style="color:#996600;">&quot;wb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">rescue</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># 適当な処理</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; picture.<span style="color:#9900CC;">destroy</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; render <span style="color:#ff3333; font-weight:bold;">:nothing</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>これで画像を投稿できるようになりました。</p>
<h2><a name="list">投稿された画像の一覧を表示できる</a></h2>
<p>画像は投稿できるようになったけれども、<br />
投稿された画像を見ることができないので見れるようにします。</p>
<h3>erb</h3>
<p>ただの表示用div要素です。</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- app/views/pictures/show.html --&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pictures&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span></div></div>
<h3>ruby</h3>
<p>pictures controllerにcreate actionのルーティングを追加します。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># coufig/routes.rb</span><br />
&nbsp; resources <span style="color:#ff3333; font-weight:bold;">:pictures</span>, only: <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:index</span>, <span style="color:#ff3333; font-weight:bold;">:create</span><span style="color:#006600; font-weight:bold;">&#93;</span></div></div>
<p>rails側でrenderして、HTMLをクライアントに返しても良いですが、<br />
今回はディレクトリの構造が安易なのでRailsはidだけ渡して、残りはブラウザで処理してもらいます。</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># app/controllers/pictures_controller.rb</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> index<br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@response</span> = <span style="color:#996600;">''</span>.<span style="color:#9900CC;">tap</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>me<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; Picture.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">reverse</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>picture<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; me <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;#{picture.id},&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- app/views/pictures/index.html.erb&quot;&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;%= @response %&gt;</span></div></div>
<h3>coffee script</h3>
<p>小さい画像を表示します。<br />
実際にリサイズなどしていないので注意です。<br />
画像をクリックすると、キャンバスにその画像が上書きされるようにしました。<br />
これで人の描いた絵に落書きできますね。</p>
<h3>coffee script</h3>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; reloadPictures <span style="color: #339933;">=</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; $.<span style="color: #660066;">get</span> <span style="color: #3366CC;">'/pictures'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>result<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; ids <span style="color: #339933;">=</span> result.<span style="color: #660066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">','</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; pictures <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#pictures&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; pictures.<span style="color: #660066;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; ids.<span style="color: #660066;">forEach</span> <span style="color: #009900;">&#40;</span>id<span style="color: #339933;">,</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> parseInt<span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pictures.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&lt;img src=<span style="color: #000099; font-weight: bold;">\&quot;</span>/images/#{id}.png<span style="color: #000099; font-weight: bold;">\&quot;</span> class=<span style="color: #000099; font-weight: bold;">\&quot;</span>thumbnail<span style="color: #000099; font-weight: bold;">\&quot;</span> /&gt;&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; # ここからコピー処理<br />
&nbsp; &nbsp; &nbsp; thumb_pics <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#pictures .thumbnail&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; thumb_pics.<span style="color: #660066;">click</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; image <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Image<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; image.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'src'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; image.<span style="color: #000066;">onload</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">clearRect</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">width</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">height</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">drawImage</span><span style="color: #009900;">&#40;</span>image<span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><br />
&nbsp; reloadPictures<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></div></div>
<p>画像を保存するボタンを押した時の処理に、投稿画像一覧を更新する処理を入れます。</p>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// app/assets/javascripts/pictures.js.coffee</span><br />
&nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#save-button&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span> <span style="color: #339933;">-&gt;</span><br />
&nbsp; &nbsp; url <span style="color: #339933;">=</span> canvas<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">toDataURL</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; $.<span style="color: #660066;">post</span> <span style="color: #3366CC;">'/pictures'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>data<span style="color: #339933;">:</span> url<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span> # この<span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-&gt;</span> 以降を追加<br />
&nbsp; &nbsp; &nbsp; reloadPictures<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></div></div>
<p>以上です。<br />
これで安易すぎるお絵かき投稿サイトができました。<br />
デザインなど、各自調整してみてください。<br />
下に見本を置いておきます。</p>
<h2>完成品</h2>
<p>ご自由に投稿して下さいませ。<br />
<a href="http://canvas.d-adv.net/">http://canvas.d-adv.net/</a></p>
<h3>github</h3>
<p>ご自由にcloneして下さいませ。<br />
<s>git://github.com/asaumi/canvas_post.git</s><br />
<b>git@github.com:asaumi/canvas_post.git<b></p>
<h2>色々書いたよ</h2>
<p><a href="http://kray.jp/blog/rails3-html5-canvas/attachment/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88%ef%bc%882011-11-13-0-28-05%ef%bc%89/" rel="attachment wp-att-5220"><img src="http://kray.jp/wp-content/uploads/2011/11/81f8b061b1fbaab81d86c5b3d2ed1045.png" alt="" title="マイピクチャー" width="410" height="273" class="alignnone size-full wp-image-5220" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/rails3-html5-canvas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>学んだことまとめ 2011/10/31〜11/4</title>
		<link>http://kray.jp/blog/daily-2011-1031-1104/</link>
		<comments>http://kray.jp/blog/daily-2011-1031-1104/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 02:20:37 +0000</pubDate>
		<dc:creator>morimori</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=5021</guid>
		<description><![CDATA[2011/10/31 〜 11/4 までに学んだことをまとめました。]]></description>
			<content:encoded><![CDATA[<h2>まえがき</h2>
<p>久方ぶりの、もりもりです。</p>
<div class="polnareff" style="line-height: 1.2; font-family: 'MS UI Gothic'; margin-bottom: 15px;">
　　　　　　　　 ,. -‐&#8221;&#8221;&#8217;&#8221;"¨¨¨ヽ<br />
　　　　 　 　 (.＿＿_,,,&#8230; -ｧァﾌ|　　　　　　　　　　あ…ありのまま 今　起こった事を話すぜ！<br />
　 　 　 　 　 |i i|　 　 }!　}} /／|<br />
　　　　 　 　 |l､{　 　j}　/,,ｨ//｜　　　　　　　『学んだことまとめが当番制になったので毎週更新されると<br />
　　　　　　　 i|:!ヾ､_ﾉ／ u {:}//ﾍ　　　　　　　　思ったらいつのまにか2週間経っていた』<br />
　　　　　　　 |ﾘ u&#8217; }　 ,ﾉ　_,!V,ﾊ |<br />
　　 　 　 ／´fト､_{ﾙ{,ィ&#8217;ｅﾗ　, ﾀ人　　　　　　　　な…　何を言ってるのか　わからねーと思うが<br />
　　　　 /&#8217; 　 ヾ|宀| {´,)⌒`/ |<ヽﾄiゝ　　　　　　　　おれも何をされたのかわからなかった…<br />
　　　　,ﾞ　 ／ )ヽ iLﾚ 　u' |　| ヾｌﾄﾊ〉<br />
　　 　 |／_／　 ﾊ !ニ⊇　'／:} 　V:::::ヽ　　　　　　　　頭がどうにかなりそうだった…<br />
　　　 /／ 二二二7'T'' ／u'　__ /:::::::/｀ヽ<br />
　　　/'´r　-―一ｧ‐ﾞＴ´　'"´ ／::::／-‐ 　＼　　　　催眠術だとか超スピードだとか<br />
　　 / // 　 广¨´ 　/'　　 ／:::::／´￣｀ヽ ⌒ヽ　　　　そんなチャチなもんじゃあ　断じてねえ<br />
　　ﾉ ' /　 ノ:::::`ー-､___／:::::／/ 　 　 　 ヽ　　}<br />
_／｀丶　/::::::::::::::::::::::::::￣`ー-{:::...　　　 　　　ｲ　 もっと恐ろしいものの片鱗を味わったぜ…
</div>
<p>それでは、先週の学んだことまとめです。</p>
<h2>まとめ</h2>
<h3>Ruby, Rails 関連</h3>
<blockquote><p><a href="https://www.relishapp.com/rspec/rspec-mocks/v/2-7">RSpec Mocks 2.7 – RSpec – Relish</a> によると、stub / mockはそのうちdeprecatedになって消えるとのことなので、doubleを使いましょう。</p></blockquote>
<p><a href="http://rubygems.org/gems/rr">rr</a> を使えってことかと思ったんですが、rspec 自体に double というメソッドがあるんですね。</p>
<hr />
<blockquote><p><a href="https://github.com/sosedoff/capistrano-unicorn">capistrano-unicorn</a><br />
unicornのstart時に、BUNDLE_GEMFILE=#{current_path}/Gemfileを付けてくれない。一度テストしたところ影響が見られなかったが、観察を続ける</p></blockquote>
<p><a href="http://blog.twiwt.org/e/2e6270">こちらの記事</a>の件ですね。<br />
やはり付けないとダメなようで、<a href="https://github.com/sosedoff/capistrano-unicorn/pull/2">pull request を送った</a>とのことです。</p>
<hr />
<blockquote><p>capistranoのdeploy/assets<br />
capistrano 2.8以降なら、Capfileの下の行をアンコメントするだけでrake assets:precompileしてくれる<br />
load &#8216;deploy/assets&#8217;</p></blockquote>
<p>知らずに自分で after &#8216;deploy:update_code&#8217;, &#8216;deploy:precompile_assets&#8217; なんてやってました。</p>
<hr />
<blockquote><p><a href="http://mongoid.org/docs/documents/inheritance.html">mongoid の INHERITANCE</a> が便利だった。</p></blockquote>
<p>ActiveRecord の STI に相当するものですが、これはたしかに MongoDB 向きの機能ですね。</p>
<hr />
<blockquote><p><a href="https://gist.github.com/1330095">ruby の Digest のベンチマークを取ってみた</a></p>
<ul>
<li>SHA2 が結構遅い。SHA1 と 倍くらい違う</li>
<li>SHA2 と SHA256 は同じ結果になるのに、なぜか結構差が出る</li>
<li>1.9.3-p0 は REE-2011.03 より 2 割くらい速い</li>
</ul>
</blockquote>
<p>現在開発中のサービス内で使うワンタイムトークンの生成に使うハッシュ関数を、どれにしようかと迷って調べてみました。<br />
SHA2 と SHA256 で差がでるのは、SHA256 で呼び出すと C のコードが直接実行されるけど、SHA2 で呼び出すと ruby のコードが間に入るからってことですかね。</p>
<hr />
<blockquote><p><a href="https://gist.github.com/1346867">PDF &lt;=&gt; JPEG 変換ベンチマーク</a></p>
<ul>
<li><a href="https://gist.github.com/1346867#file_pdf_to_jpg1.rb">RMagick で PDF の各ページを JPEG で出力</a><br />
読み込みに時間がかかる。</li>
<li><a href="https://gist.github.com/1346867#file_pdf_to_jpg2.rb">QuickMagick で PDF の各ページを JPEG で出力</a><br />
クイックだから早いかと思ったら、とても遅い。</li>
<li><a href="https://gist.github.com/1346867#file_jpg_to_pdf.rb">RMagic で複数の JPEG を 一つの PDF にまとめて出力</a><br />
pdf → jpgよりだいぶ早い。</li>
</ul>
</blockquote>
<p>JPEG ⇒ PDF が速いのは、PDF のパースにかかるコストが大きいってことですかね。</p>
<hr />
<blockquote><p>動作確認環境(integration)を構築しているが、stylesheet_link_tagとjavascript_include_tagがそれぞれ/stylesheets/&#8230;と/javascripts/&#8230;に展開されてしまうために、ブラウザがcssとjsを取得できない。本来なら両方とも/assets/&#8230;になるはず。</p></blockquote>
<p>config/application.rb に require &#8220;sprockets/railtie&#8221; が足りなかったようです。</p>
<hr />
<blockquote><p><a href="https://github.com/dokipen/ruby-querystring">dokipen/ruby-querystring – GitHub</a><br />
ハッシュからクエリストリングを生成するためのライブラリ。<br />
同名のパラメータが複数あるクエリストリングを生成するのに使った。</p>
<ul>
<li>例
<pre>QueryString.stringify({:a =&gt; ["hoge", "fuga"]}) #=&gt; a=hoge&amp;a=fuga</pre>
</li>
</ul>
</blockquote>
<p>オプションによって出力フォーマットを変えられるので、便利そうです。</p>
<h3>Ruby 1.9.3-p0 関連</h3>
<p>先月末に Ruby 1.9.3-p0 がリリースされました。<br />
先週は日報にも 1.9.3-p0 についていくつか書かれていたので、トピックを分けてみます。</p>
<blockquote><p>ruby-1.9.3-p0 が出たので RHEL5/6 用の x86/x64 用 RPM を作成</p>
<ul>
<li><a href="http://pkgs.kray.jp/rhel/5/ruby19/">RHEL5 用</a></li>
<li><a href="http://pkgs.kray.jp/rhel/6/ruby19/">RHEL6 用</a></li>
</ul>
</blockquote>
<p><a href="http://www.momonga-linux.org/">Momonga Linux</a> の spec ファイルをベースに、CentOS 5(x86,x64) / CentOS 6(x64) / Scientific Linux 6(x86) の環境でビルドしたものです。<br />
他にも色々置いてありますが、<strong>お使いの際は自己責任でお願いします。</strong></p>
<hr />
<blockquote><p>ruby-1.9.3-p0 が出たので早速 rvm upgrade 1.9.2-p290 1.9.3-p0 した</p>
<ul>
<li>gemset を引き継ぐところでちょくちょくエラーになる、けど止まらずに最後まで終了。<br />
多数のファイルが 1.9.2-p290 を見るようになったままになっていたので、全 gem を再インストール中、therubyracer のビルドに失敗する。どうやら clang がダメっぽい。</li>
<li>therubyracer のビルド時だけ、一時的に rbconfig.rb の CC と CXX を gcc-4.2 と g++-4.2 に変更してビルドしてみたら通ったけど、こんなんでいいのか・・・？</li>
<li>なんか色々動かないっぽい。一旦戻すべきか。。。？</li>
<li>rvm が <a href="https://github.com/wayneeseguin/rvm/blob/2c8d9cd1ba9e0c5b311a0669c78f2ae149b83a0a/scripts/functions/build">Xcode 4.2 が入ってる環境では強制的に clang を使うように設定</a>してしまうので、該当部分を llvm-gcc-4.2 を使うように変更してみた。<br />
⇒ rbconfig.rb で gcc-4.2 を使うようにした時とたぶん同じ状態<br />
コンパイラは問題ないけど、ruby 1.9.3 に対応できてない gem がいくつかあるっぽい。</p>
<ul>
<li> ruby-debug-base19<br />
ビルドはできるけど、シンボルが見つからなくてロード時点で落ちる</li>
<li>fabrication<br />
spork と組み合わせた時に Fabricate でブロックする</li>
</ul>
</li>
<li>結局まだ早いってことで 1.9.2-p290 に戻した</li>
</ul>
</blockquote>
<p>rvm が clang を強制する件については、<a href="https://github.com/wayneeseguin/rvm/blob/master/scripts/functions/build">最新のコード</a>では <strong>clang を使わない</strong>ように変更されていました。<br />
そもそも「<strong>Xcode 4.2 users &#8211; please be warned &#8211; in case of any compilation issues downgrade to Xcode 4.1 and reinstall your rubies.</strong>」という警告が出るので、4.1 にダウングレードするのが今のところ正解なんでしょうか。。。</p>
<hr />
<blockquote><p><a href="https://github.com/sstephenson/rbenv">rbenv</a>と<a href="https://github.com/sstephenson/ruby-build">ruby-build</a>でruby-1.9.3をインストールする</p>
<ul>
<li>configureにオプションを渡すにはCONFIGURE_OPTSを使う
<pre>CONFIGURE_OPTS="--enable-shared --with-opt-dir=/usr/local" rbenv install 1.9.3-p0</pre>
</li>
<li>ruby-debugはlinecache19とruby-debug-baseをrubyforge.orgから(!)ダウンロードしてインストールする</li>
</ul>
</blockquote>
<p>最近は rbenv + ruby-build が流行っているようですね。<br />
ruby-debug-base19 と linecache19 は<a href="http://rubyforge.org/frs/?group_id=8883">ここ</a>にある gem なら 1.9.3-p0 に対応しているようです。</p>
<hr />
<h3>HTML5 関連</h3>
<blockquote><p><a href="http://liveminutes.com/">LiveMinutes</a><br />
参考になるかも、と思ったら、肝心の共有部分は Flash だった</p></blockquote>
<p><span style="color: red;">【</span>残念です。<span style="color: green;">】</span></p>
<hr />
<blockquote><p><a href="http://html5test.com/">HTML5TEST</a></p></blockquote>
<p><a href="http://html5.jp/tutorial/apicheck/">HTML5 API チェッカー</a>もありますね。</p>
<hr />
<blockquote><p>HTML5には、ブラウザ（ユーザ）を守りつつcross domain XHRを許可する <a href="http://www.w3.org/TR/cors/">Cross-Origin Resource Sharing</a> という仕組みがあり、これを利用することでcross domainファイルアップロードが可能になる。<br />
『<a href="http://www.amazon.co.jp/gp/product/4798028215/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;tag=kray07-22&amp;linkCode=as2&amp;camp=247&amp;creative=1211&amp;creativeASIN=4798028215">徹底解説 HTML5 APIガイドブック コミュニケーション系API編</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.jp/e/ir?t=kray07-22&amp;l=as2&amp;o=9&amp;a=4798028215" border="0" alt="" width="1" height="1" />』の第３章に詳しく書かれている。</p></blockquote>
<p><a href="http://www.amazon.co.jp/gp/product/4798028541/ref=as_li_tf_tl?ie=UTF8&amp;tag=kray07-22&amp;linkCode=as2&amp;camp=247&amp;creative=1211&amp;creativeASIN=4798028541">ビジュアル系API編</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.jp/e/ir?t=kray07-22&amp;l=as2&amp;o=9&amp;a=4798028541" border="0" alt="" width="1" height="1" />、<a href="http://www.amazon.co.jp/gp/product/4798025291/ref=as_li_tf_tl?ie=UTF8&amp;tag=kray07-22&amp;linkCode=as2&amp;camp=247&amp;creative=1211&amp;creativeASIN=4798025291">マークアップガイドブック</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.jp/e/ir?t=kray07-22&amp;l=as2&amp;o=9&amp;a=4798025291" border="0" alt="" width="1" height="1" />もオススメです。</p>
<hr />
<blockquote><p>iPad だと動画の始まるタイミングがずれるのが再現しない。</p>
<ul>
<li><a href="https://github.com/mschrag/speedlimit">speedlimit</a><br />
シミュレータで 3G 回線のスピードにしたりできるので便利。<br />
だが再現せず。</li>
</ul>
</blockquote>
<p>HTML5 の video タグでの件なんですが、回線速度ではないとすると、CPU パワーの問題でしょうか。。。</p>
<h3>その他</h3>
<blockquote><p>node.jsのredis client<br />
githubで調べたらいっぱいあってどれがいいんだろうか。</p>
<ul>
<li><a href="https://github.com/bnoguchi/redis-node">https://github.com/bnoguchi/redis-node</a></li>
<li><a href="https://github.com/fictorial/redis-node-client">https://github.com/fictorial/redis-node-client</a></li>
<li><a href="https://github.com/mranney/node_redis">https://github.com/mranney/node_redis</a></li>
<li><a href="https://github.com/Tim-Smart/node-redis">https://github.com/Tim-Smart/node-redis</a></li>
</ul>
</blockquote>
<p><a href="https://github.com/mranney/node_redis">https://github.com/mranney/node_redis</a>を使うことにしたようです。</p>
<hr />
<blockquote><p><a href="https://github.com/ErikDubbelboer/phpRedisAdmin">ErikDubbelboer/phpRedisAdmin – GitHub</a></p></blockquote>
<p>最近 Redis を使うことが増えてきたので、開発用に使う管理ツールを探してみました。</p>
<h3>あとがき</h3>
<p>来週の当番はいっしーです。ご期待ください。<br />
（と、プレッシャーをかけておく）</p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/daily-2011-1031-1104/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>学んだことまとめ 2011 10/11〜10/14</title>
		<link>http://kray.jp/blog/daily-2011-1011-1014/</link>
		<comments>http://kray.jp/blog/daily-2011-1011-1014/#comments</comments>
		<pubDate>Wed, 26 Oct 2011 02:48:16 +0000</pubDate>
		<dc:creator>ダニー</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[情報共有]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=4967</guid>
		<description><![CDATA[反省 毎週書くつもりが、いつの間にか2ヶ月経ってました。 学んだことまとめをまとめるのは、当番制になりました。今回はダニーですこんにちは。 Webアプリ開発 バーコード生成 https://rubygems.org/ge [...]]]></description>
			<content:encoded><![CDATA[<h2>反省</h2>
<p>毎週書くつもりが、いつの間にか2ヶ月経ってました。<br />
学んだことまとめをまとめるのは、当番制になりました。今回はダニーですこんにちは。</p>
<h2>Webアプリ開発</h2>
<h4>バーコード生成</h4>
<p><a href="https://rubygems.org/gems/barby">https://rubygems.org/gems/barby</a><br />
barcode = Barby::Code128C.new ‘123456789012’ #EAN-13は13桁だけど最後のチェックディジットは面倒を見てくれるので12桁で指定する。<br />
あとは barcode.to_png でpng化、など。</p>
<h4>高度な日時操作</h4>
<p><a href="https://github.com/mojombo/chronic">https://github.com/mojombo/chronic</a><br />
日付・時間っぽい文字列をよきに計らって Time オブジェクトにしてくれる。<br />
25:00のような時間もパースできた。</p>
<h4>Added Rails 3.1 asset pipeline support to #save_and_open_page</h4>
<p><a href="https://github.com/JangoSteve/capybara/commit/bd1524508b64d97964b482e7dfae026978d66d09">https://github.com/JangoSteve/capybara/commit/bd1524508b64d97964b482e7dfae026978d66d09</a></p>
<h4>Call Wikipedia API using jQuery</h4>
<p><a href="http://labs.steren.fr/2010/11/18/call-wikipedia-api-using-jquery">http://labs.steren.fr/2010/11/18/call-wikipedia-api-using-jquery</a><br />
WikipediaのAPIの使い方。</p>
<h2>iPhoneアプリ開発</h2>
<h4>External Accessory</h4>
<p>iOS5から外部デバイス利用時に設定が必要になった。<br />
Info.plistにUISupportedExternalAccessoryProtocolsにプロトコルを追加。<br />
<a href="http://developer.apple.com/library/ios/#featuredarticles/ExternalAccessoryPT/Introduction/Introduction.html">http://developer.apple.com/library/ios/#featuredarticles/ExternalAccessoryPT/Introduction/Introduction.html</a></p>
<h2>開発環境</h2>
<h4>git-dude</h4>
<p><a href="http://www.moongift.jp/2011/10/20111013-2">http://www.moongift.jp/2011/10/20111013-2</a><br />
設定したリモートリポジトリへの push を growl で通知してくれる。</p>
<h4>Sublime Text</h4>
<p><a href="http://www.sublimetext.com">http://www.sublimetext.com</a></p>
<h2>アジャイル</h2>
<h4>ユーザーストーリーのReadyの定義</h4>
<p><a href="http://www.ryuzee.com/contents/blog/4264">http://www.ryuzee.com/contents/blog/4264</a><br />
プロダクトオーナーの参考に。</p>
<p><br style="clear: both;" /></p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/daily-2011-1011-1014/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>学んだことまとめ 2011 7/11〜7/15</title>
		<link>http://kray.jp/blog/daily-2011-711-715/</link>
		<comments>http://kray.jp/blog/daily-2011-711-715/#comments</comments>
		<pubDate>Thu, 25 Aug 2011 02:52:40 +0000</pubDate>
		<dc:creator>amachin</dc:creator>
				<category><![CDATA[ブログ]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[情報共有]]></category>

		<guid isPermaLink="false">http://kray.jp/?p=4937</guid>
		<description><![CDATA[反省 毎週書くつもりが、いつの間にか1ヶ月経ってました。 まとめ Fiber と Proc 手続きを抽象化する二つの機能 Fiber はよく Thread と比較されるけど、並列実行できるわけではない？ これが一番スッキ [...]]]></description>
			<content:encoded><![CDATA[<h2>反省</h2>
<p>毎週書くつもりが、いつの間にか1ヶ月経ってました。</p>
<h2>まとめ</h2>
<h4>Fiber と Proc</h4>
<p><a href="http://jp.rubyist.net/magazine/?0034-FiberForBeginners">手続きを抽象化する二つの機能</a></p>
<p>Fiber はよく Thread と比較されるけど、並列実行できるわけではない？<br />
これが一番スッキリわかった。</p>
<p><strong>Fiber で抽象化した「処理」は「処理」の中で Fiber.yield が呼ばれたタイミングで処理が終了し、再度呼び出した場合は Fiber.yield の呼び出しの続きから「処理」が再開されるのに対して、Proc で抽象化した「処理」は何度呼び出してもその「処理」の最初から実行されます。</strong></p>
<p>Fiber はそれを作ったスレッドからしか使えない。<br />
別スレッドに参照を渡して実行しようとすると、「fiber called across threads (FiberError)」となる。</p>
<h4>特定のパスへのアクセスだけRails以外で処理する</h4>
<p>DocumentRoot を Passenger にまかせて、特定のパスへのアクセスだけ Alias で Rails 以外で処理しようとしても、ファイル名まで指定しないと Rails に行ってしまう。<br />
以下の設定は /wordpress/ にアクセスしても rails が処理しようとしてルーティングエラーになるけど、/wordpress/index.php だと php が実行される。</p>
<p>以下の設定にすると、/wordpress/ へのアクセスでも php が実行されるようになる。</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">DocumentRoot <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>rails-app<span style="color: #000000; font-weight: bold;">/</span>public<br />
Alias <span style="color: #000000; font-weight: bold;">/</span>wordpress <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>wordpress<br />
<br />
<span style="color: #000000; font-weight: bold;">&lt;</span>location <span style="color: #000000; font-weight: bold;">/</span>wordpress<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; PassengerEnabled <span style="color: #c20cb9; font-weight: bold;">false</span><br />
<span style="color: #000000; font-weight: bold;">&lt;/</span>location<span style="color: #000000; font-weight: bold;">&gt;</span></div></div>
<h4>LANG=C だと ruby 1.9 でインストールに失敗する gem がある</h4>
<p>ja_JP.UTF-8 等の UTF-8 な LANG を指定することで回避</p>
<h4>multipart対応ライブラリ</h4>
<p>httpartyだとmultipartに対応して送れない。<br />
fardayが最近、他のgemをインストールすると要求されて使われているらしい。<br />
<a href="https://github.com/technoweenie/faraday">https://github.com/technoweenie/faraday</a></p>
<p>fardayはmultipart対応<br />
<a href="https://spreadsheets0.google.com/pub?hl=en&#038;hl=en&#038;key=0AiZsKd8d4hSJdHFFbjR5aWNjWjlzWlhiNGxQejdBWWc&#038;output=html">https://spreadsheets0.google.com/pub?hl=en&#038;hl=en&#038;key=0AiZsKd8d4hSJdHFFbjR5aWNjWjlzWlhiNGxQejdBWWc&#038;output=html</a></p>
<h4>OAuth2.0</h4>
<p>OAuth2.0ではSSLを使うことで署名を無くした<br />
<a href="http://www.atmarkit.co.jp/fsmart/articles/oauth2/02.html">http://www.atmarkit.co.jp/fsmart/articles/oauth2/02.html</a></p>
<p>HTTPSを必須にし、署名をなくし、トークン取得も簡略化<br />
<a href="http://developer.mixi.co.jp/connect/mixi_graph_api/api_auth/">http://developer.mixi.co.jp/connect/mixi_graph_api/api_auth/</a></p>
<p>OAuth2.0での疑問点<br />
<strong>通常のAPIへのアクセス時にHTTPを利用するのは危険か？</strong></p>
<h4>REST API</h4>
<p><a href="http://www.infoq.com/jp/news/2011/06/RestAPIs">REST APIの良い、悪い、醜い</a></p>
<p><a href="http://www.infoq.com/jp/news/2010/01/rest-api-authentication-schemes">RESTful API の 認証の枠組</a></p>
<p><a href="http://www.oreillynet.com/pub/au/429">George Reese Blog</a></p>
<p><a href="http://www.infoq.com/jp/news/2011/07/unrest">unRESTは新しいRESTか</a></p>
<h4>iphoneでクラッシュしたときバックトレースを出す方法</h4>
<p><a href="http://www.slideshare.net/kamiyan2/iphone-1929423">http://www.slideshare.net/kamiyan2/iphone-1929423</a></p>
<h4>ファイル判別</h4>
<p><a href="http://d.hatena.ne.jp/keita_yamaguchi/20070805/1186304326">http://d.hatena.ne.jp/keita_yamaguchi/20070805/1186304326</a><br />
こっちの方がいいのでは？<br />
<a href="https://github.com/blackwinter/ruby-filemagic">https://github.com/blackwinter/ruby-filemagic</a></p>
<h4>画像変換</h4>
<p>MiniMagickかImageScience、Imlib2-Rubyを検討。<br />
MagicWandを使うのが良さそうだけど、ローカルでコンパイルできなかったので、当面はMiniMagickを使用する。</p>
<h4>S3のライブラリの選定</h4>
<p>aws-s3ではなく、awsを使用。（元々はrightscaleみたい）<br />
<a href="https://github.com/appoxy/aws">https://github.com/appoxy/aws</a><br />
connection_modeを選べるのは良さそう。</p>
<h4>複合主キーを避けるべき理由</h4>
<p><a href="http://d.hatena.ne.jp/torazuka/20110713/pk">http://d.hatena.ne.jp/torazuka/20110713/pk</a><br />
ここで紹介されてる「楽々ERDレッスン」が良書のようなので、とりあえず本屋で探して見てみる。<br />
<a href="http://www.amazon.co.jp/dp/4798110663">http://www.amazon.co.jp/dp/4798110663</a></p>
<h4>AWS 公式 Ruby ライブラリ</h4>
<p><a href="http://aws.typepad.com/aws_japan/2011/07/introducing-the-aws-sdk-for-ruby.html">http://aws.typepad.com/aws_japan/2011/07/introducing-the-aws-sdk-for-ruby.html</a><br />
EC2, S3, SQS, SNS, SES 用のライブラリと、SDB の O/R マッパー。</p>
<h4>更新日時が一番最近のファイルを取得</h4>
<p>find -printf ”%TY%Tm%Td%TH%TM.%TS %p\n” | sort -r | head -n1</p>
<h4>あるファイルの更新日時を指定した時間に変更</h4>
<p>touch -t YYYYMMDDhhmm.ss 対象ファイル</p>
<h4>更新日時が指定したファイル以前のものを取得</h4>
<p>find ! -newer 基準ファイル</p>
<h2>気になったリンク</h2>
<h4>TT, KTはいけてる</h4>
<p><a href="http://fallabs.com/blog-ja/promenade.cgi?id=108">http://fallabs.com/blog-ja/promenade.cgi?id=108</a></p>
<h4>RabbitMQ</h4>
<p><a href="http://www.rabbitmq.com/clustering.html">http://www.rabbitmq.com/clustering.html</a><br />
queueは1ノードにしか乗らないらしい</p>
<h4>Google製のセキュリティチェッカー「Skipfish」</h4>
<p><a href="http://www.moongift.jp/2011/07/20110713/">http://www.moongift.jp/2011/07/20110713/</a></p>
<h4>CentOS6リリース</h4>
<p><a href="http://sourceforge.jp/magazine/11/07/12/0437244">http://sourceforge.jp/magazine/11/07/12/0437244</a></p>
<h4>復習のタイミングを変えるだけで記憶の定着度は４倍になる</h4>
<p><a href="http://readingmonkey.blog45.fc2.com/blog-entry-499.html">http://readingmonkey.blog45.fc2.com/blog-entry-499.html</a></p>
<h4>Selenium 2.0リリース</h4>
<p><a href="http://sourceforge.jp/magazine/11/07/11/0525248">http://sourceforge.jp/magazine/11/07/11/0525248</a></p>
<h4>認証？委譲？仕様</h4>
<p>Facebook<br />
<a href="http://developers.facebook.com/docs/authentication/">http://developers.facebook.com/docs/authentication/</a></p>
<p>Instagram<br />
<a href="http://tech.kayac.com/archive/instagramapi.html">http://tech.kayac.com/archive/instagramapi.html</a></p>
<h4>iTerm2</h4>
<p><a href="http://journal.mycom.co.jp/column/osxhack/005/index.html">http://journal.mycom.co.jp/column/osxhack/005/index.html</a></p>
<h4>fluxflex</h4>
<p><a href="https://www.fluxflex.com/">https://www.fluxflex.com/</a><br />
Github 連携が便利そう。</p>
<h4>電話番号、郵便番号、郵便番号の正規表現</h4>
<p><a href="http://blog.livedoor.jp/nipotan/archives/51644244.html">http://blog.livedoor.jp/nipotan/archives/51644244.html</a></p>
<h4>TDD</h4>
<p><a href="http://www.slideshare.net/keiswd/tddtdd">http://www.slideshare.net/keiswd/tddtdd</a></p>
<p><br style="clear: both;" /></p>
]]></content:encoded>
			<wfw:commentRss>http://kray.jp/blog/daily-2011-711-715/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

