记录一次微信小程序进行长连接通信使用emoji表情

前言

起因是工作中微信小程序要做一个实时聊天功能并且可以发表情,在微信官方文档中其实是有emoji扩展组件的,用法也大概说明;自己看了一下文档。

之后自己理了理思路,摸索着自己写一个。

正文

Emoji代码大全:http://www.oicqzone.com/tool/emoji/

以下代码都是使用的上面网址的emoji表情代码

首先分析一下,微信小程序聊天功能还带发表情的思路,我的思路如下

  • 用户在input框输入内容&选择表情,input中显示的是内容和表情(eg:这是内容😵);
  • 前端进行相关转码处理,将input的内容变成(这是内容#emo34_),然后点击发送将转码后的文本内容发送给后端
  • websocket服务器进行广播,将(这是内容#emo34_)这段文字发给前端
  • 前端对(这是内容#emo34_)这段文字进行解码处理,最后变成(这是内容😵),从而渲染在页面上
直接上代码
准备工作:
//失焦后确认焦点位置
blurcursor: '',
//失焦后的文本
blurText: '',
//用于存储当前表情
currentEmoji: {},
//当前文本内容,用于用户输入框展示
inputText: '',
//当前文本内容,所有表情转换为(#emoxx_)格式,发给后端也是发送inputText_code
inputText_code: '',
//input框光标位置,后续input框删除文字或标签会用到
input_cursor: 0,
//定义一个emoji表情的数组,emoji字段用于展现到页面上,code字段用于传输
emojiArr: [
      { emoji: '😠', code: '#emo30_' },
      { emoji: '😩', code: '#emo31_' },
      { emoji: '😲', code: '#emo32_' },
      { emoji: '😞', code: '#emo33_' },
      { emoji: '😵', code: '#emo34_' },
      { emoji: '😰', code: '#emo35_' },
      { emoji: '😒', code: '#emo36_' },
      { emoji: '😍', code: '#emo37_' },
      { emoji: '😤', code: '#emo38_' },
      { emoji: '😜', code: '#emo39_' },
      { emoji: '😝', code: '#emo40_' },
      { emoji: '😋', code: '#emo41_' },
      { emoji: '😘', code: '#emo42_' },
      { emoji: '😚', code: '#emo43_' },
      { emoji: '😷', code: '#emo44_' },
      { emoji: '😳', code: '#emo45_' },
      { emoji: '😃', code: '#emo46_' },
      { emoji: '😅', code: '#emo47_' },
      { emoji: '😆', code: '#emo48_' },
      { emoji: '😁', code: '#emo49_' },
      { emoji: '😂', code: '#emo50_' },
      { emoji: '😊', code: '#emo51_' },
      { emoji: '😄', code: '#emo53_' },
      { emoji: '😢', code: '#emo54_' },
      { emoji: '😭', code: '#emo55_' },
      { emoji: '😨', code: '#emo56_' },
      { emoji: '😣', code: '#emo57_' },
      { emoji: '😡', code: '#emo58_' },
      { emoji: '😌', code: '#emo59_' },
      { emoji: '😖', code: '#emo60_' },
      { emoji: '😔', code: '#emo61_' },
      { emoji: '😱', code: '#emo62_' },
      { emoji: '😪', code: '#emo63_' },
      { emoji: '😏', code: '#emo64_' },
      { emoji: '😓', code: '#emo65_' },
      { emoji: '😥', code: '#emo66_' },
      { emoji: '😫', code: '#emo67_' },
      { emoji: '😉', code: '#emo68_' },
    ]
实现:
  1. 在wxml中将emojiArr遍历,取emoji字段渲染在页面中,data-code为code字段的内容,data-emoji为emoji字段

    <view style="display:{{bottom3Isshow}}" class="bottom-3">
                <view class="emoji" wx:for="{{emojiArr}}" wx:for-item="item" wx:key="id" bindblur='bindblur'  bindtap='changeCurrentEmoji' data-code='{{item.code}}' data-emoji='{{item.emoji}}'>
                    {{item.emoji}}
                </view>
    </view>
    
  2. 为上面遍历出来的表情都加一个点击事件,用于存储当前表情

//添加当前表情
  changeCurrentEmoji(e) {
    let tempCursor = this.data.blurcursor
    let tempText = (this.data.blurText).split('')
    if (tempCursor == tempText.length) {
      this.setData({
        currentEmoji: e.currentTarget.dataset
      }, () => {
        this.setData({
          inputText: this.data.inputText + this.data.currentEmoji.emoji
        })
        this.setData({
          inputText_code: this.data.inputText_code + this.data.currentEmoji.code
        })
      })
    } else {
      let inputText_code = this.data.inputText_code
      let inputText = this.data.inputText
      inputText_code = inputText_code.split(/[\#,_]/)
      //去空
      inputText_code = inputText_code.filter(value => value)
      inputText = inputText.split('')
      for (let i = 0; i < inputText_code.length; i++) {
        if (inputText_code[i].indexOf("emo") == -1) {
          inputText_code[i] = inputText_code[i].split('')
        } else {
          inputText_code[i] = ['emo_delet', inputText_code[i]]
        }
      }
      //扁平化
      inputText_code = [].concat.apply([], inputText_code);
      console.log('inputText_code', inputText_code)
      inputText_code.splice(tempCursor, 0, e.currentTarget.dataset.code)
      let newCode = inputText_code.filter(value => {
        if (value.indexOf('emo_delet') == -1) {
          return value
        }
      })
      for (let i = 0; i < newCode.length; i++) {
        if (newCode[i].indexOf("emo") != -1) {
          // console.log(newCode[i])
          let temp = newCode[i].split('')
          if(temp[0] != '#'){
            newCode[i] = "#" + newCode[i] + "_"
          }
        }
      }
      let newCode_1 = [...newCode]
      let newCode_2 = ''
      for(let i=0;i<newCode_1.length;i++){
        newCode_2+=newCode_1[i]
      }

      for (let i = 0; i < newCode.length; i++) {
        if (newCode[i].indexOf("emo") != -1) {
          for (let j = 0; j < this.data.emojiArr.length; j++) {
            if ((this.data.emojiArr[j].code).indexOf(newCode[i]) != -1) {
              newCode[i] = this.data.emojiArr[j].emoji
            }
          }
        }
      }
      let newText = newCode
      let newText_2 = ''
      for(let i=0;i<newText.length;i++){
        newText_2+=newText[i]
      }
      this.setData({
        inputText:newText_2,
        inputText_code:newCode_2
      })
      console.log('newCode', newCode_2)
      console.log('newText', newText_2)
    }
  },

//监听input焦点
  bindblur(e) {
    console.log(e.detail) //cursor
    this.setData({
      blurcursor: e.detail.cursor,
      blurText: e.detail.value
    })
  },
  1. 为input绑定内容改变事件,用于实时改变inputText(用于显示在用户输入的input框)和inputText_code(用于发送给服务器)的值

    gitText(e) {
        //获取当前输入和上一次输入的差数
        let temp = (e.detail.value).slice((this.data.inputText).length)
        //确定光标位置,因为涉及到用户输入内容后可能会删除部分内容,这里做了这个处理,定位到用户想删除的内容从而进行改变inputText_code的值
        if (parseInt(e.detail.keyCode) == 8) {
          this.setData({
            input_cursor: e.detail.cursor
          }, () => {
              //这里的transcoder()方法后面会写到
            this.transcoder()
          })
        }
        else {
          this.setData({
            inputText: e.detail.value
          })
          this.setData({
            inputText_code: this.data.inputText_code + temp
          })
        }
    
      },
    
    //文字带表情转为文字+表情code
      transcoder() {
        let cursor = parseInt(this.data.input_cursor) + 1
        let temp = this.data.inputText_code
        let temp_1 = temp.split(/[\#,_]/)
        //去空字符串
        let newtemp = temp_1.filter(value => value)
        let count = 0
        for (let i = 0; i < newtemp.length; i++) {
          if (newtemp[i].indexOf('emo') == -1) {
            count += newtemp[i].length
            if (count >= cursor) {
              let delIndex = newtemp[i].length - (count - cursor) - 1
              let temp_2 = newtemp[i].split('')
              temp_2[delIndex] = ''
              let temp_3 = temp_2.filter(value => value)
              let str1 = ''
              for (let v = 0; v < temp_3.length; v++) {
                str1 += temp_3[v]
              }
              newtemp[i] = str1
              break
            }
          } else {
            count += 2
            if (count - 1 == cursor) {
              newtemp[i] = ''
            }
          }
        }
        let str = ''
        for (let y = 0; y < newtemp.length; y++) {
          if (newtemp[y].indexOf('emo') != -1) {
            str += "#" + newtemp[y] + "_"
          } else {
            str += newtemp[y]
          }
        }
        this.setData({
          inputText_code: str
        })
      },
    
  2. 将服务器发送过来的内容,也就是发给服务器的inputText_code转换为文字+表情

    //接收带表情的文字把表情转码
      decode(str) {
        let tempArr = str.split(/[\#,_]/)
        let newArr = tempArr.filter(value => value)
        for (let i = 0; i < newArr.length; i++) {
          for (let j = 0; j < (this.data.emojiArr).length; j++) {
            if (newArr[i].indexOf('emo') != -1 && (this.data.emojiArr[j]).code.indexOf(newArr[i]) != -1) {
              newArr[i] = (this.data.emojiArr[j]).emoji
            }
          }
        }
        let src = ''
        for (let i = 0; i < newArr.length; i++) {
          src += newArr[i]
        }
        return src
      },
    
最后总结一下:

在代码中以数组的方式存储emoji表情,数组的每一个值是一个对象,对象中有emoji表情代码和自定义的表情码,用户在input框输入文字加标签时,显示的是文字+表情代码;实际上传送给后端的是文字+自定义的表情码;当后端有内容传给前端时,前端再对文字+自定义表情码进行转换,最终变成文字+表情代码渲染在页面上。

这样的好处其实是为了减轻后端压力,不必考虑数据库是否可以存放emoji表情代码,数据库中只用存放特定的字符串,发给前端使用时,前端对特定的字符串进行处理

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值