天天看點

Websocket直播間聊天室教程 - GoEasy快速實作聊天室Websocket直播間聊天室教程 - GoEasy快速實作聊天室登入聊天室(直播間)

Websocket直播間聊天室教程 - GoEasy快速實作聊天室

最近兩年直播那個火啊,真的是無法形容!經常有朋友問起,我想實作一個直播間聊天或者我想開發一個聊天室, 要如何開始呢?

Websocket直播間聊天室教程 - GoEasy快速實作聊天室Websocket直播間聊天室教程 - GoEasy快速實作聊天室登入聊天室(直播間)

今天小編就手把手的教你用GoEasy做一個聊天室,當然也可以用于直播間内的互動。

本教程主要目的是為大家介紹實作思路,為了確定本教程能幫助到使用不同前端技術的朋友,采用了HTML + JQuery的方式,後續還會推出Uniapp(vue/nvue)和小程式版本,大家可以持續關注。

我們這次要實作的聊天室,有兩個界面,分别是:

  • 登入界面
  • 聊天室界面

登入

Websocket直播間聊天室教程 - GoEasy快速實作聊天室Websocket直播間聊天室教程 - GoEasy快速實作聊天室登入聊天室(直播間)

對于登入界面,我們期望:

  • 使用者可以輸入自己的昵稱
  • 使用者可以選擇自己喜歡的頭像
  • 使用者可以選擇進入不同的聊天室(直播間)

實作步驟

登入界面的實作,不用多說,因為真的是So Easy! 一個簡單的界面,隻包含三個簡單的邏輯:

  • 驗證是否輸入昵稱
  • 驗證是否選擇一個頭像
  • 根據選擇進入相應的聊天室

下邊重點講一下聊天室的實作。

聊天室(直播間)

Websocket直播間聊天室教程 - GoEasy快速實作聊天室Websocket直播間聊天室教程 - GoEasy快速實作聊天室登入聊天室(直播間)

當我們進入一個聊天室後,我們期望:

  • 使用者能看到目前有多少使用者線上,這個數字能夠實時的更新
  • 使用者能看到目前線上使用者們的頭像,而且能夠實時的更新
  • 如果有使用者進入或離開聊天室
    1. 聊天室會有“XXX進來了"或"XXX離開了"的提示
    2. 線上使用者的數字和使用者的頭像清單會随之自動更新
  • 使用者可以在聊天裡發言
  • 使用者可以發送道具:火箭或者比心

第一步:聊天室界面顯示

1. 初始化:

當使用者選擇了一個聊天室,顯示聊天室界面之前,我們首先要進行以下初始化工作:

  • 初始化目前使用者currentUser,使用者id,昵稱,頭像
  • 初始化目前聊天室ID: currentRoomId
  • 初始化GoEasy對象,注意一定要加上userId參數(可以是該使用者的uuid或id等唯一辨別,隻有設定了userId的用戶端在上下線時,才會觸發上下線提醒)。同時需要将頭像和昵稱放入userData,當我們收到一個使用者上線提醒的時候,我們需要知道這個使用者的頭像和昵稱。
  • 初始化onlineUsers,onlineUsers是用來存放目前聊天室線上使用者數和線上使用者清單。 将目前聊天室Id (currentRoomId)作為channel,執行goEasy.hereNow查詢此刻聊天室線上使用者數和使用者清單,指派給onlineUsers。除了在進入聊天室的時候初始化onlineUsers,當有使用者進入或離開時,也會動态的更新onlineUsers。
  • 以目前聊天室的id(currentRoomId)作為channel,執行subscriber方法監聽和接收聊天室新消息。
  • 以目前聊天室的id(currentRoomId)作為channel,執行subscriberPresence監聽使用者進入和離開事件。

參考代碼:service.js

//初始化聊天室
this.joinRoom = function(userId,nickName, avatar, roomID) {
        //初始化目前使用者
        this.currentUser = new User(userId, nickName, avatar);
        //初始化目前聊天室id
        this.currentRoomId = roomID;
        //初始化goeasy,建立長連接配接
        this.goeasy = new GoEasy({
            host: "hangzhou.goeasy.io",
            appkey: "您的appkey",
            userId: this.currentUser.id,
            userData: '{"nickname":"' + this.currentUser.nickname + '","avatar":"' + this.currentUser.avatar + '"}',
            onConnected: function () {
                console.log( "GoEasy connect successfully.")
            },
            onDisconnected: function () {
                console.log("GoEasy disconnected.")
            }
        });
        //查詢目前線上使用者清單,初始化onlineUsers對象
        this.initialOnlineUsers();
        //監聽使用者上下線提醒,實時更新onlineUsers對象
        this.subscriberPresence();
        //監聽和接收新消息
        this.subscriberNewMessage();
};           

2. 頁面展示:

完成初始化之後,就跳轉到直播間界面,在頁面上顯示以下資料:

  • 目前聊天室的名稱
  • 聊天記錄,并且顯示聊天室界面
  • 展示聊天室界面

參考代碼:controller.js

//頁面切換到聊天室界面
function showChatRoom() {
    //更新房間名
    $("#chatRoom-header").find(".current-chatRoom-name").text(loginCommand.roomName);

    //加載聊天曆史
    var chatHistory = service.loadChatHistory();
    chatHistory.forEach(function (item) {
        //展示發送的消息
        var otherPerson = createCurrentChatRoomPerson(item.senderNickname + ":", item.content)
        $(".chatRoom-content-box").append($(otherPerson));
    });

    //隐藏登入界面
    $(".chat-login-box").hide();
    // //顯示聊天界面
    $(".chatRoom-box").show();
    // //滑動到最後一行
    scrollBottom();
}           

