kagamihogeの日記

kagamihogeの日記です。

GlassFish 4のWebSocket + html5 canvasで共有ホワイトボード


引き続きGlassFish 4で遊ぶため、WebSocketでお絵かきチャット的なアレを作る。

やったこと

まずNetBeansとGlassFishを使ってJavaEE7のWebSocketを遊ぶ。あとAWSでデプロイとか。 - Yuji Blogを読んでWebSocketの基本的なことを確認しておく。

archetypeでwebapp-javaee7を選んでプロジェクトを作る。

Play FrameworkのWebSocket + html5 canvasで共有ホワイトボード - kagamihogeのblogからhtmlの部分をコピーしてくる。WebSocketに渡すURLの部分を適当なものに書き換える。あとはそのまんま。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>title</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
    $(function() {
        var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket;
        var socket = new WS("ws://localhost:8080/glassfish4websocket/sharedwhiteboard");
        socket.onmessage = function(event) {
            var data = JSON.parse(event.data);
            drawWhiteboard(data.x, data.y, "#CC0000");
        }

        var isMousedrag = false;
        $("#whiteboardcanvas").mousedown(function(event) {
            isMousedrag = true;
        });
        $("#whiteboardcanvas").mousemove(function(e) {
            if (!isMousedrag) {
                return;
            }
            var rect = e.target.getBoundingClientRect();
            mouseX = e.clientX - rect.left;
            mouseY = e.clientY - rect.top;

            drawWhiteboard(mouseX, mouseY, "#000000");

            socket.send(JSON.stringify({
                x : mouseX,
                y : mouseY
            }));
        });

        function drawWhiteboard(x, y, fillStyle) {
            var c = document.getElementById('whiteboardcanvas');
            var boardctx = c.getContext('2d');
            boardctx.beginPath();
            boardctx.fillStyle = fillStyle;
            boardctx.arc(x, y, 3, 0, Math.PI * 2, false);
            boardctx.fill();
        }

        $("#whiteboardcanvas").mouseup(function(event) {
            isMousedrag = false;
        });
        $("#whiteboardcanvas").mouseout(function(event) {
            isMousedrag = false;
        });
    })
</script>
</head>
<body>
    <canvas id="whiteboardcanvas" width="1400" height="140"></canvas>
</body>
</html>

Java側を作る。基本的には、座標の入ったテキストメッセージ({x:10, y:20}みたいなの)を送り返すだけ。あと、自分自身には送り返さない。

package glassfish4websocket;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/sharedwhiteboard")
public class SharedWhiteBoard {
    
    private static Set<Session> sessionSet = Collections
            .synchronizedSet(new HashSet<Session>());

    @OnOpen
    public void open(Session session){sessionSet.add(session); }

    @OnClose
    public void close(Session session){sessionSet.remove(session); }

    @OnMessage
    public void onMessage(String message, Session session) {
        for(Session s : sessionSet){
            if (session == s) {
                continue;
            }
            s.getAsyncRemote().sendText(message);
        }
    }
}