刚出炉的 Nodejs 多人多房间在线画板

刚出炉的 Nodejs 多人多房间在线画板

  1. 效果见http://banling.com/weixin/draw/
    2.前几天群里见这个坐着发了这个东东, 蛮好玩, 貌似可以做个你画我猜的游戏, 本着html开源的精神, 我就把前端的html和js全扒下来了, 请作者见谅,^_^ .
  2. 根据前端 js代码的提示, 把服务器代码补充完了,代码如下, 服务器端很简单, 感觉还是前端难点,
/**
 * Module dependencies.
 */

var express = require(‘express’); var routes = require(’./routes’); var user = require(’./routes/user’); var http = require(‘http’); var path = require(‘path’);

var sio = require(‘socket.io’);

var app = express();

// all environments app.set(‘port’, process.env.PORT || 3000); app.set(‘views’, path.join(__dirname, ‘views’)); //app.set(‘view engine’, ‘jade’); app.set(‘view engine’, ‘ejs’); app.use(express.favicon()); //app.use(express.logger(‘dev’)); app.use(express.json()); app.use(express.urlencoded()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, ‘public’)));

// development only if (‘development’ == app.get(‘env’)) { app.use(express.errorHandler()); }

app.get(’/’, routes.index); app.get(’/users’, user.list); app.get(’/opt’, routes.opt)

var server = http.createServer(app).listen(app.get(‘port’), function(){ console.log('Express server listening on port ’ + app.get(‘port’)); });

var io = sio.listen(server); var roomList = {}; var socketMap = {};

io.on(‘connection’, function(socket){

//create a room
socket.on('iJoin', function(data){
    var roomid = data.room;
    var user = {
        id: socket.id,
        ip:socket.handshake.address,
        cname: ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).slice(-6)
    }

    console.log(user);

    //把socket 加入房间
    socket.join(roomid);
    socket['roomid'] = roomid;
    socketMap[socket.id] = socket;

    var sid = user.id;

    //假如room已经存在,则添加,不存在,则创建
    if(in_array(roomList, roomid)){
        roomList[roomid][sid] = user;
    }else {
        roomList[roomid] = {};
        roomList[roomid][sid] = user;
    }

    console.log('^^^^^^^^^^^^^^^^^^')
    console.log(roomList)

    var data = {
        'members':roomList[roomid],
        'user':user
    }
    //给群里所有人广播
    setTimeout(function () {
        socket.broadcast.in(roomid).emit('userIn', data);
        socket.emit('userIn', data);
        console.log('shit    .....')
    }, 500)



})

//客户端该名称
socket.on('setNickname', function(nickname){
    var roomid = socket['roomid'];
    roomList[roomid][socket.id]['cname'] = nickname;
    var user = {
        id: socket.id,
        cname: nickname
    }
    console.log('setNickname .................')
    console.log(roomList)
    socket.broadcast.to(socket.roomid).emit('shake hands', user);
})


socket.on('disconnect', function(){
    var user = {
        id: socket.id,
        ip:socket.handshake.address,
        cname: roomList[roomid][socket.id]['cname']
    }

    var roomid = socket['roomid'];
    delete roomList[roomid][socket.id];

    socket.broadcast.to(socket.roomid).emit('userOut', user);
})

socket.on('say msgs', function(data){
    console.log('say msg..............')
    console.log(data)
    if(data.id){
        var msg = {
            to:data.id,
            id: socket.id,
            txt:data.say
        }
        socketMap[data.id].emit('say msg', msg);
    }else{
        var msg = {
            id: socket.id,
            txt:data.say
        }
        socket.broadcast.in(socket.roomid).emit('say msg', msg);
    }
})

socket.on('drawClick', function(data){
    socket.broadcast.in(socket.roomid).emit('draw', data.data);
})

})

function in_array(arr, str){ for(var index in arr){ if(index == str){ return true; } } return false; }


7 回复

刚出炉的 Nodejs 多人多房间在线画板

效果演示

访问 在线画板 查看效果。

前言

前几天在群里看到有人分享了一个在线画板的小项目,感觉挺有趣的。于是就决定尝试一下,看看能不能实现一个多人多房间的在线画板,并且能够应用于你画我猜等游戏。为了方便学习和研究,我把前端的HTML和JS代码扒了下来,希望能对大家有所帮助。

服务器端代码

根据前端的JS代码提示,我补充完成了服务器端的代码。整体来说,服务器端的逻辑相对简单,主要通过Socket.IO实现了房间管理和消息广播。以下为服务器端的主要代码:

/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');

var sio = require('socket.io');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);
app.get('/opt', routes.opt);

var server = http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

var io = sio.listen(server);
var roomList = {};
var socketMap = {};

io.on('connection', function(socket) {

    // 创建房间
    socket.on('iJoin', function(data) {
        var roomid = data.room;
        var user = {
            id: socket.id,
            ip: socket.handshake.address,
            cname: ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).slice(-6)
        };

        console.log(user);

        // 将socket加入房间
        socket.join(roomid);
        socket['roomid'] = roomid;
        socketMap[socket.id] = socket;

        var sid = user.id;

        // 如果房间已存在,则添加用户,否则创建新房间
        if (in_array(Object.keys(roomList), roomid)) {
            roomList[roomid][sid] = user;
        } else {
            roomList[roomid] = {};
            roomList[roomid][sid] = user;
        }

        console.log('^^^^^^^^^^^^^^^^^^');
        console.log(roomList);

        var data = {
            'members': roomList[roomid],
            'user': user
        };
        
        // 广播给房间内的所有用户
        setTimeout(function () {
            socket.broadcast.to(roomid).emit('userIn', data);
            socket.emit('userIn', data);
            console.log('shit    .....')
        }, 500);
    });

    // 设置昵称
    socket.on('setNickname', function(nickname) {
        var roomid = socket['roomid'];
        roomList[roomid][socket.id]['cname'] = nickname;
        var user = {
            id: socket.id,
            cname: nickname
        };
        console.log('setNickname .................');
        console.log(roomList);
        socket.broadcast.to(socket.roomid).emit('shake hands', user);
    });

    socket.on('disconnect', function() {
        var user = {
            id: socket.id,
            ip: socket.handshake.address,
            cname: roomList[socket['roomid']][socket.id]['cname']
        };

        var roomid = socket['roomid'];
        delete roomList[roomid][socket.id];

        socket.broadcast.to(roomid).emit('userOut', user);
    });

    socket.on('say msgs', function(data) {
        console.log('say msg..............');
        console.log(data);
        if (data.id) {
            var msg = {
                to: data.id,
                id: socket.id,
                txt: data.say
            };
            socketMap[data.id].emit('say msg', msg);
        } else {
            var msg = {
                id: socket.id,
                txt: data.say
            };
            socket.broadcast.to(socket.roomid).emit('say msg', msg);
        }
    });

    socket.on('drawClick', function(data) {
        socket.broadcast.to(socket.roomid).emit('draw', data.data);
    });
});

