含有Emoji字符串长度截取
前言
在处理字符串截取长度的时候,发现 emoji
获得的长度并不是1,因它本身可能是两个字节或四个字节的,复杂表情长度可能更加长,如下:
console.log('😍'.length); // 2
console.log('👨👩👧👦'.length); // 11
实现
实现原理,通过正则对emoji
的字符范围匹配,再分对获取emoji
对应的位置和长度。
/**
* 截取字符
* 说明:汉字、中文标点、emoji、日文、韩文算作 1个字
* ASCII, 英文、英文标点、数字算作 0.5个字
* @params { String } 待处理的字符串
* @params { Number } 需要截取的长度
* @returns { String } 还回的字符串
*/
export let interceptStr = (str, len) => {
// 绝大部分emoji
let reg = /[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/ig;
let strArr = str.split(''); // 字符数组
let strEmojiArr = []; // emoji对象
let tempArr;
let countLen = 0; // 需要转为2倍长度处理,避免小数点
let strIndex = 0; // 字符数组对应的指针
let emojiIndex = 0; // emoji对象对应的指针
let newStrArr = []; // 新字符数组
len = len * 2; // 转为2倍长度处理,避免小数点
if(!str){
return str;
}
// 获取到对应的emoji位置
while ((tempArr = reg.exec(str)) !== null) {
let word = tempArr[0]; // 获取到emoji
let wordLen = word.length; // emoji长度
let startIndex = reg.lastIndex - wordLen; // 出现开始位置
strEmojiArr.push({
word, // emoji字符
startIndex, // emoji出现的开始位置
wordLen // emoji长度
});
}
for(var i = 0; i < strArr.length - 1; i++){
// 判断指针是否大于字符数组下标
if(strIndex > i){
continue;
}
// 判断是否是emoji
let emojis = strEmojiArr.filter((item) => {
emojiIndex++;
return item.startIndex == strIndex;
});
if(emojis.length > 0){
countLen += 2;
if(countLen > len){
newStrArr.push('...');
break;
}
let emoji = emojis[0];
strEmojiArr.splice(emojiIndex, 1); // 删掉已显示过的emoji
strIndex += Number(emoji.wordLen);
newStrArr.push(emoji.word);
} else {
if(/[\x00-\xff]+/g.test(strArr[i])){
countLen += 1;
} else {
countLen += 2;
}
if(countLen > len){
newStrArr.push('...');
break;
}
newStrArr.push(strArr[i]);
strIndex += 1;
}
}
return newStrArr.join('');
};
∠( ᐛ 」∠)_
୧(๑•̀⌄•́๑)૭你好
|´・ω・)ノφ( ̄∇ ̄o)