一、canvas绘制文字的方法和属性
1. fillText(text, x, y [, maxWidth])
text:绘制文本;x:文本起点的 x 轴坐标;y:文本起点的 y 轴坐标;
maxWidth:可选,绘制的最大宽度。如果指定了值,计算字符串的值比最大宽度还要宽,字体为了适应会水平缩放。
将返回一个 TextMetrics对象的宽度、所在像素,这些体现文本特性的属性。
3. font
符合CSS font 语法的DOMString 字符串。默认字体是 10px sans-serif
属性:
<font-style> <font-variant> <font-weight> <font-stretch> <line-height> 可选
形如:italic small-caps bold 16px/2 cursive;
line-height必须紧跟font-size,在“/”之前,比如:“16px/3”,(注:node-canvas下,无效)
4. textAlign
文本对齐选项. 可选的值包括:start, end, left, right or center. 默认值是 start
5. textBaseline
基线对齐选项. 可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic
6. direction
文本方向。值包括:ltr, rtl, inherit。默认值是 inherit;
7. fillStyle
使用 fillStyle 属性设置填充颜色
fillStyle有三种属性值:color(颜色),gradient(渐变),pattern(非透明对象)
二、绘制有行高和宽度的单行文字
1. 首先绘制一个矩形裁切区域
ctx.rect(x, y, width, lineHeight);
ctx.clip();
2. 绘制文字
ctx.textBaseline ='middle';
ctx.fillText(text, x, y + lineHeight / 2);
3. 让文字水平对齐
(1) 左对齐
ctx.textAlign = ‘left’;
ctx.fillText(text, x, y + lineHeight / 2);
(2) 居中对齐
ctx.textAlign = ‘center’;
ctx.fillText(text, x + width / 2, y + lineHeight / 2);
(3) 右对齐
ctx.textAlign = ‘right’;
ctx.fillText(text, x + width, y + lineHeight / 2);
三、绘制多行文本
1. 根据文字宽度和字体大小将长文字分割为多段文字
/**
* 将一段文字拆成多段
* @params ctx CanvasRenderingContext2D
* @param text 文字内容
* @param fontSize 文字大小
* @param width 文字限定的宽度
* @param maxLine 文字最多显示多少行
* @return 多段文字
*/
const splitText = (
ctx: CanvasRenderingContext2D,
text:string,
fontSize:number,
width:number,
maxLine:number,
): Array<{text:string, width:number}> => {
const arr: Array<{text:string, width:number}> = [];
// 记录剩余文字
let remainText = text;
while (arr.length < maxLine -1 && ctx.measureText(remainText).width > width) {
// 估算一行能容纳多少文字
let assumTextNum = Math.floor(width / fontSize);
// 计算假定文字的宽度
let {width:assumTextWidth} = ctx.measureText(remainText.substr(0, assumTextNum));
if (assumTextWidth > width) {
while (assumTextWidth > width) {
assumTextWidth = ctx.measureText(remainText.substr(0, --assumTextNum)).width;
}
}else {
while (assumTextWidth <= width) {
assumTextWidth = ctx.measureText(remainText.substr(0, ++assumTextNum)).width;
}
assumTextWidth = ctx.measureText(remainText.substr(0, --assumTextNum)).width;
}
arr.push({
text: remainText.substr(0, assumTextNum),
width:assumTextWidth,
});
remainText = remainText.substr(assumTextNum);
}
arr.push({
text: remainText,
width: ctx.measureText(remainText).width,
});
return arr;
};
2. 将分割后的多段文字,按照单行文字的绘制方式一一绘制,代码如下
const texts =splitText(ctx, text, fontSize, width, maxLine);
for (let i =0; i < texts.length; i++) {
const txtObj = texts[i];
const offsetY = i * lineHeight;
// 绘制单行文字
drawSingleLineText(ctx, txtObj.text, fontSize, x, y + offsetY, width, lineHeight);
}