it-swarm.com.de

Wie können Sie die Texthöhe auf einer HTML-Zeichenfläche ermitteln?

Die Spezifikation verfügt über eine Funktion context.measureText (text), die angibt, wie viel Breite zum Drucken des Texts erforderlich ist. Ich kann jedoch nicht herausfinden, wie hoch der Text ist. Ich weiß, dass es auf der Schrift basiert, aber ich weiß nicht, wie man eine Schriftzeichenfolge in eine Texthöhe umwandelt.

140
swampsjohn

[~ # ~] update [~ # ~] - für ein Beispiel dieser Arbeitsweise habe ich diese Technik im Carota Editor verwendet .

Nach der Antwort von ellisbben ist hier eine verbesserte Version, um den Aufstieg und Abstieg von der Grundlinie zu erhalten, dh dieselbe wie tmAscent und tmDescent, die von Win32s GetTextMetric zurückgegeben werden API. Dies ist erforderlich, wenn Sie eine Textfolge mit Zeilenumbrüchen in verschiedenen Schriftarten und -größen erstellen möchten.

Big Text on canvas with metric lines

Das obige Bild wurde auf einer Leinwand in Safari erstellt, wobei Rot die oberste Zeile ist, in der die Leinwand den Text zeichnen soll, Grün die Grundlinie und Blau die Unterseite (so dass Rot zu Blau die volle Höhe ist).

Verwenden von jQuery für Prägnanz:

var getTextHeight = function(font) {

  var text = $('<span>Hg</span>').css({ fontFamily: font });
  var block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>');

  var div = $('<div></div>');
  div.append(text, block);

  var body = $('body');
  body.append(div);

  try {

    var result = {};

    block.css({ verticalAlign: 'baseline' });
    result.ascent = block.offset().top - text.offset().top;

    block.css({ verticalAlign: 'bottom' });
    result.height = block.offset().top - text.offset().top;

    result.descent = result.height - result.ascent;

  } finally {
    div.remove();
  }

  return result;
};

Zusätzlich zu einem Textelement füge ich ein div mit display: inline-block Hinzu, damit ich dessen vertical-align - Stil festlegen und dann herausfinden kann, wo der Browser es abgelegt hat.

Sie erhalten also ein Objekt mit ascent, descent und height zurück (was der Einfachheit halber nur ascent + descent ist). Zum Testen lohnt es sich, eine Funktion zu haben, die eine horizontale Linie zeichnet:

var testLine = function(ctx, x, y, len, style) {
  ctx.strokeStyle = style; 
  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(x + len, y);
  ctx.closePath();
  ctx.stroke();
};

Dann können Sie sehen, wie der Text auf der Leinwand relativ zur Ober-, Grund- und Unterseite positioniert ist:

var font = '36pt Times';
var message = 'Big Text';

ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top'; // important!
ctx.font = font;
ctx.fillText(message, x, y);

// Canvas can tell us the width
var w = ctx.measureText(message).width;

// New function gets the other info we need
var h = getTextHeight(font);

testLine(ctx, x, y, w, 'red');
testLine(ctx, x, y + h.ascent, w, 'green');
testLine(ctx, x, y + h.height, w, 'blue');
74

Die Canvas-Spezifikation gibt uns keine Methode zum Messen der Höhe eines Strings. Sie können jedoch die Größe Ihres Texts in Pixeln festlegen und in der Regel relativ einfach herausfinden, wie hoch die vertikalen Grenzen sind.

Wenn Sie etwas genaueres benötigen, können Sie Text auf die Leinwand werfen und dann Pixeldaten abrufen und herausfinden, wie viele Pixel vertikal verwendet werden. Dies wäre relativ einfach, aber nicht sehr effizient. Sie könnten so etwas tun (es funktioniert, zeichnet aber Text auf die Leinwand, den Sie entfernen möchten):

function measureTextHeight(ctx, left, top, width, height) {

    // Draw the text in the specified area
    ctx.save();
    ctx.translate(left, top + Math.round(height * 0.8));
    ctx.mozDrawText('gM'); // This seems like tall text...  Doesn't it?
    ctx.restore();

    // Get the pixel data from the canvas
    var data = ctx.getImageData(left, top, width, height).data,
        first = false, 
        last = false,
        r = height,
        c = 0;

    // Find the last line with a non-white pixel
    while(!last && r) {
        r--;
        for(c = 0; c < width; c++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                last = r;
                break;
            }
        }
    }

    // Find the first line with a non-white pixel
    while(r) {
        r--;
        for(c = 0; c < width; c++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                first = r;
                break;
            }
        }

        // If we've got it then return the height
        if(first != r) return last - first;
    }

    // We screwed something up...  What do you expect from free code?
    return 0;
}

