天天看點

node.js,微信聊天

微信聊天

node.js,微信聊天

app.js

var express = require('express');
var app = express();//執行個體化一個express的app伺服器  建立express伺服器 不是必要的  
var fs = require('fs');
var http = require('http');
var http1 = http.Server(app);//把app的這個伺服器傳到 原生的http伺服器中 
var io = require('socket.io');//引用socket.io子產品
var socket  = io(http1);//socket的執行個體化  建立了 以http1  為伺服器的  socket的  協定伺服器
var path=require('path')
app.use(express.static(path.join(__dirname,'static')));
app.get('/',function (req,res) {
	fs.readFile('./index.html',function (err,data) {
		if(err){
			throw err;
		}
		res.end(data);
	})
})
socket.on('connection',function (socket) {
	socket.on('myMessage',function (data) {//當客服端有使用者發送資訊的時候
		socket.broadcast.emit('oterFriend',data);//廣播資訊給其他客服端
	})
	socket.on('newFriend',function (data) {
		socket.broadcast.emit('message',data);
	})
})
http1.listen(8081);

           

index.html

<style type="text/css">
			 ::-webkit-scrollbar {
            width: 0px;
        }
			*{
				margin: 0;
				padding: 0;
			}
			/*聊天界面的大盒子*/
			.box{
				width: 360px;
				height: 500px;
				margin: 30px auto;
			}
			#max {
				list-style: none;
				width: 340px;
				height: 400px;
				margin: 0 auto;
				overflow-y: auto;
				background-color: #fbfbfb;
			}
			/*每一條聊天資訊
			 給其他客服端的資訊加上左浮動*/
			#max li{
				position: relative;
				float: left;
				margin-left: 11px;
				margin-top: 23px;
				padding: 5px 10px;
				max-width: 200px;
				height: auto;
				background: #fff;
				color: #333;
				clear: both;
				word-break: break-all;
			}
			/*給自己發送的資訊加上右浮動*/
			li.f_r{
				float:right !important;
				clear: both !important;
				background: #a3d54e !important;
				color: #333 !important; 
				margin-right: 11px;
			}
			/*新好友上線提示框*/
			#p_f{
				position: fixed;
				left: 4px;
				top: 4px;
				width: 150px;
				height: 32px;
				line-height: 32px;
				background-color: aquamarine;
				box-shadow:0 0 6px rgba(0,0,0,.4);
			}
			/*發送資訊功能區盒子*/
			.message{
				width: 340px;
				margin: 0 auto;
				background-color: #e5e5e5;
				border-top: 1px solid #d2cfcf;
				height: 40px;
				line-height: 40px;
			}
			/*圖示按鈕*/
			#ejmo{
				float: left;
				width: 26px;
				height: 26px;
				background: url('images/ejom.png');
				background-size: 100%;
				cursor: pointer;
				margin-left: 10px;
				margin-top: 7px;
				position: relative;
			}
			.biaoqian{
				width: 360px;
				margin-top: 40px;
			}
			/*全部表情圖檔*/
			.biaoqian img{
				display: inline-block;
				width: 26px;
				height: 26px;
				margin-right: 18px;
				margin-top: 8px;
			}
			/*表情的切換頁圓點*/
			#subNum{
				text-align: center;	
				display: none;
			}
			#subNum li{
				margin-left: 10px;
				display: inline-block;
				list-style: none;
				width: 10px;
				height: 10px;
				border-radius: 50%;
				background: #BBBBBB;
				cursor: pointer;
			}
			/*發送文本框和發送按鈕*/
			#userval,#btn{
				float: right;
				margin-right: 10px;
				margin-top: 3px;
				border: none;
				border-radius: 4px;
			}
			#userval{
				width: 210px;
				height: 24px;
				padding: 4px;
				background: white;
				line-height: 24px;
				overflow:hidden;
			}
			/*發送按鈕*/
			#btn{
				width: 50px;
				height: 30px;
				background: #05c25e;
				color: white;
			}
			.triangleLeft,.triangleRight{
				position: absolute;
				width: 0; 
				height: 0;
				border-width: 6px;
				border-style: solid;
				top: 7px;
			}
			/*每條資訊旁邊的右三角形*/
			.triangleRight{
				border-color:transparent transparent transparent #a3d54e;
				right: -11px;
			}
			/*每條資訊旁邊的左三角形*/
			.triangleLeft{
				border-color:transparent white transparent transparent;
				left: -11px;
			}
			.timer{
				position: absolute;
				width: 320px;
				text-align: center;
				top: -17px;
				right: 0;
			}
		</style>
	</head>
	<body  >
		<div class="box">
			<!--資訊記錄-->
			<ul id="max">
			</ul>
			<!--發資訊功能區-->
			<div class="message">
				<!--表情-->
				<div id="ejmo"></div>
				<!--文本輸入框-->
				<input type="button" id="btn" value="發送" />
				<p id="userval" contenteditable="true"></p>
				<!--表情大全-->
				<dl class="biaoqian"></dl>
				<!--切換表情頁-->
				<ul id="subNum">
					<li></li>
					<li></li>
					<li></li>
					<li></li>
				</ul>
			</div>
		</div>
	</body>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
	<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.dev.js"></script>
	<script type="text/javascript">
		//封裝擷取id的方法
		function $(ele){
			return document.getElementById(ele);
		}
		
		//前端沒有傳入任何的伺服器  預設會傳入目前伺服器
    	var socket = io();
    	//當使用者第一次進入頁面的時候  給其他客服端發送提示
    	//重新整理頁面的時候  如果我們已經登入過的狀态的時候  不應該提醒另外的用戶端 新使用者上線 
    	
    	socket.emit('newFriend','有新的好友進入聊天室..');
    	
    	//監聽當有新使用者加入的時候
    	socket.on('message',function(data){
    	   var p=document.createElement('p');
	      p.innerHTML=data;
	      p.id='p_f';
	      document.body.appendChild(p);
	      //擷取上面建立新使用者進入提示的p元素
	      var alertBox=$('p_f');
	      var num=0;
	      var timer=setInterval(function(){
	      	num++;
	      	if(num>5){
	      		//顯示5秒後  删除新使用者進入提示的p元素
	      		alertBox.remove();
	      		clearInterval('timer');
	      	}
	      },1000)
    	});
    	
    	//當收到其他客服端發送的消息的時候   在頁面上顯示其他客服端發送的消息
		socket.on('oterFriend',function (obj) {
			craeteLi(obj,'','<span class="triangleLeft"></span>')
		});
		
		//當點選發送資訊按鈕的時候
		var btn=$('btn');//發送消息按鈕
		var val=$('userval');//消息輸入框
		btn.onclick = function () {
			if(val.innerHTML!=''){
				//給發送給伺服器顯示給它客服端顯示目前發送的資訊
				socket.emit('myMessage',val.innerHTML);
		      craeteLi(val.innerHTML,'f_r','<span class="triangleRight"></span>');
		      val.innerHTML='';//點選發送後清空目前文本框
			}
		}
		
		//發送一條消息或者   接受一條消息就往ul消息大盒子中  建立li節點
		function craeteLi(val,cla,fx){
			var oLi=document.createElement('li');
			//擷取時間盒子
			var oSpan=document.getElementsByClassName('timer');
			//擷取目前的時間
			var newDate=`${new Date().getHours()}:${new Date().getMinutes()}`;
			var timer=`<span class="timer">${newDate}</sapn>`.toString();
			for(var i=0;i<oSpan.length;i++){
				if(oSpan[i].innerHTML==newDate){
					timer='';
				}
			}
	      oLi.innerHTML=val+fx+timer;
	      oLi.className=cla;
	      $('max').appendChild(oLi);//包裹聊天資訊的ul大盒子
	      $('max').scrollTop=$('max').scrollHeight;
		};
		
    	//裝表情圖的大盒子
    	var biaoQ=document.getElementsByClassName('biaoqian')[0];
    	var toggle=true;
    	//點選表情圖示  顯示裝表情圖的大盒子
    	$('ejmo').onclick=function(){
    		if(toggle==true){
    			toggle=false;
    			biaoQ.style.display='block';
    			//切換表情頁的小圓點
    			$('subNum').style.display='block';
    			//首次點選表情圖示後顯示第一頁的24個表情
    			toggleImg(0,24)
    		}else{
    			toggle=true
				biaoQ.style.display='none';
				$('subNum').style.display='none';
    		}
		}
    	
    	//切換表情圖示的小圓點頁
    	var biaoPage=$('subNum').getElementsByTagName('li');
    	for(var i=0;i<biaoPage.length;i++){
    		biaoPage[i].index=i+1;
    		biaoPage[i].onclick=function(){//點選小圓點切換相應的圖檔
    			//自定義屬性*24-24為目前表情圖檔序号最小值     自定義屬性*24為目前表情圖檔序号最大值   一頁表情24個表情圖示
    			toggleImg(this.index*24-24,this.index*24);
    		}
    	}
    	
    	//點選圖示頁的小圓點  切換相應的表情頁封裝函數
    	function toggleImg(min,max){
    		var str='';
			for(var i=min;i<max;i++){
				var str1='<img src="images\\arclist\\'+i+'.gif">';
				str+=`<img src="images/arclist/${i}.gif">`;
			}
			biaoQ.innerHTML=str;
			$('subNum').style.display='block';
    	}
    	
    	//阻止contenteditable  輸入框回車換行的預設事件
		val.onkeydown=function(e){
			if(e.keyCode==13){
				btn.click();
				e.preventDefault();
			}
		}
		//點選某個表情圖示的時候    插入點選的表情圖示到内容輸入框
    	biaoQ.onclick=function(ev){
    		if(ev.target.nodeName=='IMG'){
    			var imgSrc=ev.srcElement.currentSrc.split('arclist/')[1];
				val.focus();
	    		insertHtmlAtCaret(`<img src="images/arclist/${imgSrc}">`);//插入表情到輸入框
    		}
    	}
    	
		//解決在輸入框不能在光标位置插入表情的函數封裝
		function insertHtmlAtCaret(html) {
        var sel, range;
        if (window.getSelection) {
            // IE9 and non-IE
            sel = window.getSelection();
            if (sel.getRangeAt && sel.rangeCount) {
                range = sel.getRangeAt(0);
                range.deleteContents();
                // Range.createContextualFragment() would be useful here but is
                // non-standard and not supported in all browsers (IE9, for one)
                var el = document.createElement("div");
                el.innerHTML = html;
                var frag = document.createDocumentFragment(), node, lastNode;
                while ((node = el.firstChild)) {
                    lastNode = frag.appendChild(node);
                }
                range.insertNode(frag);
                // Preserve the selection
                if (lastNode) {
                    range = range.cloneRange();
                    range.setStartAfter(lastNode);
                    range.collapse(true);
                    sel.removeAllRanges();
                    sel.addRange(range);
                }
            }
         }else if (document.selection && document.selection.type != "Control") {
            document.selection.createRange().pasteHTML(html);
        }
      }
	</script>
           

繼續閱讀