function in_array(arr, str) {
    for (var index in arr) {
        if (index === str) {
            return true;
        }
    }
    return false;
}

说明

  • 创建房间:当用户加入房间时,会触发iJoin事件,服务器将用户信息存储到房间列表中。
  • 设置昵称:用户可以通过setNickname事件来设置自己的昵称。
  • 断开连接:当用户离开时,会触发disconnect事件,从房间列表中移除用户信息并通知其他用户。
  • 发送消息:用户可以通过say msgs事件向其他用户发送文本消息。
  • 绘制操作:用户可以通过drawClick事件将绘制操作同步给其他用户。

以上就是本次项目的完整代码。希望这些代码对你有所帮助!


很有意思,32赞

Wonderful! 多谢分享~

有趣,赞!

我是做PC端画板软件的,其实我目前也在构思一个这样的项目(在线的互动白板) ,支持多人在线绘画,分享和讨论, 技术方向是选择 nodejs + sockio + fabric + expressJS不知道大家有什么看法或者建议,可以给我信息。

根据提供的代码,我们可以构建一个简单的多人多房间在线画板。以下是关键部分的解释和示例代码。

关键功能解释

  1. 连接处理

    • 当用户连接时,会触发connection事件。
    • 用户可以通过发送iJoin事件加入指定房间,并在房间中生成唯一的ID和昵称。
  2. 房间管理

    • 使用socket.join(roomid)方法将用户加入到指定的房间。
    • roomList对象用于存储每个房间的用户信息。
  3. 用户操作

    • 用户可以设置昵称(setNickname)。
    • 用户可以发送消息(say msgs)。
    • 用户可以在画板上绘制并共享给其他用户(drawClick)。

示例代码

// 创建HTTP服务器和Socket.IO实例
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

// 房间列表和用户映射
let roomList = {};
let socketMap = {};

// Socket.IO连接处理
io.on('connection', (socket) => {
    // 用户加入房间
    socket.on('iJoin', (data) => {
        const roomid = data.room;
        const user = {
            id: socket.id,
            ip: socket.handshake.address,
            cname: ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).slice(-6)
        };

        socket.join(roomid);
        socket['roomid'] = roomid;
        socketMap[socket.id] = socket;

        if (!roomList[roomid]) {
            roomList[roomid] = {};
        }
        roomList[roomid][socket.id] = user;

        const data = { members: roomList[roomid], user };
        setTimeout(() => {
            socket.broadcast.to(roomid).emit('userIn', data);
            socket.emit('userIn', data);
        }, 500);
    });

    // 设置昵称
    socket.on('setNickname', (nickname) => {
        const roomid = socket['roomid'];
        roomList[roomid][socket.id]['cname'] = nickname;
        const user = { id: socket.id, cname: nickname };
        socket.broadcast.to(socket.roomid).emit('shake hands', user);
    });

    // 用户断开连接
    socket.on('disconnect', () => {
        const roomid = socket['roomid'];
        const user = {
            id: socket.id,
            ip: socket.handshake.address,
            cname: roomList[roomid][socket.id]['cname']
        };
        delete roomList[roomid][socket.id];
        socket.broadcast.to(socket.roomid).emit('userOut', user);
    });

    // 发送消息
    socket.on('say msgs', (data) => {
        const msg = data.id ? 
                    { to: data.id, id: socket.id, txt: data.say } : 
                    { id: socket.id, txt: data.say };
        socketMap[data.id]?.emit('say msg', msg);
        socket.broadcast.to(socket.roomid).emit('say msg', msg);
    });

    // 绘制
    socket.on('drawClick', (data) => {
        socket.broadcast.to(socket.roomid).emit('draw', data.data);
    });
});

server.listen(3000, () => {
    console.log('Server is running on port 3000');
});

总结

这段代码展示了如何使用Node.js和Socket.IO实现一个简单的多人多房间在线画板。通过处理用户的连接、房间管理和各种操作,可以实现多人协同绘图的功能。

回到顶部