index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在线聊天</title>
</head>
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.out {
width: 1000px;
height: 600px;
margin: 0 auto;
display: flex;
}
.left {
flex: 1;
height: 100%;
background-color: rgb(112, 109, 109);
box-sizing: border-box;
padding: 0 10px;
display: flex;
flex-direction: column;
color: rgb(216, 213, 213);
}
.avatr {
width: 50px;
height: 50px;
}
.top {
height: 10%;
display: flex;
align-items: center;
}
.nth {
height: 5%;
}
.list {
flex: 1;
}
.list li {
display: flex;
align-items: center;
margin-bottom: 5px;
border-bottom: 1px solid white;
padding-bottom: 5px;
}
.right {
flex: 3;
height: 100%;
background-color: rgb(224, 220, 212);
display: flex;
flex-direction: column;
}
.right_top {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
border-bottom: 1px solid #ccc;
}
.chat {
flex: 7;
position: relative;
overflow-y: scroll;
overflow-x: hidden;
}
.word {
flex: 4;
}
.message {
position: relative;
left: 328px;
margin-top: 5px;
font-size: 12px;
color: rgb(143, 140, 140);
}
.word {
position: relative;
}
.word textarea {
width: 100%;
height: 100%;
border: none;
outline: none;
font-size: 16px;
border-bottom: 1px solid #ccc;
}
.send {
position: absolute;
width: 70px;
background-color: #fff;
border: 1px solid #ccc;
right: 30px;
bottom: 10px;
}
.login {
width: 500px;
border: 1px solid #ccc;
margin: 200px auto;
text-align: center;
}
.avatrs {
display: flex;
justify-content: center;
}
.login .avatr {
margin: 10px;
}
.login .active {
border: 3px solid red;
}
.goChat {
width: 300px;
height: 30px;
border: 1px solid #ccc;
background-color: rgb(22, 170, 22);
color: white;
outline: none;
font-size: 13px;
margin: 10px 0;
}
.user {
float: left;
width: 100%;
clear: both;
position: relative;
font-size: 13px;
margin-bottom: 10px;
}
.user .avatr {
float: left;
}
.user .username {
position: absolute;
left: 52px;
top: 0px;
}
.user .content {
position: absolute;
left: 53px;
bottom: 2px;
background-color: #fff;
font-size: 14px;
}
.self {
float: right;
width: 100%;
clear: both;
position: relative;
font-size: 13px;
margin-bottom: 10px;
}
.self .avatr {
float: right;
}
.self .username {
position: absolute;
right: 52px;
top: 0px;
}
.self .content {
position: absolute;
right: 53px;
bottom: 2px;
font-size: 14px;
}
</style>
<body>
<div class="login">
<h2>用户登录</h2>
<div>用户名:</div>
<input type="text" style="text-align: center; font-size: 16px; color: rgb(231, 118, 118);" class="login_name">
<div>选择聊天头像</div>
<div class="avatrs">
<div class="avatr active" style="background-image: url('./imgs/1.jpg'); background-size: cover;"></div>
<div class="avatr" style="background-image: url('./imgs/2.jpg'); background-size: cover;"></div>
<div class="avatr" style="background-image: url('./imgs/3.jpg'); background-size: cover;"></div>
<div class="avatr" style="background-image: url('./imgs/4.jpg'); background-size: cover;"></div>
<div class="avatr" style="background-image: url('./imgs/5.png'); background-size: cover;"></div>
</div>
<button class="goChat">登录</button>
</div>
<div class="out" style="display: none;">
<div class="left">
<div class="top">
<div class="avatr" style="background-image: url('./imgs/1.jpg'); background-size: cover;"></div>
<span class="loginSucc_name">布丁</span>
</div>
<div class="nth" style="color: #bfa;">用户列表</div>
<ul class="list">
</ul>
</div>
<div class="right">
<div class="right_top">聊天室(0)</div>
<div class="chat">
</div>
<div class="word">
<textarea class="message_content"></textarea>
<button class="send">发送</button>
</div>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/socket.io/3.0.0-rc4/socket.io.js"></script>
<script src="./jquery/jquery-1.12.4.min.js"></script>
<script src="./index.js"></script>
</body>
</html>
index.js
var socket = io.connect('http://localhost:3000');
// 定义用户名和头像
let username;
let avatar;
// 选择头像事件
$('.avatrs .avatr').click(function () {
$(this).addClass('active').siblings().removeClass('active');
})
// 点击登录
$('.goChat').click(function () {
// 获取用户名
const username = $('.login_name').val().trim();
if (username === '') {
alert('请输入用户名!');
return;
}
// 获取头像
let avatar = $('.avatrs .active').css('background-image').split("\"")[1];
avatar = avatar.slice(22);
avatar = './' + avatar;
socket.emit('login', {
username,
avatar
});
})
// 登录失败
socket.on('loginError', (data) => {
alert(data.message)
})
// 登录成功
socket.on('loginSuccess', (data) => {
$('.login').css('display', 'none')
$('.out').css('display', 'flex')
// 设置自己的头像和用户名
$('.left .top .avatr').css('background-image', 'url("' + data.avatar + '")');
$('.loginSucc_name').text(data.username);
// 将全局的username和avatar重新赋值
username = data.username;
avatar = data.avatar;
})
// 设置加入聊天的信息
socket.on('addUser', (data) => {
const message = ` <div class="message">"${data.username}" 加入了群聊</div>`;
$('.chat').append(message);
})
// 设置用户列表刷新
socket.on('updateList', (data) => {
// 先清空列表再遍历,防止用户列表出现重复用户
$('.list').html('');
// 设置总列表用户
data.forEach(item => {
let child = ` <li>
<div class="avatr" style="background-image: url('${item.avatar}'); background-size: cover;"></div>
<span> ${item.username}</span>
</li>`;
$('.list').append(child);
});
// 设置聊天室总人数
$('.right_top').text(`聊天室(${data.length})`);
})
// 设置退出聊天事件
socket.on('loginOut', (data) => {
console.log(data);
// 设置加入聊天的信息
const message = ` <div class="message">"${data.username}" 退出了群聊</div>`;
$('.chat').append(message);
})
// 设置发送信息事件
$('.send').click(function () {
// 获取消息
const content = $('.message_content').val().trim();
if (content == '') {
alert('发送的消息不能为空!');
return;
}
// 向socket发送 trigger_send事件,带上 发送的内容 以及 当事人名字 和 头像
socket.emit('trigger_send', { content, username, avatar });
})
// 发送消息
socket.on('send', (data) => {
let message;
// 自己发的消息
if (username === data.username) {
message = ` <div class="self">
<div class="avatr" style="background-image: url('${data.avatar}'); background-size: cover;"></div>
<div class="username">${data.username}</div>
<div class="content" style="background-color: rgb(22, 170, 22); color:white">${data.content}</div>
</div>`;
} else {
// 别人发的消息
message = ` <div class="user">
<div class="avatr" style="background-image: url('${data.avatar}'); background-size: cover;"></div>
<div class="username">${data.username}</div>
<div class="content">${data.content}</div>
</div>`;
}
// 添加消息
$('.chat').append(message);
// 清空输入内容
$('.message_content').val('');
// 滚动到最下面
$('.chat').children(':last')[0].scrollIntoView();
})
app.js
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(3000, () => {
console.log('成功建立连接');
});
app.use(require('express').static('public'));
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
let users = [];
io.on('connection', function (socket) {
// 处理登录事件
socket.on('login', (data) => {
// 查找是否重复登录
let res = users.find(item => item.username === data.username)
if (res) {
socket.emit('loginError', { message: '用户已登录!不能重复登录' })
} else {
// 为socket对象添加当前用户标识
socket.username = data.username;
socket.avatar = data.avatar;
// 添加到总用户中
users.push(data);
// 个人事件
socket.emit('loginSuccess', data);
// 广播加入聊天事件
io.emit('addUser', data);
// 重新设置列表人数
io.emit('updateList', users);
}
});
// 监听退出连接事件
socket.on('disconnect', () => {
// 查找退出登录的用户索引
const i = users.findIndex(item => item.username === socket.username);
// 发送广播退出聊天事件
io.emit('loginOut', users[i]);
// 删除该用户
users.splice(i, 1);
// 重新设置列表人数
io.emit('updateList', users);
})
// 设置发送信息聊天事件
socket.on('trigger_send', (data) => {
// 广播 触发 发送消息
io.emit('send', data);
})
});