小程序vancas绘制海报时短句文案指定换行的处理

小程序在使用 vancas 2D 绘制海报时,想要添加短句作文案,会涉及到短句的换行问题,今天我们来讨论一下!

需求分析

比如有这样一首诗,在 canvas 绘制时,如果不处理换行,则会显示到同一行,超出海报宽度的部分将不可见了,因此需要对文案做自动换行处理

《清平乐·六盘山》
天高云淡,望断南飞雁。
不到长城非好汉,屈指行程二万。
六盘山上高峰,红旗漫卷西风。
今日长缨在手,何时缚住苍龙?

由于都是短句文案,在后端新增文案时,可以使用 input 表单来填写,入库时是这样的

《清平乐·六盘山》天高云淡,望断南飞雁。不到长城非好汉,屈指行程二万。六盘山上高峰,红旗漫卷西风。今日长缨在手,何时缚住苍龙?

短句文案按宽度或字数自动换行

我们首先可以按宽度来实现自动换行,当文字排版超出宽度,则自动换行。

在小程序 .js 文件中,可以利用如下 dealWords() 方法来处理。

注:按每行显示宽度,按每行展示字数都行。

/**
 * 绘制多行文本, 文本换行
 * @param ctx canvas对象
 * @param word 文本
 * @param fontSize 字体大小
 * @param x 文字在x轴要显示的位置
 * @param y 文字在y轴要显示的位置
 * @param maxWidth 一行文字最大宽度
 * @param maxLine 文字最多显示的行数
 * @returns {*}
 */
dealWords(options) {
	//options.ctx.setFontSize(options.fontSize); //旧版 设置字体大小
	options.ctx.font = options.fontSize; //新版

	var allRow = Math.ceil(options.ctx.measureText(options.word).width / options.maxWidth); //实际总共能分多少行
	var count = allRow >= options.maxLine ? options.maxLine : allRow; //实际能分多少行与设置的最大显示行数比,谁小就用谁做循环次数

	var endPos = 0; //当前字符串的截断点
	for (var j = 0; j < count; j++) {
		var nowStr = options.word.slice(endPos); //当前剩余的字符串
		var rowWid = 0; //每一行当前宽度		
		if (options.ctx.measureText(nowStr).width > options.maxWidth) { //如果当前的字符串宽度大于最大宽度,然后开始截取
			for (var m = 0; m < nowStr.length; m++) {
				rowWid += options.ctx.measureText(nowStr[m]).width; //当前字符串总宽度
				if (rowWid > options.maxWidth) {
					if (j === options.maxLine - 1) { //如果是最后一行
						options.ctx.fillText(nowStr.slice(0, m - 1) + '...', options.x, options.y + (j + 1) * 25); //(j+1)*20这是每一行的高度				
					}
					else {
						options.ctx.fillText(nowStr.slice(0, m), options.x, options.y + (j + 1) * 25);
					}
					endPos += m; //下次截断点
					break;
				}
			}
		}
		//如果当前的字符串宽度小于最大宽度就直接输出
		else {
			options.ctx.fillText(nowStr.slice(0), options.x, options.y + (j + 1) * 25);
		}
	}
},

调用示例如下

//多行绘制 自动换行
that.dealWords({
	ctx: context, //画布上下文 canvasID
	fontSize: 'normal lighter 16px sans-serif', //字体 PingFang SC sans-serif arial
	word: the_sentence, //需要处理的文字
	maxWidth: 270, //一行文字最大宽度
	x: 30, //文字在x轴要显示的位置
	y: 100, //文字在y轴要显示的位置
	maxLine: 6 //文字最多显示的行数
});

我们来看一下效果

如果这是一段普通的文案,这样排版是没有问题的,但是对于诗句,我们还是更想让它按句来分段换行,这就涉及到多行文本换行的处理了。

短句文案按指定方式分段换行

可以看出这首诗的每一小段的字数是不一样的,因此如果按上述自动换行,显然不是我们想要的效果,这里我们按指定的方式分段换行,有如下两种方案,我们一一来分析。