部分emoji表情在手机上显示不出来,什么情况?

背景

上周在工作中遇到一个历史遗留缺陷,在管理后台配置的emoji表情,在有些手机上,部分emoji图标显示成方框格子,这个问题要是放在平时比较忙碌的时候,随便找个理由就能把产品和测试糊弄过去,但上周工作不算饱和,工作不饱和的时候,人的求知欲就比较旺盛,于是决定探究一下。

这是后端接口返回的emoji编码:

json 复制代码
{
  "ret": 0,
  "retmsg": "ok",
  "retdata": {
    "content": [
      {
        // ...
        "momentText": "\uD83D\uDE43\uD83E\uDD17\uD83E\uDD10\uD83D\uDE1C\uD83D\uDE2A\uD83E\uDD12\uD83E\uDD12\uD83E\uDDB7\uD83E\uDDB5\uD83E\uDD1B\uD83D\uDC48\uD83E\uDD1A\uD83D\uDE40\uD83D\uDE48\uD83D\uDC47\uD83D\uDC9C\uD83D\uDC97\uD83E\uDDE1\uD83E\uDD0E\uD83D\uDCA2\uD83E\uDD4B\uD83C\uDFD3\uD83E\uDD4E\uD83C\uDF81\uD83C\uDFB6\uD83C\uDFB6\uD83C\uDFBC\uD83D\uDD14\uD83E\uDE93\uD83E\uDE79\uD83E\uDDEC♉♌\uD83D\uDEC4\uD83D\uDD1B\uD83D\uDFE0\uD83D\uDD34\uD83D\uDFE8\uD83D\uDD39\uD83C\uDE50\n天天好心情",
      },
    ],
  },
}

这是正常的显示:

这是部分emoji图标显示成方框的情形:

emoji的前世今生

1999年从日本的手机中诞生emoji,emoji这个词在日语里的含义是"绘文字"。 "绘"对应"e","文字"对应"moji"。第一版emoji大部分是表达天气、交通、科技的符号,而非表情。如今已经成为社交软件中不可缺少的存在。emoji从诞生之日起就一直被一个问题所困扰,在不同的平台,同样的表情,展示效果看起来并不一样,没有标准化与统一化。不同的平台都根据本平台的审美来重新解读与设计 emoji 表情。苹果的设计风格特征是立体,渐变和阴影的细节比较考究;Google 则是更加轻松和卡通化; 微软喜欢又黑又粗的边框,可能是想与文字明显区分开来;Facebook(现在的Meta)的emoji表情表现力比较强,Twitter的emoji非常简洁,基本没有阴影渐变这些细节。如下图所示,同样一个翻白眼的表情,在每个平台看起来差别还是比较明显的。

emoji与unicode的关系

每一个 emoji,就是一个 Unicode 字符。全世界的 emoji 都由统一码联盟(The Unicode Consortium)来投票选拔和公布,世界各地的人们可以向联盟提交 emoji 提案。而统一码联盟的 emoji 规范,只是定义了某个字符的语义,再由 Emojipedia这个网站对 emoji 进行描述表达,最后允许大家按照对描述的理解,自由地去设计图案。

从2010年开始,Unicode 开始为 Emoji 分配码点。比如:U+1F4C5,U+1F468, U+1F600等。 Unicode 只是规定了 Emoji 的码点和含义,并没有规定它的外观展示。举例来说,码点U+1F600表示一张微笑的脸,但是这张微笑的脸表情长什么样,则由各个平台(Windows,Mac,Linux, IOS, Android等)自己实现。如果用户的系统没有实现这个Emoji符号,用户就会看到一个没有内容的方框(如下图所示,三者必居其一,不光是emoji表情,其它类型的字体图标渲染不出来的时候也是这样的展示),因为系统无法渲染这个码点。

所以在PC端展示正常的emoji表情,在低版本的Android或IOS系统上,可能展示不太正常。

着手解决

知道了emoji表情为什么显示不出来的原因,解决方案也就水落石出。

  • 下载emoji字体到自己的应用中 从网络下载所需的emoji表情字体,这样就可以摆脱对平台emoji字体的依赖。(靠谱)
  • 升级操作系统 新版本的操作系统通常会包含更完整的emoji表情支持。(代价高)
  • 替换为图片 即使表情显示不正常,也可以将emoji表情替换为等效的图片来表示。(说易行难)。
  • 安装emoji表情包 有些手机厂商会提供额外的emoji表情包用于扩展默认的表情集。可以在应用商店搜索并安装适用于手机的emoji表情包。(不通用)

这里选择了可行性比较强的第一种方案,解决部分emoji表情在低版本手机上无法显示的问题。出现问题项目是个H5应用,所以采用Web开发技术中的css自定义字体解决这个问题。使用@font-face自定义字体时,通常需要加载好几种字体格式,以前不是很清楚这几种字体格式的区别,趁着这次机会,刚好梳理一下这一块。

