canvas绘制文字段落一
工作中一个场景需要用canvas绘制多段文字,尝试了“\r\n”,结果没用。没法投机取巧了,老实写逻辑吧。更多复杂情况(首行缩进、段间距等等的)等需要时再实现吧。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="mycanvas" width="240" height="630"></canvas>
<script>
let canvas = document.getElementById("mycanvas")
let ctx = canvas.getContext("2d")
ctx.font = "20px sans-serif"
ctx.fillStyle = "#E992B9"
ctx.textBaseline = "top"
let rows = 0
const LINEHEIGHT = 20
const LINEWIDTH = canvas.width - 40
let str = "这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的光里,总该另有一番样子吧。"
/**
@method drawTextParagraph
@params {string} str 要绘制的字符串
@params {number} rows 从第多少行开始绘制
@params {number} lineHeight 每行的行高
@params {number} lineWidth 每行的宽度
@params {number} offsetX 行的左侧偏移
@return {number} 返回该段落渲染了多少行
*/
const drawTextParagraph = (str, rows = 0, lineHeight, lineWidth, offsetX = 0) => {
let line= 0
let delta = 1
while(ctx.measureText(str).width > lineWidth){
let lineStr = str.substring(0, delta)
if(ctx.measureText(lineStr).width <= lineWidth){
delta ++
continue
}
// 当字符串宽度大于允许行宽且delta大于1时,说明两个或两个以上的字符才会大于允许行宽
// 这时需要往回退一个字符,如果delta就是1的话,那就不退了
if(delta > 1){
delta --
lineStr = str.substring(0, delta)
}
ctx.fillText(lineStr, offsetX, (rows + line) * lineHeight)
str = str.substring(delta) // 把渲染过得字符串去掉,保留剩余的字符串
line ++ // 行数加1
delta = 1 // 索引重置为1
}
// 经过上面的处理,str可能有剩于内容,或者被切成了空字符串。如果有剩余就再绘制一下
if(str) {
ctx.fillText(str, offsetX, (rows + line) * lineHeight)
line ++
}
return line
}
rows += drawTextParagraph(str, rows, LINEHEIGHT, LINEWIDTH, 20)
rows += drawTextParagraph(str, rows, LINEHEIGHT, LINEWIDTH, 20)
rows += drawTextParagraph(str, rows, LINEHEIGHT, LINEWIDTH, 20)
console.log(rows)
</script>
</body>
</html>
转载请注明出处。