Node.js + express + socket 实现在线实时多人聊天室
来源:互联网 发布:邓肯数据 编辑:程序博客网 时间:2024/05/21 09:27
项目目录结构:
前端部分:
登录页面Login部分:
login.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>login</title> <link rel="stylesheet" href="css/login.css"></head><body> <div class="login-box flex-box"> <!--登录标题栏--> <h2 class="sign-title box-width">LOGIN</h2> <!--头像栏--> <div class="picture-carousel"> <div class="arrow left-arrow"> <div class="before-arrow"></div> </div> <img class="p1 img-setting" src="img/1.png" alt="1.png"> <img class="p2 img-setting" src="img/2.png" alt="2.png"> <img class="p3 img-setting" src="img/3.png" alt="3.png"> <img class="p2 img-setting" src="img/4.png" alt="4.png"> <img class="p1 img-setting" src="img/5.png" alt="5.png"> <div class="arrow right-arrow"> <div class="after-arrow"></div> </div> </div> <!--用户名栏--> <div class="name-box box-width"> <input type="text" class="user-name box-width" placeholder="Please Type Your Name"> </div> <!--确认栏--> <div class="button-box box-width"> <input type="button" class="login-button box-width" value="Login The Chatroom"> </div> <!--错误信息栏--> <div class="error-box box-width"> <span class="error-message">Welcome to chatroom!</span> </div> </div></body><script src="js/login.js"></script></html>
login.css
* { padding: 0; margin: 0; font-family: "Microsoft Yahei";}html,body { width: 100%; height: 100%; font-family: "Microsoft Yahei"; display: flex; justify-content: center; align-items: center;}body { background: linear-gradient(-135deg, #51D15B, #42A855); background: -moz-linear-gradient(-135deg, #51D15B, #42A855); background: -webkit-linear-gradient(-135deg, #51D15B, #42A855); background: -o-linear-gradient(-135deg, #51D15B, #42A855);}.flex-box { display: flex; justify-content: center; align-items: center;}.box-width { width: 80%;}/*最外层*/.login-box { width: 20%; min-width: 304px; max-width: 404px; height: 50%; min-height: 368px; max-height: 468px; flex-direction: column; box-shadow: 1px 1px 15px #7B8C99; background: #fff;}/*LOGIN标题*/.sign-title { color: #42A855; border: 2px solid #42A855; border-top: transparent; border-left: transparent; border-right: transparent;}/*图片切换*/.picture-carousel { position: relative; display: flex; margin: 10%;}/*图片切换箭头*/.arrow { z-index: 3; position: absolute; font-size: 60px; height: 100%; width: 30%; display: flex; justify-content: center; align-items: center; color: #ffffff;}.arrow:hover { cursor: pointer;}.left-arrow { left: 0;}.before-arrow { width: 0px; height: 0px; border-width: 30px; border-style: solid; border-color: transparent #51D15B transparent transparent;}.right-arrow { right: 0;}.after-arrow{ width: 0px; height: 0px; border-width: 30px; border-style: solid; border-color: transparent transparent transparent #51D15B; }.picture-carousel img { width: 80px; height: 80px; transition: all 0.2s linear; -moz-transition: all 0.2s ease-out; -webkit-transition: all 0.2s ease-out; -o-transition: all 0.2s ease-out;}.img-setting { margin: 0px -15px;}.p1 { transform: scale(0.6); z-index: 1;}.p1:hover { transform: scale(0.8);}.p2 { transform: scale(0.8); z-index: 2;}.p2:hover { transform: scale(1);}.p3 { transform: scale(1); z-index: 3;}.p3:hover { transform: scale(1.2);}/*用户名*/.name-box { display: flex; justify-content: center; border: 1px solid #51D15B;}.name-box .user-name { width: 100%; text-align: center; padding: 10px; outline-color: #42A855; border: none; font-size: 16px;}/*登录按钮*/.button-box { display: flex; justify-content: center; margin: 10px 0px 20px;}.button-box .login-button { width: 100%; padding: 10px 20px; outline: none; border: none; background: #42A855; color: white; font-size: 16px;}/*错误信息*/.error-box { color: #42A855; border: 2px solid #42A855; border-top: transparent; border-left: transparent; border-right: transparent;}.error-box span { visibility: hidden; color: #d43f3a; font-size: 14px;}
login.js
//用于存储图片顺序var imgArray = ['1', '2', '3', '4', '5']; //获取箭头var leftArrow = document.getElementsByClassName('left-arrow')[0];var rightArrow = document.getElementsByClassName('right-arrow')[0];//获取用户名var userName = document.getElementsByClassName('user-name')[0];//获取登录按钮var loginButton = document.getElementsByClassName('login-button')[0];// 获取错误信息栏var errorMessage = document.getElementsByClassName('error-message')[0];// 添加左箭头监听事件leftArrow.addEventListener('click', function () { imgArray.unshift(imgArray[imgArray.length - 1]); //把最后的元素放在第一位 imgArray.pop(); carouselImg();});// 添加右箭头监听事件rightArrow.addEventListener('click', function () { imgArray.push(imgArray[0]); //把第一个元素放在最后 imgArray.shift(); carouselImg();});// 切换图片function carouselImg() { for (var count = 0; count < imgArray.length; count++) { document.getElementsByTagName('img')[count].src = 'img/' + imgArray[count] + '.png'; document.getElementsByTagName('img')[count].alt = imgArray[count] + '.png'; };};// 添加登录按钮监听事件loginButton.addEventListener('click', function () { if (userName.value === '') { errorMessage.innerHTML = 'Please Type You Name'; errorMessage.style.visibility = 'visible'; } else if (userName.value.length > 8) { errorMessage.innerHTML = 'Your Name Cannot Over 8 Words'; errorMessage.style.visibility = 'visible'; } else { window.location.href = encodeURI('index.html?selectpicture=' + document.getElementsByClassName('p3')[0].alt + '&username=' + userName.value); }});// Enter按键绑定登录事件document.onkeydown = function (event) { var e = event || window.event; if (e && e.keyCode == 13) { loginButton.click(); }};
效果图
聊天页面index部分:
index.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>chat-room</title> <link rel="stylesheet" href="css/index.css"></head><body> <div class="chat-box"> <!--聊天框头部--> <div class="chat-header"> <div class="button-box"> <input type="button" class="log-out" value="LOGOUT"> </div> </div> <!--聊天框主体--> <div class="chat-body"> <!--聊天框左侧--> <div class="chat-body-left"> <!--聊天框左侧聊天内容--> <div class="chat-content"></div> <!--聊天框左侧聊天输入框--> <div class="chat-edit"> <input type="text" class="edit-box" placeholder="Please Type You Message" maxlength="15"> <input type="button" class="edit-button" value="SEND"> </div> </div> <!--聊天框右侧--> <div class="chat-body-right"> <!--聊天框右侧统计人数--> <div class="online-count">Online:0</div> <!--聊天框右侧用户名--> <div class="user-name">user-name</div> <!--聊天框右侧头像--> <img class="user-img" /> </div> </div> </div></body><script src="js/socket.io.js"></script><script src="js/index.js"></script></html>
index.css
* { margin: 0; padding: 0; font-family: "Mircrosoft Yahei"; /*border: 1px solid black;*/}html,body { width: 100%; height: 100%;}/*背景色*/body { display: flex; justify-content: center; align-items: center; background: linear-gradient(-135deg, #51D15B, #42A855); background: -moz-linear-gradient(-135deg, #51D15B, #42A855); background: -webkit-linear-gradient(-135deg, #51D15B, #42A855); background: -o-linear-gradient(-135deg, #51D15B, #42A855);}/*最外层*/.chat-box { width: 50%; max-width: 720px; min-width: 400px; height: 80%; min-height: 530px; max-height: 530px; display: flex; flex-direction: column; background: #fff; box-shadow: 1px 1px 15px #333333;}/*头部*/.chat-header { margin: 5px; box-shadow: 1px 1px 15px #7B8C99;}.button-box { display: flex; justify-content: flex-end;}.log-out { height: 100%; font-size: 14px; font-weight: bold; padding: 5px 15px; color: #79C2EA; background: #fff; outline: none; border: none; border-radius: 15px; cursor: pointer;}/*主体*/.chat-body { height: 90%; display: flex; flex-direction: row; justify-content: space-around; align-items: center; margin: 5px; padding: 5px;}/*主体左侧*/.chat-body-left { height: 100%; width: 70%; display: flex; flex-direction: column; justify-content: space-around; margin: 5px;}/*左侧内容*/.chat-content { margin-bottom: 5px; height: 100%; box-shadow: 1px 1px 15px #7B8C99; overflow: scroll;}/*聊天气泡*/.my-message-box { display: flex; justify-content: flex-end; align-content: center; margin: 5px;}.other-message-box { display: flex; justify-content: flex-start; align-content: center; margin: 5px;}.message-content { display: flex; justify-content: center; align-content: center; background-color: #51D15B; padding: 5px 10px; border-radius: 15px; color: #fff;}.other-message-content { display: flex; justify-content: center; align-content: center; background-color: #79C2EA; padding: 5px 10px; border-radius: 15px; color: #fff;}.message-content span { padding: 20px 0px;}.other-message-content span { padding: 20px 0px;}.message-arrow { width: 0px; height: 0px; border-width: 8px; border-style: solid; border-color: transparent transparent transparent #51D15B; align-self: center;}.other-message-arrow { width: 0px; height: 0px; border-width: 8px; border-style: solid; border-color: transparent #79C2EA transparent transparent; align-self: center;}.user-information { display: flex; flex-direction: column; align-content: flex-end;}.other-user-information { display: flex; flex-direction: column; align-content: flex-end;}.user-chat-img { width: 50px; height: 50px;}.user-chat-name { color: #333333; font-size: 16px; text-align: center;}/*聊天输入框*/.chat-edit { margin-top: 5px; display: flex; justify-content: space-between; align-items: center; box-shadow: 1px 1px 15px #7B8C99; overflow: hidden;}/*聊天输入框输入区域*/.edit-box { width: 80%; height: 100%; margin: 5px; border: none; outline: none;}/*聊天框输入按钮*/.edit-button { height: 100%; padding: 5px 15px; background: #fff; color: #79C2EA; outline: none; border: none; border-radius: 15px; cursor: pointer; font-size: 14px; font-weight: bold;}/*主体右侧*/.chat-body-right { height: 100%; width: 30%; display: flex; flex-direction: column; justify-content: center; align-items: center; margin: 5px; box-shadow: 1px 1px 15px #7B8C99;}/*右侧内容*/.user-name { margin: 15px; font-size: 18px; font-weight: bold; color: #79C2EA;}.user-img { width: 100px; height: 100px; margin: 5px;}.online-count { font-size: 18px; font-weight: bold; color: #79C2EA;}/*兼容小屏幕*/@media screen and (max-width: 420px) { .chat-box { width: 50%; max-width: 720px; min-width: 300px; height: 80%; min-height: 530px; max-height: 530px; } .chat-body-left { height: 100%; width: 100%; display: flex; flex-direction: column; justify-content: space-around; margin: 5px; } .chat-body-right { display: none; }}
index.js
// 获取url里面的内容var url = decodeURI(location.href).split('?')[1].split('&');// 获取聊天内容框var chatContent = document.getElementsByClassName('chat-content')[0];// 获取聊天输入框var editBox = document.getElementsByClassName('edit-box')[0];// 获取聊天输入框发送按钮var editButton = document.getElementsByClassName('edit-button')[0];// 获取用户名栏var userName = document.getElementsByClassName('user-name')[0];// 获取在线人数栏var onlineCount = document.getElementsByClassName('online-count')[0];// 把登录页面的名称放在右侧userName.innerHTML = url[1].split('=')[1];var userImg = document.getElementsByClassName('user-img')[0];// 把登录页面的头像放在右侧userImg.src = 'img/' + url[0].split('=')[1];var logOut = document.getElementsByClassName('log-out')[0];// 发送按钮绑定点击事件editButton.addEventListener('click', sendMessage);// 登出按钮绑定点击事件logOut.addEventListener('click', closePage);// 绑定Enter键和发送事件document.onkeydown = function (event) { var e = event || window.event; if (e && e.keyCode === 13) { if (editBox.value !== '') { editButton.click(); } }};// 关闭页面function closePage() { var userAgent = navigator.userAgent; if (userAgent.indexOf("Firefox") != -1 || userAgent.indexOf("Chrome") != -1) { window.location.href = "about:blank"; } else { window.opener = null; window.open("", "_self"); window.close(); }}// socket部分var socket = io();// 当接收到消息并且不是本机时生成聊天气泡socket.on('message', function (information) { if (information.name !== userName.textContent) { createOtherMessage(information); }});// 当接收到有人连接进来socket.on('connected', function (onlinecount) { console.log(onlinecount); onlineCount.innerHTML = 'Online:' + onlinecount;});// 当接收到有人断开后socket.on('disconnected', function (onlinecount) { console.log(onlinecount); onlineCount.innerHTML = 'Online:' + onlinecount;});// 发送本机的消息function sendMessage() { if (editBox.value != '') { var myInformation = { name: userName.textContent, chatContent: editBox.value, img: userImg.src }; socket.emit('message', myInformation); createMyMessage(); editBox.value = ''; }};// 生成本机的聊天气泡function createMyMessage() { var myMessageBox = document.createElement('div'); myMessageBox.className = 'my-message-box'; var messageContent = document.createElement('div'); messageContent.className = 'message-content'; var text = document.createElement('span'); text.innerHTML = editBox.value; messageContent.appendChild(text); myMessageBox.appendChild(messageContent); var arrow = document.createElement('div') arrow.className = 'message-arrow'; myMessageBox.appendChild(arrow); var userInformation = document.createElement('div'); userInformation.className = 'user-information'; var userChatImg = document.createElement('img'); userChatImg.className = 'user-chat-img'; userChatImg.src = userImg.src; var userChatName = document.createElement('div'); userChatName.className = 'user-chat-name'; userChatName.innerHTML = userName.textContent; userInformation.appendChild(userChatImg); userInformation.appendChild(userChatName); myMessageBox.appendChild(userInformation); chatContent.appendChild(myMessageBox); chatContent.scrollTop = chatContent.scrollHeight;}// 生成其他用户的聊天气泡function createOtherMessage(information) { var otherMessageBox = document.createElement('div'); otherMessageBox.className = 'other-message-box'; var otherUserInformation = document.createElement('div'); otherUserInformation.className = 'other-user-information'; var userChatImg = document.createElement('img'); userChatImg.className = 'user-chat-img'; userChatImg.src = information.img; var userChatName = document.createElement('span'); userChatName.className = 'user-chat-name'; userChatName.innerHTML = information.name; otherUserInformation.appendChild(userChatImg); otherUserInformation.appendChild(userChatName); otherMessageBox.appendChild(otherUserInformation); var otherMessageArrow = document.createElement('div'); otherMessageArrow.className = 'other-message-arrow'; otherMessageBox.appendChild(otherMessageArrow); var otherMessageContent = document.createElement('div'); otherMessageContent.className = 'other-message-content'; var text = document.createElement('span'); text.innerHTML = information.chatContent; otherMessageContent.appendChild(text); otherMessageBox.appendChild(otherMessageContent); chatContent.appendChild(otherMessageBox); chatContent.scrollTop = chatContent.scrollHeight;}
效果图
后端部分:
server.js
// 引入必须模块var express = require('express');var app = express();var http = require('http').Server(app);var io = require('socket.io')(http);var path = require('path');// 在线人数统计var onlineCount = 0;app.use(express.static(__dirname));// 路径映射app.get('/login.html', function (request, response) { response.sendFile('login.html');});// 当有用户连接进来时io.on('connection', function (socket) { console.log('a user connected'); // 发送给客户端在线人数 io.emit('connected', ++onlineCount); // 当有用户断开 socket.on('disconnect', function () { console.log('user disconnected'); // 发送给客户端断在线人数 io.emit('disconnected', --onlineCount); console.log(onlineCount); }); // 收到了客户端发来的消息 socket.on('message', function (message) { // 给客户端发送消息 io.emit('message', message); });});var server = http.listen(4000, function () { console.log('Sever is running');});
总结:
后端部分使用了Node.js + express 实现
前端部分的布局使用了CSS3的flex来布局
聊天页面的交互使用socket进行了聊天消息的发送与接收的消息机制,避免了用Ajax有时会丢失聊天消息的情况
兼容性目前测试通过的有Chrome 58、Opera 45、Firefox 53、IE 11
待解决的问题:
用户名重复没有检测,后续打算添加用户注册功能,需要使用数据库
无法查看聊天记录,后续打算使用数据库进行聊天记录存储
代码规范还有待提高
界面设计有待提高
接下来还会更新本项目
github地址:https://github.com/CyanChan/chatroom
在线演示地址:http://119.29.19.27:4000/login.html
阅读全文
0 0
- Node.js + express + socket 实现在线实时多人聊天室
- Node.js+Express+Socket.IO搭建在线聊天室
- 用Node.js编写多人实时在线聊天室
- Node.js websocket 使用 socket.io库实现实时聊天室
- Node.js websocket 使用 socket.io库实现实时聊天室
- Node.js websocket 使用 socket.io库实现实时聊天室
- node.js+express+socket的聊天室示例
- phaChat聊天室(Node.js+express+mysql+socket)
- 使用node.js和socket.io实现多人聊天室
- Node.js+socket.io在线聊天室
- node.js实现即时聊天室,使用模块(express+socket.io),附源码
- 基于Node.js,Express,Socket.io创建简单聊天室
- 使用Node.js+Socket.IO搭建WebSocket实时应用(聊天室)
- 入门WebSocket和socket.io,实现在线实时聊天室
- socket.io & Node.js搭建多聊天室
- socket.io & Node.js搭建多聊天室
- node.js+socket.io 实现一个web聊天室
- Node.js+Socket.IO实现的WebSocket群聊天室源码
- [R语言]总体概率的区间估计学习
- hdu2669
- kali安装flash插件
- OpenCV——KNN分类算法 <摘>
- #3 条件判断
- Node.js + express + socket 实现在线实时多人聊天室
- log4j提供的日志级别
- .net发送邮件
- Prim 算法
- javaBean_EL
- 微信小程序swiper高度自适应方法
- 生产者与消费者模型
- Bootstrap学习笔记(二)
- 在windows上搭建redis集群(redis-cluster)