// Set the font
context.mozTextStyle = '32px Arial';

// Specify a context and a rect that is safe to draw in when calling measureTextHeight
var height = measureTextHeight(context, 0, 0, 50, 50);
console.log(height);

Für Bespin fälschen sie eine Höhe, indem sie die Breite eines Kleinbuchstabens 'm' messen ... Ich weiß nicht, wie dies verwendet wird, und ich würde diese Methode nicht empfehlen. Hier ist die relevante Bespin-Methode:

var fixCanvas = function(ctx) {
    // upgrade Firefox 3.0.x text rendering to HTML 5 standard
    if (!ctx.fillText && ctx.mozDrawText) {
        ctx.fillText = function(textToDraw, x, y, maxWidth) {
            ctx.translate(x, y);
            ctx.mozTextStyle = ctx.font;
            ctx.mozDrawText(textToDraw);
            ctx.translate(-x, -y);
        }
    }

    if (!ctx.measureText && ctx.mozMeasureText) {
        ctx.measureText = function(text) {
            ctx.mozTextStyle = ctx.font;
            var width = ctx.mozMeasureText(text);
            return { width: width };
        }
    }

    if (ctx.measureText && !ctx.html5MeasureText) {
        ctx.html5MeasureText = ctx.measureText;
        ctx.measureText = function(text) {
            var textMetrics = ctx.html5MeasureText(text);

            // fake it 'til you make it
            textMetrics.ascent = ctx.html5MeasureText("m").width;

            return textMetrics;
        }
    }

    // for other browsers
    if (!ctx.fillText) {
        ctx.fillText = function() {}
    }

    if (!ctx.measureText) {
        ctx.measureText = function() { return 10; }
    }
};
37
Prestaul

Sie können eine sehr genaue Annäherung an die vertikale Höhe erhalten, indem Sie die Länge eines Großbuchstaben M überprüfen.

ctx.font='bold 10px Arial';

lineHeight=ctx.measureText('M').width;
29
Vic Fanberg

BEARBEITEN: Verwenden Sie Canvas-Transformationen? Wenn ja, müssen Sie die Transformationsmatrix verfolgen. Die folgende Methode sollte die Texthöhe mit der anfänglichen Transformation messen.

BEARBEITUNG 2: Seltsamerweise liefert der folgende Code keine korrekten Antworten, wenn ich ihn auf dieser StackOverflow-Seite ausführe. Es ist durchaus möglich, dass das Vorhandensein einiger Stilregeln diese Funktion beeinträchtigt.

Die Zeichenfläche verwendet nach CSS definierte Schriftarten. Theoretisch können wir dem Dokument also nur einen entsprechend gestalteten Textabschnitt hinzufügen und seine Höhe messen. Ich denke, dies ist bedeutend einfacher als das Rendern von Text und das anschließende Überprüfen von Pixeldaten. Außerdem sollten Auf- und Abwärtspfade berücksichtigt werden. Überprüfen Sie Folgendes:

var determineFontHeight = function(fontStyle) {
  var body = document.getElementsByTagName("body")[0];
  var dummy = document.createElement("div");
  var dummyText = document.createTextNode("M");
  dummy.appendChild(dummyText);
  dummy.setAttribute("style", fontStyle);
  body.appendChild(dummy);
  var result = dummy.offsetHeight;
  body.removeChild(dummy);
  return result;
};

