HTML5 canvas ctx.fillText 不会做换行符吗?

2022-08-30 04:45:53

如果文本包含“\n”,我似乎无法向画布添加文本。我的意思是,换行符不显示/工作。

ctxPaint.fillText("s  ome \n \\n <br/> thing", x, y);

上面的代码将在一行上绘制 。"s ome \n <br/> thing"

这是fillText的限制还是我做错了?“\n”在那里,没有打印出来,但它们也不起作用。


答案 1

如果您只想处理文本中的换行符,则可以通过在换行符处拆分文本并多次调用fillText()

类似 http://jsfiddle.net/BaG4J/1/

var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';
    console.log(c);
var txt = 'line 1\nline 2\nthird line..';
var x = 30;
var y = 30;
var lineheight = 15;
var lines = txt.split('\n');

for (var i = 0; i<lines.length; i++)
    c.fillText(lines[i], x, y + (i*lineheight) );
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>

我刚刚做了一个包装概念证明(在指定宽度的绝对包装。没有处理单词中断,但
示例在 http://jsfiddle.net/BaG4J/2/

var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';

var txt = 'this is a very long text to print';

printAt(c, txt, 10, 20, 15, 90 );


function printAt( context , text, x, y, lineHeight, fitWidth)
{
    fitWidth = fitWidth || 0;
    
    if (fitWidth <= 0)
    {
         context.fillText( text, x, y );
        return;
    }
    
    for (var idx = 1; idx <= text.length; idx++)
    {
        var str = text.substr(0, idx);
        console.log(str, context.measureText(str).width, fitWidth);
        if (context.measureText(str).width > fitWidth)
        {
            context.fillText( text.substr(0, idx-1), x, y );
            printAt(context, text.substr(idx-1), x, y + lineHeight, lineHeight,  fitWidth);
            return;
        }
    }
    context.fillText( text, x, y );
}
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>

和换行(在空格处断开)概念证明。
http://jsfiddle.net/BaG4J/5/

var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';

var txt = 'this is a very long text. Some more to print!';

printAtWordWrap(c, txt, 10, 20, 15, 90 );


function printAtWordWrap( context , text, x, y, lineHeight, fitWidth)
{
    fitWidth = fitWidth || 0;
    
    if (fitWidth <= 0)
    {
        context.fillText( text, x, y );
        return;
    }
    var words = text.split(' ');
    var currentLine = 0;
    var idx = 1;
    while (words.length > 0 && idx <= words.length)
    {
        var str = words.slice(0,idx).join(' ');
        var w = context.measureText(str).width;
        if ( w > fitWidth )
        {
            if (idx==1)
            {
                idx=2;
            }
            context.fillText( words.slice(0,idx-1).join(' '), x, y + (lineHeight*currentLine) );
            currentLine++;
            words = words.splice(idx-1);
            idx = 1;
        }
        else
        {idx++;}
    }
    if  (idx > 0)
        context.fillText( words.join(' '), x, y + (lineHeight*currentLine) );
}
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>

在第二个和第三个示例中,我使用的是 measureText() 方法,该方法显示字符串在打印时的长度(以像素为单位)。


答案 2

恐怕这是Canvas'的局限性。没有多行支持。更糟糕的是,没有内置的方法来测量线条高度,只有宽度,这使得自己做更难!fillText

很多人都写了自己的多行支持,也许最值得注意的项目是Mozilla Skywriter

您需要做的要点是多次调用,同时每次将文本的高度添加到y值。(我相信,测量M的宽度是天空作家人们用来近似文本的方法。fillText