React Native 开发系列6 假名标注

react-native | Comments

HTML5里自带的ruby tag可以用来展示日语的假名标注, 就像这样:東京とうきょう, 但是iOS的Text组件并不能用来展示html,只好自己写了一个组件来解析和展示这种格式。

目录

  1. 项目搭建 – 底部导航栏及搜索
  2. 实现搜索 – 调用API及自定义组件
  3. 登录注册 – 使用cookies
  4. 学习卡片 – flash/swipe card
  5. 学习模块,社区,账号设置
  6. 假名标注

首先,需要能够在服务端生成日语单词对应的假名,MeCab是一个比较好用的日语分词软件,用它在服务端生成了带ruby tag的形式的内容,返回给客户端用,当然也可以选择返回更友好的格式,客户端只需要负责render,但是考虑到更好的兼容性,最后还是决定返回标准的ruby文本,由客户端来负责parse和render。 关于Mecab的使用方法,可以参考这个翻译的中文MeCab文档

写了一个RubyText组件来render这种格式的内容。先把内容按tag解析开,然后在render的时候根据不同的情况render成一个包含两个Text的View或者一个普通的Text。parse部分的代码借鉴了react-native-parsed-text

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
28
29
30
31
32
33
34
35
36
const PATTERNS = {
  ruby: /<ruby>(.*?)<\/ruby>/,
  rt: /<rt>(.*?)<\/rt>/
};

parse() {
    const parts = [];
    let textLeft = this.props.children;

    while (textLeft) {
      const matches = PATTERNS.ruby.exec(textLeft);
      if (!matches) { break; }

      const previousText = textLeft.substr(0, matches.index);
      if (previousText.length) {
        parts.push([previousText]);
      }

      const matched = matches[1];
      const rt_matches = PATTERNS.rt.exec(matched);
      if (rt_matches) {
        const rb = matched.substr(0, rt_matches.index);
        parts.push([rb, rt_matches[1]]);
      } else {
        parts.push([matches[1]]);
      }

      textLeft = textLeft.substr(matches.index + matches[0].length);
    }

    if (textLeft.length) {
      parts.push([textLeft]);
    }

    return parts;
  }

完整的代码在GitHub上RubyText.js

本来是把它做成一个开源的组件提交到npm的,但是对textAlign和获取系统默认字体大小一直没弄清楚,所以代码里有很多hardcode的地方,如果有人对react native比较熟的的话,欢迎fork、修改,提交到npm上供其他人使用。

Comments