//A little test...
var exampleFamilies = ["Helvetica", "Verdana", "Times New Roman", "Courier New"];
var exampleSizes = [8, 10, 12, 16, 24, 36, 48, 96];
for(var i = 0; i < exampleFamilies.length; i++) {
  var family = exampleFamilies[i];
  for(var j = 0; j < exampleSizes.length; j++) {
    var size = exampleSizes[j] + "pt";
    var style = "font-family: " + family + "; font-size: " + size + ";";
    var pixelHeight = determineFontHeight(style);
    console.log(family + " " + size + " ==> " + pixelHeight + " pixels high.");
  }
}

Sie müssen sicherstellen, dass der Schriftstil für das DOM-Element, dessen Höhe Sie messen, korrekt ist, aber das ist ziemlich einfach. eigentlich solltest du sowas benutzen

var canvas = /* ... */
var context = canvas.getContext("2d");
var canvasFont = " ... ";
var fontHeight = determineFontHeight("font: " + canvasFont + ";");
context.font = canvasFont;
/*
  do your stuff with your font and its height here.
*/
21
ellisbben

Browser beginnen, erweiterte Textmetriken zu unterstützen, was diese Aufgabe trivial macht, wenn sie weitgehend unterstützt wird:

let metrics = ctx.measureText(text);
let fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
let actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;

Mit fontHeight erhalten Sie die Begrenzungsrahmenhöhe, die unabhängig von der wiedergegebenen Zeichenfolge konstant ist. actualHeight ist spezifisch für den gerenderten String.

Spec: https://www.w3.org/TR/2012/CR-2dcontext-20121217/#dom-textmetrics-fontboundingboxascent und die Abschnitte direkt darunter.

Support-Status (20. August 2017):

18
ZachB

Wie JJ Stiff vorschlägt, können Sie Ihren Text zu einer Spanne hinzufügen und dann die Offset-Höhe der Spanne messen.

var d = document.createElement("span");
d.font = "20px arial";
d.textContent = "Hello world!";
document.body.appendChild(d);
var emHeight = d.offsetHeight;
document.body.removeChild(d);

Wie auf HTML5Rocks gezeigt

10
Matt Palmerlee

Entspricht die Höhe des Texts in Pixeln nicht der Schriftgröße (in Pkt), wenn Sie die Schrift mit context.font definieren?

10
Bachalo

Nur um Daniels Antwort hinzuzufügen (was großartig und absolut richtig ist!), Version ohne JQuery:

function objOff(obj)
{
    var currleft = currtop = 0;
    if( obj.offsetParent )
    { do { currleft += obj.offsetLeft; currtop += obj.offsetTop; }
      while( obj = obj.offsetParent ); }
    else { currleft += obj.offsetLeft; currtop += obj.offsetTop; }
    return [currleft,currtop];
}
function FontMetric(fontName,fontSize) 
{
    var text = document.createElement("span");
    text.style.fontFamily = fontName;
    text.style.fontSize = fontSize + "px";
    text.innerHTML = "ABCjgq|"; 
    // if you will use some weird fonts, like handwriting or symbols, then you need to edit this test string for chars that will have most extreme accend/descend values

    var block = document.createElement("div");
    block.style.display = "inline-block";
    block.style.width = "1px";
    block.style.height = "0px";

    var div = document.createElement("div");
    div.appendChild(text);
    div.appendChild(block);

    // this test div must be visible otherwise offsetLeft/offsetTop will return 0
    // but still let's try to avoid any potential glitches in various browsers
    // by making it's height 0px, and overflow hidden
    div.style.height = "0px";
    div.style.overflow = "hidden";

    // I tried without adding it to body - won't work. So we gotta do this one.
    document.body.appendChild(div);

    block.style.verticalAlign = "baseline";
    var bp = objOff(block);
    var tp = objOff(text);
    var taccent = bp[1] - tp[1];
    block.style.verticalAlign = "bottom";
    bp = objOff(block);
    tp = objOff(text);
    var theight = bp[1] - tp[1];
    var tdescent = theight - taccent;

    // now take it off :-)
    document.body.removeChild(div);

    // return text accent, descent and total height
    return [taccent,theight,tdescent];
}

