東京NODE学園祭2011に行ってきた

体調悪くてぼやっとしてたんだけど、Guillermo Rauchさんのライブコーディングになって目が覚めた。Twitterでも驚きの声多数って感じだったんだけど、アレはすごいわ。タイピングの速さも異常だけど(最初本当に今やってるのか疑ってしまったよ)、見てて飽きない題材で(canvasを使ってブラウザ上で絵を描いて、最終的にはそのデータをサーバに送って動画にする)複雑にならないように極力シンプルなコードをその場で説明しながら書いて行く様は、本当にびっくりした。

ということで、そのときのコードを思い出しながら書いてみたが、サーバ側はちょっと手を抜いてブラウザで書いた絵をそのままtest.pngとして出力しているだけ。あと、本当はSocket.IOとか使ってごにょごにょという話だったきもするけど、忘れちゃった。

<html>
  <style>
  body {
    margin: 0;
    padding: 0;
    background-color: #eee;
  }
  #c {
    background-color: #fff;
    border-bottom: solid #999 1px;
  } 
  </style>
  <script>
  window.onload = function() {
    var canvas = document.getElementById('c')
      , ctx = canvas.getContext('2d')
      , noop = function() {}
      , result = null
      , history = [];

    ctx.strokeStyle = 'red';

    window.onmousedown = function() {
 console.log('down');
      ctx.beginPath();
      result = [];
      result[0] = ctx.strokeStyle;
      result[1] = [];
      window.onmousemove = function(e) {
        move(e.clientX, e.clientY);
      }
    }
    window.onmouseup = function() {
      history.push(result);
      ctx.stroke();
      window.onmousemove = noop;
    }
    function move(x, y) {
      result[1].push([x, y]);
      ctx.lineTo(x, y);
      ctx.stroke();
    }
    var color = document.getElementById('color');
    color.onclick = function() {
      var c = prompt('Stroke color');
      ctx.strokeStyle = c;
    }
    var send = document.getElementById('send');
    send.onclick = function() {
      console.log(history);
      xhr = new XMLHttpRequest();
      xhr.open('POST', '/', true);
      xhr.setRequestHeader('Content-Type', 'application/json');
      xhr.send(JSON.stringify(history));
    }
  } 
  </script>
<body>
<canvas id="c" width="600" height="400"></canvas><br />
<input type="button" id="color" value="color"></input>
<input type="button" id="send" value="send"></input>
</body>
</html>

Node.js側のコード

var express = require('express')
  , fs = require('fs')
  , Canvas = require('canvas')
  , canvas = new Canvas(600, 400)
  , ctx = canvas.getContext('2d');

var app = express.createServer();
app.use(express.bodyParser());
app.get('/', function(req, res) {
  fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, text){
      res.send(text);
  });
});

app.post('/', function(req, res) {
  console.log(req.body);
  ctx.fillStyle = '#fff';
  ctx.fillRect(0,0,600,400);
  var history = req.body;
  for (var i in history) {
    var result = history[i];
    ctx.beginPath();
    ctx.strokeStyle =  result[0];
    for (var j in result[1]) {
      var pos = result[1][j];
      ctx.lineTo(pos[0], pos[1]);
    }
    ctx.stroke();
  }
  var out = fs.createWriteStream(__dirname + '/test.png')
    , stream = canvas.createPNGStream();
  stream.on('data', function(chunk) {
    out.write(chunk);
  });
  canvas.toBuffer();
});

app.listen(3000);

いや、もっと奇麗なコードだったと思うんだけど。

インストールしたとは以下の通り。expressはnode.jsのwebフレームワーク。canvasってのがサーバサイドでHTML5canvas?を使えるようにするやつ。cairoってのはcanvasをインストールするのに必要だった。なぜかこれのインストールではまった。はじめbrewで入れようとしたんだけどうまく行かなくて、この前削除したMac portで試してたんだけどそれでもうまくいかなかったんだけど、portをselfupdateしたあとにもう一回インストールしたらなんとかうまくいった。

$ npm install express
$ sudo port install cairo
$ npm install canvas