跳转到内容

拼音标注

刀刀

1/8/2025

0 字

0 分钟

效果

效果

拼音标注的效果如上图所示,每一个汉字都有自己的拼音标注。想要实现这个效果,首先需要有思路。

思路

  1. 结构与样式

    在 HTML 中标签 rubyrt 可用于实现东亚文字的拼音标注的,该标签目前主流浏览器都能支持,如果想要兼容旧版本的浏览器,则可用 rp 标签包裹 rt 标签,这样在旧浏览器中会显示为 汉字(拼音) 的形式。

    html
    <ruby>
    
     <rt>han</rt>
    </ruby>
    html
    <ruby>
    
     <rp>(</rp>
     <rt>han</rt>
     <rp>)</rp>
    </ruby>
  2. 通过汉字拿到拼音

    最笨的方法是自己根据汉字用映射表一一对应保存,需要使用时再获取对应的拼音。但是繁琐且复杂。

    有第三方库 pinyin 可实现效果。下面介绍一下它的使用。

pinyin

首先下载第三方依赖:

shell
yarn add pinyin

引入依赖并使用:

js
import pinyin from 'pinyin'

const result = pinyin('弹')
console.log(result)

最终打印结果如下:

js
Array(1) ['dan']

之所以是一个数组,是因为要考虑到其多音字的情况。可为什么他只返回了一个没有返回两个拼音呢?

查看 官方文档 可知,如果想要实现多音字返回多个拼音,需要启用多音字模式。代码修改为下方结构:

js
import pinyin from 'pinyin'

const result = pinyin('弹', {
  heteronym: true, // 启用多音字模式
})
console.log(result)

现在输出结果如下:

js
Array(2) ['dan', 'tan']

那么我该拿哪一个读音呢?可以通过传递一串上下文文本内容,并启用分词,就能获取对应的读音了,上下文越多,其读音就越准确。代码再次修改如下:

js
import pinyin from 'pinyin'

const result = pinyin('弹', {
  segment: true, // 启用分词,以解决多音字问题。默认不开启,使用 true 开启使用 nodejieba 分词库。
  heteronym: true, // 启用多音字模式
})
console.log(result)

打印结果如下:

js
[Array(1),Array(1)] [['zi'], ['dan']]

优化

  • 包体积

    这个库由于包含了一本新华字典,因此打包后体积是非常大的,直接打包会有不小的体积压力。放到服务器或许是一个解决方法。

  • 请求时长

    如果文本内容过长,一次性传过去等到拼音标注会需要一定时间,因此通过分割并发获取是一个解决方案。

  • 内容

    文本内容可能 不一定全是中文,因此需要做判断处理。

业务完整代码

查看代码
js
import pinyin from 'pinyin'
import { computed, ref } from 'vue'

const content = ref('')

const reg = /[\u4e00-\u9fa5]/
function isChinese(char) {
    return reg.test(char)
}

const html = computed(() => {
  let tags = ''
  for(const c of content.value) {
    if(isChinese(c)) {
      tags += `<ruby>${c}<rp>(</rp><rt>pinyin(c)[0]</rt><rp>)</rp></ruby>`
    } else if(c === '\n') {
      tags += '<br />'
    } else {
      tags += c
    }
  }
})