Ich habe den obigen Code gerade getestet und funktioniert auf den neuesten Versionen von Chrome, FF und Safari auf dem Mac hervorragend.

EDIT: Ich habe auch die Schriftgröße hinzugefügt und mit webfont anstelle der Systemschrift getestet - funktioniert fantastisch.

8
Sinisa

Ich habe dieses Problem direkt gelöst - mithilfe der Pixelmanipulation.

Hier ist eine grafische Antwort:

Hier ist Code:

    function textHeight (text, font) {

    var fontDraw = document.createElement("canvas");

    var height = 100;
    var width = 100;

    // here we expect that font size will be less canvas geometry
    fontDraw.setAttribute("height", height);
    fontDraw.setAttribute("width", width);

    var ctx = fontDraw.getContext('2d');
    // black is default
    ctx.fillRect(0, 0, width, height);
    ctx.textBaseline = 'top';
    ctx.fillStyle = 'white';
    ctx.font = font;
    ctx.fillText(text/*'Eg'*/, 0, 0);

    var pixels = ctx.getImageData(0, 0, width, height).data;

    // row numbers where we first find letter end where it ends 
    var start = -1;
    var end = -1;

    for (var row = 0; row < height; row++) {
        for (var column = 0; column < width; column++) {

            var index = (row * width + column) * 4;

            // if pixel is not white (background color)
            if (pixels[index] == 0) {
                // we havent met white (font color) pixel
                // on the row and the letters was detected
                if (column == width - 1 && start != -1) {
                    end = row;
                    row = height;
                    break;
                }
                continue;
            }
            else {
                // we find top of letter
                if (start == -1) {
                    start = row;
                }
                // ..letters body
                break;
            }

        }

    }
   /*
    document.body.appendChild(fontDraw);
    fontDraw.style.pixelLeft = 400;
    fontDraw.style.pixelTop = 400;
    fontDraw.style.position = "absolute";
   */

    return end - start;

}
7
Anton Putov

Hier ist eine einfache Funktion. Keine Bibliothek benötigt.

Ich habe diese Funktion geschrieben, um die oberen und unteren Grenzen in Bezug auf die Grundlinie zu ermitteln. Wenn textBaseline auf alphabetic gesetzt ist. Es erstellt eine weitere Zeichenfläche, zeichnet dort und findet dann das oberste und das unterste nicht leere Pixel. Und das ist die Ober- und Untergrenze. Es wird als relativ zurückgegeben. Wenn also die Höhe 20px beträgt und sich nichts unter der Grundlinie befindet, ist die obere Grenze -20.

Sie müssen Zeichen eingeben. Andernfalls erhalten Sie offensichtlich 0 Höhe und 0 Breite.

Verwendung:

alert(measureHeight('40px serif', 40, 'rg').height)

Hier ist die Funktion:

