<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>简易聊天室</title>
<script src="http://localhost:5050/socket.io/socket.io.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<style>
#logpage{
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
#chatpage{
display: none;
flex-direction: column;
height: 100vh;
}
.header{ background-color: #222; height: 44px; line-height: 44px; display: flex; justify-content: space-between; padding: 0 15px; color:#fff}
.header h1{font-size: 17px; margin: 0;}
a{color:#aaa;text-decoration: none;}
#online { color: #777; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;}
.tip{
position: fixed;
left:50%;
top:50%;
transform: translate(-50%,-50%);
background-color: rgba(0,0,0,.4);
border-radius: 6px;
color:#fff;
display: none;
padding: 5px 15px;
}
.chatbox{ flex:1; background-color: #efefef;}
.msgbox{ height: 160px; display: flex;}
.msgbox button{ width: 120px;}
.msgbox textarea { flex:1;background-color: #f0f0f0;}
.msg{ margin: 15px; clear: both; display: flex; flex-direction: row-reverse; justify-content: flex-end;}
.msg .uname{
height: 60px;
line-height: 60px;
width: 60px;
overflow: hidden;
white-space: normal;
text-overflow: ellipsis;
}
.msg .content{
padding: 15px;
border-radius: 4px;
background-color: #fff;
position: relative;
max-width: 70%;
}
.msg .content::before{
content: '';
position: absolute;
width: 0;
height: 0;
border:10px solid transparent;
border-right-color:#fff;
left:-20px;
top:4px;
}
.msg.me{ flex-direction: row !important; justify-content: flex-end;}
.msg.me .uname{text-align: right;}
.me .content{ background-color: #1E90FF; color: #fff; text-align: right;}
.msg.me .content::before{
left:inherit;
right:-20px;
border-right-color:transparent;
border-left-color:#1E90FF;
}
</style>
</head>
<body>
<div id="logpage">
<input type="text" id="username"> <button onclick="login()">登录</button>
</div>
<!-- 登录页面 -->
<div id="chatpage">
<div class="header"><h1>聊天室</h1> <span><span id="user"></span> <a href="javascript:location.reload()">退出</a></span></div>
<p id="online"></p>
<div class="chatbox"></div>
<div class="msgbox">
<textarea></textarea>
<button onclick="sendMsg()">发送</button>
</div>
</div>
<div class="tip"></div>
<!-- 聊天页面 -->
<script>
var userid = new Date().getTime();
this.socket = io.connect("ws://localhost:5050"); // 连接socket服务器
var username = null;
/**
* 登录
* */
function login(){
username = document.getElementById("username").value; //获取user文本框的值
if(!username){alert("用户名不能为空");return} // 判断如果为空则返回
this.socket.emit("login",{userid:userid,username})//实现soket登录
logpage.style.display = "none";//隐藏登录页面
chatpage.style.display = "flex";// 显示聊天页面
user.innerHTML = username;
}
function sendMsg(){
var textarea = document.querySelector(".msgbox textarea"); //获取到textarea
var message = textarea.value; // 获取用户输入的值
this.socket.emit("message",{message,userid,username}); //发送信息
textarea.value = ""; //请空输入框的值
}
// 发送登录信息给服务器
this.socket.on("login",data=>{
var str = []; //定义用户列表数组
for(key in data.onlineUsers){
str.push(data.onlineUsers[key])
}
// 遍历用户信息 存储到数组
str = str.join(", ");
// 转换为字符串
online.innerHTML = `${data.onlineCount}人在线 ,${str}`;
// 用户登录提示
var tip = document.querySelector(".tip"); // 获取到提示dom
tip.innerHTML = data.user.username +'进入聊天室'; //设置提示的文本
tip.style.display="block"; //显示提示
setTimeout(()=>{
tip.style.display = 'none' //1.5s 隐藏提示
},1500)
})
// 监听登录
this.socket.on("message",data=>{
var div = document.createElement("div"); //创建div
console.log(data.userid,userid);
var cname = data.userid == userid?'msg me':'msg'; //动作设置class
div.className=cname; //添加class
div.innerHTML = `<div class="content">${data.message}</div><div class="uname">${data.username}</div>`;
//设置内容
var chatbox = document.querySelector(".chatbox");
// 选择到chatbox
chatbox.appendChild(div);
// 插入到页面中
})
// 监听 message事件 触发回调
this.socket.on("logout",data=>{
var str = [];
for(key in data.onlineUsers){
str.push(data.onlineUsers[key])
}
str = str.join(", ");
online.innerHTML = `${data.onlineCount}人在线 ,${str}`;
var tip = document.querySelector(".top")
tip.innerHTML = data.user.username +'离开聊天室'; //提示用户离开
tip.style.display="block";
setTimeout(()=>{
tip.style.display = 'none'
},1500)
})
// 监听 logout 注销事件 触发回调
</script>
</body>
</html>
后台代码
var app = require('express')();
// 创建一个app
var express = require('express');
// 需要express
var http = require('http').Server(app);
// 需要http服务
var io = require('socket.io')(http);
// 需要scocket
app.get('/', function(req, res){
res.send('<h1>Welcome Realtime Server</h1>');
});
// app.use('/public', express.static(__dirname + 'public'));
app.use(express.static('public'))
// 设置静态文件夹
//在线用户
var onlineUsers = {};
//当前在线人数
var onlineCount = 0;
// 当用前端用户连接
io.on('connection', function(socket){
console.log('a user connected');
//监听新用户加入
socket.on('login', function(obj){
//将新加入用户的唯一标识当作socket的名称,后面退出的时候会用到
socket.name = obj.userid;
//检查在线列表,如果不在里面就加入
if(!onlineUsers.hasOwnProperty(obj.userid)) {
onlineUsers[obj.userid] = obj.username;
//在线人数+1
onlineCount++;
}
//向所有客户端广播用户加入
io.emit('login', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj});
console.log(obj.username+'加入了聊天室');
});
//监听用户退出
socket.on('disconnect', function(){
//将退出的用户从在线列表中删除
if(onlineUsers.hasOwnProperty(socket.name)) {
//退出用户的信息
var obj = {userid:socket.name, username:onlineUsers[socket.name]};
//删除
delete onlineUsers[socket.name];
//在线人数-1
onlineCount--;
//向所有客户端广播用户退出
io.emit('logout', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj});
console.log(obj.username+'退出了聊天室');
}
});
//监听用户发布聊天内容
socket.on('message', function(obj){
//向所有客户端广播发布的消息
io.emit('message', obj);
console.log(obj.username+'说:'+obj.content);
});
});
http.listen(process.env.PORT || 5050, function(){
console.log('listening on *:5050');
});