200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > Emoji-Chat emoji表情包发送及显示兼容web端 移动端

Emoji-Chat emoji表情包发送及显示兼容web端 移动端

时间:2019-08-18 16:05:45

相关推荐

Emoji-Chat emoji表情包发送及显示兼容web端 移动端

Emoji-Chat emoji表情包发送及显示兼容web端、移动端

序言

在如今聊天表情包满天飞的当下,聊天过程中想发送个表情感慨一下情绪在所难免,当下我就遇到这么个需求,希望在web端聊天室中可以发送表情,还得在web端、微信H5、app端、微信公众号里均可以正常显示出来

看到这个需求我的内心是这样的

一番Google下来发现网上的大多都是移动端发送,以字典的方式匹配替换后web端只是单纯的做显示而已,难以找出符合我需求的文章了,那没办法,产品是老大,只能自己研究研究咯。。。

心痒痒的话就先看看效果:click me

完整demo在这儿:click me

设计方案一

最开始的设计思路是既然emoji表情有对应的Unicode码,那么是不是可以直接就使用Unicode码来进行传输及显示,直接不做任何处理,基于各平台对Unicode的支持,让其自生自灭呢?想着就干,尝试一波再说。。。

看到这里如果真的动手去尝试了么估计你是真的没有好好了解一波emoji的Unicode码,只要进入官网或者各统计平台应该应该都可以看到这个东西

由上图可以看出个移动端对emoji的支持都存在如此大的差异,那么PC端的差距不看也知道不忍直视了,当然可能基于好奇和专研的精神,个别还是想去尝试一波,断绝念头。。。好比如我

