使用HTML5的canvas画布功能,在页面进行绘画,然后通过SignalR将画布的每个点的颜色提交到服务端,服务端同时将这些画布的信息推送到其他客户端,实现共享同一个画板的功能

类似下图,在某一个浏览器进行绘画,其他浏览器同步显示内容,并且页面刷新或者首次加载还能显示之前的绘画内容(站点不重启的情况下)

实现过程

一、服务端

服务端的代码主要功能是接收客户端发送过来的绘画坐标点和坐标点的颜色,同时将新的坐标点信息推送给客户端,最后服务端还会保存这些绘画坐标点信息到内存中,这样客户端刷新或者首次进入就能看到之前的绘画信息。

step1:

创建一个Empty类型的ASP.NET 4.5的站点

step2:

引入SignalR的nuget包,将自动引入相关的关联包

Install-Package Microsoft.AspNet.SignalR

step3:

新建一个SignalR Hub Class

实现代码如下:

public class DrawingBoard : Hub
{
private const int BoardWidth = ;
private const int BoardHeight = ;
private static int[,] _pointBuffer = GetEmptyPointBuffer(); public Task DrawPoint(int x, int y)
{
if (x < )
{
x = ;
}
if (x >= BoardWidth)
{
x = BoardWidth - ;
}
if (y <)
{
y = ;
}
if (y >= BoardHeight)
{
y = BoardHeight - ;
}
int color = ;
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;
}
}

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

完整代码下载

用SignalR实现的共享画板例子的更多相关文章

  1. [置顶] MVC中使用signalR入门教程

    一.前言:每次写总要说一点最近的感想 进入工作快半年了,昨天是最郁闷的一天,我怀疑我是不是得了"星期一综合征",每个星期一很没有状态.全身都有点酸痛,这个可能一个星期只有周末才打一 ...

  2. OpenMP共享内存并行编程详解

    实验平台:win7, VS2010 1. 介绍 平行计算机可以简单分为共享内存和分布式内存,共享内存就是多个核心共享一个内存,目前的PC就是这类(不管是只有一个多核CPU还是可以插多个CPU,它们都有 ...

  3. http与websocket(基于SignalR)两种协议下的跨域基于ASP.NET MVC--竹子整理

    这段时间,项目涉及到移动端,这就不可避免的涉及到了跨域的问题.这是本人第一次接触跨域,有些地方的配置是有点麻烦,导致一开始的不顺. 至于websocket具体是什么意义,用途如何:请百度. 简单说就是 ...

  4. SAP内存/ABAP内存/共享内存区别

    (1).读取和使用方法不同SAP内存使用SET/GET parameters方法:SET PARAMETER ID 'MAT' field p_matnr.GET PARAMETER ID 'MAT' ...

  5. 【转】七个例子帮你更好地理解 CPU 缓存

    我的大多数读者都知道缓存是一种快速.小型.存储最近已访问的内存的地方.这个描述相当准确,但是深入处理器缓存如何工作的"枯燥"细节,会对尝试理解程序性能有很大帮助. 在这篇博文中,我 ...

  6. 读书笔记-----Java并发编程实战(二)对象的共享

    public class NoVisibility{ private static boolean ready; private static int number; private static c ...

  7. 转:Spring-session & redis 子域名共享session

    Spring-session & redis 子域名共享session 例子: a.example.com b.example.com spring 版本 4.2.6.RELEASE Spri ...

  8. .net core 使用SignalR实现实时通信

    这几天在研究SignalR,网上大部分的例子都是聊天室,我的需求是把服务端的信息发送给前端展示.并且需要实现单个用户推送. 用户登录我用的是ClaimsIdentity,这里就不多解释,如果不是很了解 ...

  9. pipeline 共享库

    目录 一.简介 二.共享库扩展 共享库使用 共享库结构 pipeline模板 一些小问题 三.共享库例子 使用公共变量 使用共享库的src方法 使用共享库的vars方法 四.插件实现pipeline ...

随机推荐

  1. 18.有一个网页地址, 比如PHP开发资源网主页: http://www.phpres.com/index.html,如何得到它的内容?

    方法1(对于PHP5及更高版本): $readcontents = fopen("http://www.phpres.com/index.html", "rb" ...

  2. windows 下编辑shell,到linux报错,也是windows换行等造成

    sed -i 's/\r$//' shell.sh 然后linux 下就不会报语法错误了.

  3. NDK开发历程(一):android native code的调试方法

    引用:http://www.cnblogs.com/ychellboy/archive/2013/02/22/2922683.html 使用NDK在android上做开发是一件“痛并快乐着”的差事,之 ...

  4. 通过代码获取res里生成R.java中的值

    引用:http://my.eoe.cn/blue_rain/archive/552.html 有的时候我们生成库文件,需要在里面加入一些UI,并提供出一些xml的资源,那如何在其他项目中使用呢? 我们 ...

  5. html5,音频代码

    <!-- <audio src="1.mp3" controls="controls"></audio> -->    &l ...

  6. 构建简单的Maven工程,使用测试驱动的方式开发项目

    构建简单的Maven工程很简单,这里写这篇随笔的原因是希望自己能记住几个小点. 一.安装Maven 1.下载maven:https://maven.apache.org/download.cgi 2. ...

  7. Nop源码分析三

    程序的初始化工作和Ioc工作已经做完,nop默认引擎已经初始化. 下面在回到global文件的启动方法Application_Start()中, 1,继续分析下面的代码: var dependency ...

  8. phpcms V9 栏目管理

    关于phpcms V9框架系统后台管理之栏目管理,请参见下文的源码分析(添加栏目和修改栏目): 参照添加栏目的界面图示,便于对源代码的理解: <?php // 文件路径:phpcms/modul ...

  9. vc6 使用的那些事

    VC6.0中Release下调试模式设置 http://blog.csdn.net/wangqinghao/article/details/7730428

  10. Java数据结构之表的增删对比---ArrayList与LinkedList之一

    一.Java_Collections表的实现 与c不同Java已经实现并封装了现成的表数据结构,顺序表以及链表. 1.ArrayList是基于数组的实现,因此具有的特点是:1.有索引值方便查找,对于g ...