常见的字体类型

常见的字体类型如下表所示,目前现代浏览器基本都支持.ttfotfwoff,.woff2,.svg字体格式,如果为了保证兼容不同的浏览器,一般会同时指定多个格式

字体类型 说明
.ttf True Type,是Windows和Mac系统最常用的字体格式,它可以任意缩放和旋转不会出现锯齿,随着 windows 的流行,已经变成最常用的一种字体文件表示方式,这种格式的字体文件体积比较大,字体文件可以达到 24MB+,通常只用作安装到计算机中的字体,或者在网页中设备不支持 WOFF2 字体情况的兜底处理。
.otf Open Type,是可缩放性的电脑字体类型,是微软与Adobe共同开发用来替代TrueType的新字形,微软的IE浏览器全部采用这种字体。致力于替代TrueType字体。OTF 字体文件体积也很大,基本和 TTF 差不多。
.eot Embedded Open Type,微软开发的嵌入字体格式,允许OpenType字体用@font-face嵌入到网页并下载至浏览器渲染,存储在临时安装文件夹下。
.woff Web Open Font Format,专门为了We设计的字体格式标准,是对True Type、Open Type等字体格式的封装,体积非常小
.woff2 WOFF 1.0使用zlib压缩,文件大小一般比TTF小40%。而WOFF 2.0使用Brotli压缩,文件大小比上一版小30%。
.svg Scalable Vector Graphics Fonts,使用SVG来呈现字体(.svgz是使用了Gzip压缩的SVG字体,这种字体是非常早期的标准,已经不推荐使用。)

由于笔者的手机系统是Android,所以需要下载的字体是Noto Color Emoji字体, 点击这里下载。下载的时候有一点要注意,你需要下载的是Noto Color Emoji而非Noto Emoji, 这两者的区别是前者的emoji图标是彩色的,图标很全面,当然emoji字体资源文件体积也比较大,接近24M,后者的emoji图标显示的是黑色,图标也不全。笔者刚开始下载的是Noto Emoji字体,发现emoji依旧不显示,经过一番排查,才发现要下载的emoji字体文件的名称应该是Noto Color Emoji

另外大家有没有发现一个问题,就是ttf的文件体积很大,会造成页面加载资源比较卡顿,需要对ttf文件进行压缩,可以采用在线压缩工具,也可以采用命令行工具(font-spider,fontforge等),因为woff2格式的字体体积比较小,所以在网页端使用的话,一般使用的都是woff或者woff2格式。

测试demo代码文件内容如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>emoji显示测试</title>
    <script src="http://cdn.staticfile.org/jquery/2.1.0/jquery.min.js"></script>

    <style>
      @font-face {
        font-family: emoji;
        src: url("./NotoColorEmoji-Regular.woff2") format('woff2');
      }

      .emoji {
        font-family: emoji;
      }
    </style>
  </head>
  <body>
    <pre class="emoji"></pre>
    <script>
      const momentText = "\uD83D\uDE43\uD83E\uDD17\uD83E\uDD10\uD83D\uDE1C\uD83D\uDE2A\uD83E\uDD12\uD83E\uDD12\uD83E\uDDB7\uD83E\uDDB5\uD83E\uDD1B\uD83D\uDC48\uD83E\uDD1A\uD83D\uDE40\uD83D\uDE48\uD83D\uDC47\uD83D\uDC9C\uD83D\uDC97\uD83E\uDDE1\uD83E\uDD0E\uD83D\uDCA2\uD83E\uDD4B\uD83C\uDFD3\uD83E\uDD4E\uD83C\uDF81\uD83C\uDFB6\uD83C\uDFB6\uD83C\uDFBC\uD83D\uDD14\uD83E\uDE93\uD83E\uDE79\uD83E\uDDEC♉♌\uD83D\uDEC4\uD83D\uDD1B\uD83D\uDFE0\uD83D\uDD34\uD83D\uDFE8\uD83D\uDD39\uD83C\uDE50\n天天好心情";

    </script>
  </body>
</html>

用VScode中的Live Server扩展启动这个页面,在手机上打开,在如下图所示,原来不能显示的emoji表情已经可以正常显示了。

相关推荐
Jiaberrr1 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy1 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白1 小时前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、1 小时前
Web Worker 简单使用
前端
web_learning_3211 小时前
信息收集常用指令
前端·搜索引擎
tabzzz2 小时前
Webpack 概念速通:从入门到掌握构建工具的精髓
前端·webpack
200不是二百2 小时前
Vuex详解
前端·javascript·vue.js
滔滔不绝tao2 小时前
自动化测试常用函数
前端·css·html5
码爸2 小时前
flink doris批量sink
java·前端·flink
深情废杨杨2 小时前
前端vue-父传子
前端·javascript·vue.js