// 判断是否输入emoji
function isEmojiCharacter(substring) {
for ( var i = 0; i < substring.length; i++) {
var hs = substring.charCodeAt(i);
if (0xd800 <= hs && hs <= 0xdbff) {
if (substring.length > 1) {
var ls = substring.charCodeAt(i + 1);
var uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
if (0x1d000 <= uc && uc <= 0x1f77f) {
return true;
}
}
} else if (substring.length > 1) {
var ls = substring.charCodeAt(i + 1);
if (ls == 0x20e3) {
return true;
}
} else {
if (0x2100 <= hs && hs <= 0x27ff) {
return true;
} else if (0x2B05 <= hs && hs <= 0x2b07) {
return true;
} else if (0x2934 <= hs && hs <= 0x2935) {
return true;
} else if (0x3297 <= hs && hs <= 0x3299) {
return true;
} else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030
|| hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b
|| hs == 0x2b50) {
return true;
}
}
}
}
/* 利用findSurrogatePair结合String.fromCharCode()来对unicode编码进行处理 */
function findSurrogatePair(point: any): any {
// assumes point > 0xffff
const offset = point - 0x10000,
lead = 0xd800 + (offset >> 10),
trail = 0xdc00 + (offset & 0x3ff);
return [lead.toString(16), trail.toString(16)];
}
let afterEmoji: any;
if (emoji.unified.length === 4) {
afterEmoji = String.fromCharCode(+'0x' + emoji.unified);
alert(afterEmoji);
} else {
const beforeEmoji = findSurrogatePair('0x' + emoji.unified);
afterEmoji = beforeEmoji.map(function (item: any, index: any): any {
const str = new String('0x' + item.trim());
return str;
});
afterEmoji = String.fromCharCode(afterEmoji[0], afterEmoji[1]);
alert(afterEmoji);
}
const expressionContent: any = afterEmoji;
<1f920只测了一部分
在安卓机上可以显示
1f920
1f930~1f93e
1f940~1f94b
1f950~1f95e
1f980~1f991
1f9c0
在安卓机上可以显示
>=20000时在pc端显示汉字等字,但是在安卓机上也没有显示出来,还是带叉的矩形框(只测了部分)
2049-fe0f这个也可以,对应的是一个感叹号加一个问号
四位数的也只测了几个,但是这几个也可以: 2753对应的是一个红色的问号 2754对应的是一个白色的问号,建议最好使用时再测一下,以防有所改动。
上面提到了charCodeAt和fromCharCode,
charCodeAt() 是普通字符串的方法,返回字符串指定位置的Unicode码点(十进制)表示。
var str=“abc”; console.log(str.charCodeAt(0);
97
fromCharCode() 它是String对象提供的静态方法(即定义在对象实例的方法),该方法的参数是一个或者多个值,代表unicode码点,返回值是这些码点组成的字符串。
String.fromCharCode(104,101,108,108,111);
hello
String.fromCharCode(97);
a
import {emojiIndex, Emoji} from 'emoji-mart'
const emINDEX: any = emojiIndex; //用于遍历表情数组,进行高级查询
1、存放表情在对应的图片中的位置posArray
2、表情集合emojiPoformaceArray
3、表情对应名字集合emojiNameArray
发送信息模块
首先得有一个用于高级查询的表情数组(如果明确要哪几个表情,没必要使用这种,可以直接使用,具体参照github对应的文章就可以。如果没有明确要哪个表情,就可以使用这种方式。
public constructor(props: IPropsSendAndShow){
/* 关于表情的部分为了防止初加载时没有显示出来对应的图片位置,对其设置了内容(即表情),后来加载出来后,需要清空之前的内容,显示图片就行 */
const timer = setInterval(function (): void {
if ($('#emoticonPackage .EmotionList-con button span')) {
if ($('#emoticonPackage .EmotionList-con button span').css('background-position')) {
$('#emoticonPackage .EmotionList-con button span').html('');
clearInterval(timer);
}
}
}, 1000);
this.state={arrayExpressSearch ['question','high five','hand','bell','+1','smile','good','congra','sad','hug','face_with_thermometer','presnt','book','paper',....]}
const aExprssion: any = this.state.arrayExpressSearch;
aExprssion.map((item: any,index: any): any=>{
const result1=emINDEX.search(item).map((o:any,Index: any): any=>{
//因为有些表情部分安卓手机显示不出来,所以做了处理
if ((o.unified <= '1f920' || o.unified >= '1f930' && o.unified <= '1f93e' || o.unified >= '1f940' && o.unified <= '1f94b' || o.unified >= '1f950' && o.unified <= '1f95e' || o.unified >= '1f980' && o.unified <= '1f991' || o.unified === '1f9c0') && o.unified < '20000' && o.unified !== "1f91f" && o.unified !== "1f481-200d-2642-fe0f" && o.unified !== "1f64b-200d-2642-fe0f" && o.unified !== "1f481-200d-2640-fe0f" && o.unified !== "1f64b-200d-2640-fe0f" || o.unified.length === 4) {
emojiPoformaceArray.push(o.native);
emojiNameArray.push(o.name);
/* const emojiProperty: any = { id: o['id'], skin: 6 };
return (
require('./images/appleExpress.png'))} onClick={(emoji, event) => that.expressionHandle(emoji)} />
); */
}
});
// resultexpression.push(result1); // 用于获取所有展示出的表情在图片中的位置集合posArray
});
public componentDidMount(): void{
const oSpan = $('.EmotionList-con span');
const oTSpan = Array.prototype.slice.call(oSpan);
const arr: any = [];
oTSpan.map((item: any, index: any) => {
arr.push($(item).css('background-position'));
});
console.log(arr);//获取到要展示的表情对应的位置,就可以直接写死了posArray(其值就是arr)
}
生成的表情块
<aside id="emoticonPackage">
<div className="emoticonPackagecontainer">
<div className="EmotionList">
<div className="EmotionList-con" style={{ top: '0px' }}>
{emojiPoformaceArray.map((item: any, index: any) => {
return (
<button title={emojiNameArray[index]} className="emoji-mart-emoji" type="button" key={index} onClick={() => that.expressionHandle(item)}>
<span style={{ backgroundPosition: posArray[index] }}>{item}</span>
</button>
);
})}
</div>
/* 最初使用下边的dom,是为了在componnetDidMount中获取所有展示出的表情在图片中的位置集合posArray,然后就可以使用上边的了 */
{/* {resultexpression} */}
</div>
</div>
</aside>
展示消息模块
searchSubStr查找一个字符串中的某个字串的位置
posLenIndex信息中的表情的在信息中对应的位置、表情的长度、表情集合中对应的索引位(用作查找到图片位置数组对应的数据)
三种情况:发的信息中有表情存在、送花、信息中没有表情
public render(): React.ReactNode {
return (
<div className="center" id="dialogue">
{this.state.message.map((item, index) => {
let content = JSON.parse(item)["content"][0];
let contentCopy: any = '';
/**
*查找一个字符串中的所有子串的位置
* * */
function searchSubStr(str: any, subStr: any, positions: any): void {
let pos = str.indexOf(subStr);
while (pos > -1) {
positions.push(pos);
pos = str.indexOf(subStr, subStr.length + pos);
}
}
const posLenIndex: any = []; // 信息中包含的所有表情对应的在信息中的位置、表情的长度、对应的表情数组的索引位(用作查找到图片位置数组对应的数据)
emojiPoformaceArray.map((item: any, index: any) => {
const xh = content.indexOf(item);
if (xh !== -1) {
const positions = new Array();
searchSubStr(content, item, positions);
posLenIndex.push({
posArr: positions,
len: item.length,
emoitionIndex: index,
});
}
});
if (posLenIndex.length > 0) { // 发的信息中有表情存在
posLenIndex.map((a: any, b: any) => {
const sen = `${posArray[a.emoitionIndex]}">`;
a.posArr.map((c: any, d: any) => { // 遍历是因为在上面emojiPoformaceArray的遍历中用g也不能全部替换,所以就在生成的posLenIndex数组中遍历
const newItem = new RegExp(emojiPoformaceArray[a.emoitionIndex], 'g'); // 带上g谁知也没有全部替换,所以就在每次变化后重新赋给content
contentCopy = content.replace(newItem, sen);
content = contentCopy;
});
});
} else if (content === '?') { // 送花
contentCopy = ``;
} else { // 没有表情信息
contentCopy = content;
}
return (
<figure key={index}>
<img src={JSON.parse(item).user.avatar} alt="头像" onError={(e: any) => { e.currentTarget.src = require("./images/rentou.jpg"); }} />
<figcaption>
<div className="left">
<p dangerouslySetInnerHTML={{ __html: contentCopy }}></p>
</div>
</figcaption>
</figure>
);
})}
</div>
);
}