js实现多人实时共享白板

js实现多人实时共享白板

js实现多人实时共享白板

在视频会议和远程一对一教学的过程中,我们经常要用到白板功能,大家打开白板页面,在白板上板书或标注,其他人都能看到,实时交互,以前要实现这个功能,要不安装一个软件,要不用flash实现,现在html5的发布,websocket的兴起,这个技术通过js就能实现,下面我们来演示讲解一下

一、对人共享白板原理

js中通过canvas将鼠标或手写板进行绘制,并将绘制的数据以对象的形式通过websocket实时发送到其他人的电脑canvas,就实现了白板共享了。

二、js白板插件

推荐canvas-designer-widget白板插件,支持铅笔、彩笔、橡皮擦、图片、pdf文件、移动、文字、放大缩小等功能,很强大,非常好用。代码如下,可以点右上角在线直接运行html代码预览。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>BFW NEW PAGE</title>
    <script id="bfwone" type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/bfwone.js"></script>
    <script type="text/javascript">
        bready(function() {
            use(["canvas-designer-widget"], function() {
                var designer = new CanvasDesigner();
                // both links are mandatory
                // widget.html will internally use widget.js
                designer.widgetHtmlURL = 'http://repo.bfw.wiki/bfwrepo/html/widget.html'; // you can place this file anywhere
                designer.widgetJsURL = 'http://repo.bfw.wiki/bfwrepo/js/widget.js'; // you can place this file anywhere
                designer.setSelected('pencil');
                designer.setTools({
                    pencil: true,
                    text: true,
                    image: true,
                    pdf: true,
                    eraser: true,
                    line: true,
                    arrow: true,
                    dragSingle: true,
                    dragMultiple: true,
                    arc: true,
                    rectangle: true,
                    quadratic: true,
                    bezier: true,
                    marker: true,
                    zoom: true,
                    lineWidth: true,
                    colorsPicker: true,
                    extraOptions: true,
                    code: true,
                    undo: true
                });
                designer.appendTo(document.getElementById("board"));
            });
        });
    </script>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
    </style>
</head>
<body>
    <div id="board" style="width:100vw;height:100vh;"></div>
</body>
</html>

三、websocket共享

后端我们选用workerman,新建WsboardServer.php,代码如下

<?php
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Worker;
require_once __DIR__ . '/Autoloader.php';
$users = [];
// 创建一个Worker监听8088端口,使用websocket协议通讯
$ws_worker = new Worker("websocket://0.0.0.0:8089");

// 启动4个进程对外提供服务
$ws_worker->count = 4;
// 当收到客户端发来的数据后
$ws_worker->onConnect=function($connection){
    $_key = $connection->getRemoteIp() . $connection->getRemotePort();
    global $users;
    if (!isset($users[$_key])) {
        $users[$_key] = $connection;
    }
};
// 当收到客户端发来的数据后
$ws_worker->onMessage = function ($connection, $data) {
    $_key = $connection->getRemoteIp() . $connection->getRemotePort();

    global $users;
    if (!isset($users[$_key])) {
        $users[$_key] = $connection;
    }
    foreach ($users as $key => $user) {
        if ($key != $_key) {
            echo "send data";
            $user->send($data);
        }
    }

    // 设置连接的onClose回调
    $connection->onClose = function ($connection) // 客户端主动关闭
{
        $_key = $connection->getRemoteIp() . $connection->getRemotePort();
        global $users;

        if (isset($users[$_key])) {

            unset($users[$_key]);
        }

        echo "connection closed\n";
    };
};

// 运行worker
Worker::runAll();

1将websocket服务启动起来php WsboardServer.php start

前端html代码如下

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>BFW NEW PAGE</title>
    <script id="bfwone" type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/bfwone.js"></script>
    <script type="text/javascript">
        bready(function() {
            use(["canvas-designer-widget"], function() {

                var websocket = new WebSocket("ws://web.debug.only.bfw.wiki:8089");
                var designer = new CanvasDesigner();
                var olddata = null;



                // both links are mandatory
                // widget.html will internally use widget.js
                designer.widgetHtmlURL = 'http://repo.bfw.wiki/bfwrepo/html/widget.html'; // you can place this file anywhere
                designer.widgetJsURL = 'http://repo.bfw.wiki/bfwrepo/js/widget.js'; // you can place this file anywhere
                websocket.onopen = function() {
                    if (designer.pointsLength > 0) {
                        // you seems having data to be synced with existing users!
                        designer.sync();
                    }
                };

                websocket.onmessage = function(event) {
                    if (olddata != event.data) {
                        console.log("not same");
                        designer.syncData(JSON.parse(event.data));
                        olddata = event.data;
                    }

                };

                designer.addSyncListener(function(data) {

                    var comedata = JSON.stringify(data);
                    if (olddata != comedata) {

                        olddata = comedata;

                        console.log("not the same");
                        websocket.send(comedata);

                    }

                });

                designer.setSelected('pencil');

                designer.setTools({
                    pencil: true,
                    text: true,
                    image: true,
                    pdf: true,
                    eraser: true,
                    line: true,
                    arrow: true,
                    dragSingle: true,
                    dragMultiple: true,
                    arc: true,
                    rectangle: true,
                    quadratic: true,
                    bezier: true,
                    marker: true,
                    zoom: true,
                    lineWidth: true,
                    colorsPicker: true,
                    extraOptions: true,
                    code: true,
                    undo: true
                });

                designer.appendTo(document.getElementById("board"));

                setInterval(function() {
                    console.log("update");
                    designer.sync();
                },
                    3000);





            });
        });
    </script>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
    </style>
</head>
<body>
    <div id="board" style="width:100vw;height:100vh;"></div>
</body>
</html>

好了,就这样实现了一个多人实时共享白板和画板效果。


{{collectdata}}

网友评论0