HTML5 canvas ctx.fillText不会换行吗?

问题描述 投票:97回答:17

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

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

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

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

javascript html canvas line break
17个回答
59
投票

恐怕是Canvas的限制fillText。没有多行支持。更糟糕的是,没有内置的方法可以测量线的高度,只有宽度,这使您自己做起来更加困难!

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

您需要做的要点是多次fillText调用,同时每次将文本的高度添加到y值。 (我相信,测量​​M的宽度是Skywriter人们为近似文本所做的工作。)


4
投票

这是Colin ctx.textBaseline="bottom"; ctx.fillText("First line", x-position, y-position); ctx.textBaseline="top"; ctx.fillText("Second line", x-position, y-position); 的一个版本,它还支持[wrapText()的垂直居中文本


3
投票
我认为您仍然可以依靠CSS

2
投票
我认为这也不可能,但是一种解决方法是创建一个http://www.html5rocks.com/en/tutorials/canvas/texteffects/元素并使用Javascript对其进行定位。

2
投票
由于同样的问题,我碰巧遇到了这个问题。我正在使用可变的字体大小,因此需要考虑以下因素:

1
投票
我为此简单使用了一个简单的npm模块。var texts=($(this).find('.noteContent').html()).split("<br>"); for (var k in texts) { ctx.fillText(texts[k], left, (top+((parseInt(ctx.font)+2)*k))); }

0
投票
画布元素不支持换行符'\ n',制表符'\ t'或
标记等字符。

尝试:


0
投票
我的ES5解决方案:

var textArray = new Array('line2', 'line3', 'line4', 'line5'); var rows = 98; ctx.fillStyle = "rgb(0, 0, 0)"; ctx.font = "bold 24px 'Verdana'"; ctx.textAlign = "center"; ctx.fillText("Game Over", mwidth, mheight); //first line for(var i=0; i < textArray.length; ++i) { rows += 30; ctx.fillText(textArray[i], mwidth, rows); }


0
投票
我用on my blog<DL>粗体显示,但可以使用说明了

57
投票

[如果只想处理文本中的换行符,则可以通过在换行处分割文本并多次调用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()方法,该方法显示字符串打印多长时间(以像素为单位


38
投票

也许参加这个聚会有点晚了,但是我发现了以下教程,可以将文本包装在完美的画布上。


25
投票

将文本分割成几行,并分别绘制:


17
投票

这是我的解决方案,修改此处已经介绍的流行的wrapText()函数。我正在使用JavaScript的原型功能,以便您可以从画布上下文中调用该函数。


11
投票

我刚刚扩展了CanvasRenderingContext2D,添加了两个函数:mlFillText和mlStrokeText。


8
投票

使用JavaScript开发了解决方案。它不漂亮,但对我有用:


7
投票

function drawMultilineText(){ // set context and formatting var context = document.getElementById("canvas").getContext('2d'); context.font = fontStyleStr; context.textAlign = "center"; context.textBaseline = "top"; context.fillStyle = "#000000"; // prepare textarea value to be drawn as multiline text. var textval = document.getElementByID("textarea").value; var textvalArr = toMultiLine(textval); var linespacing = 25; var startX = 0; var startY = 0; // draw each line on canvas. for(var i = 0; i < textvalArr.length; i++){ context.fillText(textvalArr[i], x, y); y += linespacing; } } // Creates an array where the <br/> tag splits the values. function toMultiLine(text){ var textArr = new Array(); text = text.replace(/\n\r?/g, '<br/>'); textArr = text.split("<br/>"); return textArr; } 提供的自动换行代码(在空格处中断)非常有用。我扩展了他的代码以提供对换行符@Gaby Petrioli的支持。同样,通常,具有边界框的尺寸很有用,因此\n返回宽度和高度。


5
投票

如果只需要两行文本,则可以将它们分成两个不同的fillText调用,并为每个文本指定不同的基线。

© www.soinside.com 2019 - 2024. All rights reserved.