<!DOCTYPE html><html><head><meta charset="UTF-8"><title></title><style type="text/css">.emoji-con_span {display: block;width: 300px;background-color: #cee6ff;color: #282828;border-radius: 4px;padding: 8px 12px;box-sizing: border-box;}</style></head><body><span class="emoji-con_span">emoji:😂😍😘</span></body></html>

你可以将如上代码运行于各浏览器,你可能看到这个效果

chrome

Firefox

​ IE

​ Edge

Android

由上可以看出各端的差距主要在移动端和IE之间,特别是移动端和PC端的差距,几乎改头换面了,这不说产品,自己这关很明显都过不了,况且IE非edge模式下还是黑白色。所以这个设计方案很明显被pass掉了

设计方案二

方案一的失败之处很明显,PC端各平台兼容性差而且样式和移动端相比low的不行,最好的显示效果很明显是iOS端的emoji表情图标。基于此既然我们不能统一使用Unicode码来显示,但是我们却可以使用它来传输和存储(不论云信、还是数据库都能解析),所以我们唯一需要解决的问题就是显示而已,既然如此,那么设计思路就很清晰了

不论是各端怎么传输,还是数据库存储都直接使用Unicode来进行,APP端直接使用系统自带的emoji支持来显示,PC端则使用切图将Unicode正则匹配替换来显示,即只需要做一个字典来进行正则替换就OK

有兴趣不防撸撸代码尝试一下:

<template><div id="chat" class="chat_page_con"><!-- 输入框 --><div>Ctrl + Enter 发送消息:</div><div id="charInput" @click="saveRangeLocal"@focus="saveRangeLocal" @keyup="inputSend"@input="saveRangeLocal" class="chatframe_input_con scrollbar" contenteditable="true"></div><!-- 表情选择器 --><div class="chatframe-icon"><el-popoverplacement="bottom-start"width="400"trigger="click"><el-tabs tab-position="bottom" value="Emotions" class="emoji_tabs_box"><el-tab-pane v-for="(emojiCon, emojiKey, eInd) in emojiIcon" :key="emojiKey":label="emojiKey" :name="emojiKey"><!-- 这里的label icon不能放到json配置文件中,因为icon放到配置文件中后无法渲染出来 --><!-- 这里很low可以自己修改,试用图片来替换,使用同样的图片加载方法保存在配置中 --><span v-if="eInd == 0" slot="label" class="iconfont emoji_pane_tab">&#xe612;</span><span v-if="eInd == 1" slot="label" class="iconfont emoji_pane_tab">&#xe609;</span><span v-if="eInd == 2" slot="label" class="iconfont emoji_pane_tab">&#xe62d;</span><span v-if="eInd == 3" slot="label" class="iconfont emoji_pane_tab">&#xe63c;</span><img v-for="(emoItem, emoInd) in emojiCon" :key="emoInd" :src="getIconPic(emoItem.unicode)" alt="X"@click="sendEmojiIcon(emoItem.unicode)"class="chat_emoji_item"></el-tab-pane></el-tabs><el-button class="iconfont open_emoji_icon" type="text" slot="reference">&#xe612;</el-button></el-popover></div><!-- 显示内容区 --><div>发送的消息:</div><div class="chatframe-text text_emoji" v-html="changeEmojiCon(sendValue)"></div></div></template>

页面代码设计相对简单,可以根据自己需求选取,重点是接下来的JS方法解读(这里只列出个别重要一点的方法做解释,完整demo自寻仓库取)

定义data存储字段

data () {return {emojiIcon: emojiData.icon, // 导入的emoji表情配置文件内容emojiPath: new Map(), // emoji表情地址map对象,inputRange: '',// 光标sendValue: '',// 发出的内容}}

这其中涉及到一个字段为inputRange(光标),这里解释一下,因为插入emoji表情时需要动态的往用户编辑的当前光标处去插入emoji,所以不管用户是输入还是点击都需要获取一下当前光标,然后将其记录下来,当点击emoji表情是就将其插入到记录的光标处

记录光标

// 延时记录光标到位置saveRangeLocal () {setTimeout(() => {this.inputRange = window.getSelection().getRangeAt(0)}, 0)}

获取光标保存时并不能直接就实时获取,否则会所以报错或undefined,所以这里使用宏任务来进行延时获取

插入表情到富文本

// 点击表情,将表情添加到输入框sendEmojiIcon (code) {let inputNode = document.getElementById('charInput')let html = "<img src='"+ this.getIconPic(code) +"' unicode = '" + code + "' alt='' >"let sel = window.getSelection()let range = this.inputRangelet el = document.createElement("div")let frag = document.createDocumentFragment(), node, lastNodeif (!inputNode) {return}if (!range) {inputNode.focus()range = window.getSelection().getRangeAt(0)}range.deleteContents()el.innerHTML = htmlwhile ((node = el.firstChild)) {lastNode = frag.appendChild(node)}range.insertNode(frag)if (lastNode) {range = range.cloneRange()range.setStartAfter(lastNode)range.collapse(true)sel.removeAllRanges()sel.addRange(range)}}

输入框使用的是输入框使用富文本模式,所以点击emoji表情时都是传入Unicode值,字典匹配,插入对应的表情图片,再插入的image标签上添加一个Unicode属性,用于解析时字典对比替换

图片Emoji转换及发送消息

// 将输入框中的图片替换为emoji表情formatInputCon () {let inputValue = document.getElementById('charInput').innerHTMLinputValue = inputValue.replace(/<img.*?(?:>|\/>)/gi, (val) => {let unicode = val.match(/unicode=[\'\"]?([^\'\"]*)[\'\"]?/i)[1]let icon = this.emojiIconlet iPic = ''// 遍历查找Unicode表情for (const key in icon) {if (icon.hasOwnProperty(key)) {const iType = icon[key]let flag = falsefor (let index = 0; index < iType.length; index++) {const element = iType[index]if (element.unicode == unicode) {iPic = element.emojiflag = truebreak}}if (flag) {break}}}return iPic})return inputValue}

// 发送消息inputSend (e) {if ((e.ctrlKey && e.keyCode == 13) || (e.ctrlKey && e.keyCode == 108)) {// 提交的时候使用正则替换,将br换位换行符,不能使用innertext转,有兼容性问题this.sendValue = this.formatInputCon().replace(/<br>/g, '\r\n')} }

发送消息之前需要将输入框中的Emoji图片转换为相应的Emoji的Unicode值,同时由于使用的是富文本编辑器,所以拿到的内容中换行都是以‘br’标签来实现的,转换文本时需要替换为’\r\n‘

Emoji到图片转换

// 将emoji表情转换为图片changeEmojiCon (str) {let patt = /[\ud800-\udbff][\udc00-\udfff]/g // 检测utf16字符正则str = str.replace(patt, (char) => {let H, L, codeif (char.length === 2) {H = char.charCodeAt(0) // 取出高位L = char.charCodeAt(1) // 取出低位code = (H - 0xD800) * 0x400 + 0x10000 + L - 0xDC00 // 转换算法return "&#" + code + ";"} else {return char}})str = str.replace(/&#{1}[0-9]+;{1}/ig, (a) => {let unicode = a.replace(/^&#{1}/ig, '')unicode = unicode.replace(/;{1}$/ig, '')unicode = 'U+' + (parseFloat(unicode).toString(16).toUpperCase())return "<img src='"+ this.getIconPic(unicode) +"'/>"})return str}

拿到消息体时需要将其中的Emoji的Unicode码值转换为图片,最后以InnerHTML的方式插入到显示器

转自/zhazhanitian/p/11129158.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。