canvas 中如何实现文字换行?canvas 中如何实现 letter-space 效果?

canvas 使用过程中,我们经常会遇到到把文字换行的情况,canvas 要实现换行,并没有 css 中使用样式换行那么方便,但 canvas 提供测量工具函数 measureText 给你测出每个文字的宽度,然后自己用它来按需切割文本为多行,然后按需把多行一行一行地绘画到 canvas 上实现换行效果。在 canvas 要实现 letter-space 也没有太好的办法,但在 stackoverflow 中,有人提出一种比较有效的近似的办法,,就是往文字间插入间隔空白符来实现 letter-space 的效果,下面一起来看看如何实现。

  /**
   * canvas 中如何实现文字换行?canvas 中如何实现 letter-space 效果?
   *
   * @param { CanvasRenderingContext2D } ctx
   * @param {String} text
   * @param {Number} x 
   * @param {Number} y
   * @param {Number} w 行宽 
   * @param {String} color
   * @param {Number} fontSize
   * @param {Boolean} isBold
   */
  function drawMultiLineRichText (ctx, text, x, y, w, color, fontSize, isBold) {
    if (!text) {
      return false
    }
    const rawRows = text.split('\n')
    let rows = []
    // 保存画布 用save及restore是为了不影响其他地方使用画布
    ctx.save()
    fontSize = fontSize ? fontSize : 26
    ctx.font = `${isBold ? '700' : '400'} ${fontSize}px "Hiragino Sans GB W3","Microsoft YaHei",sans-serif`
    ctx.textBaseline = 'middle'
    ctx.fillStyle = color
    rawRows.forEach((txt) => {
      const chars = txt.split('').join(String.fromCharCode(8202)).split('') // .split('').join(String.fromCharCode(8202)) 增加 letter-space, 8201 可以更宽一点。 引用自: https://stackoverflow.com/questions/8952909/letter-spacing-in-canvas-element
      let tempStr = ''
      chars.forEach((char) => {
        if (ctx.measureText(tempStr).width >= w) {
          rows.push(tempStr)
          tempStr = ''
        }
        tempStr += char
      })
      rows.push(tempStr)
    })
    rows.forEach((txt, n) => {
      ctx.fillText(txt, x, y + n * fontSize * 1.8)
    })
    ctx.restore() // 恢复画布
  }