聊天室案例
聊天室案例采用WebSocket的方式来进行,代码分为前端代码与后端代码,后端代码采用nodejs来完成
效果图
后端代码
const ws = require("nodejs-websocket");
const createServer = () => {
let server = ws.createServer(connection => {
//console.log(connection);
connection.on('text', function (result) {
// console.log('收到消息', result);
//接收到消息以后,然后再进行转到,发送到每一个客户端
broadcast(server,result);
})
connection.on('connect', function (code) {
console.log('开启连接', code)
})
connection.on('close', function (code) {
console.log('关闭连接', code)
})
connection.on('error', function (code) {
console.log('异常关闭', code)
})
});
return server;
}
// 服务端广播
function broadcast(server, msg) {
server.connections.forEach(function (conn) {
console.log(conn);
conn.sendText(msg);
})
}
let server=createServer();
server.listen(9998,function(){
console.log("服务开启成功");
})
前端代码
<!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>H1904Chat</title>
<link rel="stylesheet" href="https://at.alicdn.com/t/font_1307637_7wuk1w2g5l4.css">
<style>
.main {
width: 900px;
margin: auto;
border: 1px solid lightgray;
}
.resultDiv {
width: 100%;
height: 600px;
box-shadow: 0px 0px 15px 3px lightgray inset;
box-sizing: border-box;
padding: 20px;
overflow: auto;
}
.main .bottom {
height: 45px;
display: flex;
}
#txtMsg {
flex: 1;
box-sizing: border-box;
padding: 0px 10px;
}
#btnSend {
width: 120px;
height: 100%;
border: none;
font-size: 22px;
cursor: pointer;
}
#btnSend:disabled {
cursor: no-drop;
/* 禁用 */
}
.resultDiv>div {
line-height: 1.5;
}
.msg {
margin-top: 15px;
word-break: break-all;
}
.msg>.userInfo {
font-weight: bold;
font-size: 14px;
}
.msg>.msgContent {
margin-top: 5px;
padding: 5px 10px;
background-color: white;
/* border: 1px solid lightgray; */
border-radius: 5px;
box-shadow: 0px 0px 15px 3px lightsteelblue inset;
min-height: 34px;
display: flex;
align-items: center;
width: fit-content;
/* 元素还是块级元素,宽度随内容撑开 */
}
.icon-tupian {
font-size: 26px;
cursor: pointer;
}
.imgBox {
width: 100%;
}
.imgBox>img {
max-width: 400px;
max-height: 400px;
}
.videoDiv{
width: 600px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
border: 1px solid black;
display: none;
}
.videoDivBottom{
display: flex;
justify-content: space-around;
}
</style>
</head>
<body>
<div class="main">
<h1 style="text-align: center">H1904聊天室</h1>
<div class="resultDiv">
</div>
<div>
<input type="file" id="f1" style="display: none" onchange="fileChange(this)">
<span class="iconfont icon-tupian" onclick="this.previousElementSibling.click()"></span>
<button type="button" onclick="openVideo()">截图发送</button>
</div>
<div class="bottom">
<input type="text" id="txtMsg" oninput="txtMsgInput(this)" placeholder="请输入聊天内容">
<button type="button" disabled id="btnSend" onclick="sendMsg()">发送消息</button>
</div>
</div>
<!--div显示视频 -->
<div class="videoDiv">
<video id="v1" width="600px" height="400px"></video>
<canvas id="c1" width="600px" height="400px" style="display: none"></canvas>
<div class="videoDivBottom">
<button type="button" onclick="takePhoto()">拍照</button>
<button type="button" onclick="document.querySelector('.videoDiv').style.display='none'">关闭</button>
</div>
</div>
<template id="msgtemp">
<div class="msg">
<div class="userInfo">{{userNickName}} {{currentTime}}</div>
<div class="msgContent">{{msgContent}}</div>
{{if base64}}
<div class="imgBox">
<img src="{{base64}}">
</div>
{{/if}}
</div>
</template>
</body>
<script src="./js/template-web.js" type="text/javascript"></script>
<script src="./js/time.js" type="text/javascript"></script>
<script>
var btnSend = document.querySelector("#btnSend");
var txtMsg = document.querySelector("#txtMsg");
var resultDiv = document.querySelector(".resultDiv");
var base64Str = "";
//当页面加载的时候,我们就弹出一个输入框让用户输入信息
var flag = true;
while (flag) {
var userNickName = prompt("请输入你的昵称");
if (userNickName == null) {
flag = true;
} else if (userNickName != null && userNickName.trim() == "") {
flag = true;
} else {
flag = false;
}
}
//创建WebSocket 连接到服务器
var ws = new WebSocket("ws://192.168.6.177:9998");
ws.onopen = function () {
ws.send(userNickName + " " + getCurrentTime() + " 进入了聊天室");
}
ws.onclose = function () {
}
ws.onerror = function () {
}
ws.onmessage = function (event) {
//event.data
appendMsg(event.data);
}
function txtMsgInput(obj) {
if (obj.value.trim().length > 0) {
btnSend.disabled = false;
} else {
btnSend.disabled = true;
}
}
function appendMsg(msg) {
var d = document.createElement("div");
d.innerHTML = msg;
resultDiv.appendChild(d);
resultDiv.scrollTo(0, resultDiv.scrollHeight);
}
//格式化的方法
function formatUserMsg(userNickName, currenTime, msgContent, base64) {
var html = template("msgtemp", {
userNickName: userNickName,
currentTime: currenTime,
msgContent: msgContent,
base64: base64
});
return html;
}
//用户点击发送按钮以后
function sendMsg() {
var msg = formatUserMsg(userNickName, getCurrentTime(), txtMsg.value.trim(), base64Str);
//在发送消息之前,我要检查一下,它是否还处理连接状态
if (ws.readyState == WebSocket.OPEN) {
ws.send(msg);
txtMsg.value = ""; //清除原来的东西
btnSend.disabled = true; //按钮重新变成禁用状态
txtMsg.disabled = true;
base64Str=""; //清空base64图片地址
setTimeout(function () {
txtMsg.disabled = false;
}, 1000);
} else {
alert("服务器已关闭");
}
}
function fileChange(obj) {
if (obj.files.length == 1) {
var file = obj.files[0];
var fr = new FileReader();
fr.readAsDataURL(file);
fr.onload = function (event) {
var e = event || window.event;
base64Str = e.currentTarget.result; //它是一个图片的base64
obj.value="";
}
}
}
//打开视频
function openVideo(){
navigator.getMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia;
navigator.getMedia({
video:true,
audio:false
},function(stream){
document.querySelector("#v1").srcObject=stream;
document.querySelector("#v1").play();
document.querySelector(".videoDiv").style.display="block";
},function(err){
console.log(err);
});
}
function takePhoto(){
var c1=document.querySelector("#c1");
var ctx=c1.getContext("2d");
var v1=document.querySelector("#v1");
ctx.drawImage(v1,0,0,600,400);
base64Str = c1.toDataURL("image/png");
document.querySelector(".videoDiv").style.display="none";
}
</script>
</html>
前端代码采用了template模板以及websocket的方式,同时还完成了浏览器调用摄像头完在视频截图发送的功能
评论区