用SignalR實現的共享畫板例子


使用HTML5的canvas畫布功能,在頁面進行繪畫,然后通過SignalR將畫布的每個點的顏色提交到服務端,服務端同時將這些畫布的信息推送到其他客戶端,實現共享同一個畫板的功能

類似下圖,在某一個瀏覽器進行繪畫,其他瀏覽器同步顯示內容,並且頁面刷新或者首次加載還能顯示之前的繪畫內容(站點不重啟的情況下)

image

實現過程

一、服務端

服務端的代碼主要功能是接收客戶端發送過來的繪畫坐標點和坐標點的顏色,同時將新的坐標點信息推送給客戶端,最后服務端還會保存這些繪畫坐標點信息到內存中,這樣客戶端刷新或者首次進入就能看到之前的繪畫信息。

step1:

創建一個Empty類型的ASP.NET 4.5的站點

image

step2:

引入SignalR的nuget包,將自動引入相關的關聯包

Install-Package Microsoft.AspNet.SignalR

step3:

新建一個SignalR Hub Class

實現代碼如下:

public class DrawingBoard : Hub 
    { 
        private const int BoardWidth = 300; 
        private const int BoardHeight = 300; 
        private static int[,] _pointBuffer = GetEmptyPointBuffer();

        public Task DrawPoint(int x, int y) 
        { 
            if (x < 0) 
            { 
                x = 0; 
            } 
            if (x >= BoardWidth) 
            { 
                x = BoardWidth - 1; 
            } 
            if (y <0) 
            { 
                y = 0; 
            } 
            if (y >= BoardHeight) 
            { 
                y = BoardHeight - 1; 
            } 
            int color = 0; 
            int.TryParse(Clients.Caller.color, out color); 
            _pointBuffer[x, y] = color; 
            return Clients.Others.drawPoint(x, y, Clients.Caller.color); 
        }

        public Task Clear() 
        { 
            _pointBuffer = GetEmptyPointBuffer(); 
            return Clients.Others.clear(); 
        }

        public override Task OnConnected() 
        { 
            return Clients.Caller.update(_pointBuffer); 
        }

        private static int[,] GetEmptyPointBuffer() 
        { 
            var buffer = new int[BoardWidth, BoardWidth]; 
            return buffer; 
        } 
    }
View Code

step4:

新建一個startup類

public class Startup 
    { 
        public void Configuration(IAppBuilder app) 
        { 
            app.MapSignalR(); 
        } 
    }
Startup

到此完成服務端的功能實現

 

二、客戶端

step1:

客戶端的html頁面只需要定義一個canvas元素和一個清除畫布的按鈕

<!DOCTYPE html> 
<html> 
<head> 
    <title>在線畫板</title> 
    <meta charset="utf-8" /> 
    <style> 
        div{ 
            margin:3px; 
        } 
        canvas{ 
            border:2px solid #808080; 
            cursor:default; 
        } 
    </style> 
</head> 
<body> 
    <div> 
        <div> 
            <label for="color">Color:</label> 
            <select id="color"></select> 
        </div> 
        <canvas id="canvas" width="300" height="300"></canvas> 
        <div> 
            <button id="clear">Clear canvas</button> 
        </div> 
    </div> 
    <script src="/Scripts/jquery-1.6.4.min.js"></script> 
    <script src="/Scripts/jquery.signalR-2.2.0.min.js"></script> 
    <script src="/signalr/js"></script> 
    <script src="/Scripts/drawingboard.js"></script> 
</body> 
</html>
Html

step2:

在scripts目錄創建drawingboard.js文件,實現主要的畫布操作和SingalR事件綁定。

主要是綁定了canvas的mousemove事件,然后再mousemove事件中實現繪畫,同時將繪畫的信息發送服務器,客戶端同時接收服務端推送的繪畫信息,實時提現在本地的畫布中。

客戶端連接成功之后,會獲得從服務端推送的歷史繪畫信息,實現記載之前畫布的效果

$(function () { 
    // 畫布定義開始 
    var colors = ["black", "red", "green", "blue", "yellow", "magenta", "white"]; 
    var canvas = $("#canvas"); 
    var colorElement = $("#color"); 
    for (var i = 0; i < colors.length; i++) { 
        colorElement.append("<option value='" + (i + 1) + "'>" + colors[i] + "</option>"); 
    } 
    var buttonPressed = false; 
    canvas 
        .mousedown(function () { 
            buttonPressed = true; 
        }) 
        .mouseup(function () { 
            buttonPressed = false; 
        }) 
        .mousemove(function (e) { 
            if (buttonPressed) { 
                setPoint(e.offsetX, e.offsetY, colorElement.val()); 
            } 
        });

    var ctx = canvas[0].getContext("2d"); 
    function setPoint(x, y, color) { 
        ctx.fillStyle = colors[color - 1]; 
        ctx.beginPath(); 
        ctx.arc(x, y, 2, 0, Math.PI * 2); 
        ctx.fill(); 
    } 
    function clearPoints() { 
        ctx.clearRect(0, 0, canvas.width(), canvas.height()); 
    }

    $("#clear").click(function () { 
        clearPoints(); 
    }); 
    // 畫布定義結束

    // SignalR 客戶端代碼 
    var hub = $.connection.drawingBoard; 
    hub.state.color = colorElement.val(); 
    var connected = false;

    colorElement.change(function () { 
        hub.state.color = $(this).val(); 
    });

    canvas.mousemove(function (e) { 
        if (buttonPressed && connected) { 
            hub.server.drawPoint(Math.round(e.offsetX), Math.round(e.offsetY)); 
        } 
    });

    $("#clear").click(function () { 
        if (connected) { 
            hub.server.clear(); 
        } 
    });

    // 定義客戶端方法 
    hub.client.clear = function () { 
        clearPoints(); 
    };

    hub.client.drawPoint = function (x, y, color) { 
        setPoint(x, y, color); 
    };

    hub.client.update = function (points) { 
        if (!points) return; 
        var width = canvas.width(); 
        var height = canvas.height(); 
        for (var x = 0; x < width; x++) { 
            for (var y = 0; y < height; y++) { 
                var color = points[x][y]; 
                if (color > 0) { 
                    setPoint(x, y, color); 
                } 
            } 
        } 
    };

    $.connection.hub.start().done(function () { 
        connected = true; 
    }); 
})
drawingBoard

完整代碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM