用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 = 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;
        }
    }

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

完整代码下载

时间: 2024-11-10 16:49:57

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

画板例子实现

画板例子思路 步骤一:自定义一个画板视图 步骤二:监听手指触摸事件,当手指在视图滑动的时候,就画线. 2.1在手指开始触摸的时候,创建可变路径,并且设置路径起始点. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:self]; SUNBezierPath *pa

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

1 public class NoVisibility{ 2 private static boolean ready; 3 private static int number; 4 private static class ReaderThread extends Thread{ 5 public void run(){ 6 while(!ready) 7 Thread.yield(); 8 System.out.println(number); 9 } 10 } 11 12 public s

Asp.net MVC4 + signalR 聊天室实现

之前介绍了ServiceBus + SignalR的聊天室设计:http://blog.csdn.net/lan_liang/article/details/46480529 如果还没有Azure账号,可以先完成SignalR的实现,这个例子容易上手一些. 如果要了解Service Bus,可以参照这里: https://azure.microsoft.com/en-gb/documentation/articles/service-bus-dotnet-how-to-use-queues/ 这

画板笔记应用项目源码iPad版

一款功能强大的iPad画板笔记应用源码,也可以支持wifi共享与云同步一款功能强大的iPad画板笔记应用源码1.以略缩图列表的形式显示画板2.可以添加5种风格的画板‘3.通过wifi共享画板4.支持云同步5.支持对所有画板及画板里面写入的text文本进行全局搜索6.强大的编辑功能,支持批量复制,批量删除,批量上传7.支持向画板添加:便签板,文本区域,行,形状,图片8.支持手写,对画笔的颜色,粗细进行调整9.支持将正在编辑的画板储存为模版10.支持以PDF,图片存储在本地(使用itunes可以导出

多线程(多窗口卖票例子)

实现多线程的方式: 实现多线程的方式有多种,这里只列举两种常用的,而第一种继承Thread的方式无法实现多窗口卖票. 一,继承Thread方式: 特点:多线程多实例,无法实现资源的共享. 例子: 1 package com.demo.study.multithreading; 2 3 public class MyThread extends Thread{ 4 5 private int i = 10; 6 // 可以自行定义锁,也可以使用实例的锁 7 Object mutex = new O

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

这几天在研究SignalR,网上大部分的例子都是聊天室,我的需求是把服务端的信息发送给前端展示.并且需要实现单个用户推送. 用户登录我用的是ClaimsIdentity,这里就不多解释,如果不是很了解,可以看这篇文章https://www.cnblogs.com/zhangjd/p/11332558.html 推荐https://www.cnblogs.com/laozhang-is-phi/p/netcore-vue-signalr.html#tbCommentBody这个博客,写的很详细,并

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

这段时间,项目涉及到移动端,这就不可避免的涉及到了跨域的问题.这是本人第一次接触跨域,有些地方的配置是有点麻烦,导致一开始的不顺. 至于websocket具体是什么意义,用途如何:请百度. 简单说就是建立一个基于互联网的实时通信. 在这里整理下这些内容,方便日后回顾. 一:介绍了WebSocket下的基于SignalR的跨域与不跨域例子 二:简单介绍了Http下的跨域问题 Ⅰ.WebSocket下的跨域 如果使用原生的方法来开发WebSocket应用,还是比较复杂的,不过好在Asp.net给我们

Android 学习笔记之ContentProvider实现数据共享....

PS:最近听老师说打算让我参与企业的app制作,让我加快学习的进度...好吧,貌似下周还有考试...貌似实验室这个app也要做...暂时不管了...那就只能加快进度了,感觉略微的有点激动和紧张,总算是可以开始对项目进行着手操作了...学的东西还是很少,还要继续努力啊...搞定Android的网络通信后就可以正式的进入项目开发了...不说废话了... 学习内容: 1.使用ContentProvider存储数据 2.操作联系人的ContentProvider... 3.多媒体信息的ContentPr

Qt Quick应用开发介绍 13 (JavaScript)

Chapter13 Annexure: JavaScript Language Overview 附录: JavaScript语言概览 Js语言总览; 提供一个Qt支持的所有语言特性的概览; 通过本文了解Js语言的基本特性; 特别是当你开始学习一个相关的技术, 如QML时, 你可以在这获得帮助; 这篇文章是对 JavaScript Language Overview http://qt-project.org/wiki/JavaScript 的轻微改动版本; 内容经过Qt4.8和QtQuick1