Node.jsの勉強がてら作ってみた。

サーバーサイドとクライアントサイドが全部Javascriptで書けるというのは思った以上に気持ちいい。expressのフレームワークも最小限な構成で、ちょっとNode.jsを試したいときに助かる。

SocketSketch(公開停止中)

さくらVPS上で動かしてる。いろいろバグありますが超α版ってことでご勘弁ください。あと「こんな機能あったらおもしろそう」というのがあれば教えて下さい。頑張って考えてみます。

大したもんじゃないけどソースコードはGitHubに...。↓

memerelics/sketch-node - GitHub

※動画が最初の方バグってるのは気にしないで下さい。動画は スクリン・クロラ - The Screen Crawlers で撮った。

お絵描きアプリの素材はcho45さん

WEB+DB PRESS Vol.62
WEB+DB PRESS Vol.62
クチコミを見る

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を入れる。


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さん気に入ったので、ちょこちょこ修正して行こうと思います。