2012-04-11 17 views
12

Sto disegnando del testo in una tela HTML5 sopra un'immagine (un generatore di meme). Voglio calcolare una dimensione del font in modo che la stringa occupi l'intera larghezza della tela.Determina la larghezza della stringa nella tela HTML5

Quindi, fondamentalmente, c'è un modo in JavaScript per determinare quale dimensione del carattere dovrei usare per qualche stringa di un certo tipo di carattere per una data larghezza?

risposta

26

Il metodo fillText() ha un quarto argomento facoltativo, ovvero larghezza massima per il rendering della stringa.

documentazione del MDN dice ...

maxwidth

facoltativo; la larghezza massima da disegnare. Se specificato, e la stringa è calcolata per essere più ampia di questa larghezza, il carattere viene regolato per utilizzare un font a condensazione orizzontale più (se uno è disponibile o se uno sufficientemente leggibile può essere sintetizzato ridimensionando il font corrente orizzontalmente) o un font più piccolo.

Tuttavia, al momento della scrittura, questo argomento non è supportata navigatore ben croce, che porta alla seconda soluzione utilizzando measureText() per determinare le dimensioni di una stringa senza renderlo.

var width = ctx.measureText(text).width; 

Ecco come posso farlo ...

var canvas = document.getElementById('canvas'), 
    ctx = canvas.getContext('2d'); 

// Font sizes must be in descending order. You may need to use `sort()` 
// if you can't guarantee this, e.g. user input. 
var fontSizes = [72, 36, 28, 14, 12, 10, 5, 2], 
    text = 'Measure me!'; 

// Default styles. 
ctx.textBaseline = 'top'; 
ctx.fillStyle = 'blue'; 

var textDimensions, 
    i = 0; 

do { 
    ctx.font = fontSizes[i++] + 'px Arial'; 
    textDimensions = ctx.measureText(text);   
} while (textDimensions.width >= canvas.width); 

ctx.fillText(text, (canvas.width - textDimensions.width)/2, 10);​ 

jsFiddle.

Ho un elenco di dimensioni dei caratteri in ordine decrescente e scorre l'elenco, determinando se il testo renderizzato si adatta alle dimensioni dell'area di disegno.

Se lo fa, rendo il centro del testo allineato. Se è necessario eseguire il riempimento a sinistra ea destra del testo (che apparirà più gradevole), aggiungere il valore di riempimento allo textDimensions.width durante il calcolo se il testo si adatta.

Se si dispone di un lungo elenco di dimensioni dei caratteri da provare, è preferibile utilizzare uno binary search algorithm. Ciò aumenterà tuttavia la complessità del tuo codice.

Ad esempio, se si dispone di 200 dimensioni di carattere, l'iterazione lineare attraverso gli elementi di matrice sarà O (n).

Il chop binario deve essere O (log n).

Qui c'è il budella della funzione.

var textWidth = (function me(fontSizes, min, max) { 

    var index = Math.floor((min + max)/2); 

    ctx.font = fontSizes[index] + 'px Arial'; 

    var textWidth = ctx.measureText(text).width; 

    if (min > max) { 
     return textWidth; 
    } 

    if (textWidth > canvas.width) { 
     return me(fontSizes, min, index - 1); 
    } else { 
     return me(fontSizes, index + 1, max); 
    } 

})(fontSizes, 0, fontSizes.length - 1); 

jsFiddle.

+1

link ai documenti e/o codice di esempio potrebbe essere bello. – Phrogz

+0

@Phrogz Controlla la risposta aggiornata. :) – alex

+0

Avrei dovuto sapere che non si ottiene 90k + ripetendo di non seguire. :) Molto bella. – Phrogz

0

Ho il prossimo codice e funziona perfettamente per me. Forse c'è un piccolo errore ma non ho bisogno di avere una lista di dimensioni dei caratteri.Ho appena ottenere la larghezza con una dimensione di carattere e se è troppo grande ho calcolato una dimensione proporzionale a seconda della larghezza tela e imbottitura (50)

ctx.font = FONT_SIZE+"pt Verdana"; 
var textWidth = ctx.measureText(markText).width; 
if(textWidth > canvas.width - 50) { 
    ctx.font = parseInt(FONT_SIZE*(canvas.width-50)/textWidth)+"pt Verdana"; 
    textWidth = ctx.measureText(markText).width; 
} 
ctx.textBaseline = "middle"; 
ctx.fillStyle = "rgba(255,255,255,0.5)"; 
ctx.strokeStyle = "rgba(0,0,0,0.5)"; 
var xT = image.width/2 - textWidth/2; 
var yT = image.height/2; 
ctx.fillText(markText, xT, yT); 
ctx.strokeText(markText, xT, yT); 
Problemi correlati