Node.jsの勉強がてら作ってみた。
サーバーサイドとクライアントサイドが全部Javascriptで書けるというのは思った以上に気持ちいい。expressのフレームワークも最小限な構成で、ちょっとNode.jsを試したいときに助かる。
SocketSketch(公開停止中)
さくらVPS上で動かしてる。いろいろバグありますが超α版ってことでご勘弁ください。あと「こんな機能あったらおもしろそう」というのがあれば教えて下さい。頑張って考えてみます。
大したもんじゃないけどソースコードはGitHubに...。↓
memerelics/sketch-node - GitHub
※動画が最初の方バグってるのは気にしないで下さい。動画は スクリン・クロラ - The Screen Crawlers で撮った。
お絵描きアプリの素材はcho45さん
WEB+DB PRESS v.62で cho45 さんが書かれた特集「HTML5/CSS3/Javascript実践入門」の第五章で「お絵描きアプリケーションを作る」という内容があって、面白かったので写経してみた。
中身はほとんど、HTML5から追加された「canvas」要素。これすごいね。

あと、WEB+DB PRESSの特集のコードをそのまま撃ち込むだけでは動かなかった。以下2点を修正。
- canvas.addEventListener('mousedown', function e { ...の部分を
- → canvas.addEventListener('mousedown', function (e) { ...と、括弧でくくってやる
- カラーパレット用のHTML(リスト3)全体を「div id="tools"」で囲わないといけない。
興味がある人は上述の takuyahashimoto/sketch-node - GitHub をご覧下さい。
これを写経してみてjavascriptが面白かった(特にパレットを用意して色を変える機能とか)ので、ちょうど同時期に勉強していたNode.jsのsocket.ioライブラリを使って遊べないかと考えた。
Nodeの基本
まずは、サーバーサイドで動くJavascriptってのがどんなもんか、という感触を掴む。
Nodeで作る人工無脳 というページがとても参考になった。最後のリアルタイムチャットで使ったコードを流用して、お絵描きデータの共有に使います。詳細は後述。
あとは[node.js] - 大人になったら肺呼吸 こちらのブログは次々node.jsネタが更新されているので注目しています。
node.jsのインストール
まずnode.jsバージョン管理のnaveを入れる
$ git clone git://github.com/isaacs/nave.git ~/.nave
yumのupdateと必要パッケージのインストール(僕の環境での話)
# yum update
# yum -y install gcc-c++
# yum install -y openssl-devel
nave経由でnodeの最新版を入れる。※僕がやったときは0.4.7が落ちて来ました。
$ ~/.nave/nave.sh install latest
$ ~/.nave/nave.sh use 0.4.7
nodeを利用する前にバージョンを指定してやるのが面倒なので2行目のuse..の処理を.zshrcあたりに書いておきましょう。
npmというツールで今度はnode.jsがらみのプラグインを管理する。RubyのGemsみたいなもんか。
% curl http://npmjs.org/install.sh | sh
% npm install express ejs socket.io
用意されているインストール用シェルスクリプトを使ってさくっと入れてしまい、そのままnpm経由でいくつかplugingを入れる。
- Socket.IO: the cross-browser WebSocket for realtime apps.
- WebSocketを簡単に弄れるようにしたAPI実装(言葉合ってんのかこれ)
- express
- 超軽量なWEBアプリケーションフレームワーク
- デフォルトだとこんな構造。
sketch-node
├── app.js
├── logs
├── pids
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── test
│ └── app.test.js
└── views
├── index.ejs
└── layout.ejs
サーバーサイドのJavascript => app.js
クライアントサイドのJavascript => javascripts/hoge.js
libに読み込むライブラリを入れ、publicに利用する画像やクライアントサイドで動くJavascriptコードを入れ、viewsのHTMLを編集する。
iptables設定
忘れがちなのでついでにメモ。
# iptables -A INPUT -p tcp --dport 3030 -j ACCEPT
# iptables -A INPUT -p tcp --sport 3030 -j ACCEPT
# /etc/init.d/iptables save
# /etc/init.d/iptables restart
お絵描きアプリとNode.jsをマージする
さていよいよ本題です。本題までが長い事には定評があるブログです。
お絵描き機能をリアルタイム化してみます。
基本方針は、
- sketch/index.html の内容を => sketch-node/views/indes.ejs にマージさせる
- sketch/js/sketch.js を => sketch-node/public/javascript/ 以下に置く
- app.jsとpublic/javascript/sketch.jsの間でsocket通信を行うようにする
という感じです。まず「お絵描き」機能は実際何をやっているのかというと
という風に、マウス押下時、マウスドラッグ時、ドロップ時のイベントを判定して、"down"フラグで制御しながら座標指定で線の描画を行っています。というわけで、次はこれをリアルタイム化してみます。
クライアントサイドの設定
まずはsckech.jsに以下の記述を入れて、socketを作ります。
次にこのsocketを通じて情報を送る部分です。このとき描画すると同時にサーバにも座標情報と色情報を送るようにしてみましょう。先ほど見たmousedown/move/upイベントの中にsocket.send()メソッドを記述。
こんな感じ!socket.send()の中にJSON型式で"いまの状態(act)"、"座標(x,y)"、"色(color)(mousedown時のみ)"を渡しています。actは後で、逆に情報を受け取ったときのイベント判定に使います。
ここでサーバーサイド
つぎにサーバ側の設定。app.jsファイルを編集。とはいえ追加するのは、
この程度です。clientが接続して来て、clientからmessageが来たら、その内容(data: さきほどsocket.sendで送った内容)を、接続しているすべてのクライアントにブロードキャストする。 (イメージで理解してるだけなのでこのへん不安)
ふたたびクライアントサイド
ここでsketch.jsファイルに戻って来て、サーバからブロードキャストされたデータを受信したときの挙動を設定しましょう。
downフラグの代わりにremote_downというフラグを用意して、さっきsocket.sendの中に含めたactの中身によって挙動を振り分けています。JSONも初めて使ったけどオブジェクトな形で(?)要素を取得出来て結構便利ですね。
bugfixとかTODOとか改良案とか
- データ送信元のクライアントを区別出来るようにする
- 誰がいま接続しているのかを表示する
他にもいろいろ問題がある。
送って受けて、という単方向なら良いんだけど、同時に書こうとすると描画イベントが競合する(二人のマウスポインタ間が線で繋がれてしまう)。ctx (canvas.getContext('2d')) をクライアントの数だけ用意する必要があるのだろうか。むむ。
気になる技術をさっくり勉強、というスタンスも好きだけど、自分の成果物を育てて行くような勉強もいいですね。
Node.jsさん気に入ったので、ちょこちょこ修正して行こうと思います。




