持续创作,加速成长!这是我参与「日新计划 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); }
你可以发现这是一段比较长的文本,如果直接绘制到画布上,那么多出来的部分则会不显示。那么如何让其自动让其在一个指定宽度下换行呢?且看我们后面对它的改造。

在改成多行之前,先分析一下,其实最关键的是用到了 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
遍历去绘制每段的文本,就会发现这个文本已经满足多行显示的要求了~

演示
https://code./pen/7113749958565560350
评论(0)