web-dev-qa-db-fra.com

Comment pouvez-vous trouver la hauteur de texte sur une toile HTML?

La spécification a une fonction context.measureText (text) qui vous indique la largeur nécessaire pour imprimer ce texte, mais je ne trouve pas le moyen de déterminer sa taille. Je sais que cela dépend de la police, mais je ne sais pas convertir une chaîne de police en hauteur de texte.

140
swampsjohn

[~ # ~] update [~ # ~] - pour un exemple de ce travail, j'ai utilisé cette technique dans le éditeur Carota .

Dans la suite de la réponse d’ellisbben, voici une version améliorée pour obtenir l’ascension et la descente de la ligne de base, c’est-à-dire identique à tmAscent et tmDescent renvoyés par l’API GetTextMetric de Win32. Cela est nécessaire si vous souhaitez créer une séquence de texte enveloppée dans Word avec des plages dans différentes tailles/polices.

Big Text on canvas with metric lines

L'image ci-dessus a été générée sur une toile dans Safari, le rouge étant la ligne du haut où il a été demandé à la toile de dessiner le texte, le vert étant la ligne de base et le bleu le bas (le rouge au bleu étant la hauteur maximale).

Utiliser jQuery pour la concision:

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;
};

En plus d'un élément de texte, j'ajoute un div avec display: inline-block afin que je puisse régler sa vertical-align style, puis découvrez où le navigateur l’a mis.

Donc, vous récupérez un objet avec ascent, descent et height (qui est simplement ascent + descent pour plus de commodité). Pour le tester, il vaut la peine d'avoir une fonction qui trace une ligne horizontale:

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();
};

Ensuite, vous pouvez voir comment le texte est positionné sur le canevas par rapport au haut, à la ligne de base et au bas:

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
Daniel Earwicker

La spécification de la toile ne nous donne pas une méthode pour mesurer la hauteur d'une chaîne. Toutefois, vous pouvez définir la taille de votre texte en pixels et vous pouvez généralement déterminer quelles sont les limites verticales relativement facilement.

Si vous avez besoin de quelque chose de plus précis, vous pouvez jeter du texte sur la toile, puis obtenir des données de pixels et déterminer le nombre de pixels utilisés verticalement. Ce serait relativement simple, mais pas très efficace. Vous pouvez faire quelque chose comme ceci (cela fonctionne, mais dessine sur votre toile un texte que vous voudriez supprimer):

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);

Pour Bespin, ils simulent une hauteur en mesurant la largeur d'une lettre minuscule 'm' ... Je ne sais pas comment cela est utilisé, et je ne recommanderais pas cette méthode. Voici la méthode Bespin pertinente:

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

Vous pouvez obtenir une approximation très proche de la hauteur verticale en vérifiant la longueur d'un M. majuscule.

ctx.font='bold 10px Arial';

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

EDIT: tilisez-vous des transformations canvas? Si oui, vous devrez suivre la matrice de transformation. La méthode suivante doit mesurer la hauteur du texte avec la transformation initiale.

EDIT # 2: Bizarrement, le code ci-dessous ne donne pas les réponses correctes lorsque je l’exécute sur cette page StackOverflow. il est tout à fait possible que la présence de certaines règles de style puisse compromettre cette fonction.

Le canevas utilise les polices telles que définies par CSS. En théorie, nous pouvons donc simplement ajouter un bloc de texte de style approprié au document et en mesurer la hauteur. Je pense que cela est beaucoup plus facile que de restituer du texte, puis de vérifier les données de pixels et que cela devrait également respecter les ascendeurs et les descendeurs. Découvrez les éléments suivants:

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.");
  }
}

Vous devrez vous assurer que le style de police est correct sur l'élément DOM dont vous mesurez la hauteur, mais c'est assez simple; vraiment vous devriez utiliser quelque chose comme

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

Les navigateurs commencent à supporter métriques de texte avancées , ce qui rendra cette tâche triviale quand elle sera largement prise en charge:

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

fontHeight vous donne la hauteur du cadre de sélection constante quelle que soit la chaîne affichée. actualHeight est spécifique à la chaîne en cours de rendu.

Spec: https://www.w3.org/TR/2012/CR-2dcontext-20121217/#dom-textmetrics-fontboundingboxascent et les sections situées juste en dessous.