至此,我們已經完成了goeasy長連接配接的初始化,和一個聊天室靜态展示。接下來,我們一起來看看如何讓這個聊天室能夠動起來。

第二步:聊天室互動

1. 實時更新線上使用者數和頭像清單

之前在service.initialOnlineUsers方法已經初始化onlineUsers對象,但聊天室随時都有使用者進進出出,是以我們接下來還需要能夠在有使用者上線或下線的時候能夠實時的更新onlineUsers,并且實時顯示在頁面上。

當我們收到一個使用者上線提醒,我們将新上線的使用者的資訊存入線上使用者對象onlineUsers裡,當有使用者離開時,在本地線上使用者清單裡删除。

//監聽使用者上下線時間,維護onlineUsers對象
this.subscriberPresence = function() {
    var self = this;
    this.goeasy.subscribePresence({
        channel: this.currentRoomId,
        onPresence: function(presenceEvents) {
            presenceEvents.events.forEach(function(event) {
                var userId = event.userId;
                var count = presenceEvents.clientAmount;
                //更新onlineUsers線上使用者數
                self.onlineUsers.count = count;
                //如果有使用者進入聊天室
                if (event.action == "join" || event.action == "online") {
                    var userData = JSON.parse(event.userData);
                    var nickName = userData.nickname;
                    var avatar = userData.avatar;
                    var user = new User(userId, nickName, avatar);
                    //将新使用者加入onlineUsers清單
                    self.onlineUsers.users.push(user);
                    //觸發界面的更新
                    self.onJoinRoom(user.nickname, user.avatar);
                } else {
                    for (var i = 0; i < self.onlineUsers.users.length; i++) {
                        var leavingUser = self.onlineUsers.users[i];
                        if (leavingUser.id == userId) {
                            var nickName = leavingUser.nickname;
                            var avatar = leavingUser.avatar;
                            //将離開的使用者從onlineUsers中删掉
                            self.onlineUsers.users.splice(i, 1);
                            //觸發界面的更新
                            self.onLeaveRoom(nickName, avatar);
                        }
                    }
                }
            });
        },
        onSuccess : function () {
            console.log("監聽成功")
        },
        onFailed : function () {
            console.log("監聽失敗")
        }
    });
};           

2. 發送消息

  • 初始化一個chatMessage對象,包含發送方id,昵稱,消息内容,消息類型為chat
  • 将chatMessage轉換為一個Json格式的字元串
  • 調用GoEasy的Publish方法,完成消息的發送

參考代碼(service.js)

this.sendMessage = function(content) {
    var message = new ChatMessage(this.currentUser.id,this.currentUser.nickname, MessageType.CHAT, content);
    var self = this;
    this.goeasy.publish({
        channel: self.currentRoomId,
        message: JSON.stringify(message),
        onSuccess: function() {
            console.log("消息釋出成功。");
        },
        onFailed: function(error) {
            console.log("消息發送失敗,錯誤編碼:" + error.code + " 錯誤資訊:" + error.content);
        }
    });
};           

3. 接收和顯示新消息/道具

之前我們已經在初始化頁面的時候執行了service.subscriberNewMessage(),當我們收到一條消息時:

  • 根據消息類型判斷是一條聊天消息,還是一個道具
  • 如果收到的是一條聊天消息,直接顯示到界面
  • 如果是道具,就播放動畫

參考代碼(service.js)

//監聽消息或道具
this.subscriberNewMessage = function() {
    var self = this;
    this.goeasy.subscribe({
        channel: this.currentRoomId, //替換為您自己的channel
        onMessage: function(message) {
            var chatMessage = JSON.parse(message.content);
            //todo:事實上不推薦在前端收到時儲存, 一個使用者開多個視窗,會導緻重複儲存, 建議所有消息都是都在發送時在伺服器端儲存,這裡隻是為了示範
            self.restapi.saveChatMessage(self.currentRoomId, chatMessage);
            //如果收到的是一個消息,就顯示為消息
            if (chatMessage.type == MessageType.CHAT) {
                var selfSent = chatMessage.senderUserId == self.currentUser.id;
                var content = JSON.parse(message.content);
                self.onNewMessage(chatMessage.senderNickname, content, selfSent);
            }
            //如果收到的是一個道具,就播放道具動畫
            if (chatMessage.type == MessageType.PROP) {
                if (chatMessage.content == Prop.ROCKET) {
                    self.onNewRocket(chatMessage.senderNickname);
                }
                if (chatMessage.content == Prop.HEART) {
                    self.onNewHeart(chatMessage.senderNickname);
                }
            }
        }
    });
};           

4. 發送和接收并展示道具

其實和發送消息的實作幾乎是一樣的,具體代碼請參考service.js的sendProp方法,controller.js的onNewHeart()方法。動畫的播放,使用了TweenMax這個庫,主要是為了展示一個實作思路,小編也不知道這個庫是否有很好的相容性,以及是否能夠用在Uniapp和小程式下,知道的朋友可以留言分享給大家。

this.sendProp = function(prop) {
    var self = this;
    var message = new ChatMessage(this.currentUser.id,this.currentUser.nickname, MessageType.PROP, prop);
    this.goeasy.publish({
        channel: self.currentRoomId,
        message: JSON.stringify(message),
        onSuccess: function() {
            console.log("道具釋出成功。");
        },
        onFailed: function(error) {
            console.log("道具發送失敗,錯誤編碼:" + error.code + " 錯誤資訊:" + error.content);
        }
    });
};           

至此,一個聊天室就搞定了,是不是很簡單?

全套源碼已經開源,git位址:

https://gitee.com/goeasy-io/GoEasyDemo-Live-Chatroom.git

繼續閱讀