canvas+WebSocket(node.js)で画像にポインタを表示する[Firefox限定]
canvas上でマウスクリックしたポインタと背景画像を画像合成して,
WebSocketで送信するサンプルアプリを作成しました.
とりあえずFirefox限定です.
Chromeだと合成した画像が表示されません.
StackOverFlowでimg.onload = function() {}でイケると書いてありましたが,
動きませんでした.
- 参考にしたサイト
- https://github.com/einaros/ws
- http://www.osaka3t.com/socket/realtime.html
- http://nigohiroki.hatenablog.com/entry/2013/01/04/025502
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
- http://blog.agektmr.com/2013/09/canvas-png-blob.html
- http://d.hatena.ne.jp/miruto824/20110527/1306472982
動作
- クライアント画面のcanvas上でマウスクリックをするとjpegの背景画像と,ポインタを表示する
- マウスクリックをトリガに背景画像とポインタを合成して,WebSocketサーバに送信する
- WebSocketサーバは受信した画像を全クライアントへブロードキャストする
- 全クライアントからポインタ情報を送信可能
構成
- WebSocketサーバ:node.js + ws
- HTTPサーバ:node.js + express
WebSocketサーバ(localhost:8080) <-> Clients(Firefox) <-> HTTPサーバ(localhost:8080)
実行手順
- コードを以下の通り配置する
/hoge SampleWebSocketServer.js SimpleWebSocketServer.js /hoge/public SampleWebSocketCanvasClient.html backgtround.jpg
- 2つのコンソールで以下を実行する
node SimpleWebSocket.js node SimpleWebServer.js
Code
SimpleWebServer.js(HTTPサーバ)
var express = require("express"), app = express(); app.configure(function() { app.use(express.static(__dirname + "/public")); }); app.use(express.logger("dev")); app.listen(8000);
SampleWebSocketServer.js(WebSocketサーバ)
var WebSocketServer = require("ws").Server; var clients = []; function initialize() { wss = new WebSocketServer({port:8080}); wss.on("connection", function(ws) { clients.push(ws); ws.on("message", function(data, flags) { var type; // Check binary if(flags.binary) { console.log("binary"); type = "binary"; broadcast(data, flags.binary); } else { console.log("text"); type = "text"; broadcast(data. flags.binary); } }); // Broadcast function broadcast(data, flag) { clients.forEach(function (client, i) { client.send(data, {binary:flag, mask:false}); }); } ws.on("close", function() { console.log("disconnected"); clients = clients.filter(function (client) { return (client === ws) ? false : true; }); }); }); } initialize();
SampleWebSocketCanvasClient.html(クライアント)
<!DOCTYPE HTML> <html lang="ja-JP"> <head> <meta charset="UTF-8"> <script type="text/javascript"> // constant var canvasFrameEndX = 300; var canvasFrameEndY = 300; // canvas var canvas; var context; var saveImage; // global variables var img; var host = "ws://localhost:8080"; var ws = new WebSocket(host); function initialize() { // DOM img = document.getElementById("img"); canvas = document.getElementById("canvas"); // Canvas context context = canvas.getContext("2d"); // 画像の読み込み canvas.addEventListener('mousedown', function(e) { clear(); var x; var y; if(e.hasOwnProperty("offsetX")) { x = e.offsetX; y = e.offsetX; } else { // for Firefox x = e.layerX; y = e.layerY; } draw(x, y); }, false); // Canvas context.strokeStyle = '#FF0000'; context.lineWidth = 5; context.strokeStyle =""; // WebSocket ws.onopen = function() { console.log("WebSocket connect"); ws.onmessage = function(e) { if(e.data instanceof Blob) { console.log("blob"); img.src = (URL || WebKit).createObjectURL(e.data); } else if(typeof e.data === "string") { console.log("string"); console.log(e.data); } }; }; } function clear() { context.clearRect(0, 0, canvasFrameEndX, canvasFrameEndY); } function draw(x, y) { var background = new Image(); background.src = "background.jpg"; background.onload = function() { // img.onloadに入れても動かない }; context.drawImage(background, 0, 0); context.strokeRect(x, y, 50, 50); /*** canvas に絵を書くコード ***/ var type = 'image/png'; // canvas から DataURL で画像を出力 var dataurl = canvas.toDataURL(type); // DataURL のデータ部分を抜き出し、Base64からバイナリに変換 var bin = atob(dataurl.split(',')[1]); // 空の Uint8Array ビューを作る var buffer = new Uint8Array(bin.length); // Uint8Array ビューに 1 バイトずつ値を埋める for (var i = 0; i < bin.length; i++) { buffer[i] = bin.charCodeAt(i); } // Uint8Array ビューのバッファーを抜き出し、それを元に Blob を作る var blob = new Blob([buffer.buffer], {type: type}); //console.log(blob); ws.send(blob); } window.addEventListener("load", initialize, false); </script> <title>canvas sample</title> <style type="text/css"> #canvasdiv { width: 300px; border-style: solid; border-color: green; } #canvas { width: 300px; border-style: solid; border-color: red; } #recieveimage { width: 300px; border-style: solid; border-color: blue; } </style> </head> <body> <div id="canvasdiv"> <canvas id="canvas" width="300px" height="300px"></canvas> </div> overlay <div id="recieveimage"> <img src="data:image/jpeg,base64" id="img" width="300px"/> </div> </body> </html>