开发:emoji 显示

字数统计: 1.7k 阅读时间: 3 mins 访问次数: ... 评论统计: ...

  成了(成了)。
  那么接下来请 4o 给大家表演一个川剧变脸::4o-o1: :4o-o2: :4o-o3: :4o-o4: :4o-o3: :4o-o1:
  感觉画得还差那么点意思……五官太小头太大了,总之今天先解决了代码的问题,可喜可贺可喜可贺!

  本来打算直接照搬西柚子的 co5emoji ,但是我画的图线条没她清楚,放大 span 之后又会影响行距。于是虽然在捣鼓 css 的时候被伪元素伤透了心,今天还是决定用伪元素来实现排版功能……
  我也不知道这是什么心态,大概就是犯贱吧 :4o-2:

实现

  大体上还是照搬了 co5emoji ,思路也是手动写入 emojiList 后用 JS 查找替换成相应 classname 的 span。
  依稀记得西柚子说过她的插件会影响 canvas 绘制,看了一下少女癌的页面,好像 next 主题的 post 会专门生成在一个 id="post" 的 div 内,所以西柚子是把替换范围限定在了这个 div 内,然后把她的 canvas 换头小游戏放在了 page 里。
  但是我用的主题它没有这功能啊!!page 和 post 用的是同一个 layout 啊!!!
  于是实现思路变成了:数组里写入 emojiList ,然后查找所有 p 元素挨个把里面的 emojiTag 替换。因为替换和查找元素都需要批处理于是选择了用 jQuery 来实现。
  这次没有问哆啦馒头!这次是我自己在谷歌上抄的作业!虽然有些地方还是不太懂为什么这么写,但是日本程序员的笔记真的,比中文也就好看懂那么几十倍吧……
  想起我年轻时还吐槽过日本程序员的代码逻辑自成一派,但是他们做笔记真的好认真,比这群机翻洗稿的中文代码剪辑师友好多了【

输入

  首先是标签输入方面,虽然并不打算和其它网站复制的文本做兼容但还是用了 :emojiname: 的形式,当然 JS 处理完之后就变成没有内容的空 span 了,这个问题应该不大,等后续有空再修正。
  然后是 emojiList ,依然是手动输入。另外由于 emoji 排版用到了伪元素,所以背景图的链接也是手动在 css 里逐个关联的。严格上来说这个库做得还是不够完善,但是因为不打算引入外部表情包所以目前的功能就够用了……毕竟我也画不了那么多

JS 处理 + 输出

  再次诚挚感谢 霓虹程序员的笔记,从「单个元素内按单一规律替换单个对象」到「多个元素内按多个规律替换多个对象」一共罗列了 6 种解法并都提供了代码,孩子抄得很顺利,谢谢茄子。

  最终的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const emojiList = [
'4o-1','4o-2','4o-3',
// 手动输入所有 emoji tag 名
];

var elm = $('p');
// 用 jQuery 选择器选择所有类型为 p 的元素

elm.each(function(i){
// 对选中的所有 p 元素逐一执行以下事件:
$.each(emojiList, function(ii,emojiName) {
// 对 emojiList 中的每一项都执行以下事件:
var emojiTag = ':' + emojiName + ':',
// 设置输入的 emoji tag 格式
emojiSpan =
'<span class="emoji '
// ! 后面这个空格不可以去掉
+ emojiName
+ '"></span>';
// 设置输出的 emoji span 格式
var txt = elm.eq(i).html();
elm.eq(i).html(
txt.replaceAll(emojiTag,emojiSpan)
);
// 将区域内所有 emojiTag 替换为 emojiSpan
});
});

  是说不太懂的地方就是这个 eq(i) ,实测删掉之后会把所有 p 元素都替换成第一个 p 的内容……我的理解大概是把获取的 html 内容临时存储在了 i 这个变量里,然后对第二个 p 元素进行替换的时候更新了变量的值?

更新:在手机端预览时遇到了 replaceAll 不执行的状况
   初步判断是 api 兼容性有些问题,改用普通正则后可以正常输出
   代价是加载速度肉眼可见地变慢了……

css

  西柚子的 emoji span 是全部在同一个 classname 下然后用不同的 id 来区分样式的,但是这几天在查资料的时候发现规范的 html 页面下每一个 id 应该仅对应一个元素,于是生成了带空格的 classname。
  是说其实我不知道为什么要这么写……但是实际结果好像就是把元素归类到了两个不同层级的 classname 下。

举例:有 class=".aa bb"class=".aa cc" 两个元素
   css 中输入 .aa 可以同时选中两个元素
   输入 .bb.aa.bb 只能访问前者,输入 .cc.aa.cc 只能访问后者

  最终的 css 文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.emoji {
display: inline-block;
position: relative;
width: 2.2em;
height: 1em;
vertical-align: sub;
}
.emoji::before {
content: ' ';
position: absolute;
top:-0.9em;
left: 0;
width: 2.2em;
height: 2.2em;
background-size: cover;
}
.emojiName1::before{background-image: url('emojiUrl-1.png');}
.emojiName2::before{background-image: url('emojiUrl-2.png');}
.emojiName3...

踩坑

  css 貌似无法识别以数字开头的类名,导致我一度以为无法通过双重类名定位到同一个伪元素……解决方法就是在生成类名的时候在前面加一个字母,所以 4o 就变成了 e4o【乐
  另外还有 jQuery 在用 each 访问数组的时候似乎是会固定先输出内容的编号,比如上面那段代码如果我只写 $.each(emojiList, function(emojiName) 的话输出的就是我需要的 emojiNameemojiList 中的编号,构建的 emojiTag 也变成了 :0: :1: :2:,需要在前面再加一个输入值 ii 才能正常使用数组里写入的内容。

参考链接


  1. 1. 实现
    1. 1.1. 输入
    2. 1.2. JS 处理 + 输出
    3. 1.3. css
  2. 2. 踩坑
  3. 3. 参考链接