含有Emoji字符串长度截取

含有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('');
};

参考

https://www.ruanyifeng.com/blog/2017/04/emoji.html

最后修改:2019 年 05 月 27 日 12 : 34 PM

发表评论