node+websocket+html模仿腾讯课堂聊天室聊天功能

前端部分用到的知识:websocket,h5,contenteditable属性

服务端部分:node, websocket

部分效果:

功能细节需要注意的地方

前端部分:


(1)输入框要可以输入表情图片( 不能用textarea,要用contenteditable='true'来实现)

(2)消息数量的显示限制,比如我最多只显示最新的30条消息 (通过对dom节点的长度判断和移除实现)

  (3) 最新消息要始终显示在底部(通过scrollTop来实现)

 (4)对信息分类进行区分,是用户进入,离开,普通消息,还是送花进行划分

服务端部分:

websocket相关知识的运用

代码:

<!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">
    <link rel="stylesheet" type="text/css" href="css/style.css" />
    <title>聊天室</title>
</head>
 
<body>
    <div class="container">
        <header>不充钱你觉得你会变得更强吗!!!</header>
        <div class="cont">
            <video src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" controls="controls"></video>
        </div>
        <div class="right">
            <div class="right_top">
                <div class="item ac_border">讨论</div>
                <div class="item" id="person">成员</div>
            </div>
            <div class="r_item">
                <div class="right_cont">
                    <ul id="messageWrap"></ul>
                </div>
                <div class="right_bot">
                    <div class="r_b_t clearfix">
                        <div class="emoji " title="选择标签"></div>
                        <div class="flower" title="献花"></div>
                    </div>
                    <div class="inputMeg_f">
                        <!--inputMeg外添加div inputMeg_f 的原因是为了自定义滚动条的手势是箭头,如果不加,改成inputMeg设置滚动条样式,那么滚动条的熟悉是输入手势-->
                        <div class="inputMeg" contenteditable="true" placeholder="请输入文字"></div>
                    </div>
                    <div class="send_btn">发送</div>
                    <div id="emojiBox" class="clearfix"></div>
                </div>
            </div>
            <div class="r_item" style="display: none">
                 <ul class="personWrap"></ul>
            </div>
        </div>
    </div>
</body>
 
<script src="../jquery.js"></script>
<script>
    $(".right_top .item").click(function () {
        $(this).siblings().removeClass('ac_border')
        $(this).addClass('ac_border')
        $('.r_item').css('display','none').eq($(this).index()).css('display','block')
    })
 
    function checkValue() {
 
        $(".emoji").off('click').click(function (e) {
            $("#emojiBox").css('display', 'block')
            var ev = e || window.event;
            ev.stopPropagation();
        })
        $(".container").off('click').click(function () {
            $("#emojiBox").css('display', 'none')
        })
 
 
    }
    checkValue();
 
    //生成表情
    var emojiHtml = '';
    var emojiBox = document.getElementById('emojiBox');
    for (var i = 0; i < 7; i++) {
        for (var j = 0; j < 15; j++) {
            var dom = document.createElement('div');
            dom.className = 'emojiItem';
            dom.style.backgroundPositionX = -24 * j + 'px';
            dom.style.backgroundPositionY = -29 * i + 'px';
            emojiBox.appendChild(dom)
            chooseEmoji(i, j, dom)
        }
 
    }
 
    function chooseEmoji(i, j, dom) {
        dom.onclick = function (e) {
            const src = 'img/icon' + (i * 15 + j) + '.gif';
            var img = $('<img class="emojiImg" src=' + src + '>')
            $('.inputMeg').append(img)
            $("#emojiBox").css('display', 'none')
            var ev = e || window.event;
            ev.stopPropagation();
        }
    }
 
    var userName=''; //当前登录的用户
    //websocket
    var websocket = new WebSocket(
    'ws://localhost:8001/'); //连接的地址,是ws协议,不是http协议(本地地址localhost:8001,要想手机也能访问到,改成本地ip192.168.0.107:8001)
    websocket.onopen = function () { //监听建立连接
        $('.send_btn').off('click').click(function () {
            var text = $('.inputMeg').html()
            if (text != '' && text != '请输入文字') {
                websocket.send(JSON.stringify({data:text,type:'message'})) //发送消息
                $('.inputMeg').html('')
            }
        });
 
        $('.flower').off('click').click(function(){ //送花
           var dom= '<span>"'+userName+'"</span>送给<br> "春哥" 一朵小花<i class="flowIcon"></i>'
           
           websocket.send(JSON.stringify({data:dom,type:'flower'})) //发送消息
        })
 
    }
    websocket.onmessage = function (e) {
        var res = JSON.parse(e.data);
        message(res)
    }
 
 
    function message(res) {
        var dom = document.createElement('li');
        switch (res.type) {
            case 'enter':
                dom.innerHTML = res.data;
                dom.style.color = 'green';
                userName=res.nickname;
                person(res);
                break;
            case 'leave':
                dom.innerHTML = res.data;
                dom.style.color = 'red';
                person(res)
                break;
            case 'message':
                name.innerHTML = res.nickname + ': ';
                dom.innerHTML = "<span class='nickName'>" + res.nickname + ": </span> " + res.data + ""
                break;
            case 'flower':
                dom.className='flowerLi';
                dom.innerHTML=res.data;
                break;
            default:
                break;
        }
        document.getElementById('messageWrap').appendChild(dom);
        limitLength(30)
        scrollBottom();
 
        //成员显示
 
    }
 
    function scrollBottom() { //显示最新消息在底部
        var h1 = document.getElementsByClassName('right_cont')[0].offsetHeight;
        var h2 = document.getElementById('messageWrap').offsetHeight;
        if (h2 > h1) {
            $('.right_cont').scrollTop(h2 - h1);
        }
    }
 
    function limitLength(num) { //限制聊天室最多能显示几条消息
        var li = $('#messageWrap li')
        if (li.length > num) {
            li.eq(0).remove();
        }
    }
 
    function person(res){  //成员显示
        var html=''
        for(var i=0;i<res.client.length;i++){
            html+= '<li><span class="nickname">'+res.client[i]+'</span></li>'
        }
        $('.personWrap').html(html);
        
        $('#person').html('成员('+res.client.length+')')
 
    }
</script>
 
</html>
 
 
server.js:
var ws = require("nodejs-websocket")
var port=8001;
var clientCount=0;
var nicknameArr=[];
var server = ws.createServer(function (conn) {
	clientCount++;
	conn.nickname='user'+clientCount;
	nicknameArr.push(conn.nickname)
	var mes={type:'enter',data:'欢迎 '+conn.nickname+' 进入聊天',nickname:conn.nickname,client:nicknameArr}
	broadcast(JSON.stringify(mes))
	conn.on("text", function (str) {  //监听客户端发送过来的消息
		var zstr=JSON.parse(str)
		var mes={type:zstr.type,data:zstr.data,nickname:conn.nickname,client:nicknameArr}
		broadcast(JSON.stringify(mes))
		
	})
	conn.on("close", function (code, reason) {
		clientCount--;
		for(var i=nicknameArr.length-1;i>=0;i--){  //删除退出的用户
			if(conn.nickname==nicknameArr[i]){
				nicknameArr.splice(i,1)
			}
		}
		var mes={type:'leave',data:conn.nickname+' 离开聊天',nickname:conn.nickname,client:nicknameArr}
		broadcast(JSON.stringify(mes))
	});
	conn.on('error',function(err){
		console.log('handle err')
	})
}).listen(port)
function broadcast(str){  //获取客户端连接的人数并返回消息
	server.connections.forEach(function(connection){
		connection.sendText(str)
	})
 
}


落魄前端-小陈
0
0
0
评论
浏览
收藏