系列索引
Unicode 与 Emoji
字典树 TrieTree 与性能测试
生产实践
生产实践
我们最终要解决 Emoji 在浏览器和打印物上的显示一致.
进行了多番对比,, 在显示效果和精度上, macOS 和 Unicode 标准的风格相近, 最终决定使用 Unicode 提供的图片作为跨平台显示.
浏览器和渲染程序在渲染文本前, 将内容交由后端进行 Emoji 检索.
提交请求示例如下:
- {
- "sections":[
- "颠簸了三小时飞机两小时公交地铁四小时大巴一小时 终于到了我们的目的地像面粉一样的沙滩和碧绿的大海 这就是我们第一次旅行的地方 in 沙美岛"
- ]
- }
后端使用了 MongoDB 存储了所有 Emoji 的 base64 表示, 检索到 Emoji 字符后输出替换内容.
- {
- "sections": [ "颠簸了三小时飞机 [chuye-emoji://1835][chuye-emoji://2263] 两小时公交地铁 [chuye-emoji://1792][chuye-emoji://2263] 四小时大巴 [chuye-emoji://2263] 一小时[chuye-emoji://1834] 终于到了我们的目的地像面粉一样的沙滩和碧绿的大海 这就是我们第一次旅行的地方 in 沙美岛[chuye-emoji://1734]"
- ],
- "regExp": "\\[chuye\\-emoji:\\/\\/(\\d+)\\]",
- "images": {
- "1734": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAAABGdBTUEAALGPC...",
- "1792": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAAABGdBTUEAALGPC...",
- "1834": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAAABGdBTUEAALGPC...",
- "1835": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAAABGdBTUEAALGPC...",
- "2263": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABEBAMAAADQAW4PAAAABGdBTUEAALGPC..."
- },
- "emojis": {
- "1734": "",
- "1792": "",
- "1834": "",
- "1835": "",
- "2263": ""
- }
- }
移除了 base64 后面的更多内容, 只起示例作用.
返回内容包含以下字段
字段 | 类型 | |
---|---|---|
sections | 字符串数组 | 替换 Emoji 后的字符串输出 |
regExp | 字符串 | 辅助定位 Emoji 表达式 的正则表达式 |
images | 字典 / 对象 | 所有 < strong ztid="78" ow="91" oh="17">Emoji 表达式 的 base64 编码表示 |
示例请求包含了 5 个 emoji 字符, 后端将它们一一替换成了所谓的 emoji 表达式, 依次为 [chuye-emoji://1734], [chuye-emoji://1792], [chuye-emoji://1834], [chuye-emoji://1835], [chuye-emoji://2263].
Emoji 表达式: 作者自己的定义, 表示一段 emoji , 固定格式形如 [chuye-emoji://1734], 尾部的数字是序号. 整个表达式可以用响应携带的正则表达式 regExp 字段匹配.
浏览器在拿到响应后, 使用正则定位该表达式, 再替换其为 <img class="emoji" /> 标签并应用响应中的 base64 资源, 最后将文本当作 html 输出即可. 演示代码:
- let req = {sections: ["..."]};
- let resp = // POST req to service and get response
- let regExp = new RegExp(resp.regExp, 'g');
- let replacments = [];
- for (let section of resp.sections) {
- let replacment = section.replace(regExp, (...args) => {
- let id = args[1];
- let src = resp.images[id];
- return `<img class="emoji" src="${src}" title="${id}" />`
- });
- replacments.push(replacment);
- }
- //do stuff with replacments
简化 base64 后的输出内容是文本和 img 标签混合的 html 内容.
emoji style 的定义如下(引用自 Twitter 方案, 并未精确测试)
- img.emoji {
- height: 1em;
- width: 1em;
- margin: 0 .05em 0 .1em;
- vertical-align: -0.1em;
- }
使用 base64 而不是将资源扔到 CDN 上, 还是基于现有状况进行的测试.
我们的打印物可能包含 10-20 个 emoji 字符, 将对应的 base64 合并在响应中, 大小在 100k 左右, 再放大 2 倍也可以接受.
如果替代以 16 个 URL 资源, 请求成本就非常夸张了;
合并图片的做法虽然可以减少 HTTP 请求, 但成倍地放大了解决方案复杂度;
来源: https://www.cnblogs.com/Jusfr/p/9576886.html