持续创作,加速成长!这是我参与「日新计划 6 月更文挑战」的第7天,点击查看活动详情

介绍

或许你时不时会用纯画布来完成一些简单的绘制任务,但是很多小伙伴经常遇到在canvas的文字它不自动换行,就有些烦躁,不要怕,本期就用短短几行的代码来让你canvas的文字多行显示,而且兼容性也是非常不错的,还等什么,我们这就是出发~

正文

在完成多行文本之前,我们先来写一个普通文本绘制到画布上的示例:

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
createCard();
function createCard(w = width, h = height) {
  let gradient = ctx.createLinearGradient(0, h, w, 0);
  gradient.addColorStop(0, '#8A88FB');
  gradient.addColorStop(1, '#D079EE');
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, w, h);
  let text = "春有百花秋有月,夏有凉风冬有雪。莫将闲事挂心头,便是人间好时节。";
  drawText(text,10,100)
}
function drawText(text,x = 0, y = 0) {
  ctx.font = window.getComputedStyle(canvas).font;
  ctx.fillStyle = 'white'
  ctx.textAlign = "start"
  ctx.textBaseline = "top"
  ctx.fillText(text, x, y);
}

你可以发现这是一段比较长的文本,如果直接绘制到画布上,那么多出来的部分则会不显示。那么如何让其自动让其在一个指定宽度下换行呢?且看我们后面对它的改造。

如何让Canvas中的文本多行显示


在改成多行之前,先分析一下,其实最关键的是用到了 CanvasRenderingContext2D.measureText() 这个方法,它会返回一个关于被测文本 TextMetrics 的对象信息,TextMetrics 里面的信息都是只读的,其中我们就用到了它里面的 width 即,该文本的宽度 。我们将会逐字进行遍历,不断叠加字符串来判断这个字符串是否超过了所需的最大限宽,如果到达了减到一个字符再保存这一段字符串,然后再继续下一段的获取。周而复始,我们将会得到一个段落的数组,最后再遍历绘制这数组里的文本段落就可以实现换行操作啦。

function getWrapText(text = "", maxWidth = 200) {
  let txtList = [];
  let str = "";
  for (let i = 0, len = text.length; i < len; i++) {
    str += text.charAt(i);
    if (ctx.measureText(str).width > maxWidth) {
      txtList.push(str.substring(0, str.length - 1))
      str = ""
      i--
    }
  }
  txtList.push(str)
  return txtList;
}

我们先写一个 getWrapText 方法来获取文本拆分后的数组,这里唯一要注意的是如果大于宽度要减去一个字符,此时 i 需要减去1的,表示从被减去的那个序列为下一段的开始。

然后,我们还要改写一下 drawText 方法:

function drawText(text, x = 0, y = 0, lineHeight = 60, maxWidth = 200) {
  ctx.font = window.getComputedStyle(canvas).font;
  ctx.fillStyle = 'white'
  ctx.textAlign = "start"
  ctx.textBaseline = "top"
  getWrapText(text, maxWidth).forEach((txt, index) => {
    ctx.fillText(txt, x, y + lineHeight * index);
  })
}

这里我们加入了 lineHeight 表示行高, maxWidth 表示最大限宽。最后我们通过 forEach 遍历去绘制每段的文本,就会发现这个文本已经满足多行显示的要求了~

如何让Canvas中的文本多行显示

演示

https://code./pen/7113749958565560350