前言
本来我做的这个简易聊天室程序是想上课堂展示的,但是这个idea和我的好朋友本门课程的大作业有一些相似,所以为了不尴尬,我就不上去展示。
我就展示给简书上面感兴趣的用户吧,希望大家能够欣赏,从中收获到一些东西。
整个项目的github地址
前端设计
对于前端的设计,这个真的是很考验一个人的审美观,我想我也很难讲明白,我就讲讲我的设计灵感吧。或许你能够从中受到一些启发,设计出更加出色的聊天室。
整个界面如图所示
对于整个聊天室的顶端,是一个仿Mac的设计,主要的作用是用来显示,当前聊天室的名称。其实,一开始我是没有想到这样的设计,但是我在观看socket.io官网主页的时候,发现这是一个不错的设计,所以我就提取了其中的html和css作为自己聊天室的顶部栏。
至于侧边栏显示当前用户的头像和昵称,我是借鉴了微信的设计,但是代码并没有抄微信的,而是根据这个排版,自己去设计。
至于在线人数的设计,我是参考了这个网站的设计MDBootstrap
, 我觉得这个框架是基于Bootstrap
进一步的美化,所有的控件我觉得都是做的非常好看,至少比Bootstrap
的好看,希望自己的网页炫酷的可以看看这个。
至于左边用户显示栏,一开始我想的是用<ul>
布局,后来觉得有点麻烦,还是改用<div>
布局吧。我觉得比较重要的一点就是关注用 float
来对齐,让某一个元素脱离文档流。
至于消息气泡的设计,就是一个圆角矩形 + 一个三角形,至于三角形的制作,就是将width
和 height
全部设为0, 通过设置 border
,设置一面有颜色,其余三面都是透明,就可以实现这个效果。
聊天的效果图
后端开发
后端的开发主要是 nodejs
+ angularjs
+ express
+ socket.io
其中 nodejs
主要用于服务端开发,angularjs
用于数据绑定,将更改后的数据快速映射到前端页面。socket.io
用于通信,消息传递。
其中,服务端开启监听端口,监听客户端的连接,每次监听到客户端的连接时,负责随机为用户生成一个昵称和头像,以及一个uid
用来标识用户。
服务端监听到客户端连接的代码如下:
socket.uid = uuidv4();
var userinfo = randomUserInfo();
socket.nickname = userinfo.nickname;
socket.avatar = userinfo.avatar;
connectedSockets[socket.uid] = socket;
userinfo.uid = socket.uid;
userinfo.tag = 'user';
userinfo.hasMessages = 0;
allUsers.push(userinfo);
socket.emit('accept', userinfo);
socket.broadcast.emit('userAdded', userinfo);
socket.emit("allUser", allUsers);
当服务器接收到发送消息的请求是,首先判断这个发送的消息是给特定的用户还是群聊消息,如果是特定的用户,只需要找到对应用户的socket
,即可发送相应的消息;如果是群聊消息,则需要将这条消息广播出去。
对应的代码如下:
socket.on('addMessage',function(data){ //有用户发送新消息
data.position = 'left';
if(data.to.tag === "user"){//发给特定用户
connectedSockets[data.to.uid].emit('messageAdded',data);
}else{//群发
socket.broadcast.emit('messageAdded',data);//广播消息,除原发送者外都可看到
}
});
客户端要做的就是,当用户点击发送按钮,或者按下回车键之后,构造发送的消息,消息的字段包括了发送者,接收者,发送内容,消息的显示位置等信息。
还有就是判断当前的是否是群聊,如果是群聊,则需要将消息广播出去。
具体实现的代码如下:
$scope.postMessage = function() {
var msg = {
content: $scope.chatContent,
from: $scope.self,
to: $scope.receiver,
type: "normal",
position: 'right',
time : new Date()
};
if(msg.content.length === 0) return; // 内容为空
var rec = $scope.receiver;
if (rec.tag === "user") { //私信
if (!$scope.privateMessages[rec.uid]) {
$scope.privateMessages[rec.uid] = [];
}
$scope.privateMessages[rec.uid].push(msg);
} else { //群聊
$scope.publicMessages.push(msg);
}
$scope.chatContent = "";
if (rec.uid !== $scope.self.uid) { //排除给自己发的情况
socket.emit("addMessage", msg);
}
}
其实,客户端之间的通信,都是用服务器作为了一个中间媒介,所有的消息发送可以看成是客户端与服务器之间的通信,而这两者之间的通信有很类似TCP
协议中的三次握手。
参考博客
总结
这个项目还有挺多没有完善的,比如发送表情,发送图片,登陆用户自己设定用户名与头像等,如果有人感兴趣的话,我可以把大家加为合作者,一起把整个项目完善,甚至做的更好。