Statut de support (20-Aug-2017):

18
ZachB

Comme le suggère JJ Stiff, vous pouvez ajouter votre texte à une étendue, puis mesurer la hauteur offsetHeight de celle-ci.

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);

Comme indiqué sur HTML5Rocks

10
Matt Palmerlee

La hauteur du texte en pixels n'est-elle pas égale à la taille de la police (en pts) si vous définissez la police à l'aide de context.font?

10
Bachalo

Juste pour ajouter à la réponse de Daniel (ce qui est génial! Et tout à fait correct!), Version sans 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];
}

Je viens de tester le code ci-dessus et fonctionne très bien sur les derniers Chrome, FF et Safari sur Mac.

EDIT: J'ai également ajouté la taille de la police et testé avec webfont au lieu de la police système - fonctionne à merveille.

8
Sinisa

J'ai résolu ce problème sans détour - en utilisant la manipulation de pixels.

Voici la réponse graphique:

Voici le 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

Voici une fonction simple. Aucune bibliothèque nécessaire.

J'ai écrit cette fonction pour obtenir les limites supérieure et inférieure par rapport à la ligne de base. Si textBaseline est défini sur alphabetic. Cela crée une autre zone de travail, puis dessine à cet endroit, puis trouve le pixel le plus haut et le plus bas, le plus non vide. Et ce sont les limites supérieure et inférieure. Il le renvoie sous forme relative. Si la hauteur est 20px et qu'il n'y a rien en dessous de la ligne de base, la limite supérieure est -20.

Vous devez lui fournir des caractères. Sinon, cela vous donnera évidemment 0 hauteur et 0 largeur.

Usage:

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

Voici la fonction:

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 et height sont les éléments utiles de l'objet de retour.

Voici un exemple d'utilisation:

<!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>

Les relativeBot et relativeTop sont ce que vous voyez dans cette image ici:

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

3
Noitidart

réponse en une ligne

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

CSS "line-height: normal" compris entre 1 et 1.2

lire ici pour plus d'informations

2
Durgpal Singh

J'ai mis en place une bibliothèque Nice pour mesurer la hauteur et la largeur exactes du texte à l'aide de la toile HTML. Cela devrait faire ce que vous voulez.

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

2
ChrisBellew

J'écris un émulateur de terminal et j'ai donc dû dessiner des rectangles autour des caractères.

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

Évidemment, si vous voulez la quantité exacte d'espace que le personnage occupe, cela ne vous aidera pas. Mais cela vous donnera une bonne approximation pour certains usages.

2
tomdxw

J'ai trouvé que JUST FOR ARIAL Le moyen le plus simple, le plus rapide et le plus précis de trouver la hauteur du cadre de sélection est d'utiliser la largeur de certaines lettres. Si vous prévoyez d'utiliser une police donnée sans permettre à l'utilisateur de choisir une police différente, vous pouvez effectuer quelques recherches afin de trouver la lettre appropriée pour cette police.

<!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

Tout d'abord, vous devez définir la hauteur d'une taille de police, puis en fonction de la valeur de la hauteur de la police pour déterminer la hauteur actuelle de votre texte, combien de lignes de texte croisé, bien sûr, la même hauteur de la police doit s'accumuler si le texte ne dépasse pas la plus grande hauteur de la zone de texte Hauteur, tout s'affiche, sinon, affichez uniquement le texte dans le texte de la boîte. Les valeurs élevées ont besoin de votre propre définition. Plus la hauteur prédéfinie est grande, plus le texte devant être affiché et intercepté est élevé.

Après que l'effet soit traité (résoudre)

Avant que l'effet soit traité (non résolu)

  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

Voici ce que j'ai fait en me basant sur certaines des autres réponses ici:

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));

C'est drôle que TextMetrics ait seulement de la largeur et pas de hauteur:

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

Pouvez-vous utiliser une portée comme sur cet exemple?

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

1
JJ Stiff

définir la taille de la police peut ne pas être pratique, car

ctx.font = ''

utilisera celle définie par CSS ainsi que toutes les balises de police incorporées. Si vous utilisez la police CSS, vous n'avez aucune idée de la hauteur d'une programmation, à l'aide de la méthode measureText, qui est très myope. Sur une autre note cependant, IE8 renvoie la largeur et la hauteur.

0
Rahly