function measureHeight(aFont, aSize, aChars, aOptions={}) {
    // if you do pass aOptions.ctx, keep in mind that the ctx properties will be changed and not set back. so you should have a devoted canvas for this
    // if you dont pass in a width to aOptions, it will return it to you in the return object
    // the returned width is Math.ceil'ed
    console.error('aChars: "' + aChars + '"');
    var defaultOptions = {
        width: undefined, // if you specify a width then i wont have to use measureText to get the width
        canAndCtx: undefined, // set it to object {can:,ctx:} // if not provided, i will make one
        range: 3
    };

    aOptions.range = aOptions.range || 3; // multiples the aSize by this much

    if (aChars === '') {
        // no characters, so obviously everything is 0
        return {
            relativeBot: 0,
            relativeTop: 0,
            height: 0,
            width: 0
        };
        // otherwise i will get IndexSizeError: Index or size is negative or greater than the allowed amount error somewhere below
    }

    // validateOptionsObj(aOptions, defaultOptions); // not needed because all defaults are undefined

    var can;
    var ctx; 
    if (!aOptions.canAndCtx) {
        can = document.createElement('canvas');;
        can.mozOpaque = 'true'; // improved performanceo on firefox i guess
        ctx = can.getContext('2d');

        // can.style.position = 'absolute';
        // can.style.zIndex = 10000;
        // can.style.left = 0;
        // can.style.top = 0;
        // document.body.appendChild(can);
    } else {
        can = aOptions.canAndCtx.can;
        ctx = aOptions.canAndCtx.ctx;
    }

    var w = aOptions.width;
    if (!w) {
        ctx.textBaseline = 'alphabetic';
        ctx.textAlign = 'left'; 
        ctx.font = aFont;
        w = ctx.measureText(aChars).width;
    }

    w = Math.ceil(w); // needed as i use w in the calc for the loop, it needs to be a whole number

    // must set width/height, as it wont Paint outside of the bounds
    can.width = w;
    can.height = aSize * aOptions.range;

    ctx.font = aFont; // need to set the .font again, because after changing width/height it makes it forget for some reason
    ctx.textBaseline = 'alphabetic';
    ctx.textAlign = 'left'; 

    ctx.fillStyle = 'white';

    console.log('w:', w);

    var avgOfRange = (aOptions.range + 1) / 2;
    var yBaseline = Math.ceil(aSize * avgOfRange);
    console.log('yBaseline:', yBaseline);

    ctx.fillText(aChars, 0, yBaseline);

    var yEnd = aSize * aOptions.range;

    var data = ctx.getImageData(0, 0, w, yEnd).data;
    // console.log('data:', data)

    var botBound = -1;
    var topBound = -1;

    // measureHeightY:
    for (y=0; y<=yEnd; y++) {
        for (var x = 0; x < w; x += 1) {
            var n = 4 * (w * y + x);
            var r = data[n];
            var g = data[n + 1];
            var b = data[n + 2];
            // var a = data[n + 3];

            if (r+g+b > 0) { // non black px found
                if (topBound == -1) { 
                    topBound = y;
                }
                botBound = y; // break measureHeightY; // dont break measureHeightY ever, keep going, we till yEnd. so we get proper height for strings like "`." or ":" or "!"
                break;
            }
        }
    }

    return {
        relativeBot: botBound - yBaseline, // relative to baseline of 0 // bottom most row having non-black
        relativeTop: topBound - yBaseline, // relative to baseline of 0 // top most row having non-black
        height: (botBound - topBound) + 1,
        width: w// EDIT: comma has been added to fix old broken code.
    };
}

relativeBot, relativeTop und height sind die nützlichen Dinge im Rückgabeobjekt.

Hier ist ein Anwendungsbeispiel:

