用SignalR实现的共享画板例子
使用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实现的共享画板例子的更多相关文章
- [置顶]
MVC中使用signalR入门教程
一.前言:每次写总要说一点最近的感想 进入工作快半年了,昨天是最郁闷的一天,我怀疑我是不是得了"星期一综合征",每个星期一很没有状态.全身都有点酸痛,这个可能一个星期只有周末才打一 ...
- OpenMP共享内存并行编程详解
实验平台:win7, VS2010 1. 介绍 平行计算机可以简单分为共享内存和分布式内存,共享内存就是多个核心共享一个内存,目前的PC就是这类(不管是只有一个多核CPU还是可以插多个CPU,它们都有 ...
- http与websocket(基于SignalR)两种协议下的跨域基于ASP.NET MVC--竹子整理
这段时间,项目涉及到移动端,这就不可避免的涉及到了跨域的问题.这是本人第一次接触跨域,有些地方的配置是有点麻烦,导致一开始的不顺. 至于websocket具体是什么意义,用途如何:请百度. 简单说就是 ...
- SAP内存/ABAP内存/共享内存区别
(1).读取和使用方法不同SAP内存使用SET/GET parameters方法:SET PARAMETER ID 'MAT' field p_matnr.GET PARAMETER ID 'MAT' ...
- 【转】七个例子帮你更好地理解 CPU 缓存
我的大多数读者都知道缓存是一种快速.小型.存储最近已访问的内存的地方.这个描述相当准确,但是深入处理器缓存如何工作的"枯燥"细节,会对尝试理解程序性能有很大帮助. 在这篇博文中,我 ...
- 读书笔记-----Java并发编程实战(二)对象的共享
public class NoVisibility{ private static boolean ready; private static int number; private static c ...
- 转:Spring-session & redis 子域名共享session
Spring-session & redis 子域名共享session 例子: a.example.com b.example.com spring 版本 4.2.6.RELEASE Spri ...
- .net core 使用SignalR实现实时通信
这几天在研究SignalR,网上大部分的例子都是聊天室,我的需求是把服务端的信息发送给前端展示.并且需要实现单个用户推送. 用户登录我用的是ClaimsIdentity,这里就不多解释,如果不是很了解 ...
- pipeline 共享库
目录 一.简介 二.共享库扩展 共享库使用 共享库结构 pipeline模板 一些小问题 三.共享库例子 使用公共变量 使用共享库的src方法 使用共享库的vars方法 四.插件实现pipeline ...
随机推荐
- python入门到精通[三]:基础学习(2)
摘要:Python基础学习:列表.元组.字典.函数.序列化.正则.模块. 上一节学习了字符串.流程控制.文件及目录操作,这节介绍下列表.元组.字典.函数.序列化.正则.模块. 1.列表 python中 ...
- Slackware Linux or FreeBSD 配置中文环境。
配置中文环境. Slackware Linux 如果在控制面板的语言与地区选项中没有找到中文,那说明在安装系统选择软件的时候没有将国际语言支持包选上,可以从slackware的安装盘或ISO文件中提取 ...
- Android 自定义 view(三)—— onDraw 方法理解
前言: 上一篇已经介绍了用自己定义的属性怎么简单定义一个view<Android 自定义view(二) -- attr 使用>,那么接下来我们继续深究自定义view,下一步将要去简单理解自 ...
- 解决:IntelliJ IDEA 编译错误,提示 Compilation failed: internal java compiler error
原因可能是项目指定的JDK与当前环境JDK不符合,解决办法:File->Setting->Compiler->Java Compiler, 在相应的module中选择合适的JDK版本 ...
- Markdown语法说明(详解版)
####date: 2016-05-26 20:38:58 tags: Markdown tags && Syntax ##Markdown语法说明(详解版)杨帆发表于 2011-11 ...
- NDK开发-零散知识点整理
JavaVM 标准Java平台下,每一个Process可以产生很多JavaVM对象,但在Android平台上,每一个Process只能产生一个Dalvik VM对象,也就是说在Android进程中是通 ...
- HTML5探秘:用requestAnimationFrame优化Web动画
本文转载自: HTML5探秘:用requestAnimationFrame优化Web动画
- mysql 每秒钟查询次数、插入次数、删除次数、更新次数的统计
-show global status where Variable_name in('com_select','com_insert','com_delete','com_update'); 查询出 ...
- AngularJs的UI组件ui-Bootstrap---tabs控件
tabs控件使用uib-tabset指令和uib-tab指令,效果是这样的: <!DOCTYPE html> <html ng-app="ui.bootstrap.demo ...
- jQuery使用serialize()表单序列化时出现中文乱码问题&js获取url中的参数,并保证获取到的参数不乱码
序列化中文时之所以乱码是因为.serialize()调用了encodeURLComponent方法将数据编码了 解决方法就是进行解码 原因:.serialize()自动调用了encodeURIComp ...