部分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表情已经可以正常显示了。

相关推荐
mldong6 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60617 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角9 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!9 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰9 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi10 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马12 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒12 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端