<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script>
function measureHeight(aFont, aSize, aChars, aOptions={}) {
        // if you do pass aOptions.ctx, keep in mind that the ctx properties will be changed and not set back. so you should have a devoted canvas for this
        // if you dont pass in a width to aOptions, it will return it to you in the return object
        // the returned width is Math.ceil'ed
        console.error('aChars: "' + aChars + '"');
        var defaultOptions = {
                width: undefined, // if you specify a width then i wont have to use measureText to get the width
                canAndCtx: undefined, // set it to object {can:,ctx:} // if not provided, i will make one
                range: 3
        };
        
        aOptions.range = aOptions.range || 3; // multiples the aSize by this much
        
        if (aChars === '') {
                // no characters, so obviously everything is 0
                return {
                        relativeBot: 0,
                        relativeTop: 0,
                        height: 0,
                        width: 0
                };
                // otherwise i will get IndexSizeError: Index or size is negative or greater than the allowed amount error somewhere below
        }
        
        // validateOptionsObj(aOptions, defaultOptions); // not needed because all defaults are undefined
        
        var can;
        var ctx; 
        if (!aOptions.canAndCtx) {
                can = document.createElement('canvas');;
                can.mozOpaque = 'true'; // improved performanceo on firefox i guess
                ctx = can.getContext('2d');
                
                // can.style.position = 'absolute';
                // can.style.zIndex = 10000;
                // can.style.left = 0;
                // can.style.top = 0;
                // document.body.appendChild(can);
        } else {
                can = aOptions.canAndCtx.can;
                ctx = aOptions.canAndCtx.ctx;
        }
        
        var w = aOptions.width;
        if (!w) {
                ctx.textBaseline = 'alphabetic';
                ctx.textAlign = 'left'; 
                ctx.font = aFont;
                w = ctx.measureText(aChars).width;
        }
        
        w = Math.ceil(w); // needed as i use w in the calc for the loop, it needs to be a whole number
        
        // must set width/height, as it wont Paint outside of the bounds
        can.width = w;
        can.height = aSize * aOptions.range;
        
        ctx.font = aFont; // need to set the .font again, because after changing width/height it makes it forget for some reason
        ctx.textBaseline = 'alphabetic';
        ctx.textAlign = 'left'; 
        
        ctx.fillStyle = 'white';
        
        console.log('w:', w);
        
        var avgOfRange = (aOptions.range + 1) / 2;
        var yBaseline = Math.ceil(aSize * avgOfRange);
        console.log('yBaseline:', yBaseline);
        
        ctx.fillText(aChars, 0, yBaseline);
        
        var yEnd = aSize * aOptions.range;
        
        var data = ctx.getImageData(0, 0, w, yEnd).data;
        // console.log('data:', data)
        
        var botBound = -1;
        var topBound = -1;
        
        // measureHeightY:
        for (y=0; y<=yEnd; y++) {
                for (var x = 0; x < w; x += 1) {
                        var n = 4 * (w * y + x);
                        var r = data[n];
                        var g = data[n + 1];
                        var b = data[n + 2];
                        // var a = data[n + 3];
                        
                        if (r+g+b > 0) { // non black px found
                                if (topBound == -1) { 
                                        topBound = y;
                                }
                                botBound = y; // break measureHeightY; // dont break measureHeightY ever, keep going, we till yEnd. so we get proper height for strings like "`." or ":" or "!"
                                break;
                        }
                }
        }
        
        return {
                relativeBot: botBound - yBaseline, // relative to baseline of 0 // bottom most row having non-black
                relativeTop: topBound - yBaseline, // relative to baseline of 0 // top most row having non-black
                height: (botBound - topBound) + 1,
                width: w
        };
}

</script>
</head>
<body style="background-color:steelblue;">
<input type="button" value="reuse can" onClick="alert(measureHeight('40px serif', 40, 'rg', {canAndCtx:{can:document.getElementById('can'), ctx:document.getElementById('can').getContext('2d')}}).height)">
<input type="button" value="dont reuse can" onClick="alert(measureHeight('40px serif', 40, 'rg').height)">
<canvas id="can"></canvas>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
</body>
</html>

Die relativeBot und relativeTop sehen Sie in diesem Bild hier:

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_text

3
Noitidart

einzeilige Antwort

var height = parseInt(ctx.font) * 1.2; 

CSS "Zeilenhöhe: normal" liegt zwischen 1 und 1,2

lesen Sie hier für weitere Informationen

2
Durgpal Singh

Ich habe eine Nice-Bibliothek implementiert, um die exakte Höhe und Breite von Text mithilfe der HTML-Zeichenfläche zu messen. Dies sollte tun, was Sie wollen.

https://github.com/ChrisBellew/text-measurer.js

2
ChrisBellew

Ich schreibe einen Terminal-Emulator, also musste ich Rechtecke um Zeichen zeichnen.

var size = 10
var lineHeight = 1.2 // CSS "line-height: normal" is between 1 and 1.2
context.font = size+'px/'+lineHeight+'em monospace'
width = context.measureText('m').width
height = size * lineHeight

Offensichtlich hilft es nichts, wenn Sie genau den Platz wollen, den der Charakter einnimmt. Aber es gibt Ihnen eine gute Annäherung für bestimmte Verwendungen.

