2021-06-14 Socketio学习使用搭建一个聊天室
Socketio搭建一個聊天室
前言
本次實驗所用編程語言為HTML以及javascript和JQurey語言和Socketio框架,所用編輯文本工具為VS code。
注意事項
(1)前端編程注意HTML語言的靈活運(yùn)用以及javascript語言的使用。
(2)所要使用圖片自己上網(wǎng)尋找替換即可。
(3)由于涉及隱私問題,所以代碼實現(xiàn)效果圖沒有全部放出來。
(4)本文章主要用于大家學(xué)習(xí)參考,博客中代碼按照步驟來即可執(zhí)行使用,但請不要商用。。
(5)本聊天室功能參照B站視頻完成,視頻網(wǎng)址如下:https://www.bilibili.com/video/BV14K411T7cd?from=search&seid=16452167357705157739。
聊天室具體功能
1、完成點對點即時的文本消息聊天功能。
2、實現(xiàn)Web的表情的發(fā)送、接收和顯示功能。
3、實現(xiàn)Web的圖片的發(fā)送、接收和顯示功能。
4、實現(xiàn)本地消息的存儲,在離線的時候也能加載和查看歷史消息。
5、實現(xiàn)本地截圖工具的調(diào)用。
6、實現(xiàn)視頻的傳輸。
聊天室具體實現(xiàn)步驟
1、將VS code安裝好。
(步驟一:進(jìn)入VS code官網(wǎng)下載VS code安裝包。)
(步驟二:選好安裝路徑,安裝步驟直接默認(rèn)即可。)
2、安裝node.js。
(步驟一:進(jìn)入node.js官網(wǎng)下載node.js安裝包。注意點擊圖中紅線所畫,下載穩(wěn)定版本。)
(步驟二:選好安裝路徑,安裝步驟直接默認(rèn)即可。)
3、打開VS code,創(chuàng)建一個文件夾,再在文件夾下創(chuàng)建一個文件命名為app.js。
4、右擊app.js,點擊圖中紅線所劃打開終端。
5、在終端中執(zhí)行指令yarn add nodejs-websocket添加node_modules。
(本步驟可能遇到的報錯一:)
(問題原因:Windows沒有安裝yarn)
(解決辦法:在Windows上安裝yarn)
【步驟一:運(yùn)用管理員身份打開Windws PowerShell】
【步驟二:在Windws PowerShell按照如下圖所示執(zhí)行指令】
6、在文件app.js中寫如下代碼。 (注:app.js是服務(wù)器文件)
/* 啟動聊天的服務(wù)端程序 */ var app = require('express')() var server = require('http').Server(app) var io = require('socket.io')(server) // 記錄所有已經(jīng)登錄過的用戶 const users = []server.listen(3000, () => {console.log('服務(wù)器啟動成功了') })// express處理靜態(tài)資源 // 把public目錄設(shè)置為靜態(tài)資源目錄 app.use(require('express').static('public'))app.get('/', function(req, res) {res.redirect('/index.html') })io.on('connection', function(socket) {socket.on('login', data => {// 判斷,如果data在users中存在,說明該用戶已經(jīng)登錄了,不允許登錄// 如果data在users中不存在,說明該用戶沒有登錄,允許用戶登錄let user = users.find(item => item.username === data.username)if (user) {// 表示用戶存在, 登錄失敗. 服務(wù)器需要給當(dāng)前用戶響應(yīng),告訴登錄失敗socket.emit('loginError', { msg: '登錄失敗' })// console.log('登錄失敗')} else {// 表示用戶不存在, 登錄成功users.push(data)// 告訴用戶,登錄成功socket.emit('loginSuccess', data)// console.log('登錄成功')// 告訴所有的用戶,有用戶加入到了聊天室,廣播消息// socket.emit: 告訴當(dāng)前用戶// io.emit : 廣播事件io.emit('addUser', data)// 告訴所有的用戶,目前聊天室中有多少人io.emit('userList', users)// 把登錄成功的用戶名和頭像存儲起來socket.username = data.usernamesocket.avatar = data.avatar}})// 用戶斷開連接的功能// 監(jiān)聽用戶斷開連接socket.on('disconnect', () => {// 把當(dāng)前用戶的信息從users中刪除掉let idx = users.findIndex(item => item.username === socket.username)// 刪除掉斷開連接的這個人users.splice(idx, 1)// 1. 告訴所有人,有人離開了聊天室io.emit('delUser', {username: socket.username,avatar: socket.avatar})// 2. 告訴所有人,userList發(fā)生更新io.emit('userList', users)})// 監(jiān)聽聊天的消息socket.on('sendMessage', data => {console.log(data)// 廣播給所有用戶io.emit('receiveMessage', data)})// 接收圖片信息socket.on('sendImage', data => {// 廣播給所有用戶console.log(data);io.emit('receiveImage', data)})// 接收視頻信息socket.on('sendVideo',data=>{//廣播給所有用戶console.log(data)io.emit('receiveVideo', data)})})7、在wechart文件夾下創(chuàng)建一個public文件夾,用來存放css文件和js文件和images文件以及配置文件和index.html文件。
(注:index.html文件中代碼如下:)
(注:index.css文件中代碼如下:)
* {margin: 0;padding: 0;list-style: none; } html, body {height: 100%; }body {background: url('../images/bg.jpg') no-repeat center center;background-size: cover; } .container {max-width: 1000px;min-width: 800px;height: 100%;margin: 0 auto;background-color: pink; }/*用戶列表*/ .user-list {width: 280px;height: 100%;float: left;position: relative;/*background-color:#2e3238;*/background-color: #a5aebd; }/*聊天主窗口*/ .box {overflow: hidden;height: 100%;background-color: #eee;position: relative; }/*聊天窗口頭部*/ .box-hd {text-align: center;position: absolute;top: 0;left: 0;width: 100%;line-height: 30px; }/*聊天窗口頭部文字*/ .box-hd h3 {font-size: 18px;font-weight: 400;padding: 10px 0;margin: 0 20px;border-bottom: 1px solid #ccc;z-index: 999;box-sizing: border-box; }.message-box {overflow: hidden; }/*聊天窗口主體部分*/ .box-bd {position: absolute;width: 100%;bottom: 180px;top: 51px;overflow-y: auto;overflow-x: hidden; }.system {overflow: hidden; } .message_system {text-align: center;margin: 10px auto;max-width: 50%; }.message_system .content {display: inline-block;font-size: 12px;padding: 1px 18px;color: #b2b2b2;border-radius: 2px; }.other {margin-bottom: 16px;float: left;width: 100%;padding-left: 20px;box-sizing: border-box; }.my {margin-bottom: 16px;float: right;width: 100%;text-align: right;padding-right: 20px;box-sizing: border-box; }.my.message .avatar {float: right; }.message .content {overflow: hidden; }.message .content .nickname {font-weight: 400;padding-left: 10px;font-size: 12px;height: 22px;line-height: 24px;color: #4f4f4f;width: 350px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;word-wrap: normal; }.message .avatar {width: 40px;height: 40px;border-radius: 2px;float: left;cursor: pointer; }.my.message .bubble {background-color: #b2e281; } .message .bubble {max-width: 500px;min-height: 1em;display: inline-block;vertical-align: top;position: relative;text-align: left;font-size: 14px;border-radius: 3px;margin: 0 10px;background-color: #fff; }/*圖片信息*/ .message .bubble img {display: inline-block;cursor: pointer;max-width: 350px;max-height: 240px; }/*自己消息信息*/ .message .bubble video {display: inline-block;cursor: pointer;max-width: 350px;max-height: 240px; }.other .bubble:before {position: absolute;top: 14px;left: -10px;border: 6px solid transparent;content: ' ';border-right-color: #fff;border-right-width: 4px; }.my .bubble:before {position: absolute;top: 14px;right: -10px;border: 6px solid transparent;content: ' ';border-left-color: #b2e281;border-left-width: 4px; }.bubble_cont {word-wrap: break-word;word-break: break-all;min-height: 25px;padding: 9px 13px; }/*他人視頻消息*/ .bubble_cont video {word-wrap: break-word;word-break: break-all;min-height: 25px;padding: 9px 13px; }/*聊天窗口底部區(qū)域*/ .box-ft {border-top: 1px solid #ccc;position: absolute;height: 180px;bottom: 0;right: 0;left: 0; }.box-ft .toolbar {height: 30px;padding: 5px 20px; }.box-ft .toolbar .face {display: inline-block;vertical-align: middle;width: 30px;height: 30px;background: url('../images/wechat-sprit.png') no-repeat -404px -398px; }.box-ft .toolbar .screen-cut {display: inline-block;vertical-align: middle;width: 30px;height: 30px;background: url('../images/wechat-sprit.png') no-repeat -30px -432px; }/*聊天窗口底部截屏*/ .box-ft .toolbar .screen-cut label {opacity: 0;width: 100%;height: 100%;display: block;cursor: pointer;background: rgb(255, 255, 255); }.box-ft .toolbar .file label {opacity: 0;width: 100%;height: 100%;display: block;cursor: pointer;background: rgb(255, 255, 255); }.box-ft .toolbar .file {display: inline-block;vertical-align: middle;width: 30px;height: 30px;background: url('../images/wechat-sprit.png') no-repeat -120px -432px; }.box-ft .toolbar .videos label {opacity: 0;width: 100%;height: 100%;display: block;cursor: pointer;background: rgb(255, 255, 255); }/*視頻按鈕*/ .box-ft .toolbar .videos {display: inline-block;vertical-align: middle;width: 30px;height: 30px;background: url('../images/wechat-sprit.png') no-repeat -430px -398px; }.box-ft .content {height: 90px;overflow-x: hidden;padding: 0px 20px; }.box-ft .content .text {resize: none;border: none;outline: none;width: 100%;height: 84px;font-size: 16px;background-color: #eee; }.box-ft .action {text-align: right;margin-top: 5px;padding-right: 20px; }.box-ft .action .desc {color: #888;font-size: 12px;margin-left: 10px;margin-right: 7px; }.btn-send {display: inline-block;border: 1px solid #c1c1c1;text-decoration: none;background-color: #fff;color: #222;border-radius: 4px;padding: 3px 30px;font-size: 14px; }.btn-send:hover {background-color: #d8d8d8; }.header {padding: 18px;position: relative; }.header .avatar {display: table-cell;vertical-align: middle;word-wrap: break-word;word-break: break-all;white-space: nowrap;padding-right: 10.625px; }.header .avatar .img {width: 40px;height: 40px;border-radius: 2px;display: block;cursor: pointer; }.header .info {display: table-cell;vertical-align: middle;word-wrap: break-word;word-break: break-all;width: 2000px; }.header .info h3 {display: inline-block;font-weight: 400;width: 156px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;word-wrap: normal;color: #fff;font-size: 18px;vertical-align: top;line-height: 31px;text-decoration: none; }.title {padding: 13px 18px 11px;border-bottom: 1px solid #24272c;border-top: 1px solid #24272c;color: #fff; }.title h3 {font-weight: 400;font-size: 18px; }.user {overflow: hidden;padding: 12px 18px 11px;border-bottom: 1px solid #292c33;cursor: pointer;position: relative; }.user .avatar {float: left;margin-right: 10px;position: relative; }.user .avatar img {display: block;width: 40px;height: 40px;border-radius: 2px; }.user .name {color: #fff;overflow: hidden;line-height: 36px; }.login_box {position: absolute;top: 50%;left: 50%;width: 380px;height: 380px;transform: translate(-50%, -50%);border-radius: 4px;/*background-color: #fff;*/background-color: rgba(128, 128, 128, 0.801);box-shadow: #999 0 2px 10px; }.login_box h3 {text-align: center;color: #ffffff;/*color: #333;*/font-size: 24px;font-weight: 400;line-height: 100px; }.login_box input {width: 300px;height: 30px;line-height: 30px;margin: 0 auto;padding: 0;display: block;outline: none;margin-bottom: 5px; }.weui-btn {position: relative;display: block;width: 300px;margin: 0 auto;box-sizing: border-box;font-size: 14px;text-align: center;text-decoration: none;color: #ffffff;line-height: 2.55555556;border-radius: 5px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);overflow: hidden;background-color:lightgray;/*background-color: #1aad19;*/border: none;cursor: pointer;margin-top: 5px; }.login_box ul {overflow: hidden;width: 280px;margin: 0 auto;border: 1px solid rgba(128, 128, 128, 0.801);/*border: 1px solid #ccc;*/padding: 0 10px; }.login_box li {float: left;width: 44px;height: 44px;border: 2px solid transparent;margin: 0 4px;cursor: pointer; }.login_box li.now {/*border-color: #1aad19;*/border-color:honeydew; }.login_box img {width: 40px;height: 40px;display: block; }.login_box p {height: 30px;line-height: 30px;padding-left: 38px;color: #ffffff; }::-webkit-scrollbar-track-piece {background-color: #f8f8f8; } ::-webkit-scrollbar {width: 6px;height: 6px;border-radius: 3px; } ::-webkit-scrollbar-thumb {background-color: #ccc;background-clip: padding-box;min-height: 28px; } ::-webkit-scrollbar-thumb:hover {background-color: #666; }(注:index.js文件中代碼如下:)
/* 聊天室的主要功能 */ /* 1. 連接socketio服務(wù) */ var socket = io('http://localhost:3000') var username, avatar /* 2. 登錄功能 */ $('#login_avatar li').on('click', function() {$(this).addClass('now').siblings().removeClass('now') }) // 點擊按鈕,登錄 $('#loginBtn').on('click', function() {// 獲取用戶名var username = $('#username').val().trim()if (!username) {alert('請輸入用戶名')return}// 獲取選擇的頭像var avatar = $('#login_avatar li.now img').attr('src')// 需要告訴socket io服務(wù),登錄socket.emit('login', {username: username,avatar: avatar}) })// 監(jiān)聽登錄失敗的請求 socket.on('loginError', data => {alert('用戶名已經(jīng)存在') }) // 監(jiān)聽登錄成功的請求 socket.on('loginSuccess', data => {// 需要顯示聊天窗口// 隱藏登錄窗口$('.login_box').fadeOut()$('.container').fadeIn()// 設(shè)置個人信息console.log(data)$('.avatar_url').attr('src', data.avatar)$('.user-list .username').text(data.username)username = data.usernameavatar = data.avatar })// 監(jiān)聽添加用戶的消息 socket.on('addUser', data => {// 添加一條系統(tǒng)消息$('.box-bd').append(`<div class="system"><p class="message_system"><span class="content">${data.username}加入了群聊</span></p></div>`)scrollIntoView() })// 監(jiān)聽用戶列表的消息 socket.on('userList', data => {// 把userList中的數(shù)據(jù)動態(tài)渲染到左側(cè)菜單$('.user-list ul').html('')data.forEach(item => {$('.user-list ul').append(`<li class="user"><div class="avatar"><img src="${item.avatar}" alt="" /></div><div class="name">${item.username}</div></li> `)})$('#userCount').text(data.length) })// 監(jiān)聽用戶離開的消息 socket.on('delUser', data => {// 添加一條系統(tǒng)消息$('.box-bd').append(`<div class="system"><p class="message_system"><span class="content">${data.username}離開了群聊</span></p></div>`)scrollIntoView() })// 聊天功能 $('.btn-send').on('click', () => {// 獲取到聊天的內(nèi)容var content = $('#content').html()$('#content').html('')if (!content) return alert('請輸入內(nèi)容')// 發(fā)送給服務(wù)器socket.emit('sendMessage', {msg: content,username: username,avatar: avatar}) })// 監(jiān)聽聊天的消息 socket.on('receiveMessage', data => {console.log(data);// 把接收到的消息顯示到聊天窗口中if (data.username === username) {// 自己的消息$('.box-bd').append(`<div class="message-box"><div class="my message"><img class="avatar" src="${data.avatar}" alt="" /><div class="content"><div class="bubble"><div class="bubble_cont">${data.msg}</div></div></div></div></div>`)} else {// 別人的消息$('.box-bd').append(`<div class="message-box"><div class="other message"><img class="avatar" src="${data.avatar}" alt="" /><div class="content"><div class="nickname">${data.username}</div><div class="bubble"><div class="bubble_cont">${data.msg}</div></div></div></div></div>`)}scrollIntoView() })function scrollIntoView() {// 當(dāng)前元素的底部滾動到可視區(qū)$('.box-bd').children(':last').get(0).scrollIntoView(false) }//發(fā)送圖片功能$('#file').on('change', function() {var file = this.files[0]console.log(this.files[0]);// 需要把這個文件發(fā)送到服務(wù)器, 借助于H5新增的fileReadervar fr = new FileReader()fr.readAsDataURL(file)console.log("fr = " + fr.result);fr.onload = function() {socket.emit('sendImage', {username: username,avatar: avatar,img: fr.result})} })// 監(jiān)聽圖片聊天信息 socket.on('receiveImage', data => {// 把接收到的消息顯示到聊天窗口中if (data.username === username) {// 自己的消息$('.box-bd').append(`<div class="message-box"><div class="my message"><img class="avatar" src="${data.avatar}" alt="" /><div class="content"><div class="bubble"><div class="bubble_cont"><img src="${data.img}"></div></div></div></div></div>`)} else {// 別人的消息$('.box-bd').append(`<div class="message-box"><div class="other message"><img class="avatar" src="${data.avatar}" alt="" /><div class="content"><div class="nickname">${data.username}</div><div class="bubble"><div class="bubble_cont"><img src="${data.img}"></div></div></div></div></div>`)}// 等待圖片加載完成,在滾動到底部$('.box-bd img:last').on('load', function() {scrollIntoView()}) })//建立一個可存取到該file的url function getObjectURL(file) {var url = null;if (window.createObjectURL != undefined) { // basicurl = window.createObjectURL(file);} else if (window.URL != undefined) { // mozilla(firefox)url = window.URL.createObjectURL(file);} else if (window.webkitURL != undefined) { // webkit or chromeurl = window.webkitURL.createObjectURL(file);}return url; }//傳輸視頻消息 $("#videos").change(function () {var objUrl = getObjectURL(this.files[0]);console.log("1111111111");console.log("objUrl = " + objUrl);socket.emit('sendVideo', {username: username,avatar: avatar,src: objUrl})});/* $("#screen-cut").change(function () {console.log("22222");location.href = '%windir%\system32\SnippingTool.exe'; }); */// 監(jiān)聽視頻聊天信息socket.on('receiveVideo', data => {// 把接收到的消息顯示到聊天窗口中console.log(data.src);if (data.username === username) {// 自己的消息$('.box-bd').append(`<div class="message-box"><div class="my message"><img class="avatar" src="${data.avatar}" alt="" /><div class="content"><div class="bubble"><div class="bubble_cont"><video style="height:auto;" src="${data.src}" id="video0" controls="controls"></video></div></div></div></div></div>`)} else {// 別人的消息$('.box-bd').append(`<div class="message-box"><div class="other message"><img class="avatar" src="${data.avatar}" alt="" /><div class="content"><div class="nickname">${data.username}</div><div class="bubble"><div class="bubble_cont"><video style="height:auto;" src="${data.src}" id="video0" controls="controls"></video></div></div></div></div></div>`)}// 等待圖片加載完成,在滾動到底部$('.box-bd src:last').on('load', function() {scrollIntoView()}) })// 初始化jquery-emoji插件 $('.face').on('click', function() {$('#content').emoji({// 設(shè)置觸發(fā)表情的按鈕button: '.face',showTab: false,animation: 'slide',position: 'topRight',icons: [{name: 'QQ表情',path: 'lib/jquery-emoji/img/qq/',maxNum: 91,excludeNums: [41, 45, 54],file: '.gif'}]}) })8、在js文件夾中參照網(wǎng)址http://eshengsky.github.io/jQuery-emoji/添加文件,完成文件布置。
(注:最后創(chuàng)建文件夾結(jié)構(gòu)如下)
聊天室功能實現(xiàn)效果如下
1、啟動服務(wù)器
(步驟一:打開cmd,按照如圖所示執(zhí)行指令。注:cd指令的目的是要進(jìn)入代碼文件所在目錄)
2、打開瀏覽器輸入localhost:3000,打開聊天室,進(jìn)入登陸界面,輸入用戶名,選擇頭像。
3、進(jìn)入登錄界面以后,進(jìn)行文本消息發(fā)送。
4、表情包發(fā)送。
5、截圖工具調(diào)用。
6、實現(xiàn)圖片和視頻傳輸。
總結(jié)
以上是生活随笔為你收集整理的2021-06-14 Socketio学习使用搭建一个聊天室的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑显示找不到msvcp140.dll怎
- 下一篇: 【暖手练习】MATLAB习题