2
tomdxw

Ich fand, dass JUST FOR ARIAL der einfachste, schnellste und genaueste Weg, die Höhe des Begrenzungsrahmens zu ermitteln, darin besteht, die Breite bestimmter Buchstaben zu verwenden. Wenn Sie vorhaben, eine bestimmte Schriftart zu verwenden, ohne dass der Benutzer eine andere auswählen kann, können Sie ein wenig nachforschen, um den richtigen Buchstaben für diese Schriftart zu finden.

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="700" height="200" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "100px Arial";
var txt = "Hello guys!"
var Hsup=ctx.measureText("H").width;
var Hbox=ctx.measureText("W").width;
var W=ctx.measureText(txt).width;
var W2=ctx.measureText(txt.substr(0, 9)).width;

ctx.fillText(txt, 10, 100);
ctx.rect(10,100, W, -Hsup);
ctx.rect(10,100+Hbox-Hsup, W2, -Hbox);
ctx.stroke();
</script>

<p><strong>Note:</strong> The canvas tag is not supported in Internet 
Explorer 8 and earlier versions.</p>

</body>
</html>
1
tmx976

Zunächst müssen Sie die Höhe einer Schriftgröße festlegen und dann entsprechend dem Wert der Schrifthöhe die aktuelle Höhe Ihres Textes bestimmen, wie viel Kreuztextzeilen natürlich die gleiche Höhe haben Wenn der Text die größte Höhe des Textfelds nicht überschreitet, müssen alle Schriftarten akkumulieren. Andernfalls wird nur der Text im Textfeld angezeigt. Hohe Werte benötigen eine eigene Definition. Je größer die voreingestellte Höhe ist, desto größer ist die Höhe des Texts, der angezeigt und abgefangen werden muss.

Nachdem der Effekt verarbeitet wurde (auflösen)

Bevor der Effekt bearbeitet wird (ungelöst)

  AutoWrappedText.auto_wrap = function(ctx, text, maxWidth, maxHeight) {
var words = text.split("");
var lines = [];
var currentLine = words[0];

var total_height = 0;
for (var i = 1; i < words.length; i++) {
    var Word = words[i];
    var width = ctx.measureText(currentLine + Word).width;
    if (width < maxWidth) {
        currentLine += Word;
    } else {
        lines.Push(currentLine);
        currentLine = Word;
        // TODO dynamically get font size
        total_height += 25;

        if (total_height >= maxHeight) {
          break
        }
    }
}
if (total_height + 25 < maxHeight) {
  lines.Push(currentLine);
} else {
  lines[lines.length - 1] += "…";
}
return lines;};
1
kiss_von

Dies ist, was ich basierend auf einigen der anderen Antworten hier gemacht habe:

function measureText(text, font) {
        const span = document.createElement('span');
        span.appendChild(document.createTextNode(text));
        Object.assign(span.style, {
                font: font,
                margin: '0',
                padding: '0',
                border: '0',
                whiteSpace: 'nowrap'
        });
        document.body.appendChild(span);
        const {width, height} = span.getBoundingClientRect();
        span.remove();
        return {width, height};
}

var font = "italic 100px Georgia";
var text = "abc this is a test";
console.log(measureText(text, font));

Komisch, dass TextMetrics nur Breite und keine Höhe hat:

http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#textmetrics

Können Sie eine Spanne wie in diesem Beispiel verwenden?

http://mudcu.be/journal/2011/01/html5-typographic-metrics/#alignFix

1
JJ Stiff

das Einstellen der Schriftgröße ist jedoch möglicherweise nicht sinnvoll, da die Einstellung

ctx.font = ''

verwendet die von CSS definierte sowie alle eingebetteten Schriftarten. Wenn Sie die CSS-Schriftart verwenden, wissen Sie nicht, wie hoch die Höhe auf programmatische Weise ist, wenn Sie die MeasureText-Methode verwenden, die sehr kurzsichtig ist. In einem anderen Fall gibt IE8 jedoch die Breite und Höhe zurück.

0
Rahly